Mercurial > hg > icedtea8-forest > nashorn
changeset 1982:b082c0d76be4 icedtea-3.3.0pre01
Merge jdk8u112-b16
author | andrew |
---|---|
date | Thu, 12 Jan 2017 06:59:38 +0000 |
parents | 40834ff46bfc (current diff) d1f2cab06d35 (diff) |
children | 08947f14df4e |
files | .hgtags |
diffstat | 46 files changed, 1510 insertions(+), 140 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Tue Nov 08 05:26:18 2016 +0000 +++ b/.hgtags Thu Jan 12 06:59:38 2017 +0000 @@ -646,3 +646,19 @@ 76bf7299d622029f1a579667611deeccc405e81a jdk8u111-b12 7ed1a5c5e45a1d576cc76dc96b3f0699bfe0a642 jdk8u111-b13 0fb33c8b64d1d97095c668b81ad7a11e4c06e89f icedtea-3.2.0 +97770cfdb942dce0a7c461175bce4fddac5ad339 jdk8u111-b14 +1bf96637e4bbbc31f7c560c16d62ce2ed9020e03 jdk8u112-b00 +be4ef6af7d3d67380d9df3348f75324ff6d8c971 jdk8u112-b01 +29f97057e4e10194263902a6406f65d789944c5e jdk8u112-b02 +16bc4cb8f50b251aa648c6aae5ca063c0893b44b jdk8u112-b03 +bc02dfd3deccefbcfcb71969ff56ae58ef80c686 jdk8u112-b04 +2432a2e9de108e12c3be6e52f37d7702a9a87d49 jdk8u112-b06 +d591fb5e1d37d1186290521cd31d5795d74cfa5b jdk8u112-b07 +910a02770fc92745517e63018345be36dc8d7d0c jdk8u112-b08 +51e59a0544a0be24ed72b43fc9483ffded8cdad2 jdk8u112-b09 +319eba518b6ec84fe3ff4811e66319cdb7e6f33e jdk8u112-b10 +081aa69ac6faaa8ebb9a21d9a0c617d34e03b447 jdk8u112-b11 +21b35ff81519584f5af010e852c14b6db88c1ebd jdk8u112-b12 +001041e75430b132f0e0ba96b98f3891435c4440 jdk8u112-b13 +b0aa9a71f5fbcb0d58fa009fd9bd3ea0897b315e jdk8u112-b14 +adc75eca17418a42357776339b390533a94541d6 jdk8u112-b15
--- a/LICENSE Tue Nov 08 05:26:18 2016 +0000 +++ b/LICENSE Thu Jan 12 06:59:38 2017 +0000 @@ -3,7 +3,7 @@ Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. -59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -287,8 +287,8 @@ more details. You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place, Suite 330, Boston, MA 02111-1307 USA + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail.
--- a/make/build.xml Tue Nov 08 05:26:18 2016 +0000 +++ b/make/build.xml Thu Jan 12 06:59:38 2017 +0000 @@ -83,6 +83,12 @@ <condition property="jfr.options" value="${run.test.jvmargs.jfr}" else=""> <istrue value="${jfr}"/> </condition> + + <condition property="test-sys-prop-no-security.os.not.windows"> + <not> + <os family="windows"/> + </not> + </condition> </target> <!-- check minimum ant version required to be 1.8.4 --> @@ -419,6 +425,10 @@ permission java.io.FilePermission "${basedir}/test/script/external/showdown/-", "read"; }; +grant codeBase "file:/${basedir}/test/script/basic/JDK-8158467.js" { + permission java.lang.RuntimePermission "nashorn.setConfig"; +}; + </echo> <replace file="${build.dir}/nashorn.policy"><replacetoken>\</replacetoken><replacevalue>/</replacevalue></replace> <!--hack for Windows - to make URLs with normal path separators -->
--- a/samples/exec.js Tue Nov 08 05:26:18 2016 +0000 +++ b/samples/exec.js Thu Jan 12 06:59:38 2017 +0000 @@ -39,9 +39,10 @@ $EXEC("cat", "Hello, world!") // Additional arguments can be passed after the stdin argument, as an array of -// strings, or a sequence of varargs: -$EXEC("ls", "" /* no stdin */, "-l", "-a") -$EXEC("ls", "" /* no stdin */, ["-l", "-a"]) +// strings, or a sequence of varargs (if there is no stdin, null or undefined +// can be passed): +$EXEC("ls", undefined, "-l", "-a") +$EXEC("ls", undefined, ["-l", "-a"]) // Output of running external commands is returned from $EXEC: print($EXEC("ls"))
--- a/src/jdk/nashorn/api/scripting/NashornException.java Tue Nov 08 05:26:18 2016 +0000 +++ b/src/jdk/nashorn/api/scripting/NashornException.java Thu Jan 12 06:59:38 2017 +0000 @@ -175,10 +175,8 @@ String methodName = st.getMethodName(); if (methodName.equals(CompilerConstants.PROGRAM.symbolName())) { methodName = "<program>"; - } - - if (methodName.contains(CompilerConstants.ANON_FUNCTION_PREFIX.symbolName())) { - methodName = "<anonymous>"; + } else { + methodName = stripMethodName(methodName); } filtered.add(new StackTraceElement(className, methodName, @@ -188,6 +186,22 @@ return filtered.toArray(new StackTraceElement[filtered.size()]); } + private static String stripMethodName(final String methodName) { + String name = methodName; + + final int nestedSeparator = name.lastIndexOf(CompilerConstants.NESTED_FUNCTION_SEPARATOR.symbolName()); + if (nestedSeparator >= 0) { + name = name.substring(nestedSeparator + 1); + } + + final int idSeparator = name.indexOf(CompilerConstants.ID_FUNCTION_SEPARATOR.symbolName()); + if (idSeparator >= 0) { + name = name.substring(0, idSeparator); + } + + return name.contains(CompilerConstants.ANON_FUNCTION_PREFIX.symbolName()) ? "<anonymous>" : name; + } + /** * Return a formatted script stack trace string with frames information separated by '\n' *
--- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Tue Nov 08 05:26:18 2016 +0000 +++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Thu Jan 12 06:59:38 2017 +0000 @@ -319,6 +319,9 @@ // Create new global instance mirror and associate with the Bindings. final ScriptObjectMirror mirror = createGlobalMirror(); bindings.put(NASHORN_GLOBAL, mirror); + // Since we created this global explicitly for the non-default script context we set the + // current script context in global permanently so that invokes work as expected. See JDK-8150219 + mirror.getHomeGlobal().setInitScriptContext(ctxt); return mirror.getHomeGlobal(); }
--- a/src/jdk/nashorn/internal/codegen/CompilerConstants.java Tue Nov 08 05:26:18 2016 +0000 +++ b/src/jdk/nashorn/internal/codegen/CompilerConstants.java Thu Jan 12 06:59:38 2017 +0000 @@ -78,6 +78,12 @@ /** function prefix for anonymous functions */ ANON_FUNCTION_PREFIX("L:"), + /** separator for method names of nested functions */ + NESTED_FUNCTION_SEPARATOR("#"), + + /** separator for making method names unique by appending numeric ids */ + ID_FUNCTION_SEPARATOR("-"), + /** method name for Java method that is the program entry point */ PROGRAM(":program"),
--- a/src/jdk/nashorn/internal/codegen/Namespace.java Tue Nov 08 05:26:18 2016 +0000 +++ b/src/jdk/nashorn/internal/codegen/Namespace.java Thu Jan 12 06:59:38 2017 +0000 @@ -68,7 +68,7 @@ } /** - * Create a uniqueName name in the namespace in the form base$n where n varies. + * Create a uniqueName name in the namespace in the form base-n where n varies. * Also truncates very long names that would otherwise break ASM. * * @param base Base of name. Base will be returned if uniqueName. @@ -83,7 +83,7 @@ if (counter != null) { final int count = counter + 1; namespaceDirectory.put(truncatedBase, count); - return truncatedBase + '-' + count; + return truncatedBase + CompilerConstants.ID_FUNCTION_SEPARATOR.symbolName() + count; } }
--- a/src/jdk/nashorn/internal/objects/Global.java Tue Nov 08 05:26:18 2016 +0000 +++ b/src/jdk/nashorn/internal/objects/Global.java Thu Jan 12 06:59:38 2017 +0000 @@ -928,6 +928,8 @@ private ThreadLocal<ScriptContext> scontext; // current ScriptEngine associated - can be null. private ScriptEngine engine; + // initial ScriptContext - usually null and only used for special case + private volatile ScriptContext initscontext; // ES6 global lexical scope. private final LexicalScope lexicalScope; @@ -953,9 +955,22 @@ return scontext.get(); } + /** + * Set the initial script context + * @param ctxt initial script context + */ + public void setInitScriptContext(final ScriptContext ctxt) { + this.initscontext = ctxt; + } + private ScriptContext currentContext() { final ScriptContext sc = scontext != null? scontext.get() : null; - return (sc != null)? sc : (engine != null? engine.getContext() : null); + if (sc != null) { + return sc; + } else if (initscontext != null) { + return initscontext; + } + return engine != null? engine.getContext() : null; } @Override
--- a/src/jdk/nashorn/internal/objects/NativeArray.java Tue Nov 08 05:26:18 2016 +0000 +++ b/src/jdk/nashorn/internal/objects/NativeArray.java Thu Jan 12 06:59:38 2017 +0000 @@ -247,7 +247,7 @@ @Override public MethodHandle call() { return Bootstrap.createDynamicInvoker("dyn:call", double.class, - ScriptFunction.class, Object.class, Object.class, Object.class); + Object.class, Object.class, Object.class, Object.class); } }); } @@ -1219,23 +1219,23 @@ return copy; } - private static ScriptFunction compareFunction(final Object comparefn) { + private static Object compareFunction(final Object comparefn) { if (comparefn == ScriptRuntime.UNDEFINED) { return null; } - if (! (comparefn instanceof ScriptFunction)) { + if (!Bootstrap.isCallable(comparefn)) { throw typeError("not.a.function", ScriptRuntime.safeToString(comparefn)); } - return (ScriptFunction)comparefn; + return comparefn; } private static Object[] sort(final Object[] array, final Object comparefn) { - final ScriptFunction cmp = compareFunction(comparefn); + final Object cmp = compareFunction(comparefn); final List<Object> list = Arrays.asList(array); - final Object cmpThis = cmp == null || cmp.isStrict() ? ScriptRuntime.UNDEFINED : Global.instance(); + final Object cmpThis = cmp == null || Bootstrap.isStrictCallable(cmp) ? ScriptRuntime.UNDEFINED : Global.instance(); try { Collections.sort(list, new Comparator<Object>() {
--- a/src/jdk/nashorn/internal/objects/NativeJSON.java Tue Nov 08 05:26:18 2016 +0000 +++ b/src/jdk/nashorn/internal/objects/NativeJSON.java Thu Jan 12 06:59:38 2017 +0000 @@ -35,7 +35,10 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.concurrent.Callable; +import jdk.nashorn.api.scripting.JSObject; +import jdk.nashorn.api.scripting.ScriptObjectMirror; import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Function; import jdk.nashorn.internal.objects.annotations.ScriptClass; @@ -44,7 +47,6 @@ import jdk.nashorn.internal.runtime.JSONFunctions; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.PropertyMap; -import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator; import jdk.nashorn.internal.runtime.linker.Bootstrap; @@ -68,6 +70,18 @@ }); } + private static final Object JSOBJECT_INVOKER = new Object(); + + private static MethodHandle getJSOBJECT_INVOKER() { + return Global.instance().getDynamicInvoker(JSOBJECT_INVOKER, + new Callable<MethodHandle>() { + @Override + public MethodHandle call() { + return Bootstrap.createDynamicInvoker("dyn:call", + Object.class, Object.class, Object.class); + } + }); + } private static final Object REPLACER_INVOKER = new Object(); @@ -77,7 +91,7 @@ @Override public MethodHandle call() { return Bootstrap.createDynamicInvoker("dyn:call", Object.class, - ScriptFunction.class, ScriptObject.class, Object.class, Object.class); + Object.class, Object.class, Object.class, Object.class); } }); } @@ -127,9 +141,10 @@ final StringifyState state = new StringifyState(); // If there is a replacer, it must be a function or an array. - if (replacer instanceof ScriptFunction) { - state.replacerFunction = (ScriptFunction) replacer; + if (Bootstrap.isCallable(replacer)) { + state.replacerFunction = replacer; } else if (isArray(replacer) || + isJSObjectArray(replacer) || replacer instanceof Iterable || (replacer != null && replacer.getClass().isArray())) { @@ -201,18 +216,19 @@ // stringify helpers. private static class StringifyState { - final Map<ScriptObject, ScriptObject> stack = new IdentityHashMap<>(); + final Map<Object, Object> stack = new IdentityHashMap<>(); StringBuilder indent = new StringBuilder(); String gap = ""; List<String> propertyList = null; - ScriptFunction replacerFunction = null; + Object replacerFunction = null; } // Spec: The abstract operation Str(key, holder). - private static Object str(final Object key, final ScriptObject holder, final StringifyState state) { - Object value = holder.get(key); + private static Object str(final Object key, final Object holder, final StringifyState state) { + assert holder instanceof ScriptObject || holder instanceof JSObject; + Object value = getProperty(holder, key); try { if (value instanceof ScriptObject) { final InvokeByName toJSONInvoker = getTO_JSON(); @@ -221,6 +237,12 @@ if (Bootstrap.isCallable(toJSON)) { value = toJSONInvoker.getInvoker().invokeExact(toJSON, svalue, key); } + } else if (value instanceof JSObject) { + final JSObject jsObj = (JSObject)value; + final Object toJSON = jsObj.getMember("toJSON"); + if (Bootstrap.isCallable(toJSON)) { + value = getJSOBJECT_INVOKER().invokeExact(toJSON, value); + } } if (state.replacerFunction != null) { @@ -262,10 +284,10 @@ final JSType type = JSType.of(value); if (type == JSType.OBJECT) { - if (isArray(value)) { - return JA((ScriptObject)value, state); - } else if (value instanceof ScriptObject) { - return JO((ScriptObject)value, state); + if (isArray(value) || isJSObjectArray(value)) { + return JA(value, state); + } else if (value instanceof ScriptObject || value instanceof JSObject) { + return JO(value, state); } } @@ -273,7 +295,9 @@ } // Spec: The abstract operation JO(value) serializes an object. - private static String JO(final ScriptObject value, final StringifyState state) { + private static String JO(final Object value, final StringifyState state) { + assert value instanceof ScriptObject || value instanceof JSObject; + if (state.stack.containsKey(value)) { throw typeError("JSON.stringify.cyclic"); } @@ -284,7 +308,8 @@ final StringBuilder finalStr = new StringBuilder(); final List<Object> partial = new ArrayList<>(); - final List<String> k = state.propertyList == null ? Arrays.asList(value.getOwnKeys(false)) : state.propertyList; + final List<String> k = state.propertyList == null ? + Arrays.asList(getOwnKeys(value)) : state.propertyList; for (final Object p : k) { final Object strP = str(p, value, state); @@ -349,7 +374,9 @@ } // Spec: The abstract operation JA(value) serializes an array. - private static Object JA(final ScriptObject value, final StringifyState state) { + private static Object JA(final Object value, final StringifyState state) { + assert value instanceof ScriptObject || value instanceof JSObject; + if (state.stack.containsKey(value)) { throw typeError("JSON.stringify.cyclic"); } @@ -359,7 +386,7 @@ state.indent.append(state.gap); final List<Object> partial = new ArrayList<>(); - final int length = JSType.toInteger(value.getLength()); + final int length = JSType.toInteger(getLength(value)); int index = 0; while (index < length) { @@ -413,4 +440,48 @@ return finalStr.toString(); } + + private static String[] getOwnKeys(final Object obj) { + if (obj instanceof ScriptObject) { + return ((ScriptObject)obj).getOwnKeys(false); + } else if (obj instanceof ScriptObjectMirror) { + return ((ScriptObjectMirror)obj).getOwnKeys(false); + } else if (obj instanceof JSObject) { + // No notion of "own keys" or "proto" for general JSObject! We just + // return all keys of the object. This will be useful for POJOs + // implementing JSObject interface. + return ((JSObject)obj).keySet().toArray(new String[0]); + } else { + throw new AssertionError("should not reach here"); + } + } + + private static Object getLength(final Object obj) { + if (obj instanceof ScriptObject) { + return ((ScriptObject)obj).getLength(); + } else if (obj instanceof JSObject) { + return ((JSObject)obj).getMember("length"); + } else { + throw new AssertionError("should not reach here"); + } + } + + private static boolean isJSObjectArray(final Object obj) { + return (obj instanceof JSObject) && ((JSObject)obj).isArray(); + } + + private static Object getProperty(final Object holder, final Object key) { + if (holder instanceof ScriptObject) { + return ((ScriptObject)holder).get(key); + } else if (holder instanceof JSObject) { + JSObject jsObj = (JSObject)holder; + if (key instanceof Integer) { + return jsObj.getSlot((Integer)key); + } else { + return jsObj.getMember(Objects.toString(key)); + } + } else { + return new AssertionError("should not reach here"); + } + } }
--- a/src/jdk/nashorn/internal/objects/NativeRegExp.java Tue Nov 08 05:26:18 2016 +0000 +++ b/src/jdk/nashorn/internal/objects/NativeRegExp.java Thu Jan 12 06:59:38 2017 +0000 @@ -46,7 +46,6 @@ import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.ParserException; import jdk.nashorn.internal.runtime.PropertyMap; -import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.linker.Bootstrap; @@ -656,7 +655,7 @@ * @param replacement Replacement string. * @return String with substitutions. */ - String replace(final String string, final String replacement, final ScriptFunction function) throws Throwable { + String replace(final String string, final String replacement, final Object function) throws Throwable { final RegExpMatcher matcher = regexp.match(string); if (matcher == null) { @@ -672,7 +671,7 @@ sb.append(string, 0, matcher.start()); if (function != null) { - final Object self = function.isStrict() ? UNDEFINED : Global.instance(); + final Object self = Bootstrap.isStrictCallable(function) ? UNDEFINED : Global.instance(); sb.append(callReplaceValue(getReplaceValueInvoker(), function, self, matcher, string)); } else { appendReplacement(matcher, string, replacement, sb); @@ -692,7 +691,7 @@ final StringBuilder sb = new StringBuilder(); final MethodHandle invoker = function == null ? null : getReplaceValueInvoker(); - final Object self = function == null || function.isStrict() ? UNDEFINED : Global.instance(); + final Object self = function == null || Bootstrap.isStrictCallable(function) ? UNDEFINED : Global.instance(); do { sb.append(string, thisIndex, matcher.start()); @@ -808,12 +807,13 @@ new Callable<MethodHandle>() { @Override public MethodHandle call() { - return Bootstrap.createDynamicInvoker("dyn:call", String.class, ScriptFunction.class, Object.class, Object[].class); + return Bootstrap.createDynamicInvoker("dyn:call", + String.class, Object.class, Object.class, Object[].class); } }); } - private String callReplaceValue(final MethodHandle invoker, final ScriptFunction function, final Object self, final RegExpMatcher matcher, final String string) throws Throwable { + private String callReplaceValue(final MethodHandle invoker, final Object function, final Object self, final RegExpMatcher matcher, final String string) throws Throwable { final Object[] groups = groups(matcher); final Object[] args = Arrays.copyOf(groups, groups.length + 2);
--- a/src/jdk/nashorn/internal/objects/NativeString.java Tue Nov 08 05:26:18 2016 +0000 +++ b/src/jdk/nashorn/internal/objects/NativeString.java Thu Jan 12 06:59:38 2017 +0000 @@ -56,14 +56,13 @@ import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.OptimisticBuiltins; import jdk.nashorn.internal.runtime.PropertyMap; -import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.arrays.ArrayIndex; +import jdk.nashorn.internal.runtime.linker.Bootstrap; import jdk.nashorn.internal.runtime.linker.NashornGuards; import jdk.nashorn.internal.runtime.linker.PrimitiveLookup; - /** * ECMA 15.5 String Objects. */ @@ -749,8 +748,8 @@ nativeRegExp = NativeRegExp.flatRegExp(JSType.toString(string)); } - if (replacement instanceof ScriptFunction) { - return nativeRegExp.replace(str, "", (ScriptFunction)replacement); + if (Bootstrap.isCallable(replacement)) { + return nativeRegExp.replace(str, "", replacement); } return nativeRegExp.replace(str, JSType.toString(replacement), null);
--- a/src/jdk/nashorn/internal/parser/AbstractParser.java Tue Nov 08 05:26:18 2016 +0000 +++ b/src/jdk/nashorn/internal/parser/AbstractParser.java Thu Jan 12 06:59:38 2017 +0000 @@ -200,8 +200,10 @@ * @return tokenType of next token. */ private TokenType nextToken() { - // Capture last token tokenType. - last = type; + // Capture last token type, but ignore comments (which are irrelevant for the purpose of newline detection). + if (type != COMMENT) { + last = type; + } if (type != EOF) { // Set up next token.
--- a/src/jdk/nashorn/internal/parser/Parser.java Tue Nov 08 05:26:18 2016 +0000 +++ b/src/jdk/nashorn/internal/parser/Parser.java Thu Jan 12 06:59:38 2017 +0000 @@ -459,7 +459,7 @@ final FunctionNode parentFunction = lc.getCurrentFunction(); if (parentFunction != null && !parentFunction.isProgram()) { - sb.append(parentFunction.getName()).append('$'); + sb.append(parentFunction.getName()).append(CompilerConstants.NESTED_FUNCTION_SEPARATOR.symbolName()); } assert ident.getName() != null; @@ -1135,7 +1135,7 @@ /** * ExpressionStatement : - * Expression ; // [lookahead ~( or function )] + * Expression ; // [lookahead ~({ or function )] * * See 12.4 *
--- a/src/jdk/nashorn/internal/runtime/Context.java Tue Nov 08 05:26:18 2016 +0000 +++ b/src/jdk/nashorn/internal/runtime/Context.java Thu Jan 12 06:59:38 2017 +0000 @@ -377,10 +377,12 @@ final boolean _strict; /** class loader to resolve classes from script. */ - private final ClassLoader appLoader; + private final ClassLoader appLoader; - /** Class loader to load classes from -classpath option, if set. */ - private final ClassLoader classPathLoader; + /*package-private*/ + ClassLoader getAppLoader() { + return appLoader; + } /** Class loader to load classes compiled from scripts. */ private final ScriptLoader scriptLoader; @@ -395,11 +397,12 @@ private final ClassFilter classFilter; private static final ClassLoader myLoader = Context.class.getClassLoader(); - private static final StructureLoader sharedLoader; + /** Process-wide singleton structure loader */ + private static final StructureLoader theStructLoader; /*package-private*/ @SuppressWarnings("static-method") - ClassLoader getSharedLoader() { - return sharedLoader; + ClassLoader getStructLoader() { + return theStructLoader; } private static AccessControlContext createNoPermAccCtxt() { @@ -417,7 +420,7 @@ private static final AccessControlContext CREATE_GLOBAL_ACC_CTXT = createPermAccCtxt(NASHORN_CREATE_GLOBAL); static { - sharedLoader = AccessController.doPrivileged(new PrivilegedAction<StructureLoader>() { + theStructLoader = AccessController.doPrivileged(new PrivilegedAction<StructureLoader>() { @Override public StructureLoader run() { return new StructureLoader(myLoader); @@ -495,7 +498,6 @@ this.classFilter = classFilter; this.env = new ScriptEnvironment(options, out, err); this._strict = env._strict; - this.appLoader = appLoader; if (env._loader_per_compile) { this.scriptLoader = null; this.uniqueScriptId = null; @@ -505,17 +507,17 @@ } this.errors = errors; - // if user passed -classpath option, make a class loader with that and set it as - // thread context class loader so that script can access classes from that path. + // if user passed -classpath option, make a URLClassLoader with that and + // the app loader as the parent. final String classPath = options.getString("classpath"); if (!env._compile_only && classPath != null && !classPath.isEmpty()) { // make sure that caller can create a class loader. if (sm != null) { - sm.checkPermission(new RuntimePermission("createClassLoader")); + sm.checkCreateClassLoader(); } - this.classPathLoader = NashornLoader.createClassLoader(classPath); + this.appLoader = NashornLoader.createClassLoader(classPath, appLoader); } else { - this.classPathLoader = null; + this.appLoader = appLoader; } final int cacheSize = env._class_cache_size; @@ -927,7 +929,7 @@ if (System.getSecurityManager() != null && !StructureLoader.isStructureClass(fullName)) { throw new ClassNotFoundException(fullName); } - return (Class<? extends ScriptObject>)Class.forName(fullName, true, sharedLoader); + return (Class<? extends ScriptObject>)Class.forName(fullName, true, theStructLoader); } /** @@ -1044,17 +1046,18 @@ checkPackageAccess(sm, fullName); } - // try the script -classpath loader, if that is set - if (classPathLoader != null) { - try { - return Class.forName(fullName, true, classPathLoader); - } catch (final ClassNotFoundException ignored) { - // ignore, continue search + // Try finding using the "app" loader. + if (appLoader != null) { + return Class.forName(fullName, true, appLoader); + } else { + final Class<?> cl = Class.forName(fullName); + // return the Class only if it was loaded by boot loader + if (cl.getClassLoader() == null) { + return cl; + } else { + throw new ClassNotFoundException(fullName); } } - - // Try finding using the "app" loader. - return Class.forName(fullName, true, appLoader); } /** @@ -1085,7 +1088,7 @@ // No verification when security manager is around as verifier // may load further classes - which should be avoided. if (System.getSecurityManager() == null) { - CheckClassAdapter.verify(new ClassReader(bytecode), sharedLoader, false, new PrintWriter(System.err, true)); + CheckClassAdapter.verify(new ClassReader(bytecode), theStructLoader, false, new PrintWriter(System.err, true)); } } } @@ -1201,15 +1204,10 @@ } private URL getResourceURL(final String resName) { - // try the classPathLoader if we have and then - // try the appLoader if non-null. - if (classPathLoader != null) { - return classPathLoader.getResource(resName); - } else if (appLoader != null) { + if (appLoader != null) { return appLoader.getResource(resName); } - - return null; + return ClassLoader.getSystemResource(resName); } private Object evaluateSource(final Source source, final ScriptObject scope, final ScriptObject thiz) { @@ -1336,7 +1334,7 @@ new PrivilegedAction<ScriptLoader>() { @Override public ScriptLoader run() { - return new ScriptLoader(appLoader, Context.this); + return new ScriptLoader(Context.this); } }, CREATE_LOADER_ACC_CTXT); }
--- a/src/jdk/nashorn/internal/runtime/JSONFunctions.java Tue Nov 08 05:26:18 2016 +0000 +++ b/src/jdk/nashorn/internal/runtime/JSONFunctions.java Thu Jan 12 06:59:38 2017 +0000 @@ -46,7 +46,7 @@ @Override public MethodHandle call() { return Bootstrap.createDynamicInvoker("dyn:call", Object.class, - ScriptFunction.class, ScriptObject.class, String.class, Object.class); + Object.class, Object.class, String.class, Object.class); } }); } @@ -90,16 +90,16 @@ // apply 'reviver' function if available private static Object applyReviver(final Global global, final Object unfiltered, final Object reviver) { - if (reviver instanceof ScriptFunction) { + if (Bootstrap.isCallable(reviver)) { final ScriptObject root = global.newObject(); root.addOwnProperty("", Property.WRITABLE_ENUMERABLE_CONFIGURABLE, unfiltered); - return walk(root, "", (ScriptFunction)reviver); + return walk(root, "", reviver); } return unfiltered; } // This is the abstract "Walk" operation from the spec. - private static Object walk(final ScriptObject holder, final Object name, final ScriptFunction reviver) { + private static Object walk(final ScriptObject holder, final Object name, final Object reviver) { final Object val = holder.get(name); if (val instanceof ScriptObject) { final ScriptObject valueObj = (ScriptObject)val; @@ -131,7 +131,7 @@ try { // Object.class, ScriptFunction.class, ScriptObject.class, String.class, Object.class); - return getREVIVER_INVOKER().invokeExact(reviver, holder, JSType.toString(name), val); + return getREVIVER_INVOKER().invokeExact(reviver, (Object)holder, JSType.toString(name), val); } catch(Error|RuntimeException t) { throw t; } catch(final Throwable t) {
--- a/src/jdk/nashorn/internal/runtime/NashornLoader.java Tue Nov 08 05:26:18 2016 +0000 +++ b/src/jdk/nashorn/internal/runtime/NashornLoader.java Thu Jan 12 06:59:38 2017 +0000 @@ -35,7 +35,6 @@ import java.security.PermissionCollection; import java.security.Permissions; import java.security.SecureClassLoader; -import jdk.nashorn.tools.Shell; /** * Superclass for Nashorn class loader classes. @@ -103,10 +102,10 @@ /** * Create a secure URL class loader for the given classpath * @param classPath classpath for the loader to search from + * @param parent the parent class loader for the new class loader * @return the class loader */ - static ClassLoader createClassLoader(final String classPath) { - final ClassLoader parent = Shell.class.getClassLoader(); + static ClassLoader createClassLoader(final String classPath, final ClassLoader parent) { final URL[] urls = pathToURLs(classPath); return URLClassLoader.newInstance(urls, parent); }
--- a/src/jdk/nashorn/internal/runtime/ScriptLoader.java Tue Nov 08 05:26:18 2016 +0000 +++ b/src/jdk/nashorn/internal/runtime/ScriptLoader.java Thu Jan 12 06:59:38 2017 +0000 @@ -44,20 +44,45 @@ /** * Constructor. */ - ScriptLoader(final ClassLoader parent, final Context context) { - super(parent); + ScriptLoader(final Context context) { + super(context.getStructLoader()); this.context = context; } @Override protected Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException { checkPackageAccess(name); - if (name.startsWith(NASHORN_PKG_PREFIX)) { - return context.getSharedLoader().loadClass(name); - } return super.loadClass(name, resolve); } + + @Override + protected Class<?> findClass(String name) throws ClassNotFoundException { + final ClassLoader appLoader = context.getAppLoader(); + + /* + * If the appLoader is null, don't bother side-delegating to it! + * Bootloader has been already attempted via parent loader + * delegation from the "loadClass" method. + * + * Also, make sure that we don't delegate to the app loader + * for nashorn's own classes or nashorn generated classes! + */ + if (appLoader == null || name.startsWith(NASHORN_PKG_PREFIX)) { + throw new ClassNotFoundException(name); + } + + /* + * This split-delegation is used so that caller loader + * based resolutions of classes would work. For example, + * java.sql.DriverManager uses caller's class loader to + * get Driver instances. Without this split-delegation + * a script class evaluating DriverManager.getDrivers() + * will not get back any JDBC driver! + */ + return appLoader.loadClass(name); + } + // package-private and private stuff below this point /**
--- a/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java Tue Nov 08 05:26:18 2016 +0000 +++ b/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java Thu Jan 12 06:59:38 2017 +0000 @@ -132,9 +132,9 @@ * Nashorn extension: exec a string in a separate process. * * @param self self reference - * @param args string to execute, input and additional arguments, to be appended to {@code string}. Additional arguments can be passed as - * either one JavaScript array, whose elements will be converted to strings; or as a sequence of - * varargs, each of which will be converted to a string. + * @param args string to execute, input and additional arguments, to be appended to {@code string}. Additional + * arguments can be passed as either one JavaScript array, whose elements will be converted to + * strings; or as a sequence of varargs, each of which will be converted to a string. * * @return output string from the request * @@ -167,7 +167,10 @@ // If a working directory is present, use it. final Object pwd = envProperties.get(PWD_NAME); if (pwd != UNDEFINED) { - processBuilder.directory(new File(JSType.toString(pwd))); + final File pwdFile = new File(JSType.toString(pwd)); + if (pwdFile.exists()) { + processBuilder.directory(pwdFile); + } } // Set up ENV variables. @@ -219,13 +222,13 @@ errThread.start(); // If input is present, pass on to process. - try (OutputStreamWriter outputStream = new OutputStreamWriter(process.getOutputStream())) { - if (input != UNDEFINED) { + if (!JSType.nullOrUndefined(input)) { + try (OutputStreamWriter outputStream = new OutputStreamWriter(process.getOutputStream())) { final String in = JSType.toString(input); outputStream.write(in, 0, in.length()); + } catch (final IOException ex) { + // Process was not expecting input. May be normal state of affairs. } - } catch (final IOException ex) { - // Process was not expecting input. May be normal state of affairs. } // Wait for the process to complete. @@ -275,9 +278,8 @@ * @param str a {@link String} to tokenize. * @return a {@link List} of {@link String}s representing the tokens that * constitute the string. - * @throws IOException in case {@link StreamTokenizer#nextToken()} raises it. */ - public static List<String> tokenizeString(final String str) throws IOException { + public static List<String> tokenizeString(final String str) { final StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(str)); tokenizer.resetSyntax(); tokenizer.wordChars(0, 255); @@ -287,7 +289,7 @@ tokenizer.quoteChar('\''); final List<String> tokenList = new ArrayList<>(); final StringBuilder toAppend = new StringBuilder(); - while (tokenizer.nextToken() != StreamTokenizer.TT_EOF) { + while (nextToken(tokenizer) != StreamTokenizer.TT_EOF) { final String s = tokenizer.sval; // The tokenizer understands about honoring quoted strings and recognizes // them as one token that possibly contains multiple space-separated words. @@ -306,4 +308,12 @@ } return tokenList; } + + private static int nextToken(final StreamTokenizer tokenizer) { + try { + return tokenizer.nextToken(); + } catch (final IOException ioe) { + return StreamTokenizer.TT_EOF; + } + } }
--- a/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Tue Nov 08 05:26:18 2016 +0000 +++ b/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Thu Jan 12 06:59:38 2017 +0000 @@ -159,7 +159,9 @@ return ((JSObject)callable).isStrictFunction(); } else if (callable instanceof BoundCallable) { return isStrictCallable(((BoundCallable)callable).getCallable()); - } else if (BeansLinker.isDynamicMethod(callable) || callable instanceof StaticClass) { + } else if (BeansLinker.isDynamicMethod(callable) || + callable instanceof StaticClass || + isFunctionalInterfaceObject(callable)) { return false; } throw notFunction(callable);
--- a/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java Tue Nov 08 05:26:18 2016 +0000 +++ b/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java Thu Jan 12 06:59:38 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, 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 @@ -29,6 +29,7 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.util.Map; import javax.script.Bindings; import jdk.internal.dynalink.CallSiteDescriptor; @@ -140,12 +141,15 @@ } private static GuardedInvocation findCallMethod(final CallSiteDescriptor desc) { - // TODO: if call site is already a vararg, don't do asCollector MethodHandle mh = JSOBJECT_CALL; if (NashornCallSiteDescriptor.isApplyToCall(desc)) { mh = MH.insertArguments(JSOBJECT_CALL_TO_APPLY, 0, JSOBJECT_CALL); } - return new GuardedInvocation(MH.asCollector(mh, Object[].class, desc.getMethodType().parameterCount() - 2), IS_JSOBJECT_GUARD); + final MethodType type = desc.getMethodType(); + mh = type.parameterType(type.parameterCount() - 1) == Object[].class ? + mh : + MH.asCollector(mh, Object[].class, type.parameterCount() - 2); + return new GuardedInvocation(mh, IS_JSOBJECT_GUARD); } private static GuardedInvocation findNewMethod(final CallSiteDescriptor desc) {
--- a/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Tue Nov 08 05:26:18 2016 +0000 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Thu Jan 12 06:59:38 2017 +0000 @@ -177,7 +177,7 @@ if (iface.isAnnotationPresent(FunctionalInterface.class)) { // return the first abstract method for (final Method m : iface.getMethods()) { - if (Modifier.isAbstract(m.getModifiers())) { + if (Modifier.isAbstract(m.getModifiers()) && !isOverridableObjectMethod(m)) { return m.getName(); } } @@ -188,6 +188,23 @@ return findFunctionalInterfaceMethodName(clazz.getSuperclass()); } + // is this an overridable java.lang.Object method? + private static boolean isOverridableObjectMethod(final Method m) { + switch (m.getName()) { + case "equals": + if (m.getReturnType() == boolean.class) { + final Class<?>[] params = m.getParameterTypes(); + return params.length == 1 && params[0] == Object.class; + } + return false; + case "hashCode": + return m.getReturnType() == int.class && m.getParameterCount() == 0; + case "toString": + return m.getReturnType() == String.class && m.getParameterCount() == 0; + } + return false; + } + // Returns @FunctionalInterface annotated interface's single abstract // method name. If not found, returns null. static String getFunctionalInterfaceMethodName(final Class<?> clazz) {
--- a/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java Tue Nov 08 05:26:18 2016 +0000 +++ b/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java Thu Jan 12 06:59:38 2017 +0000 @@ -80,8 +80,17 @@ this.negLookaheadLevel = negLookaheadLevel; } - boolean isContained(final int group, final int level) { - return group == this.negLookaheadGroup && level >= this.negLookaheadLevel; + /** + * Returns true if this Capture can be referenced from the position specified by the + * group and level parameters. This is the case if either the group is not within + * a negative lookahead, or the position of the referrer is in the same negative lookahead. + * + * @param group current negative lookahead group + * @param level current negative lokahead level + * @return true if this capture group can be referenced from the given position + */ + boolean canBeReferencedFrom(final int group, final int level) { + return this.negLookaheadLevel == 0 || (group == this.negLookaheadGroup && level >= this.negLookaheadLevel); } } @@ -671,8 +680,9 @@ } else if (decimalValue <= caps.size()) { // Captures inside a negative lookahead are undefined when referenced from the outside. - if (!caps.get(decimalValue - 1).isContained(negLookaheadGroup, negLookaheadLevel)) { - // Reference to capture in negative lookahead, omit from output buffer. + final Capture capture = caps.get(decimalValue - 1); + if (!capture.canBeReferencedFrom(negLookaheadGroup, negLookaheadLevel)) { + // Outside reference to capture in negative lookahead, omit from output buffer. sb.setLength(sb.length() - 1); } else { // Append backreference to output buffer.
--- a/src/jdk/nashorn/tools/Shell.java Tue Nov 08 05:26:18 2016 +0000 +++ b/src/jdk/nashorn/tools/Shell.java Thu Jan 12 06:59:38 2017 +0000 @@ -25,20 +25,6 @@ package jdk.nashorn.tools; -import static jdk.nashorn.internal.runtime.Source.sourceFor; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.PrintStream; -import java.io.PrintWriter; -import java.util.List; -import java.util.Locale; -import java.util.ResourceBundle; import jdk.nashorn.api.scripting.NashornException; import jdk.nashorn.internal.codegen.Compiler; import jdk.nashorn.internal.codegen.Compiler.CompilationPhases; @@ -54,8 +40,30 @@ import jdk.nashorn.internal.runtime.ScriptEnvironment; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptRuntime; +import jdk.nashorn.internal.runtime.ScriptingFunctions; import jdk.nashorn.internal.runtime.options.Options; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.ResourceBundle; + +import static jdk.nashorn.internal.runtime.Source.sourceFor; + /** * Command line Shell for processing JavaScript files. */ @@ -195,7 +203,8 @@ // parse options if (args != null) { try { - options.process(args); + final String[] prepArgs = preprocessArgs(args); + options.process(prepArgs); } catch (final IllegalArgumentException e) { werr.println(bundle.getString("shell.usage")); options.displayHelp(e); @@ -226,6 +235,75 @@ } /** + * Preprocess the command line arguments passed in by the shell. This method checks, for the first non-option + * argument, whether the file denoted by it begins with a shebang line. If so, it is assumed that execution in + * shebang mode is intended. The consequence of this is that the identified script file will be treated as the + * <em>only</em> script file, and all subsequent arguments will be regarded as arguments to the script. + * <p> + * This method canonicalizes the command line arguments to the form {@code <options> <script> -- <arguments>} if a + * shebang script is identified. On platforms that pass shebang arguments as single strings, the shebang arguments + * will be broken down into single arguments; whitespace is used as separator. + * <p> + * Shebang mode is entered regardless of whether the script is actually run directly from the shell, or indirectly + * via the {@code jjs} executable. It is the user's / script author's responsibility to ensure that the arguments + * given on the shebang line do not lead to a malformed argument sequence. In particular, the shebang arguments + * should not contain any whitespace for purposes other than separating arguments, as the different platforms deal + * with whitespace in different and incompatible ways. + * <p> + * @implNote Example:<ul> + * <li>Shebang line in {@code script.js}: {@code #!/path/to/jjs --language=es6}</li> + * <li>Command line: {@code ./script.js arg2}</li> + * <li>{@code args} array passed to Nashorn: {@code --language=es6,./script.js,arg}</li> + * <li>Required canonicalized arguments array: {@code --language=es6,./script.js,--,arg2}</li> + * </ul> + * + * @param args the command line arguments as passed into Nashorn. + * @return the passed and possibly canonicalized argument list + */ + private static String[] preprocessArgs(final String[] args) { + if (args.length == 0) { + return args; + } + + final List<String> processedArgs = new ArrayList<>(); + processedArgs.addAll(Arrays.asList(args)); + + // Nashorn supports passing multiple shebang arguments. On platforms that pass anything following the + // shebang interpreter notice as one argument, the first element of the argument array needs to be special-cased + // as it might actually contain several arguments. Mac OS X splits shebang arguments, other platforms don't. + // This special handling is also only necessary if the first argument actually starts with an option. + if (args[0].startsWith("-") && !System.getProperty("os.name", "generic").startsWith("Mac OS X")) { + processedArgs.addAll(0, ScriptingFunctions.tokenizeString(processedArgs.remove(0))); + } + + int shebangFilePos = -1; // -1 signifies "none found" + // identify a shebang file and its position in the arguments array (if any) + for (int i = 0; i < processedArgs.size(); ++i) { + final String a = processedArgs.get(i); + if (!a.startsWith("-")) { + final Path p = Paths.get(a); + String l = ""; + try (final BufferedReader r = Files.newBufferedReader(p)) { + l = r.readLine(); + } catch (IOException ioe) { + // ignore + } + if (l.startsWith("#!")) { + shebangFilePos = i; + } + // We're only checking the first non-option argument. If it's not a shebang file, we're in normal + // execution mode. + break; + } + } + if (shebangFilePos != -1) { + // Insert the argument separator after the shebang script file. + processedArgs.add(shebangFilePos + 1, "--"); + } + return processedArgs.toArray(new String[0]); + } + + /** * Compiles the given script files in the command line * This is called only when using the --compile-only flag *
--- a/test/script/basic/JDK-8025515.js Tue Nov 08 05:26:18 2016 +0000 +++ b/test/script/basic/JDK-8025515.js Thu Jan 12 06:59:38 2017 +0000 @@ -61,8 +61,8 @@ var f = (function() { return function() { a.b.c; }; })(); -testMethodName(f, "f$L:62"); +testMethodName(f, "f#L:62"); testMethodName((function() { return function() { return a.b.c; }; -})(), "L:66$L:67"); +})(), "L:66#L:67");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8137240.js Thu Jan 12 06:59:38 2017 +0000 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016, 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. + */ + +/** + * JDK-8137240: Negative lookahead in RegEx breaks backreference + * + * @test + * @run + */ + + +Assert.assertEquals('aa'.replace(/(a)(?!b)\1/gm, 'c'), 'c'); + +var result = 'aa'.match(/(a)(?!b)\1/); +Assert.assertTrue(result.length === 2); +Assert.assertTrue(result[0] === 'aa'); +Assert.assertTrue(result[1] === 'a'); + +result = 'aa'.match(/(a)(?!(b))\2(a)/); +Assert.assertTrue(result.length === 4); +Assert.assertTrue(result[0] === 'aa'); +Assert.assertTrue(result[1] === 'a'); +Assert.assertTrue(result[2] === undefined); +Assert.assertTrue(result[3] === 'a');
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8156714.js Thu Jan 12 06:59:38 2017 +0000 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016, 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. + */ + +/** + * JDK-8156714: Parsing issue with automatic semicolon insertion + * + * @test + * @run + */ + +a = function() { +} + +/* */ function b() { +} + +c = function() { +} /* + +*/ function d() { +} + +try { + eval("x = function() {} /* */ function y() {}"); + throw new Error("Error expected"); +} catch (e) { + if (!(e instanceof SyntaxError)) { + throw new Error("Unexpected error: " + e); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8156896.js Thu Jan 12 06:59:38 2017 +0000 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2016, 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. + */ + +/** + * JDK-8156896: Script stack trace should display function names + * + * @test + * @run + */ + +function checkNamedFunction(stack) { + Assert.assertTrue(stack.indexOf("Error\n\tat bar (") === 0); +} + +function checkAnonymousFunction(stack) { + Assert.assertTrue(stack.indexOf("Error\n\tat <anonymous> (") === 0); +} + +// Named functions +function bar() { try { throw new Error(); } catch(e) { return e.stack; } } +checkNamedFunction(bar()); + +bar = function() { try { throw new Error(); } catch(e) { return e.stack; } }; +checkNamedFunction(bar()); + +f = (function() {return function bar() { try { throw new Error(); } catch(e) { return e.stack; } } })(); +checkNamedFunction(f()); + +f = new Function("return function bar() { try { throw new Error(); } catch(e) { return e.stack; } }")(); +checkNamedFunction(f()); + +// Anonymous functions +checkAnonymousFunction((function() { try { throw new Error(); } catch(e) { return e.stack; } })()); + +f = (function() {return function() { try { throw new Error(); } catch(e) { return e.stack; } } })(); +checkAnonymousFunction(f()); + +f = new Function("return function() { try { throw new Error(); } catch(e) { return e.stack; } }")(); +checkAnonymousFunction(f());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8157160.js Thu Jan 12 06:59:38 2017 +0000 @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2016, 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. + */ + +/** + * JDK-8157160: JSON.stringify does not work on ScriptObjectMirror objects + * + * @test + * @option -scripting + * @run + */ + +var SM = Java.type("javax.script.ScriptEngineManager"); +var AJSO = Java.type("jdk.nashorn.api.scripting.AbstractJSObject"); +var Supplier = Java.type("java.util.function.Supplier"); + +var engine = new SM().getEngineByName("nashorn"); + +// JSON stringify ScriptObjectMirror instances +print(JSON.stringify(engine.eval("({ foo : 42 })"))); +print(JSON.stringify(engine.eval("([5, 6, 76, 7])"))); +print(JSON.stringify(engine.eval(<<EOF + ({ + toJSON: function() "hello" + }) +EOF +))); + +print(JSON.stringify(engine.eval(<<EOF +obj = { + name: 'nashorn', + versions: [ 'es5.1', 'es6' ] +} +EOF +))); + +var dm = engine.eval("new Date()"); +print('"' + dm.toJSON() + '"' == JSON.stringify(dm)); + +// JSON stringifying an arbitrary JSObject impl. +var jsObj = new AJSO() { + keySet: function() { + var keys = new java.util.HashSet(); + keys.add("x"); + keys.add("y"); + return keys; + }, + + getMember: function(name) { + if (name == "x") { + return 42; + } else if (name == "y") { + return "hello"; + } + } +}; +print(JSON.stringify(jsObj)); + +// try toJSON implementation on JSObject +var jsObj2 = new AJSO() { + getMember: function(name) { + if (name == 'toJSON') { + return function() { + return "my json representation"; + } + } + } +}; +print(JSON.stringify(jsObj2)); + +var jsObj3 = new AJSO() { + getMember: function(name) { + if (name == 'toJSON') { + return new Supplier() { + "get": function() { + return "value from toJSON function"; + } + }; + } + } +}; +print(JSON.stringify(jsObj3)); + +// replacer function from another script world +print(JSON.stringify({ + foo: "hello" +}, engine.eval(<<EOF + function (key, value) { + if (key == "foo") { + return value.toUpperCase() + } + return value; + } +EOF)));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8157160.js.EXPECTED Thu Jan 12 06:59:38 2017 +0000 @@ -0,0 +1,9 @@ +{"foo":42} +[5,6,76,7] +"hello" +{"name":"nashorn","versions":["es5.1","es6"]} +true +{"x":42,"y":"hello"} +"my json representation" +"value from toJSON function" +{"foo":"HELLO"}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8157680.js Thu Jan 12 06:59:38 2017 +0000 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2016, 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. + */ + +/** + * JDK-8157680: Callback parameter of any JS builtin implementation should accept any Callable + * + * @option -scripting + * @test + * @run + */ + +var SM = Java.type("javax.script.ScriptEngineManager") +var engine = new SM().getEngineByName("nashorn") + +engine.put("output", print); +var reviver = engine.eval(<<EOF +function(name, value) { + if (name == "") return value + output(name + " = " + value) + return value +} +EOF) + +// reviver function from mirror world! +JSON.parse('{ "foo" : 44, "bar" : "hello" }', reviver) + +var AJO = Java.type("jdk.nashorn.api.scripting.AbstractJSObject") +// reviver function as a JSObject function +JSON.parse('{ "nashorn" : "hello" }', new AJO() { + isFunction: function() true, + call: function(thiz, args) { + var name = args[0], value = args[1] + if (name == "") return value + print(name + " -> " + value) + return value + } +}) + +// compare function from the mirror world +var arr = [34,567,-3, 53].sort(engine.eval(<<EOF + function(x, y) x < y? -1 : ((x > y)? 1 : 0) +EOF)) +print(arr) + +// compare function as a JSObject function +arr = [34,57,-3, 53, 670, 33].sort(new AJO() { + isFunction: function() true, + call: function(thiz, args) { + var x = args[0], y = args[1] + return x < y? -1 : ((x > y)? 1 : 0) + } +}) +print(arr) + +// replacer function from mirror world +var str = "hello".replace(/l/g, engine.eval(<<EOF + function() "_" +EOF)) +print(str) + +// replacer function as a JSObject function +str = "hello".replace(/[el]/g, new AJO() { + isFunction: function() true, + call: function(thiz, args) { + var match = args[0] + return match.toUpperCase() + } +}) +print(str)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8157680.js.EXPECTED Thu Jan 12 06:59:38 2017 +0000 @@ -0,0 +1,7 @@ +foo = 44 +bar = hello +nashorn -> hello +-3,34,53,567 +-3,33,34,53,57,670 +he__o +hELLo
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8157819.js Thu Jan 12 06:59:38 2017 +0000 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016, 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. + */ + +/** + * JDK-8157819: TypeError when a java.util.Comparator object is invoked as a function + * + * @test + * @run + */ + +var compare = java.util.Comparator.naturalOrder() +Assert.assertTrue(compare("nashorn", "ecmascript") > 0) +Assert.assertTrue(compare("abc", "xyz") < 0) +Assert.assertTrue(compare("hello", "hello") == 0) + +var rcompare = java.util.Comparator.reverseOrder() +Assert.assertTrue(rcompare("nashorn", "ecmascript") < 0) +Assert.assertTrue(rcompare("abc", "xyz") > 0) +Assert.assertTrue(rcompare("hello", "hello") == 0) + +var arr = [ "nashorn", "JavaScript", "ECMAScript", "ecmascript", "js" ] +Assert.assertEquals(arr.sort(compare).join(), + "ECMAScript,JavaScript,ecmascript,js,nashorn") +Assert.assertEquals(arr.sort(rcompare).join(), + "nashorn,js,ecmascript,JavaScript,ECMAScript") +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8158467.js Thu Jan 12 06:59:38 2017 +0000 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2016, 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. + */ + +/** + * JDK-8158467: AccessControlException is thrown on public Java class access if "script app loader" is set to null + * + * @option -scripting + * @test + * @run + */ + +var Factory = Java.type("jdk.nashorn.api.scripting.NashornScriptEngineFactory"); +var fac = new Factory(); + +// This script has to be given RuntimePermission("nashorn.setConfig") +var e = fac["getScriptEngine(java.lang.ClassLoader)"](null); + +print(e.eval("java.lang.System")); +print(e.eval("({ foo: 42})").foo); +print((e.eval("function(x) x*x"))(31)); + +e.put("output", print); +var runnable = e.eval(<<EOF + new java.lang.Runnable() { + run: function() { + output("hello Runnable"); + } + } +EOF); + +runnable.run(); + +var obj = e.eval(<<EOF +new (Java.extend(Java.type("java.lang.Object"))) { + hashCode: function() 33, + toString: function() "I'm object" +} +EOF); + +print(obj.hashCode()); +print(obj.toString()); + +// should throw SecurityException! +try { + e.eval("Packages.jdk.internal"); +} catch (ex) { + print(ex); +} + +// should throw SecurityException! +try { + e.eval("Java.type('jdk.internal.misc.Unsafe')"); +} catch (ex) { + print(ex); +} + +// should throw SecurityException! +try { + e.eval("Java.type('jdk.nashorn.internal.Context')"); +} catch (ex) { + print(ex); +} + +// should throw ClassNotFoundException as null is script +// "app loader" [and not platform loader which loads nashorn] +e.eval(<<EOF +try { + Java.type('jdk.nashorn.api.scripting.JSObject'); +} catch (ex) { + output(ex); +} +EOF);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8158467.js.EXPECTED Thu Jan 12 06:59:38 2017 +0000 @@ -0,0 +1,10 @@ +[JavaClass java.lang.System] +42 +961 +hello Runnable +33 +I'm object +java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessClassInPackage.jdk.internal") +java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessClassInPackage.jdk.internal.misc") +java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessClassInPackage.jdk.nashorn.internal") +java.lang.ClassNotFoundException: jdk.nashorn.api.scripting.JSObject
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/currently-failing/JDK-8144221.js Thu Jan 12 06:59:38 2017 +0000 @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2015, 2016, 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 that shebang handling works properly. + * + * @test + * @option -scripting + * @run + */ + +// The test generates three different JavaScript source files. The first two +// are generated at the beginning of the test and do not change. +// * a.js +// print("A: " + arguments) +// * b.js +// #!<path_to_jjs> -lalelu -- ignore +// print("B: " + arguments) +// +// The third file, shebang.js, is generated differently for each particular +// test case, containing different shebang lines and one statement: +// * shebang.js +// #!<path_to_jjs> <shebang_line> +// print("S: " + arguments) +// +// The path_to_jjs is extracted from the environment based on JAVA_HOME, so the +// latter must be set properly. +// +// Each shebang.js is run four times, in all possible combinations of values +// from the following two axes: +// * without passing any arguments, and passing the arguments 'a.js' and +// '"hello world"' (the latter being a quoted string); +// * run via jjs, and via direct shell execution (using shebang). + +var pseudosheb = "#!${jjs} -lalelu -- ignore", + System = Java.type('java.lang.System'), + Paths = Java.type('java.nio.file.Paths'), + Files = Java.type('java.nio.file.Files'), + Opt = Java.type('java.nio.file.StandardOpenOption'), + Arrays = Java.type('java.util.Arrays') + +var sep = Java.type('java.io.File').separator, + win = System.getProperty("os.name").startsWith("Windows"), + jjsName = "jjs" + (win ? ".exe" : ""), + javaHome = System.getProperty("java.home") + +var jjs = javaHome + "/../bin/".replace(/\//g, sep) + jjsName +if (!Files.exists(Paths.get(jjs))) { + jjs = javaHome + "/bin/".replace(/\//g, sep) + jjsName +} + +// Create and cwd to a temporary directory. + +var tmpdir = Files.createTempDirectory(null), + tmp = tmpdir.toAbsolutePath().toString(), + curpwd = $ENV.PWD + +$ENV.PWD = tmp + +// Test cases. Each case is documented with the expected output for the four +// different executions. + +var shebs = [ + // No arguments on the shebang line. + // noargs jjs/shebang -> no output but "S" prefix + // args jjs/shebang -> output the arguments with "S" prefix + "", + // One interpreter argument. + // noargs jjs/shebang -> no output but "S" prefix + // args jjs/shebang -> output the arguments with "S" prefix + "--language=es6", + // Two interpreter arguments. + // noargs jjs/shebang -> no output but "S" prefix + // args jjs/shebang -> output the arguments with "S" prefix + "--language=es6 -scripting", + // One interpreter argument and a JavaScript file without shebang. + // (For shebang execution, this is a pathological example, as the + // JavaScript file passed as a shebang argument will be analyzed and + // shebang mode will not be entered.) + // noargs jjs -> no output but "S" prefix + // args jjs -> output the arguments with "S" prefix + // noargs shebang -> no output but "A" and "S" prefixes + // args shebang -> output "A", "S", and "A" prefixes, then the error + // message: + // "java.io.IOException: hello world is not a file" + "-scripting a.js", + // One interpreter argument and a JavaScript file with shebang. (This + // is another pathological example, as it will force shebang mode, + // leading to all subsequent arguments, including shebang.js, being + // treated as arguments to the script b.js.) + // noargs jjs -> no output but the "S" prefix + // args jjs -> output the arguments with "S" prefix + // noargs shebang -> output shebang.js with "B" prefix + // args shebang -> output shebang.js and the arguments with "B" + // prefix + "-scripting b.js" + ] + +function write(file, lines) { + Files.write(Paths.get(tmp, file), Arrays.asList(lines), Opt.CREATE, Opt.WRITE) +} + +function insn(name) { + return "print('${name}:' + arguments)" +} + +function run(viajjs, name, arg1, arg2) { + var prefix = viajjs ? "${jjs} -scripting " : win ? 'sh -c "' : '', + suffix = viajjs ? '' : win ? '"' : '' + $EXEC("${prefix}./shebang.js ${arg1} ${arg2}${suffix}") + print("* ${name} via ${viajjs ? 'jjs' : 'shebang'}") + print($OUT.trim()) + print($ERR.trim()) +} + +write('a.js', insn('A')) +write('b.js', [pseudosheb, insn('B')]) + +shebs.forEach(function(sheb) { + var shebang = "#!${jjs} ${sheb}" + print("<<< ${sheb} >>>") + write('shebang.js', [shebang, insn('S')]) + $EXEC('chmod +x shebang.js') + run(false, 'noargs', '', '') + run(true, 'noargs', '', '') + run(false, 'withargs', 'a.js', "'hello world'") + run(true, 'withargs', 'a.js', "'hello world'") + $EXEC('rm shebang.js') +}) + +// Cleanup. + +$EXEC('rm a.js b.js') +$ENV.PWD = curpwd +Files.delete(tmpdir)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/currently-failing/JDK-8144221.js.EXPECTED Thu Jan 12 06:59:38 2017 +0000 @@ -0,0 +1,68 @@ +<<< >>> +* noargs via shebang +S: + +* noargs via jjs +S: + +* withargs via shebang +S:a.js,hello world + +* withargs via jjs +S:a.js,hello world + +<<< --language=es6 >>> +* noargs via shebang +S: + +* noargs via jjs +S: + +* withargs via shebang +S:a.js,hello world + +* withargs via jjs +S:a.js,hello world + +<<< --language=es6 -scripting >>> +* noargs via shebang +S: + +* noargs via jjs +S: + +* withargs via shebang +S:a.js,hello world + +* withargs via jjs +S:a.js,hello world + +<<< -scripting a.js >>> +* noargs via shebang +A: +S: + +* noargs via jjs +S: + +* withargs via shebang +A: +S: +A: +java.io.IOException: hello world is not a file +* withargs via jjs +S:a.js,hello world + +<<< -scripting b.js >>> +* noargs via shebang +B:./shebang.js + +* noargs via jjs +S: + +* withargs via shebang +B:./shebang.js,a.js,hello world + +* withargs via jjs +S:a.js,hello world +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/nosecurity/JDK-8130127.js Thu Jan 12 06:59:38 2017 +0000 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015, 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. + */ + +/** + * JDK-8130127: streamline input parameter of Nashorn scripting $EXEC function + * + * Test different variants of stdin passing to $EXEC. + * + * @test + * @option -scripting + * @run + */ + +var File = java.io.File, + sep = File.separator, + System = java.lang.System, + os = System.getProperty("os.name"), + win = os.startsWith("Windows"), + jjsName = "jjs" + (win ? ".exe" : ""), + javaHome = System.getProperty("java.home") + +var jjs = javaHome + "/../bin/".replace(/\//g, sep) + jjsName +if (!new File(jjs).isFile()) { + jjs = javaHome + "/bin/".replace(/\//g, sep) + jjsName +} + +var jjsCmd = jjs + " readprint.js" + +print($EXEC(jjsCmd)) +print($EXEC(jjsCmd, null)) +print($EXEC(jjsCmd, undefined)) +print($EXEC(jjsCmd, "")) + +print($EXEC(jjs, "print('hello')")) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/nosecurity/JDK-8130127.js.EXPECTED Thu Jan 12 06:59:38 2017 +0000 @@ -0,0 +1,6 @@ + + + + +hello +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/nosecurity/os-not-windows.js Thu Jan 12 06:59:38 2017 +0000 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015, 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 that we're not running on Windows. The test actually checks if the os.not.windows property is set and processed + * by runif correctly. + * + * @test + * @runif os.not.windows + * @run + */ + +var os = java.lang.System.getProperty("os.name") + +if (os.startsWith("Windows")) { + throw "This test should not be run on Windows." +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/nosecurity/readprint.js Thu Jan 12 06:59:38 2017 +0000 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2015, 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. + */ + +/** + * This is a dummy script accompanying JDK-8130127.js. + * + * @subtest + * @run ignore supplemental + */ + +var l = readLine() +print(l) +
--- a/test/script/trusted/JDK-8087292.js Tue Nov 08 05:26:18 2016 +0000 +++ b/test/script/trusted/JDK-8087292.js Thu Jan 12 06:59:38 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -29,26 +29,58 @@ * @run */ +load(__DIR__ + "JDK-util.js") + +var jHomePath = System.getenv("JAVA_HOME") +var jLauncher = "${jHomePath}/bin/java" +var altjLauncher = which('java') + +if (windows) { + if(winCyg) { + jLauncher = "${jHomePath}" + "/bin/java.exe" + jLauncher = cygpath(jLauncher,outPath.windows) + } + else { + jLauncher = "${jHomePath}" + "\\bin\\java.exe" + altjLauncher = which('java.exe') + altjLauncher = cygpath(altjLauncher,outPath.windows) + } +} + +function exists(f) { + return Files.exists(Paths.get(f)) +} + +var javaLauncher = exists(jLauncher) ? jLauncher : altjLauncher + + +if (!exists(javaLauncher)) { + throw "no java launcher found; tried ${jLauncher} and ${altjLauncher}" +} + function tryExec() { try { - `java` + $EXEC("${javaLauncher}") } catch (e) { - print(e); + print(e) } // make sure we got non-zero ("failure") exit code! if ($EXIT == 0) { - print("Error: expected $EXIT code to be non-zero"); + print("Error: expected $EXIT code to be non-zero") } } +//convert windows paths to cygwin +if (windows) + javaLauncher = (winCyg) ? cygpath(javaLauncher,outPath.mixed).trim() : cygpath(javaLauncher,outPath.windows).trim() // no exception now! -tryExec(); +tryExec() // turn on error with non-zero exit code -$EXEC.throwOnError = true; -tryExec(); +$EXEC.throwOnError = true +tryExec() // no exception after this -$EXEC.throwOnError = false; -tryExec(); +$EXEC.throwOnError = false +tryExec()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/trusted/JDK-util.js Thu Jan 12 06:59:38 2017 +0000 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2016, 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. + */ + +/** + * This file contains utility functions used by other tests. + * @subtest + */ + +var Files = Java.type('java.nio.file.Files'), + Paths = Java.type('java.nio.file.Paths'), + System = Java.type('java.lang.System') + +var File = java.io.File +var windows = System.getProperty("os.name").startsWith("Windows") +var winCyg = false + +var outPath = { + windows:0, //C:\dir + mixed:1 //C:/dir +} + +if (windows) { + //Is there any better way to diffrentiate between cygwin/command prompt on windows + var term = System.getenv("TERM") + winCyg = term ? true:false +} + +/** + * Returns which command is selected from PATH + * @param cmd name of the command searched from PATH + */ +function which(cmd) { + var path = System.getenv("PATH") + var st = new java.util.StringTokenizer(path, File.pathSeparator) + while (st.hasMoreTokens()) { + var file = new File(st.nextToken(), cmd) + if (file.exists()) { + return (file.getAbsolutePath()) + } + } +} + +/** + * Unix cygpath implementation + * Supports only two outputs,windows(C:\dir\) and mixed(C:/dir/) + */ + +function cygpath(path,mode) { + + var newpath = path + if(path.startsWith("/cygdrive/")){ + var str = path.substring(10) + var index = str.indexOf('/',0) + var drv = str.substring(0,index) + var rstr = drv.toUpperCase() + ":" + newpath = str.replaceFirst(drv,rstr) + } + if (mode == outPath.windows) + return Paths.get(newpath).toString() + else { + newpath = newpath.replaceAll('\\\\','/') + return newpath + } + +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/src/jdk/nashorn/api/scripting/test/JDK_8148140_Test.java Thu Jan 12 06:59:38 2017 +0000 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ +package jdk.nashorn.api.scripting.test; + +import java.util.Arrays; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import jdk.nashorn.api.scripting.AbstractJSObject; + +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import static org.testng.Assert.*; + +/** + * @bug 8148140 + * @summary arguments are handled differently in apply for JS functions and AbstractJSObjects + */ +public class JDK_8148140_Test { + + ScriptEngine engine; + + static final String RESULT = "[1, 2, 3]"; + + @BeforeClass + public void setupTest() { + engine = new ScriptEngineManager().getEngineByName("js"); + engine.put("f", new AbstractJSObject() { + @Override + public boolean isFunction() { + return true; + } + @Override + public Object call(Object thiz, Object... args) { + return Arrays.deepToString(args); + } + }); + } + + @Test + public void testCallF() throws ScriptException { + assertEquals(RESULT, engine.eval("f(1,2,3)")); + } + + @Test + public void testApplyF() throws ScriptException { + assertEquals(RESULT, engine.eval("Function.prototype.apply.call(f, null, [1,2,3])")); + } + +}
--- a/test/src/jdk/nashorn/api/scripting/test/ScopeTest.java Tue Nov 08 05:26:18 2016 +0000 +++ b/test/src/jdk/nashorn/api/scripting/test/ScopeTest.java Thu Jan 12 06:59:38 2017 +0000 @@ -30,6 +30,8 @@ import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; import javax.script.Bindings; +import javax.script.Compilable; +import javax.script.CompiledScript; import javax.script.Invocable; import javax.script.ScriptContext; import javax.script.ScriptEngine; @@ -911,4 +913,27 @@ Object value = ((Invocable)engine).invokeFunction("newfunc"); assertTrue(((Number)value).intValue() == 42); } + + // @bug 8150219 ReferenceError in 1.8.0_72 + // When we create a Global for a non-default ScriptContext that needs one keep the + // ScriptContext associated with the Global so that invoke methods work as expected. + @Test + public void invokeFunctionWithCustomScriptContextTest() throws Exception { + final ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn"); + + // create an engine and a ScriptContext, but don't set it as default + ScriptContext scriptContext = new SimpleScriptContext(); + + // Set some value in the context + scriptContext.setAttribute("myString", "foo", ScriptContext.ENGINE_SCOPE); + + // Evaluate script with custom context and get back a function + final String script = "function (c) { return myString.indexOf(c); }"; + CompiledScript compiledScript = ((Compilable)engine).compile(script); + Object func = compiledScript.eval(scriptContext); + + // Invoked function should be able to see context it was evaluated with + Object result = ((Invocable) engine).invokeMethod(func, "call", func, "o", null); + assertTrue(((Number)result).intValue() == 1); + } }