Thu, 31 Jan 2013 20:07:40 +0530
8007286: Add JavaAdapter and importPackage to compatibility script
Reviewed-by: lagergren, jlaskey
1.1 --- a/src/jdk/nashorn/api/scripting/NashornException.java Wed Jan 30 21:15:14 2013 +0530 1.2 +++ b/src/jdk/nashorn/api/scripting/NashornException.java Thu Jan 31 20:07:40 2013 +0530 1.3 @@ -44,6 +44,9 @@ 1.4 // script column number 1.5 private int column; 1.6 1.7 + // script source name used for "engine.js" 1.8 + protected static final String ENGINE_SCRIPT_SOURCE_NAME = "nashorn:engine/resources/engine.js"; 1.9 + 1.10 /** 1.11 * Constructor 1.12 *
2.1 --- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Wed Jan 30 21:15:14 2013 +0530 2.2 +++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Thu Jan 31 20:07:40 2013 +0530 2.3 @@ -242,41 +242,6 @@ 2.4 return UNDEFINED; 2.5 } 2.6 2.7 - /** 2.8 - * This hook is used to call js global functions exposed from Java code. 2.9 - * 2.10 - * @param self 'this' passed from the script 2.11 - * @param ctxt current ScriptContext in which method is searched 2.12 - * @param name name of the method 2.13 - * @param args arguments to be passed to the method 2.14 - * @return return value of the called method 2.15 - */ 2.16 - public Object __noSuchMethod__(final Object self, final ScriptContext ctxt, final String name, final Object args) { 2.17 - final int scope = ctxt.getAttributesScope(name); 2.18 - final ScriptObject ctxtGlobal = getNashornGlobalFrom(ctxt); 2.19 - Object value; 2.20 - 2.21 - if (scope != -1) { 2.22 - value = ctxt.getAttribute(name, scope); 2.23 - } else { 2.24 - if (self == UNDEFINED) { 2.25 - referenceError(ctxtGlobal, "not.defined", name); 2.26 - } else { 2.27 - typeError(ctxtGlobal, "no.such.function", name, ScriptRuntime.safeToString(ctxtGlobal)); 2.28 - } 2.29 - return UNDEFINED; 2.30 - } 2.31 - 2.32 - value = ScriptObjectMirror.unwrap(value, ctxtGlobal); 2.33 - if (value instanceof ScriptFunction) { 2.34 - return ScriptObjectMirror.unwrap(ScriptRuntime.apply((ScriptFunction)value, ctxtGlobal, args), ctxtGlobal); 2.35 - } 2.36 - 2.37 - typeError(ctxtGlobal, "not.a.function", ScriptRuntime.safeToString(name)); 2.38 - 2.39 - return UNDEFINED; 2.40 - } 2.41 - 2.42 private ScriptObject getNashornGlobalFrom(final ScriptContext ctxt) { 2.43 final Bindings bindings = ctxt.getBindings(ScriptContext.ENGINE_SCOPE); 2.44 if (bindings instanceof ScriptObjectMirror) { 2.45 @@ -320,10 +285,10 @@ 2.46 } 2.47 2.48 private void evalEngineScript() throws ScriptException { 2.49 - evalSupportScript("resources/engine.js"); 2.50 + evalSupportScript("resources/engine.js", NashornException.ENGINE_SCRIPT_SOURCE_NAME); 2.51 } 2.52 2.53 - private void evalSupportScript(final String script) throws ScriptException { 2.54 + private void evalSupportScript(final String script, final String name) throws ScriptException { 2.55 try { 2.56 final InputStream is = AccessController.doPrivileged( 2.57 new PrivilegedExceptionAction<InputStream>() { 2.58 @@ -333,7 +298,7 @@ 2.59 return url.openStream(); 2.60 } 2.61 }); 2.62 - put(ScriptEngine.FILENAME, "<engine>:" + script); 2.63 + put(ScriptEngine.FILENAME, name); 2.64 try (final InputStreamReader isr = new InputStreamReader(is)) { 2.65 eval(isr); 2.66 } 2.67 @@ -427,7 +392,7 @@ 2.68 // NOTE: FIXME: If this is jrunscript's init.js, we want to run the replacement. 2.69 // This should go away once we fix jrunscript's copy of init.js. 2.70 if ("<system-init>".equals(fileName)) { 2.71 - evalSupportScript("resources/init.js"); 2.72 + evalSupportScript("resources/init.js", "nashorn:engine/resources/init.js"); 2.73 return null; 2.74 } 2.75
3.1 --- a/src/jdk/nashorn/api/scripting/resources/engine.js Wed Jan 30 21:15:14 2013 +0530 3.2 +++ b/src/jdk/nashorn/api/scripting/resources/engine.js Thu Jan 31 20:07:40 2013 +0530 3.3 @@ -39,16 +39,6 @@ 3.4 } 3.5 }); 3.6 3.7 -Object.defineProperty(this, "__noSuchMethod__", { 3.8 - configurable: true, 3.9 - enumerable: false, 3.10 - writable: true, 3.11 - value: function (name, args) { 3.12 - 'use strict'; 3.13 - return engine.__noSuchMethod__(this, context, name, args); 3.14 - } 3.15 -}); 3.16 - 3.17 function print(str) { 3.18 var writer = context.getWriter(); 3.19 if (! (writer instanceof java.io.PrintWriter)) {
4.1 --- a/src/jdk/nashorn/internal/parser/TokenLookup.java Wed Jan 30 21:15:14 2013 +0530 4.2 +++ b/src/jdk/nashorn/internal/parser/TokenLookup.java Thu Jan 31 20:07:40 2013 +0530 4.3 @@ -32,7 +32,7 @@ 4.4 * Fast lookup of operators and keywords. 4.5 * 4.6 */ 4.7 -public class TokenLookup { 4.8 +public final class TokenLookup { 4.9 /** 4.10 * Lookup table for tokens. 4.11 */
5.1 --- a/src/jdk/nashorn/internal/parser/TokenType.java Wed Jan 30 21:15:14 2013 +0530 5.2 +++ b/src/jdk/nashorn/internal/parser/TokenType.java Thu Jan 31 20:07:40 2013 +0530 5.3 @@ -275,7 +275,7 @@ 5.4 return name != null && name.length() > 0 && name.charAt(0) == c; 5.5 } 5.6 5.7 - public static TokenType[] getValues() { 5.8 + static TokenType[] getValues() { 5.9 return values; 5.10 } 5.11
6.1 --- a/src/jdk/nashorn/internal/runtime/ECMAException.java Wed Jan 30 21:15:14 2013 +0530 6.2 +++ b/src/jdk/nashorn/internal/runtime/ECMAException.java Thu Jan 31 20:07:40 2013 +0530 6.3 @@ -58,15 +58,9 @@ 6.4 6.5 /** We assume that compiler generates script classes into the known package. */ 6.6 private static final String scriptPackage; 6.7 - 6.8 - /** Package (internal) name where Nashorn script engine implementation lives */ 6.9 - private static final String enginePackageInternal; 6.10 - 6.11 static { 6.12 String name = JS$.class.getName(); 6.13 scriptPackage = name.substring(0, name.lastIndexOf('.')); 6.14 - name = NashornScriptEngine.class.getName(); 6.15 - enginePackageInternal = name.substring(0, name.lastIndexOf('.')).replace(".", "/"); 6.16 } 6.17 6.18 /** Object thrown. */ 6.19 @@ -168,7 +162,7 @@ 6.20 * also, we don't want to report JavaScript code that lives in script engine implementation 6.21 * We want to report only user's own scripts and not any of our own scripts like "engine.js" 6.22 */ 6.23 - return source != null && !source.endsWith(".java") && !source.contains(enginePackageInternal); 6.24 + return source != null && !source.endsWith(".java") && !source.contains(ENGINE_SCRIPT_SOURCE_NAME); 6.25 } 6.26 return false; 6.27 }
7.1 --- a/src/jdk/nashorn/internal/runtime/PropertyHashMap.java Wed Jan 30 21:15:14 2013 +0530 7.2 +++ b/src/jdk/nashorn/internal/runtime/PropertyHashMap.java Thu Jan 31 20:07:40 2013 +0530 7.3 @@ -268,7 +268,7 @@ 7.4 * 7.5 * @return Array of all properties. 7.6 */ 7.7 - public Property[] getProperties() { 7.8 + Property[] getProperties() { 7.9 if (properties == null) { 7.10 final Property[] array = new Property[size]; 7.11 int i = size;
8.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Wed Jan 30 21:15:14 2013 +0530 8.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java Thu Jan 31 20:07:40 2013 +0530 8.3 @@ -1937,11 +1937,7 @@ 8.4 final boolean scopeCall = isScope() && NashornCallSiteDescriptor.isScope(desc); 8.5 8.6 if (find == null) { 8.7 - if (scopeCall) { 8.8 - ECMAErrors.referenceError("not.defined", name); 8.9 - throw new AssertionError(); // never reached 8.10 - } 8.11 - return createEmptyGetter(desc, name); 8.12 + return noSuchProperty(desc, request); 8.13 } 8.14 8.15 final ScriptFunction func = (ScriptFunction)getObjectValue(find); 8.16 @@ -3335,10 +3331,10 @@ 8.17 } 8.18 8.19 /** This is updated only in debug mode - counts number of {@code ScriptObject} instances created */ 8.20 - protected static int count; 8.21 + private static int count; 8.22 8.23 /** This is updated only in debug mode - counts number of {@code ScriptObject} instances created that are scope */ 8.24 - protected static int scopeCount; 8.25 + private static int scopeCount; 8.26 8.27 /** 8.28 * Get number of {@code ScriptObject} instances created. If not running in debug
9.1 --- a/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js Wed Jan 30 21:15:14 2013 +0530 9.2 +++ b/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js Thu Jan 31 20:07:40 2013 +0530 9.3 @@ -27,6 +27,56 @@ 9.4 * often used functionality is supported. 9.5 */ 9.6 9.7 +// JavaAdapter 9.8 +Object.defineProperty(this, "JavaAdapter", { 9.9 + configurable: true, enumerable: false, writable: true, 9.10 + value: function() { 9.11 + if (arguments.length < 2) { 9.12 + throw new TypeError("JavaAdapter requires atleast two arguments"); 9.13 + } 9.14 + 9.15 + var types = Array.prototype.slice.call(arguments, 0, arguments.length - 1); 9.16 + var NewType = Java.extend.apply(Java, types); 9.17 + return new NewType(arguments[arguments.length - 1]); 9.18 + } 9.19 +}); 9.20 + 9.21 +// importPackage 9.22 +Object.defineProperty(this, "importPackage", { 9.23 + configurable: true, enumerable: false, writable: true, 9.24 + value: (function() { 9.25 + var _packages = []; 9.26 + var global = this; 9.27 + var oldNoSuchProperty = global.__noSuchProperty__; 9.28 + global.__noSuchProperty__ = function(name) { 9.29 + for (var i in _packages) { 9.30 + try { 9.31 + var type = Java.type(_packages[i] + "." + name); 9.32 + global[name] = type; 9.33 + return type; 9.34 + } catch (e) {} 9.35 + } 9.36 + 9.37 + return oldNoSuchProperty? oldNoSuchProperty(name) : undefined; 9.38 + } 9.39 + 9.40 + var prefix = "[JavaPackage "; 9.41 + return function() { 9.42 + for (var i in arguments) { 9.43 + var pkgName = arguments[i]; 9.44 + if ((typeof pkgName) != 'string') { 9.45 + pkgName = String(pkgName); 9.46 + // extract name from JavaPackage object 9.47 + if (pkgName.startsWith(prefix)) { 9.48 + pkgName = pkgName.substring(prefix.length, pkgName.length - 1); 9.49 + } 9.50 + } 9.51 + _packages.push(pkgName); 9.52 + } 9.53 + } 9.54 + })() 9.55 +}); 9.56 + 9.57 // Object.prototype.__defineGetter__ 9.58 Object.defineProperty(Object.prototype, "__defineGetter__", { 9.59 configurable: true, enumerable: false, writable: true,
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/test/script/basic/importpackage.js Thu Jan 31 20:07:40 2013 +0530 10.3 @@ -0,0 +1,59 @@ 10.4 +/* 10.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 10.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 10.7 + * 10.8 + * This code is free software; you can redistribute it and/or modify it 10.9 + * under the terms of the GNU General Public License version 2 only, as 10.10 + * published by the Free Software Foundation. 10.11 + * 10.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 10.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 10.15 + * version 2 for more details (a copy is included in the LICENSE file that 10.16 + * accompanied this code). 10.17 + * 10.18 + * You should have received a copy of the GNU General Public License version 10.19 + * 2 along with this work; if not, write to the Free Software Foundation, 10.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 10.21 + * 10.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 10.23 + * or visit www.oracle.com if you need additional information or have any 10.24 + * questions. 10.25 + */ 10.26 + 10.27 +/** 10.28 + * Test to check importPackage function. 10.29 + * 10.30 + * @test 10.31 + * @run 10.32 + */ 10.33 + 10.34 +try { 10.35 + load("nashorn:mozilla_compat.js"); 10.36 +} catch (e) { 10.37 +} 10.38 + 10.39 +importPackage(java.util); 10.40 + 10.41 +var m = new HashMap(); 10.42 +if (!(m instanceof java.util.HashMap)) { 10.43 + fail("expected 'm' to be a java.util.HashMap instance"); 10.44 +} 10.45 + 10.46 +function checkJavaClass(cls) { 10.47 + if (! Java.isType(cls)) { 10.48 + fail(cls + " is not a Java class"); 10.49 + } 10.50 +} 10.51 + 10.52 +importPackage(java.lang.reflect, javax.script); 10.53 +checkJavaClass(Method); 10.54 +checkJavaClass(Field); 10.55 +checkJavaClass(Constructor); 10.56 +checkJavaClass(ScriptContext); 10.57 +checkJavaClass(ScriptEngine); 10.58 + 10.59 +var bindings = new SimpleBindings(); 10.60 +if (!(bindings instanceof javax.script.SimpleBindings)) { 10.61 + fail("expected 'bindings' to be a javax.script.SimpleBindings instance"); 10.62 +}
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/test/script/basic/javaadapter.js Thu Jan 31 20:07:40 2013 +0530 11.3 @@ -0,0 +1,119 @@ 11.4 +/* 11.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 11.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 11.7 + * 11.8 + * This code is free software; you can redistribute it and/or modify it 11.9 + * under the terms of the GNU General Public License version 2 only, as 11.10 + * published by the Free Software Foundation. 11.11 + * 11.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 11.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11.15 + * version 2 for more details (a copy is included in the LICENSE file that 11.16 + * accompanied this code). 11.17 + * 11.18 + * You should have received a copy of the GNU General Public License version 11.19 + * 2 along with this work; if not, write to the Free Software Foundation, 11.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 11.21 + * 11.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 11.23 + * or visit www.oracle.com if you need additional information or have any 11.24 + * questions. 11.25 + */ 11.26 + 11.27 +/** 11.28 + * Test to check JavaAdapter constructor. 11.29 + * 11.30 + * @test 11.31 + * @run 11.32 + */ 11.33 + 11.34 +try { 11.35 + load("nashorn:mozilla_compat.js"); 11.36 +} catch (e) { 11.37 +} 11.38 + 11.39 +// try various JavaAdapter cases 11.40 + 11.41 +// Single interface 11.42 +var runReached = false; 11.43 +var r = new JavaAdapter(java.lang.Runnable) { 11.44 + run: function() { 11.45 + runReached = true; 11.46 + } 11.47 +}; 11.48 + 11.49 +r.run(); 11.50 +if (! runReached) { 11.51 + fail("run was not called"); 11.52 +} 11.53 + 11.54 +if (! (r instanceof java.lang.Runnable)) { 11.55 + fail("r is not a Runnable"); 11.56 +} 11.57 + 11.58 +// Multiple intefaces 11.59 +var runReached = false; 11.60 +var actionPerformedReached = false; 11.61 + 11.62 +var obj = new JavaAdapter(java.awt.event.ActionListener, java.lang.Runnable) { 11.63 + actionPerformed : function(e) { 11.64 + actionPerformedReached = true; 11.65 + }, 11.66 + 11.67 + run: function() { 11.68 + runReached = true; 11.69 + } 11.70 +}; 11.71 + 11.72 +obj.actionPerformed(null); 11.73 +if (! actionPerformedReached) { 11.74 + fail("actionPerformed was not called"); 11.75 +} 11.76 + 11.77 +obj.run(); 11.78 +if (! runReached) { 11.79 + fail("run was not called"); 11.80 +} 11.81 + 11.82 +if (! (obj instanceof java.lang.Runnable)) { 11.83 + fail("obj is not a Runnable"); 11.84 +} 11.85 + 11.86 +if (! (obj instanceof java.awt.event.ActionListener)) { 11.87 + fail("obj is not an ActionListener"); 11.88 +} 11.89 + 11.90 +// Single class 11.91 +var obj = new JavaAdapter(java.lang.Object) { 11.92 + toString: function() { return "I am an Object"; } 11.93 +}; 11.94 + 11.95 +if (! (obj instanceof java.lang.Object)) { 11.96 + fail("obj is not an instance of java.lang.Object"); 11.97 +} 11.98 + 11.99 +if (obj.toString() != "I am an Object") { 11.100 + fail("Object.toString did not get called"); 11.101 +} 11.102 + 11.103 +// Single class and single interface 11.104 +var runReached = false; 11.105 +var obj = new JavaAdapter(java.lang.Object, java.lang.Runnable) { 11.106 + run: function() { 11.107 + runReached = true; 11.108 + }, 11.109 + 11.110 + hashCode: function() { 11.111 + return 12; 11.112 + } 11.113 +}; 11.114 + 11.115 +obj.run(); 11.116 +if (! runReached) { 11.117 + fail("run was not called"); 11.118 +} 11.119 + 11.120 +if (obj.hashCode() != 12) { 11.121 + fail("hashCode does not return 12"); 11.122 +}