8031359: Invocable.getInterface() works incorrectly if interface has default methods

Thu, 09 Jan 2014 19:23:34 +0530

author
sundar
date
Thu, 09 Jan 2014 19:23:34 +0530
changeset 755
c6ed9226b007
parent 754
8c19fdb184f8
child 756
9fe1f5e5db35

8031359: Invocable.getInterface() works incorrectly if interface has default methods
Reviewed-by: attila, hannesw

src/jdk/nashorn/api/scripting/NashornScriptEngine.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java file | annotate | diff | comparison | revisions
test/script/basic/JDK-8031359.js file | annotate | diff | comparison | revisions
test/script/basic/JDK-8031359.js.EXPECTED file | annotate | diff | comparison | revisions
test/src/jdk/nashorn/api/scripting/InvocableTest.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java	Wed Jan 08 17:51:47 2014 +0530
     1.2 +++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java	Thu Jan 09 19:23:34 2014 +0530
     1.3 @@ -628,6 +628,11 @@
     1.4                  continue;
     1.5              }
     1.6  
     1.7 +            // skip check for default methods - non-abstract, interface methods
     1.8 +            if (! Modifier.isAbstract(method.getModifiers())) {
     1.9 +                continue;
    1.10 +            }
    1.11 +
    1.12              Object obj = sobj.get(method.getName());
    1.13              if (! (obj instanceof ScriptFunction)) {
    1.14                  return false;
     2.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java	Wed Jan 08 17:51:47 2014 +0530
     2.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java	Thu Jan 09 19:23:34 2014 +0530
     2.3 @@ -645,7 +645,7 @@
     2.4              mv.athrow();
     2.5          } else {
     2.6              // If the super method is not abstract, delegate to it.
     2.7 -            emitSuperCall(mv, name, methodDesc);
     2.8 +            emitSuperCall(mv, method.getDeclaringClass(), name, methodDesc);
     2.9          }
    2.10  
    2.11          mv.visitLabel(handleDefined);
    2.12 @@ -817,12 +817,12 @@
    2.13                  SUPER_PREFIX + name, methodDesc, null, getExceptionNames(method.getExceptionTypes())));
    2.14          mv.visitCode();
    2.15  
    2.16 -        emitSuperCall(mv, name, methodDesc);
    2.17 +        emitSuperCall(mv, method.getDeclaringClass(), name, methodDesc);
    2.18  
    2.19          endMethod(mv);
    2.20      }
    2.21  
    2.22 -    private void emitSuperCall(final InstructionAdapter mv, final String name, final String methodDesc) {
    2.23 +    private void emitSuperCall(final InstructionAdapter mv, final Class owner, final String name, final String methodDesc) {
    2.24          mv.visitVarInsn(ALOAD, 0);
    2.25          int nextParam = 1;
    2.26          final Type methodType = Type.getMethodType(methodDesc);
    2.27 @@ -830,7 +830,13 @@
    2.28              mv.load(nextParam, t);
    2.29              nextParam += t.getSize();
    2.30          }
    2.31 -        mv.invokespecial(superClassName, name, methodDesc, false);
    2.32 +
    2.33 +        // default method - non-abstract, interface method
    2.34 +        if (Modifier.isInterface(owner.getModifiers())) {
    2.35 +            mv.invokespecial(Type.getInternalName(owner), name, methodDesc, false);
    2.36 +        } else {
    2.37 +            mv.invokespecial(superClassName, name, methodDesc, false);
    2.38 +        }
    2.39          mv.areturn(methodType.getReturnType());
    2.40      }
    2.41  
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/test/script/basic/JDK-8031359.js	Thu Jan 09 19:23:34 2014 +0530
     3.3 @@ -0,0 +1,62 @@
     3.4 +/*
     3.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
     3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.7 + * 
     3.8 + * This code is free software; you can redistribute it and/or modify it
     3.9 + * under the terms of the GNU General Public License version 2 only, as
    3.10 + * published by the Free Software Foundation.
    3.11 + * 
    3.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    3.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    3.15 + * version 2 for more details (a copy is included in the LICENSE file that
    3.16 + * accompanied this code).
    3.17 + * 
    3.18 + * You should have received a copy of the GNU General Public License version
    3.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    3.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    3.21 + * 
    3.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    3.23 + * or visit www.oracle.com if you need additional information or have any
    3.24 + * questions.
    3.25 + */
    3.26 +
    3.27 +/**
    3.28 + * JDK-8031359: Invocable.getInterface() works incorrectly if interface has default methods
    3.29 + *
    3.30 + * @test
    3.31 + * @run
    3.32 + */
    3.33 +
    3.34 +var func = new java.util.function.Function() {
    3.35 +    apply: function(arg) {
    3.36 +        print("func called with " + arg);
    3.37 +        return arg.toUpperCase();
    3.38 +    }
    3.39 +};
    3.40 +
    3.41 +// Function.andThen is a default method
    3.42 +func.andThen(func)("hello");
    3.43 +
    3.44 +// Function.compose is another default method
    3.45 +func.compose(new java.util.function.Function() {
    3.46 +    apply: function(arg) {
    3.47 +        print("compose called with " + arg);
    3.48 +        return arg.charAt(0);
    3.49 +    }
    3.50 +})("hello");
    3.51 +
    3.52 +var func2 = new java.util.function.Function() {
    3.53 +    apply: function(arg) {
    3.54 +        print("I am func2: " + arg);
    3.55 +        return arg;
    3.56 +    },
    3.57 +
    3.58 +    andThen: function(func) {
    3.59 +        print("This is my andThen!");
    3.60 +        return func;
    3.61 +    }
    3.62 +};
    3.63 +
    3.64 +func2.apply("hello");
    3.65 +func2.andThen(func);
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/test/script/basic/JDK-8031359.js.EXPECTED	Thu Jan 09 19:23:34 2014 +0530
     4.3 @@ -0,0 +1,6 @@
     4.4 +func called with hello
     4.5 +func called with HELLO
     4.6 +compose called with hello
     4.7 +func called with h
     4.8 +I am func2: hello
     4.9 +This is my andThen!
     5.1 --- a/test/src/jdk/nashorn/api/scripting/InvocableTest.java	Wed Jan 08 17:51:47 2014 +0530
     5.2 +++ b/test/src/jdk/nashorn/api/scripting/InvocableTest.java	Thu Jan 09 19:23:34 2014 +0530
     5.3 @@ -26,6 +26,7 @@
     5.4  package jdk.nashorn.api.scripting;
     5.5  
     5.6  import java.util.Objects;
     5.7 +import java.util.function.Function;
     5.8  import javax.script.Invocable;
     5.9  import javax.script.ScriptContext;
    5.10  import javax.script.ScriptEngine;
    5.11 @@ -522,4 +523,16 @@
    5.12          Assert.assertEquals(itf.test1(42, "a", "b"), "i == 42, strings instanceof java.lang.String[] == true, strings == [a, b]");
    5.13          Assert.assertEquals(itf.test2(44, "c", "d", "e"), "arguments[0] == 44, arguments[1] instanceof java.lang.String[] == true, arguments[1] == [c, d, e]");
    5.14      }
    5.15 +
    5.16 +    @Test
    5.17 +    @SuppressWarnings("unchecked")
    5.18 +    public void defaultMethodTest() throws ScriptException {
    5.19 +        final ScriptEngineManager m = new ScriptEngineManager();
    5.20 +        final ScriptEngine e = m.getEngineByName("nashorn");
    5.21 +        final Invocable inv = (Invocable) e;
    5.22 +
    5.23 +        Object obj = e.eval("({ apply: function(arg) { return arg.toUpperCase(); }})");
    5.24 +        Function<String, String> func = inv.getInterface(obj, Function.class);
    5.25 +        assertEquals(func.apply("hello"), "HELLO");
    5.26 +    }
    5.27  }

mercurial