Mercurial > hg > jdk9-shenandoah > nashorn
changeset 1400:6e41fdc6acdf
8068901: Surprising behavior with more than one functional interface on a class
8068903: Can't invoke vararg @FunctionalInterface methods
Reviewed-by: attila, hannesw
author | sundar |
---|---|
date | Tue, 01 Sep 2015 18:28:11 +0530 |
parents | eea9202e8930 |
children | d7d4c84bd750 |
files | src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java test/script/basic/JDK-8068901.js test/script/basic/JDK-8068901.js.EXPECTED test/script/basic/JDK-8068903.js test/src/jdk/nashorn/test/models/VarArgConsumer.java |
diffstat | 6 files changed, 158 insertions(+), 22 deletions(-) [+] |
line wrap: on
line diff
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java Mon Aug 31 15:18:59 2015 +0200 +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java Tue Sep 01 18:28:11 2015 +0530 @@ -189,7 +189,7 @@ * @return true if the obj is an instance of @FunctionalInterface interface */ public static boolean isFunctionalInterfaceObject(final Object obj) { - return !JSType.isPrimitive(obj) && (NashornBeansLinker.getFunctionalInterfaceMethod(obj.getClass()) != null); + return !JSType.isPrimitive(obj) && (NashornBeansLinker.getFunctionalInterfaceMethodName(obj.getClass()) != null); } /**
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Mon Aug 31 15:18:59 2015 +0200 +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Tue Sep 01 18:28:11 2015 +0530 @@ -79,10 +79,10 @@ } // cache of @FunctionalInterface method of implementor classes - private static final ClassValue<Method> FUNCTIONAL_IFACE_METHOD = new ClassValue<Method>() { + private static final ClassValue<String> FUNCTIONAL_IFACE_METHOD_NAME = new ClassValue<String>() { @Override - protected Method computeValue(final Class<?> type) { - return findFunctionalInterfaceMethod(type); + protected String computeValue(final Class<?> type) { + return findFunctionalInterfaceMethodName(type); } }; @@ -107,19 +107,21 @@ // 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 String name = getFunctionalInterfaceMethodName(self.getClass()); + if (name != 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(linkerServices.filterInternalObjects(desc.getLookup().unreflect(m)), 1, - callType.parameterType(1)), Guards.getInstanceOfGuard( - m.getDeclaringClass())).asTypeSafeReturn( - new NashornBeansLinkerServices(linkerServices), callType); + // drop callee (Undefined ScriptFunction) and change the request to be dyn:callMethod:<name> + final NashornCallSiteDescriptor newDesc = NashornCallSiteDescriptor.get(desc.getLookup(), + "dyn:callMethod:" + name, desc.getMethodType().dropParameterTypes(1, 2), + NashornCallSiteDescriptor.getFlags(desc)); + final GuardedInvocation gi = getGuardedInvocation(beansLinker, + linkRequest.replaceArguments(newDesc, linkRequest.getArguments()), + new NashornBeansLinkerServices(linkerServices)); + + // drop 'thiz' passed from the script. + return gi.replaceMethods( + MH.dropArguments(linkerServices.filterInternalObjects(gi.getInvocation()), 1, callType.parameterType(1)), + gi.getGuard()); } } return getGuardedInvocation(beansLinker, linkRequest, linkerServices); @@ -163,7 +165,7 @@ return arg instanceof ConsString ? arg.toString() : arg; } - private static Method findFunctionalInterfaceMethod(final Class<?> clazz) { + private static String findFunctionalInterfaceMethodName(final Class<?> clazz) { if (clazz == null) { return null; } @@ -179,20 +181,20 @@ // return the first abstract method for (final Method m : iface.getMethods()) { if (Modifier.isAbstract(m.getModifiers())) { - return m; + return m.getName(); } } } } // did not find here, try super class - return findFunctionalInterfaceMethod(clazz.getSuperclass()); + return findFunctionalInterfaceMethodName(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); + // method name. If not found, returns null. + static String getFunctionalInterfaceMethodName(final Class<?> clazz) { + return FUNCTIONAL_IFACE_METHOD_NAME.get(clazz); } static MethodHandleTransformer createHiddenObjectFilter() {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8068901.js Tue Sep 01 18:28:11 2015 +0530 @@ -0,0 +1,49 @@ +/* + * 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-8068901: Surprising behavior with more than one functional interface on a class + * + * @test + * @run + */ + +var Consumer = java.util.function.Consumer; +var JFunction = java.util.function.Function; + +var fc = new (Java.extend(JFunction, Consumer))({ + apply: function(x) { print("fc invoked as a function") }, + accept: function(x) { print("fc invoked as a consumer") } +}); + +var c = new Consumer(function(x) { print("c invoked as a consumer") }); + +var cf = new (Java.extend(Consumer, JFunction))({ + apply: function(x) { print("cf invoked as a function") }, + accept: function(x) { print("cf invoked as a consumer") } +}); + +var f = new JFunction(function(x) { print("f invoked as a function") }); + +for each(x in [fc, c, fc, cf, f, cf, c, fc, f, cf]) { x(null); } +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8068901.js.EXPECTED Tue Sep 01 18:28:11 2015 +0530 @@ -0,0 +1,10 @@ +fc invoked as a function +c invoked as a consumer +fc invoked as a function +cf invoked as a consumer +f invoked as a function +cf invoked as a consumer +c invoked as a consumer +fc invoked as a function +f invoked as a function +cf invoked as a consumer
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8068903.js Tue Sep 01 18:28:11 2015 +0530 @@ -0,0 +1,40 @@ +/* + * 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-8068903: Can't invoke vararg @FunctionalInterface methods + * + * @test + * @run + */ + +var vc = new (Java.type("jdk.nashorn.test.models.VarArgConsumer"))( + function(x) { + Assert.assertTrue(x.length == 3); + Assert.assertTrue(x[0] == 1); + Assert.assertTrue(x[1] == 2); + Assert.assertTrue(x[2] == 3); + } +); + +vc(1, 2, 3);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/src/jdk/nashorn/test/models/VarArgConsumer.java Tue Sep 01 18:28:11 2015 +0530 @@ -0,0 +1,35 @@ +/* + * 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; + +/** + * Simple function interface with a varargs SAM method. + */ +@FunctionalInterface +public interface VarArgConsumer { + public void apply(Object... o); +} +