8138616: invokeFunction fails if function calls a function defined in GLOBAL_SCOPE
Reviewed-by: hannesw, mhaupt
This commit is contained in:
parent
8b9c730750
commit
a7d931c5e1
@ -140,7 +140,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
|
|||||||
this._global_per_engine = nashornContext.getEnv()._global_per_engine;
|
this._global_per_engine = nashornContext.getEnv()._global_per_engine;
|
||||||
|
|
||||||
// create new global object
|
// create new global object
|
||||||
this.global = createNashornGlobal(context);
|
this.global = createNashornGlobal();
|
||||||
// set the default ENGINE_SCOPE object for the default context
|
// set the default ENGINE_SCOPE object for the default context
|
||||||
context.setBindings(new ScriptObjectMirror(global, global), ScriptContext.ENGINE_SCOPE);
|
context.setBindings(new ScriptObjectMirror(global, global), ScriptContext.ENGINE_SCOPE);
|
||||||
}
|
}
|
||||||
@ -167,7 +167,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
|
|||||||
// We use same 'global' for all Bindings.
|
// We use same 'global' for all Bindings.
|
||||||
return new SimpleBindings();
|
return new SimpleBindings();
|
||||||
}
|
}
|
||||||
return createGlobalMirror(null);
|
return createGlobalMirror();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compilable methods
|
// Compilable methods
|
||||||
@ -317,7 +317,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
|
|||||||
|
|
||||||
// We didn't find associated nashorn global mirror in the Bindings given!
|
// We didn't find associated nashorn global mirror in the Bindings given!
|
||||||
// Create new global instance mirror and associate with the Bindings.
|
// Create new global instance mirror and associate with the Bindings.
|
||||||
final ScriptObjectMirror mirror = createGlobalMirror(ctxt);
|
final ScriptObjectMirror mirror = createGlobalMirror();
|
||||||
bindings.put(NASHORN_GLOBAL, mirror);
|
bindings.put(NASHORN_GLOBAL, mirror);
|
||||||
return mirror.getHomeGlobal();
|
return mirror.getHomeGlobal();
|
||||||
}
|
}
|
||||||
@ -333,13 +333,13 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a new ScriptObjectMirror wrapping a newly created Nashorn Global object
|
// Create a new ScriptObjectMirror wrapping a newly created Nashorn Global object
|
||||||
private ScriptObjectMirror createGlobalMirror(final ScriptContext ctxt) {
|
private ScriptObjectMirror createGlobalMirror() {
|
||||||
final Global newGlobal = createNashornGlobal(ctxt);
|
final Global newGlobal = createNashornGlobal();
|
||||||
return new ScriptObjectMirror(newGlobal, newGlobal);
|
return new ScriptObjectMirror(newGlobal, newGlobal);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new Nashorn Global object
|
// Create a new Nashorn Global object
|
||||||
private Global createNashornGlobal(final ScriptContext ctxt) {
|
private Global createNashornGlobal() {
|
||||||
final Global newGlobal = AccessController.doPrivileged(new PrivilegedAction<Global>() {
|
final Global newGlobal = AccessController.doPrivileged(new PrivilegedAction<Global>() {
|
||||||
@Override
|
@Override
|
||||||
public Global run() {
|
public Global run() {
|
||||||
@ -354,7 +354,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
|
|||||||
}
|
}
|
||||||
}, CREATE_GLOBAL_ACC_CTXT);
|
}, CREATE_GLOBAL_ACC_CTXT);
|
||||||
|
|
||||||
nashornContext.initGlobal(newGlobal, this, ctxt);
|
nashornContext.initGlobal(newGlobal, this);
|
||||||
|
|
||||||
return newGlobal;
|
return newGlobal;
|
||||||
}
|
}
|
||||||
|
@ -928,8 +928,6 @@ public final class Global extends Scope {
|
|||||||
private ThreadLocal<ScriptContext> scontext;
|
private ThreadLocal<ScriptContext> scontext;
|
||||||
// current ScriptEngine associated - can be null.
|
// current ScriptEngine associated - can be null.
|
||||||
private ScriptEngine engine;
|
private ScriptEngine engine;
|
||||||
// initial ScriptContext - can be null
|
|
||||||
private volatile ScriptContext initscontext;
|
|
||||||
|
|
||||||
// ES6 global lexical scope.
|
// ES6 global lexical scope.
|
||||||
private final LexicalScope lexicalScope;
|
private final LexicalScope lexicalScope;
|
||||||
@ -957,7 +955,7 @@ public final class Global extends Scope {
|
|||||||
|
|
||||||
private ScriptContext currentContext() {
|
private ScriptContext currentContext() {
|
||||||
final ScriptContext sc = scontext != null? scontext.get() : null;
|
final ScriptContext sc = scontext != null? scontext.get() : null;
|
||||||
return sc == null? initscontext : sc;
|
return (sc != null)? sc : (engine != null? engine.getContext() : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1067,16 +1065,14 @@ public final class Global extends Scope {
|
|||||||
* of the global scope object.
|
* of the global scope object.
|
||||||
*
|
*
|
||||||
* @param eng ScriptEngine to initialize
|
* @param eng ScriptEngine to initialize
|
||||||
* @param ctxt ScriptContext to initialize
|
|
||||||
*/
|
*/
|
||||||
public void initBuiltinObjects(final ScriptEngine eng, final ScriptContext ctxt) {
|
public void initBuiltinObjects(final ScriptEngine eng) {
|
||||||
if (this.builtinObject != null) {
|
if (this.builtinObject != null) {
|
||||||
// already initialized, just return
|
// already initialized, just return
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.engine = eng;
|
this.engine = eng;
|
||||||
this.initscontext = ctxt;
|
|
||||||
if (this.engine != null) {
|
if (this.engine != null) {
|
||||||
this.scontext = new ThreadLocal<>();
|
this.scontext = new ThreadLocal<>();
|
||||||
}
|
}
|
||||||
|
@ -1264,17 +1264,16 @@ public final class Context {
|
|||||||
*
|
*
|
||||||
* @param global the global
|
* @param global the global
|
||||||
* @param engine the associated ScriptEngine instance, can be null
|
* @param engine the associated ScriptEngine instance, can be null
|
||||||
* @param ctxt the initial ScriptContext, can be null
|
|
||||||
* @return the initialized global scope object.
|
* @return the initialized global scope object.
|
||||||
*/
|
*/
|
||||||
public Global initGlobal(final Global global, final ScriptEngine engine, final ScriptContext ctxt) {
|
public Global initGlobal(final Global global, final ScriptEngine engine) {
|
||||||
// Need only minimal global object, if we are just compiling.
|
// Need only minimal global object, if we are just compiling.
|
||||||
if (!env._compile_only) {
|
if (!env._compile_only) {
|
||||||
final Global oldGlobal = Context.getGlobal();
|
final Global oldGlobal = Context.getGlobal();
|
||||||
try {
|
try {
|
||||||
Context.setGlobal(global);
|
Context.setGlobal(global);
|
||||||
// initialize global scope with builtin global objects
|
// initialize global scope with builtin global objects
|
||||||
global.initBuiltinObjects(engine, ctxt);
|
global.initBuiltinObjects(engine);
|
||||||
} finally {
|
} finally {
|
||||||
Context.setGlobal(oldGlobal);
|
Context.setGlobal(oldGlobal);
|
||||||
}
|
}
|
||||||
@ -1290,7 +1289,7 @@ public final class Context {
|
|||||||
* @return the initialized global scope object.
|
* @return the initialized global scope object.
|
||||||
*/
|
*/
|
||||||
public Global initGlobal(final Global global) {
|
public Global initGlobal(final Global global) {
|
||||||
return initGlobal(global, null, null);
|
return initGlobal(global, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package jdk.nashorn.api.scripting;
|
package jdk.nashorn.api.scripting.test;
|
||||||
|
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
import static org.testng.Assert.assertTrue;
|
import static org.testng.Assert.assertTrue;
|
||||||
@ -33,6 +33,9 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.script.ScriptEngine;
|
import javax.script.ScriptEngine;
|
||||||
import javax.script.ScriptException;
|
import javax.script.ScriptException;
|
||||||
|
import jdk.nashorn.api.scripting.JSObject;
|
||||||
|
import jdk.nashorn.api.scripting.NashornScriptEngine;
|
||||||
|
import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
|
||||||
import org.testng.Assert;
|
import org.testng.Assert;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
@ -30,6 +30,7 @@ import static org.testng.Assert.assertFalse;
|
|||||||
import static org.testng.Assert.assertTrue;
|
import static org.testng.Assert.assertTrue;
|
||||||
import static org.testng.Assert.fail;
|
import static org.testng.Assert.fail;
|
||||||
import javax.script.Bindings;
|
import javax.script.Bindings;
|
||||||
|
import javax.script.Invocable;
|
||||||
import javax.script.ScriptContext;
|
import javax.script.ScriptContext;
|
||||||
import javax.script.ScriptEngine;
|
import javax.script.ScriptEngine;
|
||||||
import javax.script.ScriptEngineFactory;
|
import javax.script.ScriptEngineFactory;
|
||||||
@ -855,4 +856,59 @@ public class ScopeTest {
|
|||||||
assertTrue(ret, "Expected true in iteration " + i);
|
assertTrue(ret, "Expected true in iteration " + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @bug 8138616: invokeFunction fails if function calls a function defined in GLOBAL_SCOPE
|
||||||
|
@Test
|
||||||
|
public void invokeFunctionInGlobalScopeTest() throws Exception {
|
||||||
|
final ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
|
||||||
|
final ScriptContext ctxt = engine.getContext();
|
||||||
|
|
||||||
|
// define a function called "func"
|
||||||
|
engine.eval("func = function() { return 42 }");
|
||||||
|
|
||||||
|
// move ENGINE_SCOPE Bindings to GLOBAL_SCOPE
|
||||||
|
ctxt.setBindings(ctxt.getBindings(ScriptContext.ENGINE_SCOPE), ScriptContext.GLOBAL_SCOPE);
|
||||||
|
|
||||||
|
// create a new Bindings and set as ENGINE_SCOPE
|
||||||
|
ctxt.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
|
||||||
|
|
||||||
|
// define new function that calls "func" now in GLOBAL_SCOPE
|
||||||
|
engine.eval("newfunc = function() { return func() }");
|
||||||
|
|
||||||
|
// call "newfunc" and check the return value
|
||||||
|
Object value = ((Invocable)engine).invokeFunction("newfunc");
|
||||||
|
assertTrue(((Number)value).intValue() == 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @bug 8138616: invokeFunction fails if function calls a function defined in GLOBAL_SCOPE
|
||||||
|
// variant of above that replaces default ScriptContext of the engine with a fresh instance!
|
||||||
|
@Test
|
||||||
|
public void invokeFunctionInGlobalScopeTest2() throws Exception {
|
||||||
|
final ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
|
||||||
|
|
||||||
|
// create a new ScriptContext instance
|
||||||
|
final ScriptContext ctxt = new SimpleScriptContext();
|
||||||
|
// set it as 'default' ScriptContext
|
||||||
|
engine.setContext(ctxt);
|
||||||
|
|
||||||
|
// create a new Bindings and set as ENGINE_SCOPE
|
||||||
|
ctxt.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
|
||||||
|
|
||||||
|
// define a function called "func"
|
||||||
|
engine.eval("func = function() { return 42 }");
|
||||||
|
|
||||||
|
// move ENGINE_SCOPE Bindings to GLOBAL_SCOPE
|
||||||
|
ctxt.setBindings(ctxt.getBindings(ScriptContext.ENGINE_SCOPE), ScriptContext.GLOBAL_SCOPE);
|
||||||
|
|
||||||
|
// create a new Bindings and set as ENGINE_SCOPE
|
||||||
|
ctxt.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
|
||||||
|
|
||||||
|
// define new function that calls "func" now in GLOBAL_SCOPE
|
||||||
|
engine.eval("newfunc = function() { return func() }");
|
||||||
|
|
||||||
|
// call "newfunc" and check the return value
|
||||||
|
Object value = ((Invocable)engine).invokeFunction("newfunc");
|
||||||
|
assertTrue(((Number)value).intValue() == 42);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user