2

我将 Rhino 嵌入到 Java 应用程序中。基本上,我运行一个 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”变量。第二次执行脚本时抛出异常,尽管我使用相同的代码初始化第二个作用域。

我究竟做错了什么?

谢谢!

4

0 回答 0