changeset 1064:a8d44c7c2ac0

8050977: Java8 Javascript Nashorn exception: no current Global instance for nashorn Reviewed-by: attila, lagergren, hannesw
author sundar
date Mon, 13 Oct 2014 23:38:49 +0530
parents e0b9b2ef8442
children 488ce6b8c41b
files src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngine.java src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJava.java src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornLinker.java src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/mozilla_compat.js test/script/basic/convert.js test/script/nosecurity/JDK-8044798.js test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java
diffstat 14 files changed, 177 insertions(+), 98 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngine.java	Mon Oct 13 17:16:32 2014 +0200
+++ b/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/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java	Mon Oct 13 17:16:32 2014 +0200
+++ b/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/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java	Mon Oct 13 17:16:32 2014 +0200
+++ b/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/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJava.java	Mon Oct 13 17:16:32 2014 +0200
+++ b/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/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java	Mon Oct 13 17:16:32 2014 +0200
+++ b/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/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java	Mon Oct 13 17:16:32 2014 +0200
+++ b/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/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java	Mon Oct 13 17:16:32 2014 +0200
+++ b/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/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java	Mon Oct 13 17:16:32 2014 +0200
+++ b/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/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornLinker.java	Mon Oct 13 17:16:32 2014 +0200
+++ b/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/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/mozilla_compat.js	Mon Oct 13 17:16:32 2014 +0200
+++ b/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/test/script/basic/convert.js	Mon Oct 13 17:16:32 2014 +0200
+++ b/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/test/script/nosecurity/JDK-8044798.js	Mon Oct 13 17:16:32 2014 +0200
+++ b/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/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java	Mon Oct 13 17:16:32 2014 +0200
+++ b/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/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java	Mon Oct 13 17:16:32 2014 +0200
+++ b/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);