8007286: Add JavaAdapter and importPackage to compatibility script
Reviewed-by: lagergren, jlaskey
This commit is contained in:
parent
fcd28bdcc5
commit
bdcffc23f7
@ -44,6 +44,9 @@ public class NashornException extends RuntimeException {
|
||||
// script column number
|
||||
private int column;
|
||||
|
||||
// script source name used for "engine.js"
|
||||
protected static final String ENGINE_SCRIPT_SOURCE_NAME = "nashorn:engine/resources/engine.js";
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
|
@ -242,41 +242,6 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
|
||||
return UNDEFINED;
|
||||
}
|
||||
|
||||
/**
|
||||
* This hook is used to call js global functions exposed from Java code.
|
||||
*
|
||||
* @param self 'this' passed from the script
|
||||
* @param ctxt current ScriptContext in which method is searched
|
||||
* @param name name of the method
|
||||
* @param args arguments to be passed to the method
|
||||
* @return return value of the called method
|
||||
*/
|
||||
public Object __noSuchMethod__(final Object self, final ScriptContext ctxt, final String name, final Object args) {
|
||||
final int scope = ctxt.getAttributesScope(name);
|
||||
final ScriptObject ctxtGlobal = getNashornGlobalFrom(ctxt);
|
||||
Object value;
|
||||
|
||||
if (scope != -1) {
|
||||
value = ctxt.getAttribute(name, scope);
|
||||
} else {
|
||||
if (self == UNDEFINED) {
|
||||
referenceError(ctxtGlobal, "not.defined", name);
|
||||
} else {
|
||||
typeError(ctxtGlobal, "no.such.function", name, ScriptRuntime.safeToString(ctxtGlobal));
|
||||
}
|
||||
return UNDEFINED;
|
||||
}
|
||||
|
||||
value = ScriptObjectMirror.unwrap(value, ctxtGlobal);
|
||||
if (value instanceof ScriptFunction) {
|
||||
return ScriptObjectMirror.unwrap(ScriptRuntime.apply((ScriptFunction)value, ctxtGlobal, args), ctxtGlobal);
|
||||
}
|
||||
|
||||
typeError(ctxtGlobal, "not.a.function", ScriptRuntime.safeToString(name));
|
||||
|
||||
return UNDEFINED;
|
||||
}
|
||||
|
||||
private ScriptObject getNashornGlobalFrom(final ScriptContext ctxt) {
|
||||
final Bindings bindings = ctxt.getBindings(ScriptContext.ENGINE_SCOPE);
|
||||
if (bindings instanceof ScriptObjectMirror) {
|
||||
@ -320,10 +285,10 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
|
||||
}
|
||||
|
||||
private void evalEngineScript() throws ScriptException {
|
||||
evalSupportScript("resources/engine.js");
|
||||
evalSupportScript("resources/engine.js", NashornException.ENGINE_SCRIPT_SOURCE_NAME);
|
||||
}
|
||||
|
||||
private void evalSupportScript(final String script) throws ScriptException {
|
||||
private void evalSupportScript(final String script, final String name) throws ScriptException {
|
||||
try {
|
||||
final InputStream is = AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<InputStream>() {
|
||||
@ -333,7 +298,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
|
||||
return url.openStream();
|
||||
}
|
||||
});
|
||||
put(ScriptEngine.FILENAME, "<engine>:" + script);
|
||||
put(ScriptEngine.FILENAME, name);
|
||||
try (final InputStreamReader isr = new InputStreamReader(is)) {
|
||||
eval(isr);
|
||||
}
|
||||
@ -427,7 +392,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
|
||||
// NOTE: FIXME: If this is jrunscript's init.js, we want to run the replacement.
|
||||
// This should go away once we fix jrunscript's copy of init.js.
|
||||
if ("<system-init>".equals(fileName)) {
|
||||
evalSupportScript("resources/init.js");
|
||||
evalSupportScript("resources/init.js", "nashorn:engine/resources/init.js");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -39,16 +39,6 @@ Object.defineProperty(this, "__noSuchProperty__", {
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(this, "__noSuchMethod__", {
|
||||
configurable: true,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
value: function (name, args) {
|
||||
'use strict';
|
||||
return engine.__noSuchMethod__(this, context, name, args);
|
||||
}
|
||||
});
|
||||
|
||||
function print(str) {
|
||||
var writer = context.getWriter();
|
||||
if (! (writer instanceof java.io.PrintWriter)) {
|
||||
|
@ -32,7 +32,7 @@ import static jdk.nashorn.internal.parser.TokenType.IDENT;
|
||||
* Fast lookup of operators and keywords.
|
||||
*
|
||||
*/
|
||||
public class TokenLookup {
|
||||
public final class TokenLookup {
|
||||
/**
|
||||
* Lookup table for tokens.
|
||||
*/
|
||||
|
@ -275,7 +275,7 @@ public enum TokenType {
|
||||
return name != null && name.length() > 0 && name.charAt(0) == c;
|
||||
}
|
||||
|
||||
public static TokenType[] getValues() {
|
||||
static TokenType[] getValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
|
@ -58,15 +58,9 @@ public final class ECMAException extends NashornException {
|
||||
|
||||
/** We assume that compiler generates script classes into the known package. */
|
||||
private static final String scriptPackage;
|
||||
|
||||
/** Package (internal) name where Nashorn script engine implementation lives */
|
||||
private static final String enginePackageInternal;
|
||||
|
||||
static {
|
||||
String name = JS$.class.getName();
|
||||
scriptPackage = name.substring(0, name.lastIndexOf('.'));
|
||||
name = NashornScriptEngine.class.getName();
|
||||
enginePackageInternal = name.substring(0, name.lastIndexOf('.')).replace(".", "/");
|
||||
}
|
||||
|
||||
/** Object thrown. */
|
||||
@ -168,7 +162,7 @@ public final class ECMAException extends NashornException {
|
||||
* also, we don't want to report JavaScript code that lives in script engine implementation
|
||||
* We want to report only user's own scripts and not any of our own scripts like "engine.js"
|
||||
*/
|
||||
return source != null && !source.endsWith(".java") && !source.contains(enginePackageInternal);
|
||||
return source != null && !source.endsWith(".java") && !source.contains(ENGINE_SCRIPT_SOURCE_NAME);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -268,7 +268,7 @@ public final class PropertyHashMap implements Map <String, Property> {
|
||||
*
|
||||
* @return Array of all properties.
|
||||
*/
|
||||
public Property[] getProperties() {
|
||||
Property[] getProperties() {
|
||||
if (properties == null) {
|
||||
final Property[] array = new Property[size];
|
||||
int i = size;
|
||||
|
@ -1937,11 +1937,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
|
||||
final boolean scopeCall = isScope() && NashornCallSiteDescriptor.isScope(desc);
|
||||
|
||||
if (find == null) {
|
||||
if (scopeCall) {
|
||||
ECMAErrors.referenceError("not.defined", name);
|
||||
throw new AssertionError(); // never reached
|
||||
}
|
||||
return createEmptyGetter(desc, name);
|
||||
return noSuchProperty(desc, request);
|
||||
}
|
||||
|
||||
final ScriptFunction func = (ScriptFunction)getObjectValue(find);
|
||||
@ -3335,10 +3331,10 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
|
||||
}
|
||||
|
||||
/** This is updated only in debug mode - counts number of {@code ScriptObject} instances created */
|
||||
protected static int count;
|
||||
private static int count;
|
||||
|
||||
/** This is updated only in debug mode - counts number of {@code ScriptObject} instances created that are scope */
|
||||
protected static int scopeCount;
|
||||
private static int scopeCount;
|
||||
|
||||
/**
|
||||
* Get number of {@code ScriptObject} instances created. If not running in debug
|
||||
|
@ -27,6 +27,56 @@
|
||||
* often used functionality is supported.
|
||||
*/
|
||||
|
||||
// JavaAdapter
|
||||
Object.defineProperty(this, "JavaAdapter", {
|
||||
configurable: true, enumerable: false, writable: true,
|
||||
value: function() {
|
||||
if (arguments.length < 2) {
|
||||
throw new TypeError("JavaAdapter requires atleast two arguments");
|
||||
}
|
||||
|
||||
var types = Array.prototype.slice.call(arguments, 0, arguments.length - 1);
|
||||
var NewType = Java.extend.apply(Java, types);
|
||||
return new NewType(arguments[arguments.length - 1]);
|
||||
}
|
||||
});
|
||||
|
||||
// importPackage
|
||||
Object.defineProperty(this, "importPackage", {
|
||||
configurable: true, enumerable: false, writable: true,
|
||||
value: (function() {
|
||||
var _packages = [];
|
||||
var global = this;
|
||||
var oldNoSuchProperty = global.__noSuchProperty__;
|
||||
global.__noSuchProperty__ = function(name) {
|
||||
for (var i in _packages) {
|
||||
try {
|
||||
var type = Java.type(_packages[i] + "." + name);
|
||||
global[name] = type;
|
||||
return type;
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
return oldNoSuchProperty? oldNoSuchProperty(name) : undefined;
|
||||
}
|
||||
|
||||
var prefix = "[JavaPackage ";
|
||||
return function() {
|
||||
for (var i in arguments) {
|
||||
var pkgName = arguments[i];
|
||||
if ((typeof pkgName) != 'string') {
|
||||
pkgName = String(pkgName);
|
||||
// extract name from JavaPackage object
|
||||
if (pkgName.startsWith(prefix)) {
|
||||
pkgName = pkgName.substring(prefix.length, pkgName.length - 1);
|
||||
}
|
||||
}
|
||||
_packages.push(pkgName);
|
||||
}
|
||||
}
|
||||
})()
|
||||
});
|
||||
|
||||
// Object.prototype.__defineGetter__
|
||||
Object.defineProperty(Object.prototype, "__defineGetter__", {
|
||||
configurable: true, enumerable: false, writable: true,
|
||||
|
59
nashorn/test/script/basic/importpackage.js
Normal file
59
nashorn/test/script/basic/importpackage.js
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Test to check importPackage function.
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
*/
|
||||
|
||||
try {
|
||||
load("nashorn:mozilla_compat.js");
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
importPackage(java.util);
|
||||
|
||||
var m = new HashMap();
|
||||
if (!(m instanceof java.util.HashMap)) {
|
||||
fail("expected 'm' to be a java.util.HashMap instance");
|
||||
}
|
||||
|
||||
function checkJavaClass(cls) {
|
||||
if (! Java.isType(cls)) {
|
||||
fail(cls + " is not a Java class");
|
||||
}
|
||||
}
|
||||
|
||||
importPackage(java.lang.reflect, javax.script);
|
||||
checkJavaClass(Method);
|
||||
checkJavaClass(Field);
|
||||
checkJavaClass(Constructor);
|
||||
checkJavaClass(ScriptContext);
|
||||
checkJavaClass(ScriptEngine);
|
||||
|
||||
var bindings = new SimpleBindings();
|
||||
if (!(bindings instanceof javax.script.SimpleBindings)) {
|
||||
fail("expected 'bindings' to be a javax.script.SimpleBindings instance");
|
||||
}
|
119
nashorn/test/script/basic/javaadapter.js
Normal file
119
nashorn/test/script/basic/javaadapter.js
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Test to check JavaAdapter constructor.
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
*/
|
||||
|
||||
try {
|
||||
load("nashorn:mozilla_compat.js");
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
// try various JavaAdapter cases
|
||||
|
||||
// Single interface
|
||||
var runReached = false;
|
||||
var r = new JavaAdapter(java.lang.Runnable) {
|
||||
run: function() {
|
||||
runReached = true;
|
||||
}
|
||||
};
|
||||
|
||||
r.run();
|
||||
if (! runReached) {
|
||||
fail("run was not called");
|
||||
}
|
||||
|
||||
if (! (r instanceof java.lang.Runnable)) {
|
||||
fail("r is not a Runnable");
|
||||
}
|
||||
|
||||
// Multiple intefaces
|
||||
var runReached = false;
|
||||
var actionPerformedReached = false;
|
||||
|
||||
var obj = new JavaAdapter(java.awt.event.ActionListener, java.lang.Runnable) {
|
||||
actionPerformed : function(e) {
|
||||
actionPerformedReached = true;
|
||||
},
|
||||
|
||||
run: function() {
|
||||
runReached = true;
|
||||
}
|
||||
};
|
||||
|
||||
obj.actionPerformed(null);
|
||||
if (! actionPerformedReached) {
|
||||
fail("actionPerformed was not called");
|
||||
}
|
||||
|
||||
obj.run();
|
||||
if (! runReached) {
|
||||
fail("run was not called");
|
||||
}
|
||||
|
||||
if (! (obj instanceof java.lang.Runnable)) {
|
||||
fail("obj is not a Runnable");
|
||||
}
|
||||
|
||||
if (! (obj instanceof java.awt.event.ActionListener)) {
|
||||
fail("obj is not an ActionListener");
|
||||
}
|
||||
|
||||
// Single class
|
||||
var obj = new JavaAdapter(java.lang.Object) {
|
||||
toString: function() { return "I am an Object"; }
|
||||
};
|
||||
|
||||
if (! (obj instanceof java.lang.Object)) {
|
||||
fail("obj is not an instance of java.lang.Object");
|
||||
}
|
||||
|
||||
if (obj.toString() != "I am an Object") {
|
||||
fail("Object.toString did not get called");
|
||||
}
|
||||
|
||||
// Single class and single interface
|
||||
var runReached = false;
|
||||
var obj = new JavaAdapter(java.lang.Object, java.lang.Runnable) {
|
||||
run: function() {
|
||||
runReached = true;
|
||||
},
|
||||
|
||||
hashCode: function() {
|
||||
return 12;
|
||||
}
|
||||
};
|
||||
|
||||
obj.run();
|
||||
if (! runReached) {
|
||||
fail("run was not called");
|
||||
}
|
||||
|
||||
if (obj.hashCode() != 12) {
|
||||
fail("hashCode does not return 12");
|
||||
}
|
Loading…
Reference in New Issue
Block a user