JDK-8081609 : engine.eval call from a java method which was called from a previous engine.eval results in wrong ScriptContext being used.
  • Type: Bug
  • Component: core-libs
  • Sub-Component: jdk.nashorn
  • Affected Version: 8u60,9
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2015-06-01
  • Updated: 2015-09-29
  • Resolved: 2015-06-02
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8 JDK 9
8u60Fixed 9 b68Fixed
Related Reports
Relates :  
Description
http://mail.openjdk.java.net/pipermail/nashorn-dev/2015-May/004572.html

import javax.script.*;
import jdk.nashorn.api.scripting.*;

public class Main {
    ScriptEngineFactory factory = new NashornScriptEngineFactory();
    ScriptEngine engine = factory.getScriptEngine();
    Bindings globalBindings = new SimpleBindings();
    Bindings engineBindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
    ScriptContext context = new SimpleScriptContext();

    public static void main(String[] ar) throws Exception {
        Main main = new Main();
        main.context.setBindings(main.globalBindings, ScriptContext.GLOBAL_SCOPE);
        main.context.setBindings(main.engineBindings, ScriptContext.ENGINE_SCOPE);

        main.engineBindings.put("program", main);
        main.globalBindings.put("text", "initial text");

        main.engine.eval(
            " print(text); " +
            " program.someMethod(); " +
            " print(text);", main.context);

        /* Expected output:
           initial text
           another text
           initial text

           Output seen:
           initial text
           another text
           another text
        */
    }

    public void someMethod() throws Exception {
        // a context with a new global bindings, same engine bindings
        ScriptContext context = new SimpleScriptContext();
        Bindings globalBindings = new SimpleBindings();
        context.setBindings(globalBindings, ScriptContext.GLOBAL_SCOPE);
        context.setBindings(engineBindings, ScriptContext.ENGINE_SCOPE);

        globalBindings.put("text", "another text");
        engine.eval("print(text)", context);
    }
}
Comments
Same ENGINE_SCOPE baked by same Nashorn Global instance may be used by two or more different ScriptContexts - also via different threads at the same time. So, instead of having ScriptContext instance as an instance field in Global instance, we should have it as thread local. Also, if a Global is created along with a ScriptContext (like the default context of engine) then we should store that default context and use it for lookup when there is no current "eval". Such a situation is possible if user receives ScriptObjectMirror and later calls a script functionality it's methods (without going thru script engine's eval) - in that scenario we should use that "initial" ScriptContext associated with that global [ to avoid 'surprises']
01-06-2015