From 6e67698c30cd36705f172a05ac9efbae43bcbc38 Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Wed, 25 May 2016 11:03:08 +0530 Subject: [PATCH 1/3] 8157789: Nashorn sample/test.js should not use undocumented System property Reviewed-by: mchung --- nashorn/samples/test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nashorn/samples/test.js b/nashorn/samples/test.js index dfe4b7b937a..217cab164ba 100644 --- a/nashorn/samples/test.js +++ b/nashorn/samples/test.js @@ -31,4 +31,4 @@ print("Hello World"); var System = Java.type("java.lang.System"); -print(System.getProperty("jdk.launcher.patch.0")); +print(System.getProperty("java.home")); From 883dc41e42ea5fd61cee33ab38c63e58eb912393 Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Wed, 25 May 2016 15:14:37 +0530 Subject: [PATCH 2/3] 8157680: Callback parameter of any JS builtin implementation should accept any Callable Reviewed-by: hannesw, mhaupt --- .../nashorn/internal/objects/NativeArray.java | 12 +-- .../nashorn/internal/objects/NativeJSON.java | 1 - .../internal/objects/NativeRegExp.java | 11 ++- .../internal/objects/NativeString.java | 6 +- .../internal/objects/NativeWeakMap.java | 1 - .../internal/objects/NativeWeakSet.java | 1 - .../internal/runtime/JSONFunctions.java | 10 +-- .../internal/runtime/linker/Bootstrap.java | 4 +- nashorn/test/script/basic/JDK-8157680.js | 89 +++++++++++++++++++ .../test/script/basic/JDK-8157680.js.EXPECTED | 7 ++ 10 files changed, 118 insertions(+), 24 deletions(-) create mode 100644 nashorn/test/script/basic/JDK-8157680.js create mode 100644 nashorn/test/script/basic/JDK-8157680.js.EXPECTED diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java index b2090dcca6b..0fb867f91ce 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java @@ -238,7 +238,7 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin @Override public MethodHandle call() { return Bootstrap.createDynamicCallInvoker(double.class, - ScriptFunction.class, Object.class, Object.class, Object.class); + Object.class, Object.class, Object.class, Object.class); } }); } @@ -1210,23 +1210,23 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin return copy; } - private static ScriptFunction compareFunction(final Object comparefn) { + private static Object compareFunction(final Object comparefn) { if (comparefn == ScriptRuntime.UNDEFINED) { return null; } - if (! (comparefn instanceof ScriptFunction)) { + if (!Bootstrap.isCallable(comparefn)) { throw typeError("not.a.function", ScriptRuntime.safeToString(comparefn)); } - return (ScriptFunction)comparefn; + return comparefn; } private static Object[] sort(final Object[] array, final Object comparefn) { - final ScriptFunction cmp = compareFunction(comparefn); + final Object cmp = compareFunction(comparefn); final List list = Arrays.asList(array); - final Object cmpThis = cmp == null || cmp.isStrict() ? ScriptRuntime.UNDEFINED : Global.instance(); + final Object cmpThis = cmp == null || Bootstrap.isStrictCallable(cmp) ? ScriptRuntime.UNDEFINED : Global.instance(); try { Collections.sort(list, new Comparator() { diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSON.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSON.java index b5e139c79bc..b8141a9b5fb 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSON.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSON.java @@ -47,7 +47,6 @@ import jdk.nashorn.internal.runtime.ConsString; import jdk.nashorn.internal.runtime.JSONFunctions; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.PropertyMap; -import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator; import jdk.nashorn.internal.runtime.linker.Bootstrap; diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExp.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExp.java index 3b5998063af..3bf1663933a 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExp.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExp.java @@ -45,7 +45,6 @@ import jdk.nashorn.internal.runtime.BitVector; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.ParserException; import jdk.nashorn.internal.runtime.PropertyMap; -import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.linker.Bootstrap; @@ -655,7 +654,7 @@ public final class NativeRegExp extends ScriptObject { * @param replacement Replacement string. * @return String with substitutions. */ - String replace(final String string, final String replacement, final ScriptFunction function) throws Throwable { + String replace(final String string, final String replacement, final Object function) throws Throwable { final RegExpMatcher matcher = regexp.match(string); if (matcher == null) { @@ -671,7 +670,7 @@ public final class NativeRegExp extends ScriptObject { sb.append(string, 0, matcher.start()); if (function != null) { - final Object self = function.isStrict() ? UNDEFINED : Global.instance(); + final Object self = Bootstrap.isStrictCallable(function) ? UNDEFINED : Global.instance(); sb.append(callReplaceValue(getReplaceValueInvoker(), function, self, matcher, string)); } else { appendReplacement(matcher, string, replacement, sb); @@ -691,7 +690,7 @@ public final class NativeRegExp extends ScriptObject { final StringBuilder sb = new StringBuilder(); final MethodHandle invoker = function == null ? null : getReplaceValueInvoker(); - final Object self = function == null || function.isStrict() ? UNDEFINED : Global.instance(); + final Object self = function == null || Bootstrap.isStrictCallable(function) ? UNDEFINED : Global.instance(); do { sb.append(string, thisIndex, matcher.start()); @@ -807,12 +806,12 @@ public final class NativeRegExp extends ScriptObject { new Callable() { @Override public MethodHandle call() { - return Bootstrap.createDynamicCallInvoker(String.class, ScriptFunction.class, Object.class, Object[].class); + return Bootstrap.createDynamicCallInvoker(String.class, Object.class, Object.class, Object[].class); } }); } - private String callReplaceValue(final MethodHandle invoker, final ScriptFunction function, final Object self, final RegExpMatcher matcher, final String string) throws Throwable { + private String callReplaceValue(final MethodHandle invoker, final Object function, final Object self, final RegExpMatcher matcher, final String string) throws Throwable { final Object[] groups = groups(matcher); final Object[] args = Arrays.copyOf(groups, groups.length + 2); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java index 33e087bde80..ec1619e1b88 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java @@ -58,10 +58,10 @@ import jdk.nashorn.internal.runtime.ConsString; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.OptimisticBuiltins; import jdk.nashorn.internal.runtime.PropertyMap; -import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.arrays.ArrayIndex; +import jdk.nashorn.internal.runtime.linker.Bootstrap; import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; import jdk.nashorn.internal.runtime.linker.NashornGuards; import jdk.nashorn.internal.runtime.linker.PrimitiveLookup; @@ -743,8 +743,8 @@ public final class NativeString extends ScriptObject implements OptimisticBuilti nativeRegExp = NativeRegExp.flatRegExp(JSType.toString(string)); } - if (replacement instanceof ScriptFunction) { - return nativeRegExp.replace(str, "", (ScriptFunction)replacement); + if (Bootstrap.isCallable(replacement)) { + return nativeRegExp.replace(str, "", replacement); } return nativeRegExp.replace(str, JSType.toString(replacement), null); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeWeakMap.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeWeakMap.java index 6e11734e20a..7b08a78f807 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeWeakMap.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeWeakMap.java @@ -31,7 +31,6 @@ import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; import jdk.nashorn.internal.objects.annotations.Function; import jdk.nashorn.internal.objects.annotations.ScriptClass; -import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.PropertyMap; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeWeakSet.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeWeakSet.java index 19e5f1c8405..fb27bffc7a7 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeWeakSet.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeWeakSet.java @@ -31,7 +31,6 @@ import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; import jdk.nashorn.internal.objects.annotations.Function; import jdk.nashorn.internal.objects.annotations.ScriptClass; -import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.PropertyMap; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSONFunctions.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSONFunctions.java index 5f56c364c6b..32cdc09d661 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSONFunctions.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSONFunctions.java @@ -46,7 +46,7 @@ public final class JSONFunctions { @Override public MethodHandle call() { return Bootstrap.createDynamicCallInvoker(Object.class, - ScriptFunction.class, ScriptObject.class, String.class, Object.class); + Object.class, Object.class, String.class, Object.class); } }); } @@ -90,16 +90,16 @@ public final class JSONFunctions { // apply 'reviver' function if available private static Object applyReviver(final Global global, final Object unfiltered, final Object reviver) { - if (reviver instanceof ScriptFunction) { + if (Bootstrap.isCallable(reviver)) { final ScriptObject root = global.newObject(); root.addOwnProperty("", Property.WRITABLE_ENUMERABLE_CONFIGURABLE, unfiltered); - return walk(root, "", (ScriptFunction)reviver); + return walk(root, "", reviver); } return unfiltered; } // This is the abstract "Walk" operation from the spec. - private static Object walk(final ScriptObject holder, final Object name, final ScriptFunction reviver) { + private static Object walk(final ScriptObject holder, final Object name, final Object reviver) { final Object val = holder.get(name); if (val instanceof ScriptObject) { final ScriptObject valueObj = (ScriptObject)val; @@ -131,7 +131,7 @@ public final class JSONFunctions { try { // Object.class, ScriptFunction.class, ScriptObject.class, String.class, Object.class); - return getREVIVER_INVOKER().invokeExact(reviver, holder, JSType.toString(name), val); + return getREVIVER_INVOKER().invokeExact(reviver, (Object)holder, JSType.toString(name), val); } catch(Error|RuntimeException t) { throw t; } catch(final Throwable t) { diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java index 9648da3e0f2..cdbbb0fea22 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java @@ -171,7 +171,9 @@ public final class Bootstrap { return ((JSObject)callable).isStrictFunction(); } else if (callable instanceof BoundCallable) { return isStrictCallable(((BoundCallable)callable).getCallable()); - } else if (BeansLinker.isDynamicMethod(callable) || callable instanceof StaticClass) { + } else if (BeansLinker.isDynamicMethod(callable) || + callable instanceof StaticClass || + isFunctionalInterfaceObject(callable)) { return false; } throw notFunction(callable); diff --git a/nashorn/test/script/basic/JDK-8157680.js b/nashorn/test/script/basic/JDK-8157680.js new file mode 100644 index 00000000000..02c868ecfcd --- /dev/null +++ b/nashorn/test/script/basic/JDK-8157680.js @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2016, 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-8157680: Callback parameter of any JS builtin implementation should accept any Callable + * + * @option -scripting + * @test + * @run + */ + +var SM = Java.type("javax.script.ScriptEngineManager") +var engine = new SM().getEngineByName("nashorn") + +engine.put("output", print); +var reviver = engine.eval(< " + value) + return value + } +}) + +// compare function from the mirror world +var arr = [34,567,-3, 53].sort(engine.eval(< y)? 1 : 0) +EOF)) +print(arr) + +// compare function as a JSObject function +arr = [34,57,-3, 53, 670, 33].sort(new AJO() { + isFunction: function() true, + call: function(thiz, args) { + var x = args[0], y = args[1] + return x < y? -1 : ((x > y)? 1 : 0) + } +}) +print(arr) + +// replacer function from mirror world +var str = "hello".replace(/l/g, engine.eval(< hello +-3,34,53,567 +-3,33,34,53,57,670 +he__o +hELLo From 1f0c44c1c44bcc2f022bade020645df75bc60dfb Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Wed, 25 May 2016 19:25:57 +0530 Subject: [PATCH 3/3] 8157819: TypeError when a java.util.Comparator object is invoked as a function Reviewed-by: mhaupt, forax, hannesw --- .../runtime/linker/NashornBeansLinker.java | 19 +++++++- nashorn/test/script/basic/JDK-8157819.js | 46 +++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 nashorn/test/script/basic/JDK-8157819.js diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java index b81cd2add9e..d2a46eae78f 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java @@ -186,7 +186,7 @@ public class NashornBeansLinker implements GuardingDynamicLinker { if (iface.isAnnotationPresent(FunctionalInterface.class)) { // return the first abstract method for (final Method m : iface.getMethods()) { - if (Modifier.isAbstract(m.getModifiers())) { + if (Modifier.isAbstract(m.getModifiers()) && !isOverridableObjectMethod(m)) { return m.getName(); } } @@ -197,6 +197,23 @@ public class NashornBeansLinker implements GuardingDynamicLinker { return findFunctionalInterfaceMethodName(clazz.getSuperclass()); } + // is this an overridable java.lang.Object method? + private static boolean isOverridableObjectMethod(final Method m) { + switch (m.getName()) { + case "equals": + if (m.getReturnType() == boolean.class) { + final Class[] params = m.getParameterTypes(); + return params.length == 1 && params[0] == Object.class; + } + return false; + case "hashCode": + return m.getReturnType() == int.class && m.getParameterCount() == 0; + case "toString": + return m.getReturnType() == String.class && m.getParameterCount() == 0; + } + return false; + } + // Returns @FunctionalInterface annotated interface's single abstract // method name. If not found, returns null. static String getFunctionalInterfaceMethodName(final Class clazz) { diff --git a/nashorn/test/script/basic/JDK-8157819.js b/nashorn/test/script/basic/JDK-8157819.js new file mode 100644 index 00000000000..869aa15f8d2 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8157819.js @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016, 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-8157819: TypeError when a java.util.Comparator object is invoked as a function + * + * @test + * @run + */ + +var compare = java.util.Comparator.naturalOrder() +Assert.assertTrue(compare("nashorn", "ecmascript") > 0) +Assert.assertTrue(compare("abc", "xyz") < 0) +Assert.assertTrue(compare("hello", "hello") == 0) + +var rcompare = java.util.Comparator.reverseOrder() +Assert.assertTrue(rcompare("nashorn", "ecmascript") < 0) +Assert.assertTrue(rcompare("abc", "xyz") > 0) +Assert.assertTrue(rcompare("hello", "hello") == 0) + +var arr = [ "nashorn", "JavaScript", "ECMAScript", "ecmascript", "js" ] +Assert.assertEquals(arr.sort(compare).join(), + "ECMAScript,JavaScript,ecmascript,js,nashorn") +Assert.assertEquals(arr.sort(rcompare).join(), + "nashorn,js,ecmascript,JavaScript,ECMAScript") +