* 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:
parent
67e4f11fdb
commit
d62f95e941
1 changed files with 54 additions and 23 deletions
|
@ -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) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue