8007286: Add JavaAdapter and importPackage to compatibility script
authorsundar
Thu, 31 Jan 2013 20:07:40 +0530
changeset 16205 93fda2507e35
parent 16204 c53eef0eb729
child 16206 83069fa0935b
8007286: Add JavaAdapter and importPackage to compatibility script Reviewed-by: lagergren, jlaskey
nashorn/src/jdk/nashorn/api/scripting/NashornException.java
nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java
nashorn/src/jdk/nashorn/api/scripting/resources/engine.js
nashorn/src/jdk/nashorn/internal/parser/TokenLookup.java
nashorn/src/jdk/nashorn/internal/parser/TokenType.java
nashorn/src/jdk/nashorn/internal/runtime/ECMAException.java
nashorn/src/jdk/nashorn/internal/runtime/PropertyHashMap.java
nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java
nashorn/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js
nashorn/test/script/basic/importpackage.js
nashorn/test/script/basic/javaadapter.js
--- 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");
+}