Mercurial > hg > release > icedtea8-forest-3.0 > nashorn
changeset 754:c6ed9226b007
8031359: Invocable.getInterface() works incorrectly if interface has default methods
Reviewed-by: attila, hannesw
author | sundar |
---|---|
date | Thu, 09 Jan 2014 19:23:34 +0530 |
parents | 8c19fdb184f8 |
children | 9fe1f5e5db35 |
files | src/jdk/nashorn/api/scripting/NashornScriptEngine.java src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java test/script/basic/JDK-8031359.js test/script/basic/JDK-8031359.js.EXPECTED test/src/jdk/nashorn/api/scripting/InvocableTest.java |
diffstat | 5 files changed, 96 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Wed Jan 08 17:51:47 2014 +0530 +++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Thu Jan 09 19:23:34 2014 +0530 @@ -628,6 +628,11 @@ continue; } + // skip check for default methods - non-abstract, interface methods + if (! Modifier.isAbstract(method.getModifiers())) { + continue; + } + Object obj = sobj.get(method.getName()); if (! (obj instanceof ScriptFunction)) { return false;
--- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java Wed Jan 08 17:51:47 2014 +0530 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java Thu Jan 09 19:23:34 2014 +0530 @@ -645,7 +645,7 @@ mv.athrow(); } else { // If the super method is not abstract, delegate to it. - emitSuperCall(mv, name, methodDesc); + emitSuperCall(mv, method.getDeclaringClass(), name, methodDesc); } mv.visitLabel(handleDefined); @@ -817,12 +817,12 @@ SUPER_PREFIX + name, methodDesc, null, getExceptionNames(method.getExceptionTypes()))); mv.visitCode(); - emitSuperCall(mv, name, methodDesc); + emitSuperCall(mv, method.getDeclaringClass(), name, methodDesc); endMethod(mv); } - private void emitSuperCall(final InstructionAdapter mv, final String name, final String methodDesc) { + private void emitSuperCall(final InstructionAdapter mv, final Class owner, final String name, final String methodDesc) { mv.visitVarInsn(ALOAD, 0); int nextParam = 1; final Type methodType = Type.getMethodType(methodDesc); @@ -830,7 +830,13 @@ mv.load(nextParam, t); nextParam += t.getSize(); } - mv.invokespecial(superClassName, name, methodDesc, false); + + // default method - non-abstract, interface method + if (Modifier.isInterface(owner.getModifiers())) { + mv.invokespecial(Type.getInternalName(owner), name, methodDesc, false); + } else { + mv.invokespecial(superClassName, name, methodDesc, false); + } mv.areturn(methodType.getReturnType()); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8031359.js Thu Jan 09 19:23:34 2014 +0530 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2010, 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-8031359: Invocable.getInterface() works incorrectly if interface has default methods + * + * @test + * @run + */ + +var func = new java.util.function.Function() { + apply: function(arg) { + print("func called with " + arg); + return arg.toUpperCase(); + } +}; + +// Function.andThen is a default method +func.andThen(func)("hello"); + +// Function.compose is another default method +func.compose(new java.util.function.Function() { + apply: function(arg) { + print("compose called with " + arg); + return arg.charAt(0); + } +})("hello"); + +var func2 = new java.util.function.Function() { + apply: function(arg) { + print("I am func2: " + arg); + return arg; + }, + + andThen: function(func) { + print("This is my andThen!"); + return func; + } +}; + +func2.apply("hello"); +func2.andThen(func);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8031359.js.EXPECTED Thu Jan 09 19:23:34 2014 +0530 @@ -0,0 +1,6 @@ +func called with hello +func called with HELLO +compose called with hello +func called with h +I am func2: hello +This is my andThen!
--- a/test/src/jdk/nashorn/api/scripting/InvocableTest.java Wed Jan 08 17:51:47 2014 +0530 +++ b/test/src/jdk/nashorn/api/scripting/InvocableTest.java Thu Jan 09 19:23:34 2014 +0530 @@ -26,6 +26,7 @@ package jdk.nashorn.api.scripting; import java.util.Objects; +import java.util.function.Function; import javax.script.Invocable; import javax.script.ScriptContext; import javax.script.ScriptEngine; @@ -522,4 +523,16 @@ Assert.assertEquals(itf.test1(42, "a", "b"), "i == 42, strings instanceof java.lang.String[] == true, strings == [a, b]"); Assert.assertEquals(itf.test2(44, "c", "d", "e"), "arguments[0] == 44, arguments[1] instanceof java.lang.String[] == true, arguments[1] == [c, d, e]"); } + + @Test + @SuppressWarnings("unchecked") + public void defaultMethodTest() throws ScriptException { + final ScriptEngineManager m = new ScriptEngineManager(); + final ScriptEngine e = m.getEngineByName("nashorn"); + final Invocable inv = (Invocable) e; + + Object obj = e.eval("({ apply: function(arg) { return arg.toUpperCase(); }})"); + Function<String, String> func = inv.getInterface(obj, Function.class); + assertEquals(func.apply("hello"), "HELLO"); + } }