Added DynamicGlobalObject. Currently, this just falls back to the
per-thread scope when a get() returns NOT_FOUND on the shared global scope, fixing http://helma.org/bugs/show_bug.cgi?id=322 (kind of hackish, but ok performance-wise). Potentially this might also be the place to add compile-once script modules to the global object using a mixin-style approach.
This commit is contained in:
parent
8236ff3e18
commit
908f8134cb
3 changed files with 72 additions and 14 deletions
58
src/helma/scripting/rhino/DynamicGlobalObject.java
Normal file
58
src/helma/scripting/rhino/DynamicGlobalObject.java
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Helma License Notice
|
||||
*
|
||||
* The contents of this file are subject to the Helma License
|
||||
* Version 2.0 (the "License"). You may not use this file except in
|
||||
* compliance with the License. A copy of the License is available at
|
||||
* http://adele.helma.org/download/helma/license.txt
|
||||
*
|
||||
* Copyright 1998-2003 Helma Software. All Rights Reserved.
|
||||
*
|
||||
* $RCSfile$
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
package helma.scripting.rhino;
|
||||
|
||||
import helma.framework.core.Application;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
/**
|
||||
* This class implements a global scope object that is a dynamic proxy
|
||||
* to a shared global scope and a per-thread dynamic scope.
|
||||
*/
|
||||
public class DynamicGlobalObject extends GlobalObject {
|
||||
|
||||
WeakHashMap map = new WeakHashMap();
|
||||
|
||||
public DynamicGlobalObject(RhinoCore core, Application app) {
|
||||
super(core, app);
|
||||
}
|
||||
|
||||
public Object get(String s, Scriptable scriptable) {
|
||||
Object obj = super.get(s, scriptable);
|
||||
if (obj != null && obj != NOT_FOUND)
|
||||
return obj;
|
||||
Scriptable scope = getScope();
|
||||
if (scope != null) {
|
||||
return scope.get(s, scope);
|
||||
}
|
||||
return NOT_FOUND;
|
||||
}
|
||||
|
||||
public void registerScope(Scriptable scope) {
|
||||
map.put(Thread.currentThread(), scope);
|
||||
}
|
||||
|
||||
public Scriptable unregisterScope() {
|
||||
return (Scriptable) map.remove(Thread.currentThread());
|
||||
}
|
||||
|
||||
public final Scriptable getScope() {
|
||||
return (Scriptable) map.get(Thread.currentThread());
|
||||
}
|
||||
|
||||
}
|
|
@ -37,7 +37,7 @@ public final class RhinoCore {
|
|||
public final Application app;
|
||||
|
||||
// the global object
|
||||
GlobalObject global;
|
||||
DynamicGlobalObject global;
|
||||
|
||||
// caching table for JavaScript object wrappers
|
||||
CacheMap wrappercache;
|
||||
|
@ -88,10 +88,10 @@ public final class RhinoCore {
|
|||
context.setOptimizationLevel(optLevel);
|
||||
|
||||
try {
|
||||
GlobalObject g = new GlobalObject(this, app);
|
||||
DynamicGlobalObject g = new DynamicGlobalObject(this, app);
|
||||
g.init();
|
||||
|
||||
global = (GlobalObject) context.initStandardObjects(g);
|
||||
global = (DynamicGlobalObject) context.initStandardObjects(g);
|
||||
|
||||
pathProto = new PathWrapper(this);
|
||||
|
||||
|
@ -568,15 +568,6 @@ public final class RhinoCore {
|
|||
|
||||
String protoname = n.getPrototype();
|
||||
|
||||
// set the DbMapping of the node according to its prototype.
|
||||
// this *should* be done on the objectmodel level, but isn't currently
|
||||
// for embedded nodes since there's not enough type info at the objectmodel level
|
||||
// for those nodes.
|
||||
/* if ((protoname != null) && (protoname.length() > 0) &&
|
||||
(n.getDbMapping() == null)) {
|
||||
n.setDbMapping(app.getDbMapping(protoname));
|
||||
} */
|
||||
|
||||
Scriptable op = null;
|
||||
|
||||
op = getValidPrototype(protoname);
|
||||
|
@ -761,6 +752,8 @@ public final class RhinoCore {
|
|||
private synchronized void updateEvaluator(TypeInfo type, Reader reader,
|
||||
String sourceName, int firstline) {
|
||||
// System.err.println("UPDATE EVALUATOR: "+prototype+" - "+sourceName);
|
||||
Scriptable threadScope = global.unregisterScope();
|
||||
|
||||
try {
|
||||
// get the current context
|
||||
Context cx = Context.getCurrentContext();
|
||||
|
@ -794,6 +787,9 @@ public final class RhinoCore {
|
|||
// shouldn't happen
|
||||
}
|
||||
}
|
||||
if (threadScope != null) {
|
||||
global.registerScope(threadScope);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ public class RhinoEngine implements ScriptingEngine {
|
|||
// The Rhino context
|
||||
Context context;
|
||||
|
||||
// the global object
|
||||
// the per-thread global object
|
||||
Scriptable global;
|
||||
|
||||
// the request evaluator instance owning this fesi evaluator
|
||||
|
@ -82,7 +82,7 @@ public class RhinoEngine implements ScriptingEngine {
|
|||
context.setApplicationClassLoader(app.getClassLoader());
|
||||
|
||||
try {
|
||||
global = new GlobalObject(core, app); // context.newObject(core.global);
|
||||
global = new GlobalObject(core, app);
|
||||
global.setPrototype(core.global);
|
||||
global.setParentScope(null);
|
||||
|
||||
|
@ -162,6 +162,9 @@ public class RhinoEngine implements ScriptingEngine {
|
|||
}
|
||||
|
||||
context.setOptimizationLevel(optLevel);
|
||||
// register the per-thread scope with the dynamic scope
|
||||
core.global.registerScope(global);
|
||||
// update prototypes
|
||||
core.updatePrototypes();
|
||||
context.putThreadLocal("reval", reval);
|
||||
context.putThreadLocal("engine", this);
|
||||
|
@ -216,6 +219,7 @@ public class RhinoEngine implements ScriptingEngine {
|
|||
context.removeThreadLocal("reval");
|
||||
context.removeThreadLocal("engine");
|
||||
Context.exit();
|
||||
core.global.unregisterScope();
|
||||
thread = null;
|
||||
|
||||
// loop through previous globals and unset them, if necessary.
|
||||
|
|
Loading…
Add table
Reference in a new issue