# HG changeset patch # User sundar # Date 1359643060 -19800 # Node ID 93fda2507e351301e49ec5e022c99ee059bf4508 # Parent c53eef0eb729f113e6c8c5b51b63fb929d7f2a7c 8007286: Add JavaAdapter and importPackage to compatibility script Reviewed-by: lagergren, jlaskey diff -r c53eef0eb729 -r 93fda2507e35 nashorn/src/jdk/nashorn/api/scripting/NashornException.java --- 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 * diff -r c53eef0eb729 -r 93fda2507e35 nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java --- 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() { @@ -333,7 +298,7 @@ return url.openStream(); } }); - put(ScriptEngine.FILENAME, ":" + 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 ("".equals(fileName)) { - evalSupportScript("resources/init.js"); + evalSupportScript("resources/init.js", "nashorn:engine/resources/init.js"); return null; } diff -r c53eef0eb729 -r 93fda2507e35 nashorn/src/jdk/nashorn/api/scripting/resources/engine.js --- 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)) { diff -r c53eef0eb729 -r 93fda2507e35 nashorn/src/jdk/nashorn/internal/parser/TokenLookup.java --- 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. */ diff -r c53eef0eb729 -r 93fda2507e35 nashorn/src/jdk/nashorn/internal/parser/TokenType.java --- 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; } diff -r c53eef0eb729 -r 93fda2507e35 nashorn/src/jdk/nashorn/internal/runtime/ECMAException.java --- 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; } diff -r c53eef0eb729 -r 93fda2507e35 nashorn/src/jdk/nashorn/internal/runtime/PropertyHashMap.java --- 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; diff -r c53eef0eb729 -r 93fda2507e35 nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java --- 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 diff -r c53eef0eb729 -r 93fda2507e35 nashorn/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js --- 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, diff -r c53eef0eb729 -r 93fda2507e35 nashorn/test/script/basic/importpackage.js --- /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"); +} diff -r c53eef0eb729 -r 93fda2507e35 nashorn/test/script/basic/javaadapter.js --- /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"); +}