8050977: Java8 Javascript Nashorn exception: no current Global instance for nashorn
Reviewed-by: attila, lagergren, hannesw
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngine.java Mon Oct 13 17:16:32 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngine.java Mon Oct 13 23:38:49 2014 +0530
@@ -229,6 +229,8 @@
}
private <T> T getInterfaceInner(final Object thiz, final Class<T> clazz) {
+ assert !(thiz instanceof ScriptObject) : "raw ScriptObject not expected here";
+
if (clazz == null || !clazz.isInterface()) {
throw new IllegalArgumentException(getMessage("interface.class.expected"));
}
@@ -254,17 +256,6 @@
if (! isOfContext(realGlobal, nashornContext)) {
throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
}
- } else if (thiz instanceof ScriptObject) {
- // called from script code.
- realSelf = (ScriptObject)thiz;
- realGlobal = Context.getGlobal();
- if (realGlobal == null) {
- throw new IllegalArgumentException(getMessage("no.current.nashorn.global"));
- }
-
- if (! isOfContext(realGlobal, nashornContext)) {
- throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
- }
}
if (realSelf == null) {
@@ -368,6 +359,7 @@
private Object invokeImpl(final Object selfObject, final String name, final Object... args) throws ScriptException, NoSuchMethodException {
name.getClass(); // null check
+ assert !(selfObject instanceof ScriptObject) : "raw ScriptObject not expected here";
Global invokeGlobal = null;
ScriptObjectMirror selfMirror = null;
@@ -377,20 +369,6 @@
throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
}
invokeGlobal = selfMirror.getHomeGlobal();
- } else if (selfObject instanceof ScriptObject) {
- // invokeMethod called from script code - in which case we may get 'naked' ScriptObject
- // Wrap it with oldGlobal to make a ScriptObjectMirror for the same.
- final Global oldGlobal = Context.getGlobal();
- invokeGlobal = oldGlobal;
- if (oldGlobal == null) {
- throw new IllegalArgumentException(getMessage("no.current.nashorn.global"));
- }
-
- if (! isOfContext(oldGlobal, nashornContext)) {
- throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
- }
-
- selfMirror = (ScriptObjectMirror)ScriptObjectMirror.wrap(selfObject, oldGlobal);
} else if (selfObject == null) {
// selfObject is null => global function call
final Global ctxtGlobal = getNashornGlobalFrom(context);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java Mon Oct 13 17:16:32 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java Mon Oct 13 23:38:49 2014 +0530
@@ -75,11 +75,8 @@
* @param sync the object to synchronize on
* @return a synchronizing wrapper function
*/
- public static Object makeSynchronizedFunction(final Object func, final Object sync) {
- if (func instanceof ScriptFunction) {
- return ((ScriptFunction)func).makeSynchronizedFunction(sync);
- }
- throw typeError("not.a.function", ScriptRuntime.safeToString(func));
+ public static Object makeSynchronizedFunction(final ScriptFunction func, final Object sync) {
+ return func.makeSynchronizedFunction(unwrap(sync));
}
/**
@@ -88,12 +85,8 @@
* @param obj object to be wrapped
* @return wrapped object
*/
- public static Object wrap(final Object obj) {
- if (obj instanceof ScriptObject) {
- return ScriptObjectMirror.wrap(obj, Context.getGlobal());
- }
-
- return obj;
+ public static ScriptObjectMirror wrap(final ScriptObject obj) {
+ return (ScriptObjectMirror) ScriptObjectMirror.wrap(obj, Context.getGlobal());
}
/**
@@ -160,14 +153,15 @@
}
final LinkerServices linker = Bootstrap.getLinkerServices();
- final MethodHandle converter = linker.getTypeConverter(obj.getClass(), clazz);
+ final Object objToConvert = unwrap(obj);
+ final MethodHandle converter = linker.getTypeConverter(objToConvert.getClass(), clazz);
if (converter == null) {
// no supported conversion!
throw new UnsupportedOperationException("conversion not supported");
}
try {
- return converter.invoke(obj);
+ return converter.invoke(objToConvert);
} catch (final RuntimeException | Error e) {
throw e;
} catch (final Throwable t) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java Mon Oct 13 17:16:32 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java Mon Oct 13 23:38:49 2014 +0530
@@ -98,6 +98,7 @@
import jdk.nashorn.internal.ir.RuntimeNode;
import jdk.nashorn.internal.ir.Symbol;
import jdk.nashorn.internal.ir.TryNode;
+import jdk.nashorn.internal.objects.NativeArray;
import jdk.nashorn.internal.runtime.ArgumentSetter;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.Debug;
@@ -2125,7 +2126,14 @@
int pos = 0;
for (int i = argCount - 1; i >= 0; i--) {
- paramTypes[i] = stack.peek(pos++);
+ Type pt = stack.peek(pos++);
+ // "erase" specific ScriptObject subtype info - except for NativeArray.
+ // NativeArray is used for array/List/Deque conversion for Java calls.
+ if (ScriptObject.class.isAssignableFrom(pt.getTypeClass()) &&
+ !NativeArray.class.isAssignableFrom(pt.getTypeClass())) {
+ pt = Type.SCRIPT_OBJECT;
+ }
+ paramTypes[i] = pt;
}
final String descriptor = Type.getMethodDescriptor(returnType, paramTypes);
for (int i = 0; i < argCount; i++) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJava.java Mon Oct 13 17:16:32 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJava.java Mon Oct 13 23:38:49 2014 +0530
@@ -90,7 +90,11 @@
*/
@Function(name="synchronized", attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static Object synchronizedFunc(final Object self, final Object func, final Object obj) {
- return ScriptUtils.makeSynchronizedFunction(func, obj);
+ if (func instanceof ScriptFunction) {
+ return ((ScriptFunction)func).makeSynchronizedFunction(obj);
+ }
+
+ throw typeError("not.a.function", ScriptRuntime.safeToString(func));
}
/**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java Mon Oct 13 17:16:32 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java Mon Oct 13 23:38:49 2014 +0530
@@ -152,6 +152,7 @@
static final String SET_GLOBAL_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE, OBJECT_TYPE);
static final String VOID_NOARG_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE);
+ private static final Type SCRIPT_OBJECT_TYPE = Type.getType(ScriptObject.class);
private static final Type SCRIPT_FUNCTION_TYPE = Type.getType(ScriptFunction.class);
private static final Type STRING_TYPE = Type.getType(String.class);
private static final Type METHOD_TYPE_TYPE = Type.getType(MethodType.class);
@@ -536,8 +537,8 @@
final int argLen = originalArgTypes.length;
final Type[] newArgTypes = new Type[argLen + 1];
- // Insert ScriptFunction|Object as the last argument to the constructor
- final Type extraArgumentType = fromFunction ? SCRIPT_FUNCTION_TYPE : OBJECT_TYPE;
+ // Insert ScriptFunction|ScriptObject as the last argument to the constructor
+ final Type extraArgumentType = fromFunction ? SCRIPT_FUNCTION_TYPE : SCRIPT_OBJECT_TYPE;
newArgTypes[argLen] = extraArgumentType;
System.arraycopy(originalArgTypes, 0, newArgTypes, 0, argLen);
@@ -588,6 +589,34 @@
// Initialize converters
generateConverterInit(mv, fromFunction);
endInitMethod(mv);
+
+ if (! fromFunction) {
+ newArgTypes[argLen] = OBJECT_TYPE;
+ final InstructionAdapter mv2 = new InstructionAdapter(cw.visitMethod(ACC_PUBLIC, INIT,
+ Type.getMethodDescriptor(originalCtorType.getReturnType(), newArgTypes), null, null));
+ generateOverridingConstructorWithObjectParam(mv2, ctor, originalCtorType.getDescriptor());
+ }
+ }
+
+ // Object additional param accepting constructor - generated to handle null and undefined value
+ // for script adapters. This is effectively to throw TypeError on such script adapters. See
+ // JavaAdapterServices.getHandle as well.
+ private void generateOverridingConstructorWithObjectParam(final InstructionAdapter mv, final Constructor<?> ctor, final String ctorDescriptor) {
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ final Class<?>[] argTypes = ctor.getParameterTypes();
+ int offset = 1; // First arg is at position 1, after this.
+ for (int i = 0; i < argTypes.length; ++i) {
+ final Type argType = Type.getType(argTypes[i]);
+ mv.load(offset, argType);
+ offset += argType.getSize();
+ }
+ mv.invokespecial(superClassName, INIT, ctorDescriptor, false);
+ mv.visitVarInsn(ALOAD, offset);
+ mv.visitInsn(ACONST_NULL);
+ mv.visitInsn(ACONST_NULL);
+ mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", GET_HANDLE_OBJECT_DESCRIPTOR, false);
+ endInitMethod(mv);
}
private static void endInitMethod(final InstructionAdapter mv) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java Mon Oct 13 17:16:32 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java Mon Oct 13 23:38:49 2014 +0530
@@ -39,6 +39,7 @@
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ScriptFunction;
+import jdk.nashorn.internal.runtime.ScriptObject;
/**
* This class encapsulates the bytecode of the adapter class and can be used to load it into the JVM as an actual Class.
@@ -51,7 +52,7 @@
private static final AccessControlContext CREATE_LOADER_ACC_CTXT = ClassAndLoader.createPermAccCtxt("createClassLoader");
private static final AccessControlContext GET_CONTEXT_ACC_CTXT = ClassAndLoader.createPermAccCtxt(Context.NASHORN_GET_CONTEXT);
private static final Collection<String> VISIBLE_INTERNAL_CLASS_NAMES = Collections.unmodifiableCollection(new HashSet<>(
- Arrays.asList(JavaAdapterServices.class.getName(), ScriptFunction.class.getName(), JSType.class.getName())));
+ Arrays.asList(JavaAdapterServices.class.getName(), ScriptObject.class.getName(), ScriptFunction.class.getName(), JSType.class.getName())));
private final String className;
private final byte[] classBytes;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java Mon Oct 13 17:16:32 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java Mon Oct 13 23:38:49 2014 +0530
@@ -47,7 +47,6 @@
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.Type;
import jdk.internal.org.objectweb.asm.commons.InstructionAdapter;
-import jdk.nashorn.api.scripting.ScriptUtils;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
@@ -220,7 +219,7 @@
* @return the filtered return value.
*/
public static Object exportReturnValue(final Object obj) {
- return ScriptUtils.wrap(NashornBeansLinker.exportArgument(obj));
+ return NashornBeansLinker.exportArgument(obj, true);
}
/**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Mon Oct 13 17:16:32 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Mon Oct 13 23:38:49 2014 +0530
@@ -35,17 +35,28 @@
import jdk.internal.dynalink.linker.LinkRequest;
import jdk.internal.dynalink.linker.LinkerServices;
import jdk.internal.dynalink.support.Lookup;
+import jdk.nashorn.api.scripting.ScriptUtils;
+import jdk.nashorn.internal.objects.NativeArray;
import jdk.nashorn.internal.runtime.ConsString;
+import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.options.Options;
/**
* This linker delegates to a {@code BeansLinker} but passes it a special linker services object that has a modified
* {@code asType} method that will ensure that we never pass internal engine objects that should not be externally
- * observable (currently only ConsString) to Java APIs, but rather that we flatten it into a String. We can't just add
+ * observable (currently ConsString and ScriptObject) to Java APIs, but rather that we flatten it into a String. We can't just add
* this functionality as custom converters via {@code GuaardingTypeConverterFactory}, since they are not consulted when
* the target method handle parameter signature is {@code Object}.
*/
public class NashornBeansLinker implements GuardingDynamicLinker {
+ // System property to control whether to wrap ScriptObject->ScriptObjectMirror for
+ // Object type arguments of Java method calls, field set and array set.
+ private static final boolean MIRROR_ALWAYS = Options.getBooleanProperty("nashorn.mirror.always", true);
+
private static final MethodHandle EXPORT_ARGUMENT = new Lookup(MethodHandles.lookup()).findOwnStatic("exportArgument", Object.class, Object.class);
+ private static final MethodHandle EXPORT_NATIVE_ARRAY = new Lookup(MethodHandles.lookup()).findOwnStatic("exportNativeArray", Object.class, NativeArray.class);
+ private static final MethodHandle EXPORT_SCRIPT_OBJECT = new Lookup(MethodHandles.lookup()).findOwnStatic("exportScriptObject", Object.class, ScriptObject.class);
+ private static final MethodHandle IMPORT_RESULT = new Lookup(MethodHandles.lookup()).findOwnStatic("importResult", Object.class, Object.class);
private final BeansLinker beansLinker = new BeansLinker();
@@ -67,8 +78,39 @@
return delegateLinker.getGuardedInvocation(linkRequest, new NashornBeansLinkerServices(linkerServices));
}
- static Object exportArgument(final Object arg) {
- return arg instanceof ConsString ? arg.toString() : arg;
+ @SuppressWarnings("unused")
+ private static Object exportArgument(final Object arg) {
+ return exportArgument(arg, MIRROR_ALWAYS);
+ }
+
+ @SuppressWarnings("unused")
+ private static Object exportNativeArray(final NativeArray arg) {
+ return exportArgument(arg, MIRROR_ALWAYS);
+ }
+
+ @SuppressWarnings("unused")
+ private static Object exportScriptObject(final ScriptObject arg) {
+ return exportArgument(arg, MIRROR_ALWAYS);
+ }
+
+ @SuppressWarnings("unused")
+ private static Object exportScriptArray(final NativeArray arg) {
+ return exportArgument(arg, MIRROR_ALWAYS);
+ }
+
+ static Object exportArgument(final Object arg, final boolean mirrorAlways) {
+ if (arg instanceof ConsString) {
+ return arg.toString();
+ } else if (mirrorAlways && arg instanceof ScriptObject) {
+ return ScriptUtils.wrap((ScriptObject)arg);
+ } else {
+ return arg;
+ }
+ }
+
+ @SuppressWarnings("unused")
+ private static Object importResult(final Object arg) {
+ return ScriptUtils.unwrap(arg);
}
private static class NashornBeansLinkerServices implements LinkerServices {
@@ -80,23 +122,50 @@
@Override
public MethodHandle asType(final MethodHandle handle, final MethodType fromType) {
- final MethodHandle typed = linkerServices.asType(handle, fromType);
-
final MethodType handleType = handle.type();
final int paramCount = handleType.parameterCount();
assert fromType.parameterCount() == handleType.parameterCount();
+ MethodType newFromType = fromType;
MethodHandle[] filters = null;
for(int i = 0; i < paramCount; ++i) {
- if(shouldConvert(handleType.parameterType(i), fromType.parameterType(i))) {
- if(filters == null) {
+ final MethodHandle filter = argConversionFilter(handleType.parameterType(i), fromType.parameterType(i));
+ if (filter != null) {
+ if (filters == null) {
filters = new MethodHandle[paramCount];
}
- filters[i] = EXPORT_ARGUMENT;
+ // "erase" specific type with Object type or else we'll get filter mismatch
+ newFromType = newFromType.changeParameterType(i, Object.class);
+ filters[i] = filter;
}
}
- return filters != null ? MethodHandles.filterArguments(typed, 0, filters) : typed;
+ final MethodHandle typed = linkerServices.asType(handle, newFromType);
+ MethodHandle result = filters != null ? MethodHandles.filterArguments(typed, 0, filters) : typed;
+ // Filter Object typed return value for possible ScriptObjectMirror. We convert
+ // ScriptObjectMirror as ScriptObject (if it is mirror from current global).
+ if (MIRROR_ALWAYS && areBothObjects(handleType.returnType(), fromType.returnType())) {
+ result = MethodHandles.filterReturnValue(result, IMPORT_RESULT);
+ }
+
+ return result;
+ }
+
+ private static MethodHandle argConversionFilter(final Class<?> handleType, final Class<?> fromType) {
+ if (handleType == Object.class) {
+ if (fromType == Object.class) {
+ return EXPORT_ARGUMENT;
+ } else if (fromType == NativeArray.class) {
+ return EXPORT_NATIVE_ARRAY;
+ } else if (fromType == ScriptObject.class) {
+ return EXPORT_SCRIPT_OBJECT;
+ }
+ }
+ return null;
+ }
+
+ private static boolean areBothObjects(final Class<?> handleType, final Class<?> fromType) {
+ return handleType == Object.class && fromType == Object.class;
}
@Override
@@ -104,10 +173,6 @@
return Implementation.asTypeLosslessReturn(this, handle, fromType);
}
- private static boolean shouldConvert(final Class<?> handleType, final Class<?> fromType) {
- return handleType == Object.class && fromType == Object.class;
- }
-
@Override
public MethodHandle getTypeConverter(final Class<?> sourceType, final Class<?> targetType) {
return linkerServices.getTypeConverter(sourceType, targetType);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornLinker.java Mon Oct 13 17:16:32 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornLinker.java Mon Oct 13 23:38:49 2014 +0530
@@ -292,7 +292,7 @@
@SuppressWarnings("unused")
private static Object createMirror(final Object obj) {
- return ScriptUtils.wrap(obj);
+ return obj instanceof ScriptObject? ScriptUtils.wrap((ScriptObject)obj) : obj;
}
private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/mozilla_compat.js Mon Oct 13 17:16:32 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/mozilla_compat.js Mon Oct 13 23:38:49 2014 +0530
@@ -105,7 +105,7 @@
if (arguments.length < 1 || arguments.length > 2 ) {
throw "sync(function [,object]) parameter count mismatch";
}
- return Packages.jdk.nashorn.api.scripting.ScriptUtils.makeSynchronizedFunction(func, syncobj);
+ return Java.synchronized(func, syncobj);
}
});
@@ -160,7 +160,7 @@
configurable: true, enumerable: false, writable: true,
value: function(state) {
if (! state) {
- state = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap());
+ state = java.util.Collections.newSetFromMap(new java.util.HashMap());
}
if (state.contains(this)) {
return "{}";
--- a/nashorn/test/script/basic/convert.js Mon Oct 13 17:16:32 2014 +0200
+++ b/nashorn/test/script/basic/convert.js Mon Oct 13 23:38:49 2014 +0530
@@ -42,7 +42,7 @@
// object to Map
obj = { foo: 333, bar: 'hello'};
-var map = ScriptUtils.convert(obj, java.util.Map.class);
+var map = ScriptUtils.wrap(obj);
print(map instanceof java.util.Map);
for (m in map) {
print(m + " " + map[m]);
--- a/nashorn/test/script/nosecurity/JDK-8044798.js Mon Oct 13 17:16:32 2014 +0200
+++ b/nashorn/test/script/nosecurity/JDK-8044798.js Mon Oct 13 23:38:49 2014 +0530
@@ -25,6 +25,8 @@
* JDK-8044798: API for debugging Nashorn
*
* @test
+ * @option -Dnashorn.mirror.always=false
+ * @fork
* @run
*/
--- a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java Mon Oct 13 17:16:32 2014 +0200
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java Mon Oct 13 23:38:49 2014 +0530
@@ -168,42 +168,6 @@
}
}
- @Test
- /**
- * Check that script can't implement sensitive package interfaces.
- */
- public void checkSensitiveInterfaceImplTest() throws ScriptException {
- if (System.getSecurityManager() == null) {
- // pass vacuously
- return;
- }
-
- final ScriptEngineManager m = new ScriptEngineManager();
- final ScriptEngine e = m.getEngineByName("nashorn");
- final Object[] holder = new Object[1];
- e.put("holder", holder);
- // put an empty script object into array
- e.eval("holder[0] = {}");
- // holder[0] is an object of some subclass of ScriptObject
- final Class<?> ScriptObjectClass = holder[0].getClass().getSuperclass();
- final Class<?> PropertyAccessClass = ScriptObjectClass.getInterfaces()[0];
- // implementation methods for PropertyAccess class
- e.eval("function set() {}; function get() {}; function getInt(){} " +
- "function getDouble(){}; function getLong() {}; " +
- "this.delete = function () {}; function has() {}; " +
- "function hasOwnProperty() {}");
-
- // get implementation of a restricted package interface
- try {
- log(Objects.toString(((Invocable)e).getInterface((Class<?>)PropertyAccessClass)));
- fail("should have thrown SecurityException");
- } catch (final Exception exp) {
- if (! (exp instanceof SecurityException)) {
- fail("SecurityException expected, got " + exp);
- }
- }
- }
-
// @bug 8032948: Nashorn linkages awry
public static class FakeProxy extends Proxy {
public FakeProxy(final InvocationHandler ih) {
--- a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java Mon Oct 13 17:16:32 2014 +0200
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java Mon Oct 13 23:38:49 2014 +0530
@@ -38,6 +38,7 @@
import java.util.concurrent.Callable;
import javax.script.Compilable;
import javax.script.CompiledScript;
+import javax.script.Invocable;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
@@ -629,6 +630,40 @@
assertEquals(enumerable, Boolean.FALSE);
}
+ public static class Context {
+ private Object myobj;
+
+ public void set(Object o) {
+ myobj = o;
+ }
+
+ public Object get() {
+ return myobj;
+ }
+ }
+
+ // @bug 8050977: Java8 Javascript Nashorn exception:
+ // no current Global instance for nashorn
+ @Test
+ public void currentGlobalMissingTest() throws Exception {
+ final ScriptEngineManager manager = new ScriptEngineManager();
+ final ScriptEngine e = manager.getEngineByName("nashorn");
+
+ final Context ctx = new Context();
+ e.put("ctx", ctx);
+ e.eval("var obj = { foo: function(str) { return str.toUpperCase() } }");
+ e.eval("ctx.set(obj)");
+ final Invocable inv = (Invocable)e;
+ assertEquals("HELLO", inv.invokeMethod(ctx.get(), "foo", "hello"));
+ // try object literal
+ e.eval("ctx.set({ bar: function(str) { return str.toLowerCase() } })");
+ assertEquals("hello", inv.invokeMethod(ctx.get(), "bar", "HELLO"));
+ // try array literal
+ e.eval("var arr = [ 'hello', 'world' ]");
+ e.eval("ctx.set(arr)");
+ assertEquals("helloworld", inv.invokeMethod(ctx.get(), "join", ""));
+ }
+
private static void checkProperty(final ScriptEngine e, final String name)
throws ScriptException {
final String value = System.getProperty(name);