Merge
authorlana
Fri, 16 Jan 2015 12:34:10 -0800
changeset 28442 73d6633dcfd7
parent 28436 4e8a3c7578dd (current diff)
parent 28441 beb75d5da248 (diff)
child 28443 7f79e1300840
Merge
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/AbstractJavaLinker.java	Thu Jan 15 13:09:53 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/AbstractJavaLinker.java	Fri Jan 16 12:34:10 2015 -0800
@@ -491,8 +491,9 @@
 
                 // We want setters that conform to "Object(O, V)". Note, we aren't doing "R(O, V)" as it might not be
                 // valid for us to convert return values proactively. Also, since we don't know what setters will be
-                // invoked, we'll conservatively presume Object return type.
-                final MethodType type = callSiteDescriptor.getMethodType().changeReturnType(Object.class);
+                // invoked, we'll conservatively presume Object return type. The one exception is void return.
+                final MethodType origType = callSiteDescriptor.getMethodType();
+                final MethodType type = origType.returnType() == void.class ? origType : origType.changeReturnType(Object.class);
 
                 // What's below is basically:
                 //   foldArguments(guardWithTest(isNotNull, invoke, null|nextComponent.invocation),
@@ -508,7 +509,7 @@
                 // Bind property setter handle to the expected setter type and linker services. Type is
                 // MethodHandle(Object, String, Object)
                 final MethodHandle boundGetter = MethodHandles.insertArguments(getPropertySetterHandle, 0,
-                        CallSiteDescriptorFactory.dropParameterTypes(callSiteDescriptor, 1, 2), linkerServices);
+                        callSiteDescriptor.changeMethodType(setterType), linkerServices);
 
                 // Cast getter to MethodHandle(O, N, V)
                 final MethodHandle typedGetter = linkerServices.asType(boundGetter, type.changeReturnType(
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/OverloadedMethod.java	Thu Jan 15 13:09:53 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/OverloadedMethod.java	Fri Jan 16 12:34:10 2015 -0800
@@ -123,7 +123,6 @@
         varArgMethods = new ArrayList<>(methodHandles.size());
         final int argNum = callSiteType.parameterCount();
         for(MethodHandle mh: methodHandles) {
-            mh = mh.asType(mh.type().changeReturnType(commonRetType));
             if(mh.isVarargsCollector()) {
                 final MethodHandle asFixed = mh.asFixedArity();
                 if(argNum == asFixed.type().parameterCount()) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/TypeUtilities.java	Thu Jan 15 13:09:53 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/TypeUtilities.java	Fri Jan 16 12:34:10 2015 -0800
@@ -118,17 +118,13 @@
     public static Class<?> getCommonLosslessConversionType(final Class<?> c1, final Class<?> c2) {
         if(c1 == c2) {
             return c1;
+        } else if (c1 == void.class || c2 == void.class) {
+            return Object.class;
         } else if(isConvertibleWithoutLoss(c2, c1)) {
             return c1;
         } else if(isConvertibleWithoutLoss(c1, c2)) {
             return c2;
-        }
-        if(c1 == void.class) {
-            return c2;
-        } else if(c2 == void.class) {
-            return c1;
-        }
-        if(c1.isPrimitive() && c2.isPrimitive()) {
+        } else if(c1.isPrimitive() && c2.isPrimitive()) {
             if((c1 == byte.class && c2 == char.class) || (c1 == char.class && c2 == byte.class)) {
                 // byte + char = int
                 return int.class;
@@ -268,20 +264,24 @@
     }
 
     /**
-     * Determines whether a type can be converted to another without losing any
-     * precision.
+     * Determines whether a type can be converted to another without losing any precision. As a special case,
+     * void is considered convertible only to Object and void, while anything can be converted to void. This
+     * is because a target type of void means we don't care about the value, so the conversion is always
+     * permissible.
      *
      * @param sourceType the source type
      * @param targetType the target type
      * @return true if lossless conversion is possible
      */
     public static boolean isConvertibleWithoutLoss(final Class<?> sourceType, final Class<?> targetType) {
-        if(targetType.isAssignableFrom(sourceType)) {
+        if(targetType.isAssignableFrom(sourceType) || targetType == void.class) {
             return true;
         }
         if(sourceType.isPrimitive()) {
             if(sourceType == void.class) {
-                return false; // Void can't be losslessly represented by any type
+                // Void should be losslessly representable by Object, either as null or as a custom value that
+                // can be set with DynamicLinkerFactory.setAutoConversionStrategy.
+                return targetType == Object.class;
             }
             if(targetType.isPrimitive()) {
                 return isProperPrimitiveLosslessSubtype(sourceType, targetType);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java	Thu Jan 15 13:09:53 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java	Fri Jan 16 12:34:10 2015 -0800
@@ -703,7 +703,7 @@
         final ScriptFunction func = getProgramFunction(clazz, scope);
         Object evalThis;
         if (directEval) {
-            evalThis = callThis instanceof ScriptObject || strictFlag ? callThis : global;
+            evalThis = (callThis != UNDEFINED && callThis != null) || strictFlag ? callThis : global;
         } else {
             evalThis = global;
         }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java	Thu Jan 15 13:09:53 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java	Fri Jan 16 12:34:10 2015 -0800
@@ -68,6 +68,8 @@
 
     private static final MethodHandleFunctionality MH = MethodHandleFactory.getFunctionality();
 
+    private static final MethodHandle VOID_TO_OBJECT = MH.constant(Object.class, ScriptRuntime.UNDEFINED);
+
     /**
      * The default dynalink relink threshold for megamorphisism is 8. In the case
      * of object fields only, it is fine. However, with dual fields, in order to get
@@ -189,7 +191,7 @@
      * @return true if the obj is an instance of @FunctionalInterface interface
      */
     public static boolean isFunctionalInterfaceObject(final Object obj) {
-        return !JSType.isPrimitive(obj) && (NashornBottomLinker.getFunctionalInterfaceMethod(obj.getClass()) != null);
+        return !JSType.isPrimitive(obj) && (NashornBeansLinker.getFunctionalInterfaceMethod(obj.getClass()) != null);
     }
 
     /**
@@ -481,14 +483,16 @@
     private static MethodHandle unboxReturnType(final MethodHandle target, final MethodType newType) {
         final MethodType targetType = target.type();
         final Class<?> oldReturnType = targetType.returnType();
+        final Class<?> newReturnType = newType.returnType();
         if (TypeUtilities.isWrapperType(oldReturnType)) {
-            final Class<?> newReturnType = newType.returnType();
             if (newReturnType.isPrimitive()) {
                 // The contract of setAutoConversionStrategy is such that the difference between newType and targetType
                 // can only be JLS method invocation conversions.
                 assert TypeUtilities.isMethodInvocationConvertible(oldReturnType, newReturnType);
                 return MethodHandles.explicitCastArguments(target, targetType.changeReturnType(newReturnType));
             }
+        } else if (oldReturnType == void.class && newReturnType == Object.class) {
+            return MethodHandles.filterReturnValue(target, VOID_TO_OBJECT);
         }
         return target;
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java	Thu Jan 15 13:09:53 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java	Fri Jan 16 12:34:10 2015 -0800
@@ -25,20 +25,29 @@
 
 package jdk.nashorn.internal.runtime.linker;
 
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.beans.BeansLinker;
 import jdk.internal.dynalink.linker.ConversionComparator.Comparison;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.GuardingDynamicLinker;
 import jdk.internal.dynalink.linker.LinkRequest;
 import jdk.internal.dynalink.linker.LinkerServices;
+import jdk.internal.dynalink.support.Guards;
 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.Context;
 import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
 import jdk.nashorn.internal.runtime.options.Options;
 
 /**
@@ -68,19 +77,49 @@
         FILTER_CONSSTRING    = lookup.findOwnStatic("consStringFilter", Object.class, Object.class);
     }
 
+    // cache of @FunctionalInterface method of implementor classes
+    private static final ClassValue<Method> FUNCTIONAL_IFACE_METHOD = new ClassValue<Method>() {
+        @Override
+        protected Method computeValue(final Class<?> type) {
+            return findFunctionalInterfaceMethod(type);
+        }
+    };
+
     private final BeansLinker beansLinker = new BeansLinker();
 
     @Override
     public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception {
-        if (linkRequest.getReceiver() instanceof ConsString) {
+        final Object self = linkRequest.getReceiver();
+        final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor();
+        if (self instanceof ConsString) {
             // In order to treat ConsString like a java.lang.String we need a link request with a string receiver.
             final Object[] arguments = linkRequest.getArguments();
             arguments[0] = "";
-            final LinkRequest forgedLinkRequest = linkRequest.replaceArguments(linkRequest.getCallSiteDescriptor(), arguments);
+            final LinkRequest forgedLinkRequest = linkRequest.replaceArguments(desc, arguments);
             final GuardedInvocation invocation = getGuardedInvocation(beansLinker, forgedLinkRequest, linkerServices);
             // If an invocation is found we add a filter that makes it work for both Strings and ConsStrings.
             return invocation == null ? null : invocation.filterArguments(0, FILTER_CONSSTRING);
         }
+
+        if (self != null && "call".equals(desc.getNameToken(CallSiteDescriptor.OPERATOR))) {
+            // Support dyn:call on any object that supports some @FunctionalInterface
+            // annotated interface. This way Java method, constructor references or
+            // implementations of java.util.function.* interfaces can be called as though
+            // those are script functions.
+            final Method m = getFunctionalInterfaceMethod(self.getClass());
+            if (m != null) {
+                final MethodType callType = desc.getMethodType();
+                // 'callee' and 'thiz' passed from script + actual arguments
+                if (callType.parameterCount() != m.getParameterCount() + 2) {
+                    throw typeError("no.method.matches.args", ScriptRuntime.safeToString(self));
+                }
+                return new GuardedInvocation(
+                        // drop 'thiz' passed from the script.
+                        MH.dropArguments(desc.getLookup().unreflect(m), 1, callType.parameterType(1)),
+                        Guards.getInstanceOfGuard(m.getDeclaringClass())).asTypeSafeReturn(
+                                new NashornBeansLinkerServices(linkerServices), callType);
+            }
+        }
         return getGuardedInvocation(beansLinker, linkRequest, linkerServices);
     }
 
@@ -137,6 +176,38 @@
         return arg instanceof ConsString ? arg.toString() : arg;
     }
 
+    private static Method findFunctionalInterfaceMethod(final Class<?> clazz) {
+        if (clazz == null) {
+            return null;
+        }
+
+        for (final Class<?> iface : clazz.getInterfaces()) {
+            // check accessiblity up-front
+            if (! Context.isAccessibleClass(iface)) {
+                continue;
+            }
+
+            // check for @FunctionalInterface
+            if (iface.isAnnotationPresent(FunctionalInterface.class)) {
+                // return the first abstract method
+                for (final Method m : iface.getMethods()) {
+                    if (Modifier.isAbstract(m.getModifiers())) {
+                        return m;
+                    }
+                }
+            }
+        }
+
+        // did not find here, try super class
+        return findFunctionalInterfaceMethod(clazz.getSuperclass());
+    }
+
+    // Returns @FunctionalInterface annotated interface's single abstract
+    // method. If not found, returns null.
+    static Method getFunctionalInterfaceMethod(final Class<?> clazz) {
+        return FUNCTIONAL_IFACE_METHOD.get(clazz);
+    }
+
     private static class NashornBeansLinkerServices implements LinkerServices {
         private final LinkerServices linkerServices;
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java	Thu Jan 15 13:09:53 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java	Fri Jan 16 12:34:10 2015 -0800
@@ -30,9 +30,6 @@
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
 import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
 import java.util.HashMap;
 import java.util.Map;
 import jdk.internal.dynalink.CallSiteDescriptor;
@@ -45,7 +42,6 @@
 import jdk.internal.dynalink.linker.LinkerServices;
 import jdk.internal.dynalink.support.Guards;
 import jdk.nashorn.internal.codegen.types.Type;
-import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
@@ -95,22 +91,6 @@
             }
             throw typeError("not.a.function", ScriptRuntime.safeToString(self));
         case "call":
-            // Support dyn:call on any object that supports some @FunctionalInterface
-            // annotated interface. This way Java method, constructor references or
-            // implementations of java.util.function.* interfaces can be called as though
-            // those are script functions.
-            final Method m = getFunctionalInterfaceMethod(self.getClass());
-            if (m != null) {
-                final MethodType callType = desc.getMethodType();
-                // 'callee' and 'thiz' passed from script + actual arguments
-                if (callType.parameterCount() != m.getParameterCount() + 2) {
-                    throw typeError("no.method.matches.args", ScriptRuntime.safeToString(self));
-                }
-                return Bootstrap.asTypeSafeReturn(new GuardedInvocation(
-                        // drop 'thiz' passed from the script.
-                        MH.dropArguments(desc.getLookup().unreflect(m), 1, callType.parameterType(1)),
-                        Guards.getInstanceOfGuard(m.getDeclaringClass())), linkerServices, desc);
-            }
             if(BeansLinker.isDynamicConstructor(self)) {
                 throw typeError("constructor.requires.new", ScriptRuntime.safeToString(self));
             }
@@ -218,44 +198,4 @@
         }
         return ScriptRuntime.safeToString(linkRequest.getArguments()[1]);
     }
-
-    // cache of @FunctionalInterface method of implementor classes
-    private static final ClassValue<Method> FUNCTIONAL_IFACE_METHOD = new ClassValue<Method>() {
-        @Override
-        protected Method computeValue(final Class<?> type) {
-            return findFunctionalInterfaceMethod(type);
-        }
-
-        private Method findFunctionalInterfaceMethod(final Class<?> clazz) {
-            if (clazz == null) {
-                return null;
-            }
-
-            for (final Class<?> iface : clazz.getInterfaces()) {
-                // check accessiblity up-front
-                if (! Context.isAccessibleClass(iface)) {
-                    continue;
-                }
-
-                // check for @FunctionalInterface
-                if (iface.isAnnotationPresent(FunctionalInterface.class)) {
-                    // return the first abstract method
-                    for (final Method m : iface.getMethods()) {
-                        if (Modifier.isAbstract(m.getModifiers())) {
-                            return m;
-                        }
-                    }
-                }
-            }
-
-            // did not find here, try super class
-            return findFunctionalInterfaceMethod(clazz.getSuperclass());
-        }
-    };
-
-    // Returns @FunctionalInterface annotated interface's single abstract
-    // method. If not found, returns null.
-    static Method getFunctionalInterfaceMethod(final Class<?> clazz) {
-        return FUNCTIONAL_IFACE_METHOD.get(clazz);
-    }
 }
--- a/nashorn/test/script/basic/JDK-8020324.js.EXPECTED	Thu Jan 15 13:09:53 2015 -0800
+++ b/nashorn/test/script/basic/JDK-8020324.js.EXPECTED	Fri Jan 16 12:34:10 2015 -0800
@@ -17,7 +17,7 @@
 bean.readWrite = 18: 18
 obj1.readWrite: 18
 obj1.getReadWrite(): 18
-obj1.setReadWrite(19): null
+obj1.setReadWrite(19): undefined
 obj1.readWrite: 19
 bean.readWrite: 19
 
@@ -52,7 +52,7 @@
 PropertyBind.staticReadWrite = 26: 26
 obj2.staticReadWrite: 26
 obj2.getStaticReadWrite(): 26
-obj2.setStaticReadWrite(27): null
+obj2.setStaticReadWrite(27): undefined
 obj2.staticReadWrite: 27
 PropertyBind.staticReadWrite: 27
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8068573.js	Fri Jan 16 12:34:10 2015 -0800
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8068573: POJO setter using [] syntax throws an exception
+ *
+ * @test
+ * @run
+ */
+
+// Invoke a setter using []. It's important that the setter returns void.
+var pb = new (Java.type("jdk.nashorn.test.models.PropertyBind"))
+var n = "writeOnly";
+pb[n] = 2;
+Assert.assertEquals(pb.peekWriteOnly(), 2);
+
+// Invoke an overloaded setter using []. It's important that one of the 
+// overloads returns void.
+var os = new (Java.type("jdk.nashorn.test.models.OverloadedSetter"))
+var n2 = "color";
+os[n2] = 3; // exercise int overload
+Assert.assertEquals(os.peekColor(), "3");
+os[n2] = "blue";  // exercise string overload
+Assert.assertEquals(os.peekColor(), "blue");
+for each(var x in [42, "42"]) {
+  os[n2] = x; // exercise both overloads in the same call site
+  Assert.assertEquals(os.peekColor(), "42");
+}
+
+// Invoke an overloaded method using [], repeatedly in the same call 
+// site. It's important that one of the overloads returns void.
+var n3="foo";
+var param=["xyz", 1, "zyx", 2];
+var expected=["boo", void 0, "boo", void 0];
+for(var i in param) {
+  Assert.assertEquals(os[n3](param[i]), expected[i]);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8068985.js	Fri Jan 16 12:34:10 2015 -0800
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8068985: Wrong 'this' bound to eval call within a function when caller's 'this' is a Java object
+ *
+ * @test
+ * @run
+ */
+
+function func(arg) {
+  (function() { print(eval('this')); }).call(arg);
+}
+
+// primitives
+func(undefined);
+func(null);
+func(34.23);
+func("hello");
+func(false);
+
+// script objects
+func(this);
+func({});
+func({ toString: function() { return "foo" } });
+
+// java objects
+func(new java.util.Vector());
+var m = new java.util.HashMap();
+m.put("foo", "bar");
+func(m);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8068985.js.EXPECTED	Fri Jan 16 12:34:10 2015 -0800
@@ -0,0 +1,10 @@
+[object global]
+[object global]
+34.23
+hello
+false
+[object global]
+[object Object]
+foo
+[]
+{foo=bar}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8069002.js	Fri Jan 16 12:34:10 2015 -0800
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8069002: NPE on invoking null (8068889 regression)
+ *
+ * @test
+ * @run
+ */
+
+try {
+    null();
+} catch (e) {
+    Assert.assertTrue(e instanceof TypeError);
+}
--- a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java	Thu Jan 15 13:09:53 2015 -0800
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java	Fri Jan 16 12:34:10 2015 -0800
@@ -30,12 +30,16 @@
 import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
+
 import java.io.StringReader;
 import java.io.StringWriter;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Consumer;
+import java.util.function.Function;
 import javax.script.Compilable;
 import javax.script.CompiledScript;
 import javax.script.Invocable;
@@ -680,6 +684,41 @@
         assertNull(value);
     }
 
+    // @bug JDK-8068889: ConsString arguments to a functional interface wasn't converted to string.
+    @Test
+    public void functionalInterfaceStringTest() throws Exception {
+        final ScriptEngineManager manager = new ScriptEngineManager();
+        final ScriptEngine e = manager.getEngineByName("nashorn");
+        final AtomicBoolean invoked = new AtomicBoolean(false);
+        e.put("f", new Function<String, String>() {
+            @Override
+            public String apply(String t) {
+                invoked.set(true);
+                return t;
+            }
+        });
+        assertEquals(e.eval("var x = 'a'; x += 'b'; f(x)"), "ab");
+        assertTrue(invoked.get());
+    }
+
+    // @bug JDK-8068889: ScriptObject arguments to a functional interface wasn't converted to a mirror.
+    @Test
+    public void functionalInterfaceObjectTest() throws Exception {
+        final ScriptEngineManager manager = new ScriptEngineManager();
+        final ScriptEngine e = manager.getEngineByName("nashorn");
+        final AtomicBoolean invoked = new AtomicBoolean(false);
+        e.put("c", new Consumer<Object>() {
+            @Override
+            public void accept(Object t) {
+                assertTrue(t instanceof ScriptObjectMirror);
+                assertEquals(((ScriptObjectMirror)t).get("a"), "xyz");
+                invoked.set(true);
+            }
+        });
+        e.eval("var x = 'xy'; x += 'z';c({a:x})");
+        assertTrue(invoked.get());
+    }
+
     private static void checkProperty(final ScriptEngine e, final String name)
         throws ScriptException {
         final String value = System.getProperty(name);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/src/jdk/nashorn/test/models/OverloadedSetter.java	Fri Jan 16 12:34:10 2015 -0800
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.test.models;
+
+public class OverloadedSetter {
+    private String color;
+
+    public void setColor(final int x) {
+        this.color = Integer.toString(x);
+    }
+
+    public void setColor(final String x) {
+        this.color = x;
+    }
+
+    public String peekColor() {
+        return color;
+    }
+
+    public void foo(final int x) {
+    }
+
+    public String foo(final String x) {
+        return "boo";
+    }
+}