8007286: Add JavaAdapter and importPackage to compatibility script
Reviewed-by: lagergren, jlaskey
--- a/nashorn/src/jdk/nashorn/api/scripting/NashornException.java Wed Jan 30 21:15:14 2013 +0530
+++ b/nashorn/src/jdk/nashorn/api/scripting/NashornException.java Thu Jan 31 20:07:40 2013 +0530
@@ -44,6 +44,9 @@
// 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
*
--- a/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Wed Jan 30 21:15:14 2013 +0530
+++ b/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Thu Jan 31 20:07:40 2013 +0530
@@ -242,41 +242,6 @@
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 @@
}
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 @@
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 @@
// 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;
}
--- a/nashorn/src/jdk/nashorn/api/scripting/resources/engine.js Wed Jan 30 21:15:14 2013 +0530
+++ b/nashorn/src/jdk/nashorn/api/scripting/resources/engine.js Thu Jan 31 20:07:40 2013 +0530
@@ -39,16 +39,6 @@
}
});
-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)) {
--- a/nashorn/src/jdk/nashorn/internal/parser/TokenLookup.java Wed Jan 30 21:15:14 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/parser/TokenLookup.java Thu Jan 31 20:07:40 2013 +0530
@@ -32,7 +32,7 @@
* Fast lookup of operators and keywords.
*
*/
-public class TokenLookup {
+public final class TokenLookup {
/**
* Lookup table for tokens.
*/
--- a/nashorn/src/jdk/nashorn/internal/parser/TokenType.java Wed Jan 30 21:15:14 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/parser/TokenType.java Thu Jan 31 20:07:40 2013 +0530
@@ -275,7 +275,7 @@
return name != null && name.length() > 0 && name.charAt(0) == c;
}
- public static TokenType[] getValues() {
+ static TokenType[] getValues() {
return values;
}
--- a/nashorn/src/jdk/nashorn/internal/runtime/ECMAException.java Wed Jan 30 21:15:14 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ECMAException.java Thu Jan 31 20:07:40 2013 +0530
@@ -58,15 +58,9 @@
/** 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 @@
* 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;
}
--- a/nashorn/src/jdk/nashorn/internal/runtime/PropertyHashMap.java Wed Jan 30 21:15:14 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/PropertyHashMap.java Thu Jan 31 20:07:40 2013 +0530
@@ -268,7 +268,7 @@
*
* @return Array of all properties.
*/
- public Property[] getProperties() {
+ Property[] getProperties() {
if (properties == null) {
final Property[] array = new Property[size];
int i = size;
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java Wed Jan 30 21:15:14 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java Thu Jan 31 20:07:40 2013 +0530
@@ -1937,11 +1937,7 @@
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 @@
}
/** 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
--- a/nashorn/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js Wed Jan 30 21:15:14 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js Thu Jan 31 20:07:40 2013 +0530
@@ -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,
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/importpackage.js Thu Jan 31 20:07:40 2013 +0530
@@ -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");
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/javaadapter.js Thu Jan 31 20:07:40 2013 +0530
@@ -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");
+}