* Implement ordered prototype updating in updatePrototypes():

global code is updated first, and parent prototypes are updated before
   their descendants. The purpose is to respect inter-prototype dependencies,
   i.e. HopObject code using global and parent prototype code.
* Marked some private methods as private.
* Use toString() rather than getMessage() on EcmaErrors, otherwise the
   error file/line number is missing from the message.
This commit is contained in:
hns 2004-01-21 16:56:04 +00:00
parent 67e4f11fdb
commit d62f95e941

View file

@ -143,11 +143,11 @@ public final class RhinoCore {
} }
/** /**
* Initialize a prototype without fully parsing its script files. * Initialize a prototype info without compiling its script files.
* *
* @param prototype the prototype to be created * @param prototype the prototype to be created
*/ */
synchronized TypeInfo initPrototype(Prototype prototype) { private synchronized void initPrototype(Prototype prototype) {
String name = prototype.getName(); String name = prototype.getName();
String lowerCaseName = prototype.getLowerCaseName(); String lowerCaseName = prototype.getLowerCaseName();
@ -182,8 +182,6 @@ public final class RhinoCore {
ignore.printStackTrace(); ignore.printStackTrace();
} }
} }
return type;
} }
/** /**
@ -192,7 +190,7 @@ public final class RhinoCore {
* @param type the info, containing the object proto, last update time and * @param type the info, containing the object proto, last update time and
* the set of compiled functions properties * the set of compiled functions properties
*/ */
synchronized void evaluatePrototype(TypeInfo type) { private synchronized void evaluatePrototype(TypeInfo type) {
Scriptable op = type.objectPrototype; Scriptable op = type.objectPrototype;
Prototype prototype = type.frameworkPrototype; Prototype prototype = type.frameworkPrototype;
@ -291,7 +289,7 @@ public final class RhinoCore {
* @param name the name of the constructor * @param name the name of the constructor
* @param op the object prototype * @param op the object prototype
*/ */
void installConstructor(String name, Scriptable op) { private void installConstructor(String name, Scriptable op) {
FunctionObject fo = new FunctionObject(name, HopObject.hopObjCtor, global); FunctionObject fo = new FunctionObject(name, HopObject.hopObjCtor, global);
ScriptRuntime.setFunctionProtoAndParent(global, fo); ScriptRuntime.setFunctionProtoAndParent(global, fo);
@ -317,32 +315,61 @@ public final class RhinoCore {
Collection protos = app.getPrototypes(); Collection protos = app.getPrototypes();
// in order to respect inter-prototype dependencies, we try to update
// the global prototype before all other prototypes, and parent
// prototypes before their descendants.
HashSet checked = new HashSet(protos.size()*2);
TypeInfo type = (TypeInfo) prototypes.get("global");
updatePrototype(type, checked);
for (Iterator i = protos.iterator(); i.hasNext();) { for (Iterator i = protos.iterator(); i.hasNext();) {
Prototype proto = (Prototype) i.next(); Prototype proto = (Prototype) i.next();
TypeInfo type = (TypeInfo) prototypes.get(proto.getLowerCaseName());
if (checked.contains(proto)) {
continue;
}
type = (TypeInfo) prototypes.get(proto.getLowerCaseName());
if (type == null) { if (type == null) {
// a prototype we don't know anything about yet. Init local update info. // a prototype we don't know anything about yet. Init local update info.
type = initPrototype(proto); initPrototype(proto);
} } else if (type.lastUpdate > -1) {
// only need to update prototype if it has already been initialized.
// only update prototype if it has already been initialized. // otherwise, this will be done on demand.
// otherwise, this will be done on demand updatePrototype(type, checked);
// System.err.println ("CHECKING PROTO "+proto+": "+type);
if (type.lastUpdate > -1) {
// let the type manager scan the prototype's directory
app.typemgr.updatePrototype(proto);
// and re-evaluate if necessary
if (type.needsUpdate()) {
evaluatePrototype(type);
}
} }
} }
lastUpdate = System.currentTimeMillis(); lastUpdate = System.currentTimeMillis();
} }
/**
* Check one prototype for updates. Used by <code>upatePrototypes()</code>.
*
* @param type the type info to check
* @param checked a set of prototypes that have already been checked
*/
private void updatePrototype(TypeInfo type, HashSet checked) {
// first, remember prototype as updated
checked.add(type.frameworkPrototype);
if (type.parentType != null &&
!checked.contains(type.parentType.frameworkPrototype)) {
updatePrototype(type.getParentType(), checked);
}
// let the type manager scan the prototype's directory
app.typemgr.updatePrototype(type.frameworkPrototype);
// and re-evaluate if necessary
if (type.needsUpdate()) {
evaluatePrototype(type);
}
}
/** /**
* A version of getPrototype() that retrieves a prototype and checks * A version of getPrototype() that retrieves a prototype and checks
@ -775,7 +802,7 @@ public final class RhinoCore {
// mark prototype as broken // mark prototype as broken
if (type.error == null) { if (type.error == null) {
type.error = e.getMessage(); type.error = e.getMessage();
if (type.error == null) { if (type.error == null || e instanceof EcmaError) {
type.error = e.toString(); type.error = e.toString();
} }
if ("global".equals(type.frameworkPrototype.getLowerCaseName())) { if ("global".equals(type.frameworkPrototype.getLowerCaseName())) {
@ -857,6 +884,10 @@ public final class RhinoCore {
} }
} }
public TypeInfo getParentType() {
return parentType;
}
public boolean hasError() { public boolean hasError() {
TypeInfo p = this; TypeInfo p = this;
while (p != null) { while (p != null) {