JDK-8071678 : javax.script.ScriptContext setAttribute method should clarify behavior when GLOBAL_SCOPE is used and global scope object is null
  • Type: Bug
  • Component: core-libs
  • Sub-Component: jdk.nashorn
  • Affected Version: 9
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2015-01-27
  • Updated: 2017-05-17
  • Resolved: 2016-10-18
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 9
9 b142Fixed
Related Reports
Relates :  
Description
Spec 
http://docs.oracle.com/javase/8/docs/api/javax/script/ScriptContext.html#getAttribute-java.lang.String-
says "Returns null if no attribute with the name exists in any scope."

Spec
http://docs.oracle.com/javase/8/docs/api/javax/script/ScriptContext.html#getAttributesScope-java.lang.String-
says: "Returns: The lowest scope. Returns -1 if no attribute with the given name is defined in any scope."


However for GLOBAL_SCOPE setting attribute value leads to inability to get the value which was set and the scope which was used.

Consider the following code:

        new ScriptEngineManager()
            .getEngineFactories()
            .stream()
            .map(ScriptEngineFactory::getScriptEngine)
            .map((engine) -> {
                System.err.println("engine: " + engine);
                return engine.getContext();
            })
            .forEach(c -> {
                c.setAttribute("name1234", "value", ScriptContext.GLOBAL_SCOPE);
                System.err.println("value = " + c.getAttribute("name1234"));
                System.err.println("scope = " + c.getAttributesScope("name1234"));
            });

The output will contain

engine: jdk.nashorn.api.scripting.NashornScriptEngine@f3eef9
value = null
scope = -1

The following JCK9 test will fail due to this issue:

api/javax_script/ScriptContext/index.html#SetGetAttribute[setGet]
api/javax_script/ScriptContext/index.html#SetGetAttribute[getAttributesScope]



Comments
At least there is not explicit statement that I can locate that says ScriptEngineFactory created engines have GLOBAL_SCOPE set in the default ScriptContext. But ScriptEngineManager's methods have such explicit comments like / A ScriptEngine created by the factory located in the search. Returns null if no such factory was found. The ScriptEngineManager sets its own globalScope Bindings as the GLOBAL_SCOPE Bindings of the newly created ScriptEngine./ in ScriptEngineManager.getEngineByName method's javadoc.
09-02-2015

the test assumes engines created via ScriptEngineFactory.getScriptEngine method have ScriptContext's with GLOBAL_ENGINE scope set. But that is not specified in spec. Spec. only says GLOBAL_SCOPE is set if ScriptEngineManager's methods are used to create ScriptEngine (for eg. getEngineByName)
09-02-2015

Please check again and re-open accordingly (if needed)
09-02-2015

I tried the following simple app with jdk8u40 early access build as well as jdk9-dev/nashorn build. import javax.script.*; public class Main { public static void main(String[] args) throws Exception { ScriptEngineManager m = new ScriptEngineManager(); ScriptEngine e = m.getEngineByName("nashorn"); ScriptContext c = e.getContext(); c.setAttribute("name1234", "value", ScriptContext.GLOBAL_SCOPE); System.err.println("value = " + c.getAttribute("name1234")); System.err.println("scope = " + c.getAttributesScope("name1234")); } } I get "value" and 200 printed as expected. I'm not sure of the version of JDK used while test failed as mentioned in description. Please verify again with the latest jdk8u and jdk9 builds and re-open this issue.
09-02-2015

When we get (create) engine instance via ScriptEngineManager.getEngineByName ( http://docs.oracle.com/javase/8/docs/api/javax/script/ScriptEngineManager.html#getEngineByName-java.lang.String- ), it sets it's own globalScope as GLOBAL_SCOPE of newly created engine instance. / The ScriptEngineManager sets its own globalScope Bindings as the GLOBAL_SCOPE Bindings of the newly created ScriptEngine./ When you create engine via ScriptEngineFactory.getEngineFactory directly, there is no GLOBAL_SCOPE bindings in it's default ScriptContext. And so your subsequent setAttribute with GLOBAL_SCOPE as scope is just no-op (because ScriptContext has null for GLOBAL_SCOPE bindings). This behaviour does not seem to be in violation of the spec as far as I can read.
09-02-2015