Relationship between "global" and "engine" scope

yikes aroni yikesaroni at
Mon Nov 3 20:25:13 UTC 2014

It appears that nashorn has named stuff in a non-intuitive way and I just
want to confirm that I understand things correctly. Ordinarily, I would
assume that "global" scope is a broader scope than "engine" scope, meaning
that anything defined in "global" scope would be available to the engine
scope. That would be great news! But i fear that it's not the case -- or at
least not in the specific way i'm trying to use it. Furthermore, it appears
that "engine" and "global" scope have no relationship to oneanother

I'm attempting to evaluate a library in a ScriptEngine's "engine" scope
(call this engine "baseEngine"), then set baseEngine's engine scope to the
"global" scope for another ScriptEngine ("tempEngine"). Why would I want to
do that? So that I can do the expensive eval on my script once and reuse it
by shoving it into another script engine's scope. That is, I then eval some
script in tempEngine's "engine" scope and assume that the library I shoved
into tempEngine's "global" scope can be found and leveraged by the script.
This appears not to be the case. Consider this test code:

        NashornScriptEngineFactory engineFactory = new
        ScriptEngine baseEngine = engineFactory.getScriptEngine();

        // Here's the script we ultimately want in the "global" scope of
        String script = "var test = (function() {" + "var publ = {};"
            + "var priv = {};" + "publ.hello = function() {"
            + " print('hello ' + eval('nnn'));" + "};" + "return publ;"
            + "})();";

        // Load the script into baseEngine's ENGINE bindings

        // The "library" script is now in base engine's ENGINE scope. Get a
handle on ENGINE
        // bindings to try to inject them...
        Bindings engineScopeBase =

        // Get the tempEngine
        ScriptEngine tempEngine = engineFactory.getScriptEngine();

        // eval the variable 'nnn'  into tempEngine's ENGINE scope
        tempEngine.eval("var nnn = 'fellow';",

        // Explicitly set the bindings to the temp context.
        // Comment out the first two lines to put the variable in global
scope and the script in engine scope
        // Comment the 2nd two lines to put the variable in tempEngine's
ENGINE scope and the script in its GLOBAL scope
        ScriptContext ctxTemp = new SimpleScriptContext();
        ctxTemp.setBindings(engineScopeBase, ScriptContext.ENGINE_SCOPE);

        //ctxTemp.setBindings(engineScopeBase, ScriptContext.GLOBAL_SCOPE);


        System.out.println("is nnn in engine scope?: nnn="
        System.out.println("is nnn in global scope?: nnn="
        System.out.println("is test in engine scope?: test="
        System.out.println("is test in global scope?: test="

        tempEngine.eval("print(test.hello());", ctxTemp);

The output either looks like this:
is nnn in engine scope?: nnn=null
is nnn in global scope?: nnn=fellow
is test in engine scope?: test=[object Object]
is test in global scope?: test=null

or like this:
is nnn in engine scope?: nnn=fellow
is nnn in global scope?: nnn=null
is test in engine scope?: test=null
is test in global scope?: test=[object Object]

When the last line runs, I get the error

          Exception in thread "main" javax.script.ScriptException:
ReferenceError: "nnn" is not defined in <eval>#1:95<eval>@0 at line number 1

In other words, the script can never find the variable 'nnn' -- not in the
global scope nor in the engine scope regardless of how i set up global /
engine bindings.

Is there any way to make this work? Before I give up, I want to make sure
that i'm not missing something and have exhausted all possibilities....


More information about the nashorn-dev mailing list