11

Somewhat confused about ENGINE_SCOPE and GLOBAL_SCOPE binding in Nashorn, trying to follow the discussion here.

Before reading this my understanding of scopes (at least in rhino) was that there's a single, shared Bindings in the GLOBAL_SCOPE and individual bindings in ENGINE_SCOPE for each individual engine. However this page seems to be saying that each individual engine stores the basic javascript constructs in bindings that exist in the engines ENGINE_SCOPE (confusingly called the "Nashorn Global Scope"). This sounds like it makes the GLOBAL_SCOPE bindings effectively useless (because they won't have access to any of those basic constructs).

What I'm trying to do is create a context that I can inject a few scripts into, and then repeatedly eval different bindings in the context of those scripts. However if the only context I can access is the individual engines ENGINE_SCOPE (because anything above that won't have access to basic javascript constructs) then it seems that any local invocation has to add to those same bindings. Does anyone know how to manage multiple levels of bindings in Nashorn?

Steve B.
  • 55,454
  • 12
  • 93
  • 132

2 Answers2

2

If a variable is not found in ENGINE_SCOPE, GLOBAL_SCOPE bindings is searched. Nashorn's global object (the one that has JS Object, Number, RegExp, parseInt etc.) is wrapped as Bindings - and that is your ENGINE_SCOPE. For eg. if you put "foo"->"hello" map entry into GLOBAL_SCOPE, that will be visible in scripts - if ENGINE_SCOPE does not have map entry by the name "foo".

A. Sundararajan
  • 4,277
  • 1
  • 15
  • 30
  • Yes, that comes from https://wiki.openjdk.java.net/display/Nashorn/Nashorn+jsr223+engine+notes, which looks to be something you wrote. Thanks for writing that, it's one of the few such pieces of information I could find. Sorry to say I read it several times and still can't completely make sense of it. – Steve B. Oct 01 '14 at 17:23
  • 3
    Actually, if you're familiar with this, maybe you know the answer to this: When I call scriptEngine.getContext() am I getting a new instance or the same instance? If it's the same, how do I get a new (not a shared) context? What about scriptContext.getBindings()? new bindings instance? old bindings instance? It would be incredibly helpful to have an example, particularly multithreaded - i.e something where several resources load a shared script and each run it with their individual bindings. It is frustratingly difficult to find clear documentation on how this behaves. – Steve B. Oct 02 '14 at 15:44
  • Steve, I'm struggling with same issues, namely 'several resources load a shared script and each run it with their individual bindings'. Have you found something on this topic? Also, you might be interested in this http://stackoverflow.com/questions/27324802/multi-threaded-nashorn-o-constructor-o-constructor-gives-false bug I found. – Tvaroh Dec 06 '14 at 09:12
  • I have second Steve B., I think it is really important to say yes or no to the re-use questions around contexts: 1. How can I use multiple contexts with one engine without polluting them during an execution 2. Is compiled code reusable? 3. Are engines usable on multiple threads ? Some already do that. According to its attributes it isn't. [Engines each need to warmup their code](https://deverado.wordpress.com/2015/09/22/nashorn-performance-just-use-default-settings-and-very-few-engines/) – Georg Sep 22 '15 at 09:56
-2

ENGINE_SCOPE is basically when variables put into bindings are only for that particular Engine whereas GLOBAL_SCOPE is when variables put into bindings are accessible by all engines from the same factory.

And yes you are right that if any variable is in not found in the ENGINE_SCOPE it naturally searches in GLOBAL_SCOPE.

According to the JavaDoc

static final int ENGINE_SCOPE
EngineScope attributes are visible during the lifetime of a single ScriptEngine and a set of attributes is maintained for each engine.

static final int GLOBAL_SCOPE
GlobalScope attributes are visible to all engines created by same ScriptEngineFactory.

We can use multiple scopes in Nashorn using a script context similar to this

    context = new SimpleScriptContext(); // Script Context is an interface therefor you need to use an implementation of it
    context.setBindings(engine.createBindings(), SCOPE); // Set the bindings of the context, you can then use the context as an argument with the eval method of the script engine. Here engine is again an instance of javax.script.ScriptEngine
    Bindings bindings = context.getBindings(SCOPE); // Now use this for "putting" variables into the bindings SCOPE should either be ScriptContext.ENGINE_SCOPE or ScriptContext.GLOBAL_SCOPE
    bindings.put("x", "hello world");
    // Once done you must set the bindings
    context.setBindings(scope, SCOPE);
    // This code is just rough, I'm 100% sure there can always be further optimizations to this
    // Now finally evaluate your code
    engine.eval("Some pice of code..", context);   
    // Or you can use engine.setContext(YourContext) method in case you'll use your engine as an Invocable
    engine.setContext(context);
    engine.eval("Some piece of code");
    /* Do this because sometimes due to a bug you might not be able to call methods or functions from evaluated script
    Knowing about SrciptContext will help you a lot
    Note you can have multiple contexts and switch between them like I said
    Context parameter is also applicable for eval(Reader);
    */

I hope this helps

Nikhil R
  • 19
  • 1
  • 5
  • 2
    This isn't true: "GLOBAL_SCOPE is when variables put into bindings are accessible by all engines from the same factory." – siledh Feb 08 '18 at 10:52