* Do not use Context.setCompileFunctionsWithDynamicScope() as it is
seriously BROKEN for nested functions. The only workaround needed is a little fix in HopObject.put() to set the parent scope on functions because of the funky way we compile prototypes. * Use one ContextFactory instance per RhinoCore to initialize, enter and exit contexts, and use various call() methods to actually use it in RhinoCore.evaluate() and RhinoEngine.invoke(). * Set parent scope in HopObject constructor. * Use java.lang.ThreadLocal to implement engine/thread registration. * Implement RhinoCore.getRhinoCore() and RhinoEngine.getRhinoEngine(). * Implement rhino.strictvars to throw errors on undeclared vars. * Do not declare throws Exception in RhinoCore.processXmlRpc* methods. * Clean up error logging.
This commit is contained in:
parent
68756f4b3e
commit
20354228a2
6 changed files with 188 additions and 195 deletions
|
@ -152,9 +152,7 @@ public class GlobalObject extends ImporterTopLevel implements PropertyRecorder {
|
|||
*/
|
||||
public boolean renderSkin(Object skinobj, Object paramobj)
|
||||
throws UnsupportedEncodingException, IOException {
|
||||
Context cx = Context.getCurrentContext();
|
||||
RequestEvaluator reval = (RequestEvaluator) cx.getThreadLocal("reval");
|
||||
RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine");
|
||||
RhinoEngine engine = RhinoEngine.getRhinoEngine();
|
||||
Skin skin;
|
||||
|
||||
if (skinobj instanceof Wrapper) {
|
||||
|
@ -170,7 +168,7 @@ public class GlobalObject extends ImporterTopLevel implements PropertyRecorder {
|
|||
Map param = RhinoCore.getSkinParam(paramobj);
|
||||
|
||||
if (skin != null) {
|
||||
skin.render(reval, null, param);
|
||||
skin.render(engine.reval, null, param);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -186,9 +184,7 @@ public class GlobalObject extends ImporterTopLevel implements PropertyRecorder {
|
|||
*/
|
||||
public String renderSkinAsString(Object skinobj, Object paramobj)
|
||||
throws UnsupportedEncodingException, IOException {
|
||||
Context cx = Context.getCurrentContext();
|
||||
RequestEvaluator reval = (RequestEvaluator) cx.getThreadLocal("reval");
|
||||
RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine");
|
||||
RhinoEngine engine = RhinoEngine.getRhinoEngine();
|
||||
Skin skin;
|
||||
|
||||
if (skinobj instanceof Wrapper) {
|
||||
|
@ -204,9 +200,9 @@ public class GlobalObject extends ImporterTopLevel implements PropertyRecorder {
|
|||
Map param = RhinoCore.getSkinParam(paramobj);
|
||||
|
||||
if (skin != null) {
|
||||
ResponseTrans res = reval.getResponse();
|
||||
ResponseTrans res = engine.getResponse();
|
||||
res.pushStringBuffer();
|
||||
skin.render(reval, null, param);
|
||||
skin.render(engine.reval, null, param);
|
||||
return res.popStringBuffer();
|
||||
}
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco
|
|||
this(className, core);
|
||||
this.node = node;
|
||||
setPrototype(proto);
|
||||
setParentScope(core.global);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,10 +73,8 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco
|
|||
*
|
||||
* @param core the RhinoCore
|
||||
* @return the HopObject prototype
|
||||
* @throws PropertyException
|
||||
*/
|
||||
public static HopObject init(RhinoCore core)
|
||||
throws PropertyException {
|
||||
public static HopObject init(RhinoCore core) {
|
||||
int attributes = DONTENUM | PERMANENT;
|
||||
|
||||
// create prototype object
|
||||
|
@ -197,9 +196,7 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco
|
|||
*/
|
||||
public boolean jsFunction_renderSkin(Object skinobj, Object paramobj)
|
||||
throws UnsupportedEncodingException, IOException {
|
||||
Context cx = Context.getCurrentContext();
|
||||
RequestEvaluator reval = (RequestEvaluator) cx.getThreadLocal("reval");
|
||||
RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine");
|
||||
RhinoEngine engine = RhinoEngine.getRhinoEngine();
|
||||
Skin skin;
|
||||
|
||||
if (skinobj instanceof Wrapper) {
|
||||
|
@ -217,7 +214,7 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco
|
|||
checkNode();
|
||||
|
||||
if (skin != null) {
|
||||
skin.render(reval, node, param);
|
||||
skin.render(engine.reval, node, param);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -232,9 +229,8 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco
|
|||
* @return the resource, if found, null otherwise
|
||||
*/
|
||||
public Object jsFunction_getResource(String resourceName) {
|
||||
Context cx = Context.getCurrentContext();
|
||||
RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine");
|
||||
Prototype prototype = engine.core.app.getPrototypeByName(className);
|
||||
RhinoEngine engine = RhinoEngine.getRhinoEngine();
|
||||
Prototype prototype = engine.app.getPrototypeByName(className);
|
||||
while (prototype != null) {
|
||||
Resource[] resources = prototype.getResources();
|
||||
for (int i = resources.length - 1; i >= 0; i--) {
|
||||
|
@ -256,8 +252,7 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco
|
|||
* @return an array of resources with the given name
|
||||
*/
|
||||
public Object jsFunction_getResources(String resourceName) {
|
||||
Context cx = Context.getCurrentContext();
|
||||
RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine");
|
||||
RhinoEngine engine = RhinoEngine.getRhinoEngine();
|
||||
Prototype prototype = engine.core.app.getPrototypeByName(className);
|
||||
ArrayList a = new ArrayList();
|
||||
while (prototype != null) {
|
||||
|
@ -282,9 +277,7 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco
|
|||
*/
|
||||
public String jsFunction_renderSkinAsString(Object skinobj, Object paramobj)
|
||||
throws UnsupportedEncodingException, IOException {
|
||||
Context cx = Context.getCurrentContext();
|
||||
RequestEvaluator reval = (RequestEvaluator) cx.getThreadLocal("reval");
|
||||
RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine");
|
||||
RhinoEngine engine = RhinoEngine.getRhinoEngine();
|
||||
Skin skin;
|
||||
|
||||
if (skinobj instanceof Wrapper) {
|
||||
|
@ -302,9 +295,9 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco
|
|||
checkNode();
|
||||
|
||||
if (skin != null) {
|
||||
ResponseTrans res = reval.getResponse();
|
||||
ResponseTrans res = engine.getResponse();
|
||||
res.pushStringBuffer();
|
||||
skin.render(reval, node, param);
|
||||
skin.render(engine.reval, node, param);
|
||||
return res.popStringBuffer();
|
||||
}
|
||||
|
||||
|
@ -716,6 +709,13 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco
|
|||
// register property for PropertyRecorder interface
|
||||
if (isRecording) {
|
||||
changedProperties.add(name);
|
||||
if (value instanceof Function) {
|
||||
// reset function's parent scope, needed because of the way we compile
|
||||
// prototype code, using the prototype objects as scope
|
||||
Function f = (Function) value;
|
||||
if (f.getParentScope() == this)
|
||||
f.setParentScope(core.global);
|
||||
}
|
||||
}
|
||||
super.put(name, start, value);
|
||||
} else {
|
||||
|
|
|
@ -77,9 +77,7 @@ public class JavaObject extends NativeJavaObject {
|
|||
*/
|
||||
public boolean renderSkin(Object skinobj, Object paramobj)
|
||||
throws UnsupportedEncodingException, IOException {
|
||||
Context cx = Context.getCurrentContext();
|
||||
RequestEvaluator reval = (RequestEvaluator) cx.getThreadLocal("reval");
|
||||
RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine");
|
||||
RhinoEngine engine = RhinoEngine.getRhinoEngine();
|
||||
Skin skin;
|
||||
|
||||
if (skinobj instanceof Wrapper) {
|
||||
|
@ -95,7 +93,7 @@ public class JavaObject extends NativeJavaObject {
|
|||
Map param = RhinoCore.getSkinParam(paramobj);
|
||||
|
||||
if (skin != null) {
|
||||
skin.render(reval, javaObject, param);
|
||||
skin.render(engine.reval, javaObject, param);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -111,9 +109,7 @@ public class JavaObject extends NativeJavaObject {
|
|||
*/
|
||||
public String renderSkinAsString(Object skinobj, Object paramobj)
|
||||
throws UnsupportedEncodingException, IOException {
|
||||
Context cx = Context.getCurrentContext();
|
||||
RequestEvaluator reval = (RequestEvaluator) cx.getThreadLocal("reval");
|
||||
RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine");
|
||||
RhinoEngine engine = RhinoEngine.getRhinoEngine();
|
||||
Skin skin;
|
||||
|
||||
if (skinobj instanceof Wrapper) {
|
||||
|
@ -129,9 +125,9 @@ public class JavaObject extends NativeJavaObject {
|
|||
Map param = RhinoCore.getSkinParam(paramobj);
|
||||
|
||||
if (skin != null) {
|
||||
ResponseTrans res = reval.getResponse();
|
||||
ResponseTrans res = engine.getResponse();
|
||||
res.pushStringBuffer();
|
||||
skin.render(reval, javaObject, param);
|
||||
skin.render(engine.reval, javaObject, param);
|
||||
return res.popStringBuffer();
|
||||
}
|
||||
|
||||
|
@ -170,11 +166,7 @@ public class JavaObject extends NativeJavaObject {
|
|||
* Checks whether the given property is defined in this object.
|
||||
*/
|
||||
public boolean has(String name, Scriptable start) {
|
||||
// System.err.println ("HAS: "+name);
|
||||
if (overload.containsKey(name)) {
|
||||
return true;
|
||||
}
|
||||
return super.has(name, start);
|
||||
return overload.containsKey(name) || super.has(name, start);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -227,8 +219,7 @@ public class JavaObject extends NativeJavaObject {
|
|||
* @return the resource, if found, null otherwise
|
||||
*/
|
||||
public Object getResource(String resourceName) {
|
||||
Context cx = Context.getCurrentContext();
|
||||
RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine");
|
||||
RhinoEngine engine = RhinoEngine.getRhinoEngine();
|
||||
Prototype prototype = engine.core.app.getPrototypeByName(protoName);
|
||||
while (prototype != null) {
|
||||
Resource[] resources = prototype.getResources();
|
||||
|
@ -251,8 +242,7 @@ public class JavaObject extends NativeJavaObject {
|
|||
* @return an array of resources with the given name
|
||||
*/
|
||||
public Object getResources(String resourceName) {
|
||||
Context cx = Context.getCurrentContext();
|
||||
RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine");
|
||||
RhinoEngine engine = RhinoEngine.getRhinoEngine();
|
||||
Prototype prototype = engine.core.app.getPrototypeByName(protoName);
|
||||
ArrayList a = new ArrayList();
|
||||
while (prototype != null) {
|
||||
|
|
|
@ -42,6 +42,9 @@ public final class RhinoCore implements ScopeProvider {
|
|||
// the application we're running in
|
||||
public final Application app;
|
||||
|
||||
// our context factory
|
||||
ContextFactory contextFactory;
|
||||
|
||||
// the global object
|
||||
GlobalObject global;
|
||||
|
||||
|
@ -66,17 +69,20 @@ public final class RhinoCore implements ScopeProvider {
|
|||
// Any error that may have been found in global code
|
||||
String globalError;
|
||||
|
||||
// the debugger, if active
|
||||
HelmaDebugger debugger = null;
|
||||
|
||||
// optimization level for rhino engine, ranges from -1 to 9
|
||||
int optLevel = 0;
|
||||
|
||||
// debugger/tracer flags
|
||||
boolean hasDebugger = false;
|
||||
boolean hasTracer = false;
|
||||
|
||||
// dynamic portion of the type check sleep that grows
|
||||
// as the app remains unchanged
|
||||
long updateSnooze = 500;
|
||||
|
||||
static {
|
||||
ContextFactory.initGlobal(new HelmaContextFactory());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a Rhino evaluator for the given application and request evaluator.
|
||||
*/
|
||||
|
@ -84,6 +90,8 @@ public final class RhinoCore implements ScopeProvider {
|
|||
this.app = app;
|
||||
wrappercache = new WeakCacheMap(500);
|
||||
prototypes = new Hashtable();
|
||||
contextFactory = new HelmaContextFactory();
|
||||
contextFactory.initApplicationClassLoader(app.getClassLoader());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -91,31 +99,27 @@ public final class RhinoCore implements ScopeProvider {
|
|||
* necessary to bootstrap the rest is parsed.
|
||||
*/
|
||||
protected synchronized void initialize() {
|
||||
Context context = Context.enter();
|
||||
|
||||
context.setCompileFunctionsWithDynamicScope(true);
|
||||
context.setApplicationClassLoader(app.getClassLoader());
|
||||
wrapper = new WrapMaker();
|
||||
wrapper.setJavaPrimitiveWrap(false);
|
||||
context.setWrapFactory(wrapper);
|
||||
|
||||
// Set up visual debugger if rhino.debug = true
|
||||
if ("true".equals(app.getProperty("rhino.debug"))) {
|
||||
initDebugger(context);
|
||||
}
|
||||
hasDebugger = "true".equalsIgnoreCase(app.getProperty("rhino.debug"));
|
||||
hasTracer = "true".equalsIgnoreCase(app.getProperty("rhino.trace"));
|
||||
|
||||
// Set default optimization level according to whether debugger is on
|
||||
int optLevel = debugger == null ? 0 : -1;
|
||||
|
||||
String opt = app.getProperty("rhino.optlevel");
|
||||
if (opt != null) {
|
||||
try {
|
||||
optLevel = Integer.parseInt(opt);
|
||||
} catch (Exception ignore) {
|
||||
app.logError("Invalid rhino optlevel: " + opt);
|
||||
if (hasDebugger || hasTracer) {
|
||||
optLevel = -1;
|
||||
} else {
|
||||
String opt = app.getProperty("rhino.optlevel");
|
||||
if (opt != null) {
|
||||
try {
|
||||
optLevel = Integer.parseInt(opt);
|
||||
} catch (Exception ignore) {
|
||||
app.logError("Invalid rhino optlevel: " + opt);
|
||||
}
|
||||
}
|
||||
}
|
||||
context.setOptimizationLevel(optLevel);
|
||||
wrapper = new WrapMaker();
|
||||
wrapper.setJavaPrimitiveWrap(false);
|
||||
|
||||
Context context = contextFactory.enter();
|
||||
|
||||
try {
|
||||
// create global object
|
||||
|
@ -162,29 +166,22 @@ public final class RhinoCore implements ScopeProvider {
|
|||
getPrototype("global");
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("Cannot initialize interpreter");
|
||||
System.err.println("Error: " + e);
|
||||
e.printStackTrace();
|
||||
app.logError("Cannot initialize interpreter", e);
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
} finally {
|
||||
Context.exit();
|
||||
contextFactory.exit();
|
||||
}
|
||||
}
|
||||
|
||||
void initDebugger(Context context) {
|
||||
try {
|
||||
if (debugger == null) {
|
||||
debugger = new HelmaDebugger(app.getName());
|
||||
debugger.setScopeProvider(this);
|
||||
// debugger.setScope(global);
|
||||
debugger.attachTo(context.getFactory());
|
||||
// debugger.pack();
|
||||
// debugger.getDebugFrame().setLocation(60, 60);
|
||||
}
|
||||
// if (!debugger.isVisible())
|
||||
// debugger.setVisible(true);
|
||||
if (debugger == null) {
|
||||
debugger = new HelmaDebugger(app.getName());
|
||||
debugger.setScopeProvider(this);
|
||||
debugger.attachTo(contextFactory);
|
||||
}
|
||||
} catch (Exception x) {
|
||||
x.printStackTrace();
|
||||
app.logError("Error setting up debugger", x);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -235,10 +232,10 @@ public final class RhinoCore implements ScopeProvider {
|
|||
* @param type the info, containing the object proto, last update time and
|
||||
* the set of compiled functions properties
|
||||
*/
|
||||
private synchronized void evaluatePrototype(TypeInfo type) {
|
||||
private synchronized void evaluatePrototype(final TypeInfo type) {
|
||||
|
||||
type.prepareCompilation();
|
||||
Prototype prototype = type.frameworkProto;
|
||||
final Prototype prototype = type.frameworkProto;
|
||||
|
||||
// set the parent prototype in case it hasn't been done before
|
||||
// or it has changed...
|
||||
|
@ -249,12 +246,16 @@ public final class RhinoCore implements ScopeProvider {
|
|||
globalError = null;
|
||||
}
|
||||
|
||||
// loop through the prototype's code elements and evaluate them
|
||||
Iterator code = prototype.getCodeResources();
|
||||
while (code.hasNext()) {
|
||||
evaluate(type, (Resource) code.next());
|
||||
}
|
||||
|
||||
contextFactory.call(new ContextAction() {
|
||||
public Object run(Context cx) {
|
||||
// loop through the prototype's code elements and evaluate them
|
||||
Iterator code = prototype.getCodeResources();
|
||||
while (code.hasNext()) {
|
||||
evaluate(cx, type, (Resource) code.next());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
type.commitCompilation();
|
||||
}
|
||||
|
||||
|
@ -470,7 +471,7 @@ public final class RhinoCore implements ScopeProvider {
|
|||
* Convert an input argument from Java to the scripting runtime
|
||||
* representation.
|
||||
*/
|
||||
public Object processXmlRpcArgument (Object what) throws Exception {
|
||||
public Object processXmlRpcArgument (Object what) {
|
||||
if (what == null)
|
||||
return null;
|
||||
if (what instanceof Vector) {
|
||||
|
@ -506,7 +507,7 @@ public final class RhinoCore implements ScopeProvider {
|
|||
/**
|
||||
* convert a JavaScript Object object to a generic Java object stucture.
|
||||
*/
|
||||
public Object processXmlRpcResponse (Object what) throws Exception {
|
||||
public Object processXmlRpcResponse (Object what) {
|
||||
// unwrap if argument is a Wrapper
|
||||
if (what instanceof Wrapper) {
|
||||
what = ((Wrapper) what).unwrap();
|
||||
|
@ -606,9 +607,7 @@ public final class RhinoCore implements ScopeProvider {
|
|||
HopObject hobj = (HopObject) wrappercache.get(n);
|
||||
|
||||
if (hobj == null) {
|
||||
|
||||
String protoname = n.getPrototype();
|
||||
|
||||
Scriptable op = getValidPrototype(protoname);
|
||||
|
||||
// no prototype found for this node
|
||||
|
@ -630,7 +629,6 @@ public final class RhinoCore implements ScopeProvider {
|
|||
}
|
||||
|
||||
hobj = new HopObject(protoname, this, n, op);
|
||||
|
||||
wrappercache.put(n, hobj);
|
||||
}
|
||||
|
||||
|
@ -652,12 +650,11 @@ public final class RhinoCore implements ScopeProvider {
|
|||
if (hasFunction(proto, hrefFunction)) {
|
||||
|
||||
// get the currently active rhino engine and invoke the function
|
||||
Context cx = Context.getCurrentContext();
|
||||
RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine");
|
||||
RhinoEngine eng = RhinoEngine.getRhinoEngine();
|
||||
Object result;
|
||||
|
||||
try {
|
||||
result = engine.invoke(handler, hrefFunction,
|
||||
result = eng.invoke(handler, hrefFunction,
|
||||
new Object[] { basicHref },
|
||||
ScriptingEngine.ARGS_WRAP_DEFAULT,
|
||||
false);
|
||||
|
@ -689,14 +686,13 @@ public final class RhinoCore implements ScopeProvider {
|
|||
Skin skin = null;
|
||||
Object handler = obj;
|
||||
// get the currently active rhino engine and render the skin
|
||||
Context cx = Context.getCurrentContext();
|
||||
RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine");
|
||||
RhinoEngine eng = RhinoEngine.getRhinoEngine();
|
||||
|
||||
while (handler != null) {
|
||||
Prototype proto = app.getPrototype(handler);
|
||||
|
||||
if (proto != null) {
|
||||
skin = engine.getSkin(proto.getName(), hrefSkin);
|
||||
skin = eng.getSkin(proto.getName(), hrefSkin);
|
||||
}
|
||||
|
||||
if (skin != null) {
|
||||
|
@ -707,18 +703,27 @@ public final class RhinoCore implements ScopeProvider {
|
|||
}
|
||||
|
||||
if (skin != null) {
|
||||
engine.getResponse().pushStringBuffer();
|
||||
eng.getResponse().pushStringBuffer();
|
||||
HashMap param = new HashMap();
|
||||
param.put("path", basicHref);
|
||||
skin.render(engine.getRequestEvaluator(), handler, param);
|
||||
skin.render(eng.getRequestEvaluator(), handler, param);
|
||||
|
||||
basicHref = engine.getResponse().popStringBuffer().trim();
|
||||
basicHref = eng.getResponse().popStringBuffer().trim();
|
||||
}
|
||||
}
|
||||
|
||||
return basicHref;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the RhinoCore instance associated with the current thread, or null
|
||||
* @return the RhinoCore instance associated with the current thread
|
||||
*/
|
||||
public static RhinoCore getCore() {
|
||||
RhinoEngine eng = RhinoEngine.getRhinoEngine();
|
||||
return eng != null ? eng.core : null;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// skin related methods
|
||||
/////////////////////////////////////////////
|
||||
|
@ -766,30 +771,30 @@ public final class RhinoCore implements ScopeProvider {
|
|||
* @param typename the type this resource belongs to
|
||||
* @param code a code resource
|
||||
*/
|
||||
public void injectCodeResource(String typename, Resource code) {
|
||||
TypeInfo type = (TypeInfo) prototypes.get(typename.toLowerCase());
|
||||
public void injectCodeResource(String typename, final Resource code) {
|
||||
final TypeInfo type = (TypeInfo) prototypes.get(typename.toLowerCase());
|
||||
if (type == null || type.lastUpdate == -1)
|
||||
return;
|
||||
evaluate(type, code);
|
||||
contextFactory.call(new ContextAction() {
|
||||
public Object run(Context cx) {
|
||||
evaluate(cx, type, code);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// private evaluation/compilation methods
|
||||
////////////////////////////////////////////////
|
||||
|
||||
private synchronized void evaluate (TypeInfo type, Resource code) {
|
||||
// get the current context
|
||||
Context cx = Context.getCurrentContext();
|
||||
|
||||
private synchronized void evaluate(Context cx, TypeInfo type, Resource code) {
|
||||
String sourceName = code.getName();
|
||||
Reader reader = null;
|
||||
|
||||
|
||||
Resource previousCurrentResource = app.getCurrentCodeResource();
|
||||
app.setCurrentCodeResource(code);
|
||||
|
||||
try {
|
||||
Scriptable op = type.objProto;
|
||||
|
||||
// do the update, evaluating the file
|
||||
if (sourceName.endsWith(".js")) {
|
||||
reader = new InputStreamReader(code.getInputStream());
|
||||
|
@ -805,11 +810,12 @@ public final class RhinoCore implements ScopeProvider {
|
|||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
app.logError("Error parsing file " + sourceName, e);
|
||||
ScriptingException sx = new ScriptingException(e.getMessage(), e);
|
||||
app.logError("Error parsing file " + sourceName, sx);
|
||||
// mark prototype as broken
|
||||
if (type.error == null) {
|
||||
type.error = e.getMessage();
|
||||
if (type.error == null || e instanceof EcmaError) {
|
||||
if (type.error == null) {
|
||||
type.error = e.toString();
|
||||
}
|
||||
if ("global".equals(type.frameworkProto.getLowerCaseName())) {
|
||||
|
@ -817,7 +823,6 @@ public final class RhinoCore implements ScopeProvider {
|
|||
}
|
||||
wrappercache.clear();
|
||||
}
|
||||
// e.printStackTrace();
|
||||
} finally {
|
||||
app.setCurrentCodeResource(previousCurrentResource);
|
||||
if (reader != null) {
|
||||
|
@ -931,7 +936,7 @@ public final class RhinoCore implements ScopeProvider {
|
|||
objProto.setAttributes(key, 0);
|
||||
objProto.delete(key);
|
||||
} catch (Exception px) {
|
||||
System.err.println("Error unsetting property "+key+" on "+
|
||||
app.logEvent("Error unsetting property "+key+" on "+
|
||||
frameworkProto.getName());
|
||||
}
|
||||
}
|
||||
|
@ -1036,7 +1041,6 @@ public final class RhinoCore implements ScopeProvider {
|
|||
}
|
||||
|
||||
public Scriptable wrapNewObject(Context cx, Scriptable scope, Object obj) {
|
||||
// System.err.println ("N-Wrapping: "+obj);
|
||||
if (obj instanceof INode) {
|
||||
return getNodeWrapper((INode) obj);
|
||||
}
|
||||
|
@ -1092,13 +1096,30 @@ public final class RhinoCore implements ScopeProvider {
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
class HelmaContextFactory extends ContextFactory {
|
||||
|
||||
class HelmaContextFactory extends ContextFactory {
|
||||
protected boolean hasFeature(Context cx, int featureIndex) {
|
||||
if (featureIndex == Context.FEATURE_DYNAMIC_SCOPE) {
|
||||
return true;
|
||||
final boolean strictVars = "true".equalsIgnoreCase(app.getProperty("strictVars"));
|
||||
|
||||
protected void onContextCreated(Context cx) {
|
||||
cx.setWrapFactory(wrapper);
|
||||
cx.setOptimizationLevel(optLevel);
|
||||
// Set up visual debugger if rhino.debug = true
|
||||
if (hasDebugger)
|
||||
initDebugger(cx);
|
||||
super.onContextCreated(cx);
|
||||
}
|
||||
return super.hasFeature(cx, featureIndex);
|
||||
|
||||
protected boolean hasFeature(Context cx, int featureIndex) {
|
||||
switch (featureIndex) {
|
||||
case Context.FEATURE_DYNAMIC_SCOPE:
|
||||
return true;
|
||||
|
||||
case Context.FEATURE_STRICT_VARS:
|
||||
return strictVars;
|
||||
|
||||
default:
|
||||
return super.hasFeature(cx, featureIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,8 @@ public class RhinoEngine implements ScriptingEngine {
|
|||
|
||||
// the request evaluator instance owning this fesi evaluator
|
||||
RequestEvaluator reval;
|
||||
|
||||
// the rhino core
|
||||
RhinoCore core;
|
||||
|
||||
// remember global variables from last invokation to be able to
|
||||
|
@ -66,6 +68,9 @@ public class RhinoEngine implements ScriptingEngine {
|
|||
// the thread currently running this engine
|
||||
Thread thread;
|
||||
|
||||
// thread local engine registry
|
||||
static ThreadLocal engines = new ThreadLocal();
|
||||
|
||||
// the introspector that provides documentation for this application
|
||||
DocApplication doc = null;
|
||||
|
||||
|
@ -83,9 +88,8 @@ public class RhinoEngine implements ScriptingEngine {
|
|||
this.app = app;
|
||||
this.reval = reval;
|
||||
initRhinoCore(app);
|
||||
context = Context.enter();
|
||||
context.setCompileFunctionsWithDynamicScope(true);
|
||||
context.setApplicationClassLoader(app.getClassLoader());
|
||||
|
||||
context = core.contextFactory.enter();
|
||||
|
||||
try {
|
||||
global = new GlobalObject(core, app, true);
|
||||
|
@ -105,22 +109,27 @@ public class RhinoEngine implements ScriptingEngine {
|
|||
extensionGlobals.putAll(tmpGlobals);
|
||||
}
|
||||
} catch (ConfigurationException e) {
|
||||
app.logEvent("Couldn't initialize extension " + ext.getName() + ": " +
|
||||
e.getMessage());
|
||||
app.logError("Couldn't initialize extension " + ext.getName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("Cannot initialize interpreter");
|
||||
System.err.println("Error: " + e);
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e.getMessage());
|
||||
app.logError("Cannot initialize interpreter", e);
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
} finally {
|
||||
Context.exit ();
|
||||
core.contextFactory.exit ();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the RhinoEngine associated with the current thread, or null.
|
||||
* @return the RhinoEngine assocated with the current thread
|
||||
*/
|
||||
public static RhinoEngine getRhinoEngine() {
|
||||
return (RhinoEngine) engines.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the RhinoCore instance for this engine and application.
|
||||
* @param app the application we belong to
|
||||
|
@ -145,39 +154,20 @@ public class RhinoEngine implements ScriptingEngine {
|
|||
* engine know it should update its prototype information.
|
||||
*/
|
||||
public void updatePrototypes() throws IOException {
|
||||
// remember the current thread as our thread - we this here so
|
||||
// remember the current thread as our thread - we do this here so
|
||||
// the thread is already set when the RequestEvaluator calls
|
||||
// Application.getDataRoot(), which may result in a function invocation
|
||||
// (chicken and egg problem, kind of)
|
||||
thread = Thread.currentThread();
|
||||
|
||||
context = Context.enter();
|
||||
context.setCompileFunctionsWithDynamicScope(true);
|
||||
context.setApplicationClassLoader(app.getClassLoader());
|
||||
context.setWrapFactory(core.wrapper);
|
||||
context = core.contextFactory.enter();
|
||||
|
||||
// if visual debugger is on let it know we're entering a context
|
||||
if (core.debugger != null) {
|
||||
core.initDebugger(context);
|
||||
}
|
||||
|
||||
if ("true".equals(app.getProperty("rhino.trace"))) {
|
||||
if (core.hasTracer) {
|
||||
context.setDebugger(new Tracer(getResponse()), null);
|
||||
}
|
||||
|
||||
// Set default optimization level according to whether debugger is on
|
||||
int optLevel = core.debugger == null ? 0 : -1;
|
||||
|
||||
try {
|
||||
optLevel = Integer.parseInt(app.getProperty("rhino.optlevel"));
|
||||
} catch (Exception ignore) {
|
||||
// use default opt-level
|
||||
}
|
||||
|
||||
context.setOptimizationLevel(optLevel);
|
||||
// register the per-thread scope with the dynamic scope
|
||||
context.putThreadLocal("reval", reval);
|
||||
context.putThreadLocal("engine", this);
|
||||
// register the engine with the current thread
|
||||
engines.set(this);
|
||||
// update prototypes
|
||||
core.updatePrototypes();
|
||||
}
|
||||
|
@ -224,10 +214,9 @@ public class RhinoEngine implements ScriptingEngine {
|
|||
* execution context has terminated.
|
||||
*/
|
||||
public synchronized void exitContext() {
|
||||
context.removeThreadLocal("reval");
|
||||
context.removeThreadLocal("engine");
|
||||
Context.exit();
|
||||
// core.global.unregisterScope();
|
||||
// unregister the engine threadlocal
|
||||
engines.remove();
|
||||
core.contextFactory.exit();
|
||||
thread = null;
|
||||
|
||||
// loop through previous globals and unset them, if necessary.
|
||||
|
@ -237,7 +226,7 @@ public class RhinoEngine implements ScriptingEngine {
|
|||
try {
|
||||
global.delete(g);
|
||||
} catch (Exception x) {
|
||||
System.err.println("Error resetting global property: " + g);
|
||||
app.logEvent("Error unsetting global property: " + g);
|
||||
}
|
||||
}
|
||||
lastGlobals = null;
|
||||
|
@ -265,23 +254,7 @@ public class RhinoEngine implements ScriptingEngine {
|
|||
public Object invoke(Object thisObject, String functionName, Object[] args,
|
||||
int argsWrapMode, boolean resolve) throws ScriptingException {
|
||||
try {
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
switch (argsWrapMode) {
|
||||
case ARGS_WRAP_DEFAULT:
|
||||
// convert java objects to JavaScript
|
||||
if (args[i] != null) {
|
||||
args[i] = Context.javaToJS(args[i], global);
|
||||
}
|
||||
break;
|
||||
case ARGS_WRAP_XMLRPC:
|
||||
// XML-RPC requires special argument conversion
|
||||
args[i] = core.processXmlRpcArgument(args[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
Scriptable obj = thisObject == null ? global : Context.toObject(thisObject, global);
|
||||
|
||||
// if function name should be resolved interpret it as member expression,
|
||||
// otherwise replace dots with underscores.
|
||||
if (resolve) {
|
||||
|
@ -308,7 +281,23 @@ public class RhinoEngine implements ScriptingEngine {
|
|||
return null;
|
||||
}
|
||||
|
||||
Object retval = ((Function) f).call(context, global, obj, args);
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
switch (argsWrapMode) {
|
||||
case ARGS_WRAP_DEFAULT:
|
||||
// convert java objects to JavaScript
|
||||
if (args[i] != null) {
|
||||
args[i] = Context.javaToJS(args[i], global);
|
||||
}
|
||||
break;
|
||||
case ARGS_WRAP_XMLRPC:
|
||||
// XML-RPC requires special argument conversion
|
||||
args[i] = core.processXmlRpcArgument(args[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// use Context.call() in order to set the context's factory
|
||||
Object retval = Context.call(core.contextFactory, (Function)f, global, obj, args);
|
||||
|
||||
if (retval instanceof Wrapper) {
|
||||
retval = ((Wrapper) retval).unwrap();
|
||||
|
@ -449,7 +438,6 @@ public class RhinoEngine implements ScriptingEngine {
|
|||
return prop;
|
||||
}
|
||||
} catch (Exception esx) {
|
||||
// System.err.println ("Error in getProperty: "+esx);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -479,7 +467,7 @@ public class RhinoEngine implements ScriptingEngine {
|
|||
* @throws java.io.IOException
|
||||
*/
|
||||
public void serialize(Object obj, OutputStream out) throws IOException {
|
||||
Context.enter();
|
||||
core.contextFactory.enter();
|
||||
try {
|
||||
// use a special ScriptableOutputStream that unwraps Wrappers
|
||||
ScriptableOutputStream sout = new ScriptableOutputStream(out, core.global) {
|
||||
|
@ -492,7 +480,7 @@ public class RhinoEngine implements ScriptingEngine {
|
|||
sout.writeObject(obj);
|
||||
sout.flush();
|
||||
} finally {
|
||||
Context.exit();
|
||||
core.contextFactory.exit();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -506,12 +494,12 @@ public class RhinoEngine implements ScriptingEngine {
|
|||
* @throws java.io.IOException
|
||||
*/
|
||||
public Object deserialize(InputStream in) throws IOException, ClassNotFoundException {
|
||||
Context.enter();
|
||||
core.contextFactory.enter();
|
||||
try {
|
||||
ObjectInputStream sin = new ScriptableInputStream(in, core.global);
|
||||
return sin.readObject();
|
||||
} finally {
|
||||
Context.exit();
|
||||
core.contextFactory.exit();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ public class XmlRpcObject extends BaseFunction {
|
|||
this.method = method;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* This method is used as HopObject constructor from JavaScript.
|
||||
*/
|
||||
public static Object xmlrpcObjectConstructor(Context cx, Object[] args,
|
||||
|
@ -106,20 +106,18 @@ public class XmlRpcObject extends BaseFunction {
|
|||
throw new EvaluatorException("Invalid method name");
|
||||
}
|
||||
|
||||
RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine");
|
||||
RhinoCore c = engine.getCore();
|
||||
RhinoCore core = RhinoCore.getCore();
|
||||
Scriptable retval = null;
|
||||
|
||||
try {
|
||||
retval = Context.getCurrentContext().newObject(c.getScope());
|
||||
retval = Context.getCurrentContext().newObject(core.getScope());
|
||||
XmlRpcClient client = new XmlRpcClient(url);
|
||||
|
||||
// long now = System.currentTimeMillis ();
|
||||
int l = args.length;
|
||||
Vector v = new Vector();
|
||||
|
||||
for (int i = 0; i < l; i++) {
|
||||
Object arg = c.processXmlRpcResponse(args[i]);
|
||||
Object arg = core.processXmlRpcResponse(args[i]);
|
||||
v.addElement(arg);
|
||||
}
|
||||
|
||||
|
@ -129,7 +127,7 @@ public class XmlRpcObject extends BaseFunction {
|
|||
if (result instanceof Exception) {
|
||||
throw (Exception) result;
|
||||
}
|
||||
retval.put("result", retval, c.processXmlRpcArgument(result));
|
||||
retval.put("result", retval, core.processXmlRpcArgument(result));
|
||||
|
||||
} catch (Exception x) {
|
||||
String msg = x.getMessage();
|
||||
|
|
Loading…
Add table
Reference in a new issue