# HG changeset patch # User sundar # Date 1363620791 -19800 # Node ID 8d20ffabe47e9365f5e569c23b5a77b75f00ed8b # Parent 5ba350ebcdbbab22060511de7fc7d350a78b71a1 8010199: javax.script.Invocable implementation for nashorn does not return null when matching functions are missing Reviewed-by: lagergren, jlaskey diff -r 5ba350ebcdbb -r 8d20ffabe47e nashorn/bin/jjs --- a/nashorn/bin/jjs Fri Mar 15 21:52:40 2013 +0530 +++ b/nashorn/bin/jjs Mon Mar 18 21:03:11 2013 +0530 @@ -26,4 +26,4 @@ [ -z "$JAVA_HOME" ] && echo "Please set JAVA_HOME" && exit 1; -$JAVA_HOME/bin/java -server -XX:-TieredCompilation -Xms2G -Xmx2G -esa -ea -Djava.ext.dirs=$JAVA_HOME/jre/lib/ext:`dirname $0`/../dist -XX:+HeapDumpOnOutOfMemoryError -Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -Dnashorn.debug=true jdk.nashorn.tools.Shell $* +$JAVA_HOME/bin/java -server -XX:-TieredCompilation -Xms2G -Xmx2G -esa -ea -Djava.ext.dirs=`dirname $0`/../dist:$JAVA_HOME/jre/lib/ext -XX:+HeapDumpOnOutOfMemoryError -Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -Dnashorn.debug=true jdk.nashorn.tools.Shell $* diff -r 5ba350ebcdbb -r 8d20ffabe47e nashorn/bin/jjssecure --- a/nashorn/bin/jjssecure Fri Mar 15 21:52:40 2013 +0530 +++ b/nashorn/bin/jjssecure Mon Mar 18 21:03:11 2013 +0530 @@ -26,4 +26,4 @@ [ -z "$JAVA_HOME" ] && echo "Please set JAVA_HOME" && exit 1; -$JAVA_HOME/bin/java -Xms2G -Xmx2G -XX:-TieredCompilation -server -esa -ea -Djava.security.properties=`dirname $0`/../make/java.security.override -Djava.ext.dirs=$JAVA_HOME/jre/lib/ext:`dirname $0`/../dist -XX:+HeapDumpOnOutOfMemoryError -Dnashorn.debug=true -Djava.lang.invoke.MethodHandle.DEBUG_NAMES=true -Dnashorn.home=`dirname $0`/.. -Djava.security.manager jdk.nashorn.tools.Shell $* +$JAVA_HOME/bin/java -Xms2G -Xmx2G -XX:-TieredCompilation -server -esa -ea -Djava.security.properties=`dirname $0`/../make/java.security.override -Djava.ext.dirs=`dirname $0`/../dist:$JAVA_HOME/jre/lib/ext -XX:+HeapDumpOnOutOfMemoryError -Dnashorn.debug=true -Djava.lang.invoke.MethodHandle.DEBUG_NAMES=true -Dnashorn.home=`dirname $0`/.. -Djava.security.manager jdk.nashorn.tools.Shell $* diff -r 5ba350ebcdbb -r 8d20ffabe47e nashorn/bin/nashorn --- a/nashorn/bin/nashorn Fri Mar 15 21:52:40 2013 +0530 +++ b/nashorn/bin/nashorn Mon Mar 18 21:03:11 2013 +0530 @@ -26,4 +26,4 @@ [ -z "$JAVA_HOME" ] && echo "Please set JAVA_HOME" && exit 1; -$JAVA_HOME/bin/jrunscript -J-Xms2G -J-Xmx2G -J-XX:-TieredCompilation -J-server -J-esa -J-ea -J-Djava.ext.dirs=$JAVA_HOME/jre/lib/ext:`dirname $0`/../dist -J-XX:+HeapDumpOnOutOfMemoryError -J-Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -J-Dnashorn.debug=true -l nashorn $* +$JAVA_HOME/bin/jrunscript -J-Xms2G -J-Xmx2G -J-XX:-TieredCompilation -J-server -J-esa -J-ea -J-Djava.ext.dirs=`dirname $0`/../dist:$JAVA_HOME/jre/lib/ext -J-XX:+HeapDumpOnOutOfMemoryError -J-Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -J-Dnashorn.debug=true -l nashorn $* diff -r 5ba350ebcdbb -r 8d20ffabe47e nashorn/bin/nashornsecure --- a/nashorn/bin/nashornsecure Fri Mar 15 21:52:40 2013 +0530 +++ b/nashorn/bin/nashornsecure Mon Mar 18 21:03:11 2013 +0530 @@ -26,4 +26,4 @@ [ -z "$JAVA_HOME" ] && echo "Please set JAVA_HOME" && exit 1; -$JAVA_HOME/bin/jrunscript -J-Djava.security.properties=`dirname $0`/../make/java.security.override -J-Djava.security.manager -J-Xms2G -J-Xmx2G -J-XX:-TieredCompilation -J-server -J-esa -J-ea -J-Djava.ext.dirs=$JAVA_HOME/jre/lib/ext:`dirname $0`/../dist -J-XX:+HeapDumpOnOutOfMemoryError -J-Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -J-Dnashorn.debug=true -l nashorn $* +$JAVA_HOME/bin/jrunscript -J-Djava.security.properties=`dirname $0`/../make/java.security.override -J-Djava.security.manager -J-Xms2G -J-Xmx2G -J-XX:-TieredCompilation -J-server -J-esa -J-ea -J-Djava.ext.dirs=`dirname $0`/../dist:$JAVA_HOME/jre/lib/ext -J-XX:+HeapDumpOnOutOfMemoryError -J-Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -J-Dnashorn.debug=true -l nashorn $* diff -r 5ba350ebcdbb -r 8d20ffabe47e nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java --- a/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Fri Mar 15 21:52:40 2013 +0530 +++ b/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Mon Mar 18 21:03:11 2013 +0530 @@ -32,6 +32,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; +import java.lang.reflect.Method; import java.net.URL; import java.security.AccessController; import java.security.PrivilegedAction; @@ -179,14 +180,14 @@ } private T getInterfaceInner(final Object self, final Class clazz) { - final Object realSelf; + final ScriptObject realSelf; final ScriptObject ctxtGlobal = getNashornGlobalFrom(context); if(self == null) { realSelf = ctxtGlobal; } else if (!(self instanceof ScriptObject)) { - realSelf = ScriptObjectMirror.unwrap(self, ctxtGlobal); + realSelf = (ScriptObject)ScriptObjectMirror.unwrap(self, ctxtGlobal); } else { - realSelf = self; + realSelf = (ScriptObject)self; } try { final ScriptObject oldGlobal = getNashornGlobal(); @@ -194,6 +195,10 @@ if(oldGlobal != ctxtGlobal) { setNashornGlobal(ctxtGlobal); } + + if (! isInterfaceImplemented(clazz, realSelf)) { + return null; + } return clazz.cast(JavaAdapterFactory.getConstructor(realSelf.getClass(), clazz).invoke(realSelf)); } finally { if(oldGlobal != ctxtGlobal) { @@ -463,6 +468,21 @@ } } + private static boolean isInterfaceImplemented(final Class iface, final ScriptObject sobj) { + for (final Method method : iface.getMethods()) { + // ignore methods of java.lang.Object class + if (method.getDeclaringClass() == Object.class) { + continue; + } + + Object obj = sobj.get(method.getName()); + if (! (obj instanceof ScriptFunction)) { + return false; + } + } + return true; + } + // don't make this public!! static ScriptObject getNashornGlobal() { return Context.getGlobal(); diff -r 5ba350ebcdbb -r 8d20ffabe47e nashorn/test/script/basic/JDK-8010199.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8010199.js Mon Mar 18 21:03:11 2013 +0530 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2010, 2013, 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-8010199: javax.script.Invocable implementation for nashorn does not return null when matching functions are missing + * + * @test + * @run + */ + +var m = new javax.script.ScriptEngineManager(); +var e = m.getEngineByName("nashorn"); + +var iface = e.getInterface(java.lang.Runnable.class); + +if (iface != null) { + fail("Expected interface object to be null"); +} + +e.eval("var runcalled = false; function run() { runcalled = true }"); + +iface = e.getInterface(java.lang.Runnable.class); +if (iface == null) { + fail("Expected interface object to be non-null"); +} + +iface.run(); + +if (e.get("runcalled") != true) { + fail("runcalled is not true"); +} diff -r 5ba350ebcdbb -r 8d20ffabe47e nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java --- a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java Fri Mar 15 21:52:40 2013 +0530 +++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java Mon Mar 18 21:03:11 2013 +0530 @@ -283,6 +283,68 @@ } } + public interface Foo { + public void bar(); + } + + public interface Foo2 extends Foo { + public void bar2(); + } + + @Test + public void getInterfaceMissingTest() { + final ScriptEngineManager manager = new ScriptEngineManager(); + final ScriptEngine engine = manager.getEngineByName("nashorn"); + + // don't define any function. + try { + engine.eval(""); + } catch (final Exception exp) { + exp.printStackTrace(); + fail(exp.getMessage()); + } + + Runnable runnable = ((Invocable)engine).getInterface(Runnable.class); + if (runnable != null) { + fail("runnable is not null!"); + } + + // now define "run" + try { + engine.eval("function run() { print('this is run function'); }"); + } catch (final Exception exp) { + exp.printStackTrace(); + fail(exp.getMessage()); + } + runnable = ((Invocable)engine).getInterface(Runnable.class); + // should not return null now! + runnable.run(); + + // define only one method of "Foo2" + try { + engine.eval("function bar() { print('bar function'); }"); + } catch (final Exception exp) { + exp.printStackTrace(); + fail(exp.getMessage()); + } + + Foo2 foo2 = ((Invocable)engine).getInterface(Foo2.class); + if (foo2 != null) { + throw new RuntimeException("foo2 is not null!"); + } + + // now define other method of "Foo2" + try { + engine.eval("function bar2() { print('bar2 function'); }"); + } catch (final Exception exp) { + exp.printStackTrace(); + fail(exp.getMessage()); + } + foo2 = ((Invocable)engine).getInterface(Foo2.class); + foo2.bar(); + foo2.bar2(); + } + @Test public void accessGlobalTest() { final ScriptEngineManager m = new ScriptEngineManager();