--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngine.java Thu Jun 16 20:57:01 2016 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngine.java Mon Jun 20 11:44:29 2016 +0200
@@ -318,6 +318,9 @@
// Create new global instance mirror and associate with the Bindings.
final ScriptObjectMirror mirror = createGlobalMirror();
bindings.put(NASHORN_GLOBAL, mirror);
+ // Since we created this global explicitly for the non-default script context we set the
+ // current script context in global permanently so that invokes work as expected. See JDK-8150219
+ mirror.getHomeGlobal().setInitScriptContext(ctxt);
return mirror.getHomeGlobal();
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Thu Jun 16 20:57:01 2016 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Mon Jun 20 11:44:29 2016 +0200
@@ -1087,6 +1087,8 @@
private ThreadLocal<ScriptContext> scontext;
// current ScriptEngine associated - can be null.
private ScriptEngine engine;
+ // initial ScriptContext - usually null and only used for special case
+ private volatile ScriptContext initscontext;
// ES6 global lexical scope.
private final LexicalScope lexicalScope;
@@ -1112,9 +1114,22 @@
return scontext.get();
}
+ /**
+ * Set the initial script context
+ * @param ctxt initial script context
+ */
+ public void setInitScriptContext(final ScriptContext ctxt) {
+ this.initscontext = ctxt;
+ }
+
private ScriptContext currentContext() {
final ScriptContext sc = scontext != null? scontext.get() : null;
- return (sc != null)? sc : (engine != null? engine.getContext() : null);
+ if (sc != null) {
+ return sc;
+ } else if (initscontext != null) {
+ return initscontext;
+ }
+ return engine != null? engine.getContext() : null;
}
@Override
--- a/nashorn/test/src/jdk/nashorn/api/scripting/test/ScopeTest.java Thu Jun 16 20:57:01 2016 +0000
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/test/ScopeTest.java Mon Jun 20 11:44:29 2016 +0200
@@ -30,6 +30,8 @@
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import javax.script.Bindings;
+import javax.script.Compilable;
+import javax.script.CompiledScript;
import javax.script.Invocable;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
@@ -911,4 +913,27 @@
Object value = ((Invocable)engine).invokeFunction("newfunc");
assertTrue(((Number)value).intValue() == 42);
}
+
+ // @bug 8150219 ReferenceError in 1.8.0_72
+ // When we create a Global for a non-default ScriptContext that needs one keep the
+ // ScriptContext associated with the Global so that invoke methods work as expected.
+ @Test
+ public void invokeFunctionWithCustomScriptContextTest() throws Exception {
+ final ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
+
+ // create an engine and a ScriptContext, but don't set it as default
+ ScriptContext scriptContext = new SimpleScriptContext();
+
+ // Set some value in the context
+ scriptContext.setAttribute("myString", "foo", ScriptContext.ENGINE_SCOPE);
+
+ // Evaluate script with custom context and get back a function
+ final String script = "function (c) { return myString.indexOf(c); }";
+ CompiledScript compiledScript = ((Compilable)engine).compile(script);
+ Object func = compiledScript.eval(scriptContext);
+
+ // Invoked function should be able to see context it was evaluated with
+ Object result = ((Invocable) engine).invokeMethod(func, "call", func, "o", null);
+ assertTrue(((Number)result).intValue() == 1);
+ }
}