8007286: Add JavaAdapter and importPackage to compatibility script

Reviewed-by: lagergren, jlaskey
This commit is contained in:
Athijegannathan Sundararajan 2013-01-31 20:07:40 +05:30
parent fcd28bdcc5
commit bdcffc23f7
11 changed files with 242 additions and 66 deletions

View File

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

View File

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

View File

@ -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)) {

View File

@ -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.
*/

View File

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

View File

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

View File

@ -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;

View File

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

View File

@ -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,

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

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