Changes for improved errors-as-exceptions handling.

This commit is contained in:
norris%netscape.com 1999-10-22 22:02:58 +00:00
Родитель ecae26d52e
Коммит 5f112b7933
17 изменённых файлов: 225 добавлений и 99 удалений

Просмотреть файл

@ -751,7 +751,7 @@ public final class Context {
Reader in = new StringReader(source);
// no source name or source text manager, because we're just
// going to throw away the result.
TokenStream ts = new TokenStream(in, null, 1);
TokenStream ts = new TokenStream(in, null, null, 1);
// Temporarily set error reporter to always be the exception-throwing
// DefaultErrorReporter. (This is why the method is synchronized...)
@ -1687,7 +1687,7 @@ public final class Context {
boolean returnFunction)
throws IOException
{
TokenStream ts = new TokenStream(in, sourceName, lineno);
TokenStream ts = new TokenStream(in, scope, sourceName, lineno);
return compile(scope, ts, securityDomain, returnFunction);
}

Просмотреть файл

@ -33,13 +33,15 @@
* file under either the NPL or the GPL.
*/
// API class
package org.mozilla.javascript;
/**
* The class of exceptions thrown by the JavaScript engine.
* The class of exceptions raised by the engine as described in
* ECMA edition 3. See section 15.11.6 in particular.
*/
public class EcmaError extends EvaluatorException {
public class EcmaError extends RuntimeException {
/**
* Create an exception with the specified detail message.
@ -47,13 +49,54 @@ public class EcmaError extends EvaluatorException {
* Errors internal to the JavaScript engine will simply throw a
* RuntimeException.
*
* @nativeError the NativeError object constructed for this error
* @param nativeError the NativeError object constructed for this error
*/
public EcmaError(NativeError nativeError) {
super("EcmaError");
errorObject = nativeError;
}
public NativeError errorObject;
/**
* Return a string representation of the error, which currently consists
* of the name of the error together with the message.
*/
public String toString() {
return errorObject.toString();
}
/**
* Gets the name of the error.
*
* ECMA edition 3 defines the following
* errors: ConversionError, EvalError, RangeError, ReferenceError,
* SyntaxError, TypeError, and URIError. Additional error names
* may be added in the future.
*
* See ECMA edition 3, 15.11.7.9.
*
* @return the name of the error.
*/
public String getName() {
return errorObject.getName();
}
/**
* Gets the message corresponding to the error.
*
* See ECMA edition 3, 15.11.7.10.
*
* @return an implemenation-defined string describing the error.
*/
public String getMessage() {
return errorObject.getMessage();
}
/**
* Get the error object corresponding to this exception.
*/
public Scriptable getErrorObject() {
return errorObject;
}
private NativeError errorObject;
}

Просмотреть файл

@ -1816,10 +1816,10 @@ public class Interpreter extends LabelTable {
pc = finallyStack[tryStackTop];
if (pc == 0)
throw ee;
stack[0] = ee.errorObject;
stack[0] = ee.getErrorObject();
}
else
stack[0] = ee.errorObject;
stack[0] = ee.getErrorObject();
}
else
throw ee;

Просмотреть файл

@ -44,18 +44,28 @@ package org.mozilla.javascript;
*/
public class NativeError extends ScriptableObject {
public NativeError()
{
public NativeError() {
}
public String getClassName() { return "Error"; }
public String jsFunction_toString()
{
return ScriptRuntime.toString(ScriptRuntime.getProp(this, "name", this))
+ " "
+ ScriptRuntime.toString(ScriptRuntime.getProp(this, "message", this));
public String getClassName() {
return "Error";
}
public String toString() {
return getName() + ": " + getMessage();
}
public String jsFunction_toString() {
return toString();
}
public String getName() {
return ScriptRuntime.toString(ScriptRuntime.getProp(this, "name", this));
}
public String getMessage() {
return ScriptRuntime.toString(ScriptRuntime.getProp(this, "message", this));
}
public static void finishInit(Scriptable scope, FunctionObject ctor,
Scriptable proto)

Просмотреть файл

@ -420,7 +420,7 @@ public class NativeGlobal {
// mode.
int oldOptLevel = cx.getOptimizationLevel();
cx.setOptimizationLevel(-1);
Script script = cx.compileReader(null, in, filename, linep[0],
Script script = cx.compileReader(scope, in, filename, linep[0],
securityDomain);
cx.setOptimizationLevel(oldOptLevel);
@ -442,7 +442,6 @@ public class NativeGlobal {
// should never happen since we just made the Reader from a String
throw new RuntimeException("unexpected io exception");
}
}
@ -451,7 +450,6 @@ public class NativeGlobal {
*
* See ECMA 15.11.6
*/
public static EcmaError constructError(Context cx,
String error,
String message,
@ -481,8 +479,9 @@ public class NativeGlobal {
}
}
// XXX what are these functions used for?
public static Object ConversionError(Context cx, Object[] args,
Function ctorObj, boolean inNewExpr)
Function ctorObj, boolean inNewExpr)
{
Scriptable newInstance = new NativeError();
newInstance.setPrototype((Scriptable)(ctorObj.get("prototype", ctorObj)));
@ -493,7 +492,7 @@ public class NativeGlobal {
}
public static Object EvalError(Context cx, Object[] args,
Function ctorObj, boolean inNewExpr)
Function ctorObj, boolean inNewExpr)
{
Scriptable newInstance = new NativeError();
newInstance.setPrototype((Scriptable)(ctorObj.get("prototype", ctorObj)));
@ -504,7 +503,7 @@ public class NativeGlobal {
}
public static Object RangeError(Context cx, Object[] args,
Function ctorObj, boolean inNewExpr)
Function ctorObj, boolean inNewExpr)
{
Scriptable newInstance = new NativeError();
newInstance.setPrototype((Scriptable)(ctorObj.get("prototype", ctorObj)));
@ -515,7 +514,7 @@ public class NativeGlobal {
}
public static Object ReferenceError(Context cx, Object[] args,
Function ctorObj, boolean inNewExpr)
Function ctorObj, boolean inNewExpr)
{
Scriptable newInstance = new NativeError();
newInstance.setPrototype((Scriptable)(ctorObj.get("prototype", ctorObj)));
@ -526,7 +525,7 @@ public class NativeGlobal {
}
public static Object SyntaxError(Context cx, Object[] args,
Function ctorObj, boolean inNewExpr)
Function ctorObj, boolean inNewExpr)
{
Scriptable newInstance = new NativeError();
newInstance.setPrototype((Scriptable)(ctorObj.get("prototype", ctorObj)));
@ -537,7 +536,7 @@ public class NativeGlobal {
}
public static Object TypeError(Context cx, Object[] args,
Function ctorObj, boolean inNewExpr)
Function ctorObj, boolean inNewExpr)
{
Scriptable newInstance = new NativeError();
newInstance.setPrototype((Scriptable)(ctorObj.get("prototype", ctorObj)));
@ -548,7 +547,7 @@ public class NativeGlobal {
}
public static Object URIError(Context cx, Object[] args,
Function ctorObj, boolean inNewExpr)
Function ctorObj, boolean inNewExpr)
{
Scriptable newInstance = new NativeError();
newInstance.setPrototype((Scriptable)(ctorObj.get("prototype", ctorObj)));

Просмотреть файл

@ -77,9 +77,7 @@ class Parser {
// Only report the error if the TokenStream hasn't had a chance to.
if ((ts.flags & ts.TSF_ERROR) == 0) {
String message = Context.getMessage(messageId, null);
Context.reportError(message, ts.getSourceName(), ts.getLineno(),
ts.getLine(), ts.getOffset());
ts.reportSyntaxError(messageId, null);
}
}
/* Throw an exception to unwind the recursive descent parse.

Просмотреть файл

@ -110,7 +110,7 @@ class TestScan
return;
}
TokenStream ts = new TokenStream(in, file, 1);
TokenStream ts = new TokenStream(in, null, file, 1);
if (opt == "-scan") {
int foo;
while ((foo = ts.getToken()) != ts.EOF) {

Просмотреть файл

@ -600,15 +600,19 @@ public class TokenStream {
return x & 0xff;
}
public TokenStream(Reader in,
public TokenStream(Reader in, Scriptable scope,
String sourceName, int lineno)
{
this.in = new LineBuffer(in, lineno);
this.scope = scope;
this.pushbackToken = EOF;
this.sourceName = sourceName;
flags = 0;
}
public Scriptable getScope() {
return scope;
}
/* return and pop the token from the stream if it matches...
* otherwise return null
@ -834,7 +838,7 @@ public class TokenStream {
}
if (!isDigit(c)) {
in.getString(); // throw away string in progress
reportError("msg.missing.exponent", null);
reportSyntaxError("msg.missing.exponent", null);
return ERROR;
}
do {
@ -852,7 +856,7 @@ public class TokenStream {
}
catch (NumberFormatException ex) {
Object[] errArgs = { ex.getMessage() };
reportError("msg.caught.nfe", errArgs);
reportSyntaxError("msg.caught.nfe", errArgs);
return ERROR;
}
} else {
@ -910,7 +914,7 @@ public class TokenStream {
if (c == '\n' || c == EOF_CHAR) {
in.unread();
in.getString(); // throw away the string in progress
reportError("msg.unterminated.string.lit", null);
reportSyntaxError("msg.unterminated.string.lit", null);
return ERROR;
}
@ -948,7 +952,7 @@ public class TokenStream {
}
in.unread();
if (val > 0377) {
reportError("msg.oct.esc.too.large", null);
reportSyntaxError("msg.oct.esc.too.large", null);
return ERROR;
}
c = val;
@ -1195,12 +1199,12 @@ public class TokenStream {
} else if (c == '/' && in.match('*')) {
if (in.match('/'))
return getToken();
reportError("msg.nested.comment", null);
reportSyntaxError("msg.nested.comment", null);
return ERROR;
}
}
if (c == EOF_CHAR) {
reportError("msg.unterminated.comment", null);
reportSyntaxError("msg.unterminated.comment", null);
return ERROR;
}
return getToken(); // `goto retry'
@ -1215,7 +1219,7 @@ public class TokenStream {
while ((c = in.read()) != '/') {
if (c == '\n' || c == EOF_CHAR) {
in.unread();
reportError("msg.unterminated.re.lit", null);
reportSyntaxError("msg.unterminated.re.lit", null);
return ERROR;
}
if (c == '\\') {
@ -1239,7 +1243,7 @@ public class TokenStream {
}
if (isAlpha(in.peek())) {
reportError("msg.invalid.re.flag", null);
reportSyntaxError("msg.invalid.re.flag", null);
return ERROR;
}
@ -1291,16 +1295,23 @@ public class TokenStream {
}
default:
reportError("msg.illegal.character", null);
reportSyntaxError("msg.illegal.character", null);
return ERROR;
}
}
private void reportError(String messageProperty, Object[] args) {
flags |= TSF_ERROR;
public void reportSyntaxError(String messageProperty, Object[] args) {
String message = Context.getMessage(messageProperty, args);
Context.reportError(message, getSourceName(),
getLineno(), getLine(), getOffset());
if (scope != null) {
throw NativeGlobal.constructError(
Context.getContext(), "SyntaxError",
message,
scope);
} else {
flags |= TSF_ERROR;
Context.reportError(message, getSourceName(),
getLineno(), getLine(), getOffset());
}
}
public String getSourceName() { return sourceName; }
@ -1326,6 +1337,7 @@ public class TokenStream {
private String sourceName;
private String line;
private Scriptable scope;
private int pushbackToken;
private int tokenno;

Просмотреть файл

@ -2549,9 +2549,10 @@ if (true) {
aload(savedVariableObject);
astore(variableObjectLocal);
aload(exceptionObject);
classFile.add(ByteCode.GETFIELD,
"org/mozilla/javascript/EcmaError",
"errorObject", "Lorg/mozilla/javascript/NativeError;");
addVirtualInvoke("org/mozilla/javascript/EcmaError",
"getErrorObject",
"()",
"Lorg/mozilla/javascript/Scriptable;");
releaseWordLocal(exceptionObject);
addByteCode(ByteCode.GOTO, catchLabel);
classFile.addExceptionHandler

Просмотреть файл

@ -751,7 +751,7 @@ public final class Context {
Reader in = new StringReader(source);
// no source name or source text manager, because we're just
// going to throw away the result.
TokenStream ts = new TokenStream(in, null, 1);
TokenStream ts = new TokenStream(in, null, null, 1);
// Temporarily set error reporter to always be the exception-throwing
// DefaultErrorReporter. (This is why the method is synchronized...)
@ -1687,7 +1687,7 @@ public final class Context {
boolean returnFunction)
throws IOException
{
TokenStream ts = new TokenStream(in, sourceName, lineno);
TokenStream ts = new TokenStream(in, scope, sourceName, lineno);
return compile(scope, ts, securityDomain, returnFunction);
}

Просмотреть файл

@ -33,13 +33,15 @@
* file under either the NPL or the GPL.
*/
// API class
package org.mozilla.javascript;
/**
* The class of exceptions thrown by the JavaScript engine.
* The class of exceptions raised by the engine as described in
* ECMA edition 3. See section 15.11.6 in particular.
*/
public class EcmaError extends EvaluatorException {
public class EcmaError extends RuntimeException {
/**
* Create an exception with the specified detail message.
@ -47,13 +49,54 @@ public class EcmaError extends EvaluatorException {
* Errors internal to the JavaScript engine will simply throw a
* RuntimeException.
*
* @nativeError the NativeError object constructed for this error
* @param nativeError the NativeError object constructed for this error
*/
public EcmaError(NativeError nativeError) {
super("EcmaError");
errorObject = nativeError;
}
public NativeError errorObject;
/**
* Return a string representation of the error, which currently consists
* of the name of the error together with the message.
*/
public String toString() {
return errorObject.toString();
}
/**
* Gets the name of the error.
*
* ECMA edition 3 defines the following
* errors: ConversionError, EvalError, RangeError, ReferenceError,
* SyntaxError, TypeError, and URIError. Additional error names
* may be added in the future.
*
* See ECMA edition 3, 15.11.7.9.
*
* @return the name of the error.
*/
public String getName() {
return errorObject.getName();
}
/**
* Gets the message corresponding to the error.
*
* See ECMA edition 3, 15.11.7.10.
*
* @return an implemenation-defined string describing the error.
*/
public String getMessage() {
return errorObject.getMessage();
}
/**
* Get the error object corresponding to this exception.
*/
public Scriptable getErrorObject() {
return errorObject;
}
private NativeError errorObject;
}

Просмотреть файл

@ -1816,10 +1816,10 @@ public class Interpreter extends LabelTable {
pc = finallyStack[tryStackTop];
if (pc == 0)
throw ee;
stack[0] = ee.errorObject;
stack[0] = ee.getErrorObject();
}
else
stack[0] = ee.errorObject;
stack[0] = ee.getErrorObject();
}
else
throw ee;

Просмотреть файл

@ -44,18 +44,28 @@ package org.mozilla.javascript;
*/
public class NativeError extends ScriptableObject {
public NativeError()
{
public NativeError() {
}
public String getClassName() { return "Error"; }
public String jsFunction_toString()
{
return ScriptRuntime.toString(ScriptRuntime.getProp(this, "name", this))
+ " "
+ ScriptRuntime.toString(ScriptRuntime.getProp(this, "message", this));
public String getClassName() {
return "Error";
}
public String toString() {
return getName() + ": " + getMessage();
}
public String jsFunction_toString() {
return toString();
}
public String getName() {
return ScriptRuntime.toString(ScriptRuntime.getProp(this, "name", this));
}
public String getMessage() {
return ScriptRuntime.toString(ScriptRuntime.getProp(this, "message", this));
}
public static void finishInit(Scriptable scope, FunctionObject ctor,
Scriptable proto)

Просмотреть файл

@ -420,7 +420,7 @@ public class NativeGlobal {
// mode.
int oldOptLevel = cx.getOptimizationLevel();
cx.setOptimizationLevel(-1);
Script script = cx.compileReader(null, in, filename, linep[0],
Script script = cx.compileReader(scope, in, filename, linep[0],
securityDomain);
cx.setOptimizationLevel(oldOptLevel);
@ -442,7 +442,6 @@ public class NativeGlobal {
// should never happen since we just made the Reader from a String
throw new RuntimeException("unexpected io exception");
}
}
@ -451,7 +450,6 @@ public class NativeGlobal {
*
* See ECMA 15.11.6
*/
public static EcmaError constructError(Context cx,
String error,
String message,
@ -481,8 +479,9 @@ public class NativeGlobal {
}
}
// XXX what are these functions used for?
public static Object ConversionError(Context cx, Object[] args,
Function ctorObj, boolean inNewExpr)
Function ctorObj, boolean inNewExpr)
{
Scriptable newInstance = new NativeError();
newInstance.setPrototype((Scriptable)(ctorObj.get("prototype", ctorObj)));
@ -493,7 +492,7 @@ public class NativeGlobal {
}
public static Object EvalError(Context cx, Object[] args,
Function ctorObj, boolean inNewExpr)
Function ctorObj, boolean inNewExpr)
{
Scriptable newInstance = new NativeError();
newInstance.setPrototype((Scriptable)(ctorObj.get("prototype", ctorObj)));
@ -504,7 +503,7 @@ public class NativeGlobal {
}
public static Object RangeError(Context cx, Object[] args,
Function ctorObj, boolean inNewExpr)
Function ctorObj, boolean inNewExpr)
{
Scriptable newInstance = new NativeError();
newInstance.setPrototype((Scriptable)(ctorObj.get("prototype", ctorObj)));
@ -515,7 +514,7 @@ public class NativeGlobal {
}
public static Object ReferenceError(Context cx, Object[] args,
Function ctorObj, boolean inNewExpr)
Function ctorObj, boolean inNewExpr)
{
Scriptable newInstance = new NativeError();
newInstance.setPrototype((Scriptable)(ctorObj.get("prototype", ctorObj)));
@ -526,7 +525,7 @@ public class NativeGlobal {
}
public static Object SyntaxError(Context cx, Object[] args,
Function ctorObj, boolean inNewExpr)
Function ctorObj, boolean inNewExpr)
{
Scriptable newInstance = new NativeError();
newInstance.setPrototype((Scriptable)(ctorObj.get("prototype", ctorObj)));
@ -537,7 +536,7 @@ public class NativeGlobal {
}
public static Object TypeError(Context cx, Object[] args,
Function ctorObj, boolean inNewExpr)
Function ctorObj, boolean inNewExpr)
{
Scriptable newInstance = new NativeError();
newInstance.setPrototype((Scriptable)(ctorObj.get("prototype", ctorObj)));
@ -548,7 +547,7 @@ public class NativeGlobal {
}
public static Object URIError(Context cx, Object[] args,
Function ctorObj, boolean inNewExpr)
Function ctorObj, boolean inNewExpr)
{
Scriptable newInstance = new NativeError();
newInstance.setPrototype((Scriptable)(ctorObj.get("prototype", ctorObj)));

Просмотреть файл

@ -77,9 +77,7 @@ class Parser {
// Only report the error if the TokenStream hasn't had a chance to.
if ((ts.flags & ts.TSF_ERROR) == 0) {
String message = Context.getMessage(messageId, null);
Context.reportError(message, ts.getSourceName(), ts.getLineno(),
ts.getLine(), ts.getOffset());
ts.reportSyntaxError(messageId, null);
}
}
/* Throw an exception to unwind the recursive descent parse.

Просмотреть файл

@ -600,15 +600,19 @@ public class TokenStream {
return x & 0xff;
}
public TokenStream(Reader in,
public TokenStream(Reader in, Scriptable scope,
String sourceName, int lineno)
{
this.in = new LineBuffer(in, lineno);
this.scope = scope;
this.pushbackToken = EOF;
this.sourceName = sourceName;
flags = 0;
}
public Scriptable getScope() {
return scope;
}
/* return and pop the token from the stream if it matches...
* otherwise return null
@ -834,7 +838,7 @@ public class TokenStream {
}
if (!isDigit(c)) {
in.getString(); // throw away string in progress
reportError("msg.missing.exponent", null);
reportSyntaxError("msg.missing.exponent", null);
return ERROR;
}
do {
@ -852,7 +856,7 @@ public class TokenStream {
}
catch (NumberFormatException ex) {
Object[] errArgs = { ex.getMessage() };
reportError("msg.caught.nfe", errArgs);
reportSyntaxError("msg.caught.nfe", errArgs);
return ERROR;
}
} else {
@ -910,7 +914,7 @@ public class TokenStream {
if (c == '\n' || c == EOF_CHAR) {
in.unread();
in.getString(); // throw away the string in progress
reportError("msg.unterminated.string.lit", null);
reportSyntaxError("msg.unterminated.string.lit", null);
return ERROR;
}
@ -948,7 +952,7 @@ public class TokenStream {
}
in.unread();
if (val > 0377) {
reportError("msg.oct.esc.too.large", null);
reportSyntaxError("msg.oct.esc.too.large", null);
return ERROR;
}
c = val;
@ -1195,12 +1199,12 @@ public class TokenStream {
} else if (c == '/' && in.match('*')) {
if (in.match('/'))
return getToken();
reportError("msg.nested.comment", null);
reportSyntaxError("msg.nested.comment", null);
return ERROR;
}
}
if (c == EOF_CHAR) {
reportError("msg.unterminated.comment", null);
reportSyntaxError("msg.unterminated.comment", null);
return ERROR;
}
return getToken(); // `goto retry'
@ -1215,7 +1219,7 @@ public class TokenStream {
while ((c = in.read()) != '/') {
if (c == '\n' || c == EOF_CHAR) {
in.unread();
reportError("msg.unterminated.re.lit", null);
reportSyntaxError("msg.unterminated.re.lit", null);
return ERROR;
}
if (c == '\\') {
@ -1239,7 +1243,7 @@ public class TokenStream {
}
if (isAlpha(in.peek())) {
reportError("msg.invalid.re.flag", null);
reportSyntaxError("msg.invalid.re.flag", null);
return ERROR;
}
@ -1291,16 +1295,23 @@ public class TokenStream {
}
default:
reportError("msg.illegal.character", null);
reportSyntaxError("msg.illegal.character", null);
return ERROR;
}
}
private void reportError(String messageProperty, Object[] args) {
flags |= TSF_ERROR;
public void reportSyntaxError(String messageProperty, Object[] args) {
String message = Context.getMessage(messageProperty, args);
Context.reportError(message, getSourceName(),
getLineno(), getLine(), getOffset());
if (scope != null) {
throw NativeGlobal.constructError(
Context.getContext(), "SyntaxError",
message,
scope);
} else {
flags |= TSF_ERROR;
Context.reportError(message, getSourceName(),
getLineno(), getLine(), getOffset());
}
}
public String getSourceName() { return sourceName; }
@ -1326,6 +1337,7 @@ public class TokenStream {
private String sourceName;
private String line;
private Scriptable scope;
private int pushbackToken;
private int tokenno;

Просмотреть файл

@ -2549,9 +2549,10 @@ if (true) {
aload(savedVariableObject);
astore(variableObjectLocal);
aload(exceptionObject);
classFile.add(ByteCode.GETFIELD,
"org/mozilla/javascript/EcmaError",
"errorObject", "Lorg/mozilla/javascript/NativeError;");
addVirtualInvoke("org/mozilla/javascript/EcmaError",
"getErrorObject",
"()",
"Lorg/mozilla/javascript/Scriptable;");
releaseWordLocal(exceptionObject);
addByteCode(ByteCode.GOTO, catchLabel);
classFile.addExceptionHandler