2

I'm embedding Rhino in a Java application. Basically, I run a Javascript code, that then calls a Java function, and this calls another Javascript code. When running the second Javascript code I'm having problems because the shared scope I'm using cannot see objects in the new scope.

Here is a test that shows the error (please note that I have two shared scopes to reproduce the same scenario I have in the application):

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();
    }
}

When running this test, you will get the following error:

org.mozilla.javascript.EcmaError: ReferenceError: "currentScope" is not defined. (#1)

So, I'm using dynamic sealed scopes as explained here:

https://developer.mozilla.org/en-US/docs/Rhino/Scopes_and_Contexts

What is odd to me is that the first time, when running the first Javascript code, I can access the 'currentScope' variable without problems. The exception is thrown when the second execution of the script, though I use the same code initialize the second scope.

What am I doing wrong?

Thanks!

dgaviola
  • 2,421
  • 2
  • 26
  • 37

0 Answers0