8010199: javax.script.Invocable implementation for nashorn does not return null when matching functions are missing

Reviewed-by: lagergren, jlaskey
This commit is contained in:
Athijegannathan Sundararajan 2013-03-18 21:03:11 +05:30
parent 5aea724d29
commit c846064c8f
7 changed files with 140 additions and 7 deletions
nashorn
bin
src/jdk/nashorn/api/scripting
test
script/basic
src/jdk/nashorn/api/scripting

@ -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 $*

@ -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 $*

@ -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 $*

@ -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 $*

@ -32,6 +32,7 @@ import java.io.IOException;
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 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
}
private <T> T getInterfaceInner(final Object self, final Class<T> 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 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
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 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
}
}
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();

@ -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");
}

@ -283,6 +283,68 @@ public class ScriptEngineTest {
}
}
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();