Improved error reporting:

* Track and report errors in parent prototypes
* Fix bug where global error was wrongly reset
This commit is contained in:
hns 2004-01-20 18:48:59 +00:00
parent 908f8134cb
commit e596a60f64

View file

@ -58,7 +58,7 @@ public final class RhinoCore {
PathWrapper pathProto; PathWrapper pathProto;
// Any error that may have been found in global code // Any error that may have been found in global code
EcmaError globalError; String globalError;
/** /**
* Create a Rhino evaluator for the given application and request evaluator. * Create a Rhino evaluator for the given application and request evaluator.
@ -199,9 +199,12 @@ public final class RhinoCore {
// set the parent prototype in case it hasn't been done before // set the parent prototype in case it hasn't been done before
// or it has changed... // or it has changed...
setParentPrototype(prototype, op); setParentPrototype(prototype, type);
globalError = type.error = null; type.error = null;
if ("global".equals(prototype.getLowerCaseName())) {
globalError = null;
}
// loop through the prototype's code elements and evaluate them // loop through the prototype's code elements and evaluate them
// first the zipped ones ... // first the zipped ones ...
@ -254,29 +257,29 @@ public final class RhinoCore {
* Set the parent prototype on the ObjectPrototype. * Set the parent prototype on the ObjectPrototype.
* *
* @param prototype the prototype spec * @param prototype the prototype spec
* @param op the prototype object * @param type the prototype object info
*/ */
private void setParentPrototype(Prototype prototype, Scriptable op) { private void setParentPrototype(Prototype prototype, TypeInfo type) {
String name = prototype.getName(); String name = prototype.getName();
String lowerCaseName = prototype.getLowerCaseName(); String lowerCaseName = prototype.getLowerCaseName();
if (!"global".equals(lowerCaseName) && !"hopobject".equals(lowerCaseName)) { if (!"global".equals(lowerCaseName) && !"hopobject".equals(lowerCaseName)) {
// get the prototype's prototype if possible and necessary // get the prototype's prototype if possible and necessary
Scriptable opp = null; TypeInfo parentType = null;
Prototype parent = prototype.getParentPrototype(); Prototype parent = prototype.getParentPrototype();
if (parent != null) { if (parent != null) {
// see if parent prototype is already registered. if not, register it // see if parent prototype is already registered. if not, register it
opp = getPrototype(parent.getName()); parentType = getPrototypeInfo(parent.getName());
} }
if (opp == null && !app.isJavaPrototype(name)) { if (parentType == null && !app.isJavaPrototype(name)) {
// FIXME: does this ever occur? // FIXME: does this ever occur?
opp = getPrototype("hopobject"); parentType = getPrototypeInfo("hopobject");
} }
op.setPrototype(opp); type.setParentType(parentType);
} }
} }
@ -348,11 +351,11 @@ public final class RhinoCore {
*/ */
public Scriptable getValidPrototype(String protoName) { public Scriptable getValidPrototype(String protoName) {
if (globalError != null) { if (globalError != null) {
throw new EvaluatorException(globalError.toString()); throw new EvaluatorException(globalError);
} }
TypeInfo type = getPrototypeInfo(protoName); TypeInfo type = getPrototypeInfo(protoName);
if (type != null && type.error != null) { if (type != null && type.hasError()) {
throw new EvaluatorException(type.error.toString()); throw new EvaluatorException(type.getError());
} }
return type == null ? null : type.objectPrototype; return type == null ? null : type.objectPrototype;
} }
@ -770,11 +773,13 @@ public final class RhinoCore {
System.err.println("Error parsing file " + sourceName + ": " + e); System.err.println("Error parsing file " + sourceName + ": " + e);
} }
// mark prototype as broken // mark prototype as broken
if (type.error == null && e instanceof EcmaError) { if (type.error == null) {
type.error = e.getMessage();
if (type.error == null) {
type.error = e.toString();
}
if ("global".equals(type.frameworkPrototype.getLowerCaseName())) { if ("global".equals(type.frameworkPrototype.getLowerCaseName())) {
globalError = (EcmaError) e; globalError = type.error;
} else {
type.error = (EcmaError) e;
} }
wrappercache.clear(); wrappercache.clear();
} }
@ -816,8 +821,8 @@ public final class RhinoCore {
// to get the prototype chain set. // to get the prototype chain set.
long lastUpdate = -1; long lastUpdate = -1;
// the prototype name // the parent prototype info
// String protoName; TypeInfo parentType;
// a set of property values that were defined in last script compliation // a set of property values that were defined in last script compliation
Set compiledFunctions; Set compiledFunctions;
@ -825,7 +830,7 @@ public final class RhinoCore {
// a set of property keys that were present before first script compilation // a set of property keys that were present before first script compilation
final Set predefinedProperties; final Set predefinedProperties;
EcmaError error; String error;
public TypeInfo(Prototype proto, ScriptableObject op) { public TypeInfo(Prototype proto, ScriptableObject op) {
frameworkPrototype = proto; frameworkPrototype = proto;
@ -843,6 +848,35 @@ public final class RhinoCore {
return frameworkPrototype.getLastUpdate() > lastUpdate; return frameworkPrototype.getLastUpdate() > lastUpdate;
} }
public void setParentType(TypeInfo type) {
parentType = type;
if (type == null) {
objectPrototype.setPrototype(null);
} else {
objectPrototype.setPrototype(type.objectPrototype);
}
}
public boolean hasError() {
TypeInfo p = this;
while (p != null) {
if (p.error != null)
return true;
p = p.parentType;
}
return false;
}
public String getError() {
TypeInfo p = this;
while (p != null) {
if (p.error != null)
return p.error;
p = p.parentType;
}
return null;
}
public String toString() { public String toString() {
return ("TypeInfo[" + frameworkPrototype + "," + new Date(lastUpdate) + "]"); return ("TypeInfo[" + frameworkPrototype + "," + new Date(lastUpdate) + "]");
} }