我在一个Java应用程序中嵌入了Rhino。基本上,我运行一个Javascript代码,然后调用一个Java函数,这会调用另一个Javascript代码。运行第二个Javascript代码时遇到问题,因为我使用的共享范围无法在新范围内看到对象。
这是一个显示错误的测试(请注意我有两个共享范围来重现我在应用程序中的相同方案):
import org.junit.Test;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.ContextFactory;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
public class SimpleRhinoTest {
static class DynamicScopeFactory extends ContextFactory {
@Override
protected boolean hasFeature(Context cx, int featureIndex) {
if (featureIndex == Context.FEATURE_DYNAMIC_SCOPE) {
return true;
}
return super.hasFeature(cx, featureIndex);
}
}
static {
ContextFactory.initGlobal(new DynamicScopeFactory());
}
public static class HelperScope extends ScriptableObject {
private ScriptableObject sharedScope;
@Override
public String getClassName() {
return "global";
}
public void debug(String text) {
System.out.println(text);
}
public void doSomething1(String param) {
debug(param);
Context ctx = Context.enter();
Scriptable scriptScope = ctx.newObject(sharedScope);
scriptScope.setPrototype(sharedScope);
scriptScope.setParentScope(null);
ctx.evaluateString(scriptScope, "var currentScope = 'test2';", "", 1, null);
ctx.evaluateString(scriptScope, "foo(); doSomething2('end')", "", 1, null);
Context.exit();
}
public void doSomething2(String param) {
debug(param);
}
public ScriptableObject getSharedScope() {
return sharedScope;
}
public void setSharedScope(ScriptableObject sharedScope) {
this.sharedScope = sharedScope;
}
}
@Test
public void testSharedScopes() {
// init shared scopes
Context ctx = Context.enter();
HelperScope helperScope1 = new HelperScope();
ScriptableObject sharedScope1 = ctx.initStandardObjects(helperScope1, true);
String[] names = {"doSomething1", "doSomething2", "debug"};
helperScope1.defineFunctionProperties(names, HelperScope.class, ScriptableObject.DONTENUM);
ctx.evaluateString(sharedScope1, "var foo = function() { debug(currentScope); };", "", 1, null);
sharedScope1.sealObject();
Context.exit();
ctx = Context.enter();
HelperScope helperScope2 = new HelperScope();
ScriptableObject sharedScope2 = ctx.initStandardObjects(helperScope2, true);
names = new String[] {"doSomething1", "doSomething2", "debug"};
helperScope2.defineFunctionProperties(names, HelperScope.class, ScriptableObject.DONTENUM);
ctx.evaluateString(sharedScope2, "var foo = function() { debug(currentScope); };", "", 1, null);
sharedScope1.sealObject();
Context.exit();
helperScope1.setSharedScope(helperScope2);
ctx = Context.enter();
Scriptable scriptScope1 = ctx.newObject(sharedScope1);
scriptScope1.setPrototype(sharedScope1);
scriptScope1.setParentScope(null);
ctx.evaluateString(scriptScope1, "var currentScope = 'test1'; foo(); doSomething1('entering');", "", 1, null);
Context.exit();
}
}
运行此测试时,您将收到以下错误:
org.mozilla.javascript.EcmaError: ReferenceError: "currentScope" is not defined. (#1)
所以,我正在使用动态密封范围,如下所述:
https://developer.mozilla.org/en-US/docs/Rhino/Scopes_and_Contexts
对我来说奇怪的是,第一次运行第一个Javascript代码时,我可以毫无问题地访问'currentScope'变量。第二次执行脚本时抛出异常,但我使用相同的代码初始化第二个范围。
我做错了什么?
谢谢!