# HG changeset patch # User asaha # Date 1434603479 25200 # Node ID 219967ffe903609bcc8724d8ee47310ed81bc688 # Parent 654ab44e8171dbb66c25743c7e377c11da222281# Parent 7475a2bd3c012f7dfd0532a344eb7efca56ac6e6 Merge diff -r 654ab44e8171 -r 219967ffe903 .hgtags --- a/.hgtags Wed Jun 10 23:17:34 2015 -0700 +++ b/.hgtags Wed Jun 17 21:57:59 2015 -0700 @@ -426,3 +426,4 @@ ff7052ce0f6b655d726cd0f77e9a5f8313361889 jdk8u60-b17 0b5c0f02a0b79ae0aa97520d65e5b520af8f1b2a jdk8u60-b18 3780124b6dbb100c2c4af2759b8f0e12a8bf1c4c jdk8u60-b19 +46a3d8588ad227dc390d84dfc0f89b9291395a36 jdk8u60-b20 diff -r 654ab44e8171 -r 219967ffe903 README --- a/README Wed Jun 10 23:17:34 2015 -0700 +++ b/README Wed Jun 17 21:57:59 2015 -0700 @@ -72,14 +72,11 @@ - Running tests Nashorn tests are TestNG based. Running tests requires downloading the -TestNG library and placing its jar file into the lib subdirectory: +TestNG library and placing its jar file into the test/lib subdirectory. This is +done automatically when executing the "ant externals" command to get external +test suites (see below). - # download and install TestNG - wget http://testng.org/testng-x.y.z.zip - unzip testng-x.y.z.zip - cp testng-x.y.z/testng-x.y.z.jar test/lib/testng.jar - -After that, you can run the tests using: +Once TestNG is properly installed, you can run the tests using: cd make ant clean test diff -r 654ab44e8171 -r 219967ffe903 make/build.xml --- a/make/build.xml Wed Jun 10 23:17:34 2015 -0700 +++ b/make/build.xml Wed Jun 17 21:57:59 2015 -0700 @@ -1,7 +1,7 @@ @@ -460,7 +460,7 @@ - + @@ -490,7 +490,7 @@ - + @@ -518,7 +518,7 @@ - + @@ -537,7 +537,7 @@ - + @@ -561,7 +561,7 @@ - + @@ -580,7 +580,7 @@ - + - + @@ -710,8 +710,8 @@ - - + + @@ -721,12 +721,20 @@ - - - + + + + + + + + + + - + + diff -r 654ab44e8171 -r 219967ffe903 make/project.properties --- a/make/project.properties Wed Jun 10 23:17:34 2015 -0700 +++ b/make/project.properties Wed Jun 17 21:57:59 2015 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2010, 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 @@ -77,8 +77,11 @@ # configuration for java flight recorder run.test.jvmargs.jfr=-XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:FlightRecorderOptions=defaultrecording=true,disk=true,dumponexit=true,dumponexitpath=${build.dir},stackdepth=128 +# test library location +test.lib=${basedir}${file.separator}test${file.separator}lib + # jars refererred -file.reference.testng.jar=test/lib/testng.jar +file.reference.testng.jar=${test.lib}${file.separator}testng.jar # Set testng verbose level # From TestNG docs: "the verbosity level (0 to 10 where 10 is most detailed) @@ -237,9 +240,9 @@ -fx \ ${test.script.dir}${file.separator}jfx.js -file.reference.jemmyfx.jar=test${file.separator}lib${file.separator}JemmyFX.jar -file.reference.jemmycore.jar=test${file.separator}lib${file.separator}JemmyCore.jar -file.reference.jemmyawtinput.jar=test${file.separator}lib${file.separator}JemmyAWTInput.jar +file.reference.jemmyfx.jar=${test.lib}${file.separator}JemmyFX.jar +file.reference.jemmycore.jar=${test.lib}${file.separator}JemmyCore.jar +file.reference.jemmyawtinput.jar=${test.lib}${file.separator}JemmyAWTInput.jar file.reference.jfxrt.jar=${java.home}${file.separator}lib${file.separator}ext${file.separator}jfxrt.jar testjfx.run.test.classpath=\ ${file.reference.jemmyfx.jar}${path.separator}\ diff -r 654ab44e8171 -r 219967ffe903 samples/autoimports.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/autoimports.js Wed Jun 17 21:57:59 2015 -0700 @@ -0,0 +1,163 @@ +# autoimports script requires -scripting mode + +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * It is tedious to import Java classes used in a script. Sometimes it is easier + * use simple names of java classes and have a script auto import Java classes. + * You can load this script at the start of an interactive jjs session or at the + * start of your script. This script defines a __noSuchProperty__ hook to auto + * import Java classes as needed and when they are referred to for the first time + * in your script. You can also call the "autoimports" function to print script + * statements that you need to use in your script, i.e., have the function generate + * a script to import Java classes used by your script so far. After running your + * script, you can call autoimports to get the exact Java imports you need and replace + * the autoimports load with the generated import statements (to avoid costly init of + * the autoimports script). + */ + +(function() { + var ArrayList = Java.type("java.util.ArrayList"); + var HashMap = Java.type("java.util.HashMap"); + var JarFile = Java.type("java.util.jar.JarFile"); + var File = Java.type("java.io.File"); + var Files = Java.type("java.nio.file.Files"); + var FileSystems = Java.type("java.nio.file.FileSystems"); + var System = Java.type("java.lang.System"); + var URI = Java.type("java.net.URI"); + + // initialize a class to package map by iterating all + // classes available in the system by walking through "jrt fs" + + var clsToPkg = new HashMap(); + + // locate rt.jar from sun.boot.class.path + function findRtJar() { + var paths = System.getProperty("sun.boot.class.path").split(File.pathSeparator); + for each (var p in paths) { + if (p.endsWith("rt.jar") && new File(p).exists()) { + return p; + } + } + } + + + function addToClsToPkg(c, p) { + if (clsToPkg.containsKey(c)) { + var val = clsToPkg.get(c); + if (val instanceof ArrayList) { + val.add(p); + } else { + var al = new ArrayList(); + al.add(val); + al.add(p); + clsToPkg.put(c, al); + } + } else { + clsToPkg.put(c, p); + } + } + + // handle collision and allow user to choose package + function getPkgOfCls(c) { + var val = clsToPkg.get(c); + if (val instanceof ArrayList) { + var count = 1; + print("Multiple matches for " + c + ", choose package:"); + for each (var v in val) { + print(count + ". " + v); + count++; + } + var choice = parseInt(readLine()); + if (isNaN(choice) || choice < 1 || choice > val.size()) { + print("invalid choice: " + choice); + return undefined; + } + return val.get(choice - 1); + } else { + return val; + } + } + + var rtJar = findRtJar(); + var stream = new JarFile(rtJar).stream(); + try { + stream.forEach( + function(entry) { + var str = entry.name; + if (str.endsWith(".class")) { + if (str.startsWith("java") || + str.startsWith("javax") || + str.startsWith("org")) { + var lastIdx = str.lastIndexOf('/'); + if (lastIdx != -1) { + var pkg = str.substring(0, lastIdx).replaceAll('/', '.'); + var cls = str.substring(lastIdx + 1, str.lastIndexOf(".class")); + addToClsToPkg(cls, pkg); + } + } + } + }); + } finally { + stream.close(); + } + + var imports = new ArrayList(); + var global = this; + var oldNoSuchProp = global.__noSuchProperty__; + this.__noSuchProperty__ = function(name) { + 'use strict'; + + if (clsToPkg.containsKey(name)) { + var pkg = getPkgOfCls(name); + if (pkg) { + var clsName = pkg + "." + name; + imports.add("var " + name + " = Java.type('" + clsName + "');"); + return global[name] = Java.type(clsName); + } + } else if (typeof oldNoSuchProp == 'function') { + return oldNoSuchProp.call(this, name); + } + + if (typeof this == 'undefined') { + throw new ReferenceError(name); + } else { + return undefined; + } + } + + this.autoimports = function() { + for each (var im in imports) { + print(im); + } + } +})(); diff -r 654ab44e8171 -r 219967ffe903 samples/dateconversion.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/dateconversion.js Wed Jun 17 21:57:59 2015 -0700 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Converting between #javascript Date and #java8 LocalDateTime with #nashorn + +// JavaScript Date with current time +var d = new Date(); +print(d); + +// Java 8 java.time classes used +var Instant = java.time.Instant; +var LocalDateTime = java.time.LocalDateTime; +var ZoneId = java.time.ZoneId; + +// Date.prototype.getTime + +// getTime() method returns the numeric value corresponding to the time +// for the specified date according to universal time. The value returned +// by the getTime() method is the number of milliseconds since 1 January 1970 00:00:00 UTC. +// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTime + +// Java Instant.ofEpochMilli to convert time in milliseconds to Instant object +// https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html#ofEpochMilli-long- + +var instant = Instant.ofEpochMilli(d.getTime()); + +// Instant to LocalDateTime using LocalDateTime.ofInstant +// https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html#ofInstant-java.time.Instant-java.time.ZoneId- + +var ldt = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); +print(ldt); + +// converting a LocalDateTime to JavaScript Date +// convert LocalDateTime to Instant first +// https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html#atZone-java.time.ZoneId- + +var instant = ldt.atZone(ZoneId.systemDefault()).toInstant(); + +// instant to to epoch milliseconds +// https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html#toEpochMilli-- +// and then to JavaScript Date from time in milliseconds +// https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date + +var d1 = new Date(instant.toEpochMilli()); +print(d1); diff -r 654ab44e8171 -r 219967ffe903 samples/exec.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/exec.js Wed Jun 17 21:57:59 2015 -0700 @@ -0,0 +1,50 @@ +# exec script requires -scripting mode + +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// The $EXEC builtin function can be used to run external commands: +$EXEC("ls") +$EXEC("ls -la") + +// It can also be given a string to use as stdin: +$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"]) + +// Output of running external commands is returned from $EXEC: +print($EXEC("ls")) + +// apply on $EXEC +print($EXEC.apply(this, ["ls"])); diff -r 654ab44e8171 -r 219967ffe903 samples/javahelp.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/javahelp.js Wed Jun 17 21:57:59 2015 -0700 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// script helpers to print meta info on Java instances and classes + +// print instance methods info on a Java object or static methods info of a Java class +function methods(jobj) { + if (! Java.isJavaObject(jobj)) { + throw new TypeError("not a Java object"); + } + + var isStatic = Java.isType(jobj); + var obj = Object.bindProperties({}, jobj); + for each (var i in obj) { + if (Java.isJavaMethod(i)) { + var str = String(i); + var idx = str.indexOf(' '); + var overloaded = str.substring(0, idx).endsWith("OverloadedDynamicMethod"); + var lastIdx = isStatic? str.lastIndexOf('] on') : str.lastIndexOf(']'); + print(str.substring(idx + 1, lastIdx) + (overloaded? "*" : "")) + } + } +} + +// print instance field names of a Java object or static field names of a Java class +function fields(jobj) { + if (! Java.isJavaObject(jobj)) { + throw new TypeError("not a Java object"); + } + + var obj = Object.bindProperties({}, jobj); + for (var i in obj) { + if (! Java.isJavaMethod(obj[i])) { + print(i); + } + } +} + +undefined; diff -r 654ab44e8171 -r 219967ffe903 samples/secondssince.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/secondssince.js Wed Jun 17 21:57:59 2015 -0700 @@ -0,0 +1,43 @@ +# usage: jjs secondssince.js + +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Number of seconds elapsed since the specified Instance #nashorn #javascript #java +// Input date and time in ISO 8601 format +// Example: 2001-01-01T00:00:00Z for 1 Jan 2001, 0 GMT + +var Instant = java.time.Instant; +var ChronoUnit = java.time.temporal.ChronoUnit; +print("Enter date time:"); +var sec = Instant.parse(readLine()). + until(Instant.now(), ChronoUnit.SECONDS); +print(sec); diff -r 654ab44e8171 -r 219967ffe903 src/jdk/internal/dynalink/DynamicLinker.java --- a/src/jdk/internal/dynalink/DynamicLinker.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/internal/dynalink/DynamicLinker.java Wed Jun 17 21:57:59 2015 -0700 @@ -99,10 +99,12 @@ import jdk.internal.dynalink.support.RuntimeContextLinkRequestImpl; /** - * The linker for {@link RelinkableCallSite} objects. Users of it (scripting frameworks and language runtimes) have to - * create a linker using the {@link DynamicLinkerFactory} and invoke its link method from the invokedynamic bootstrap - * methods to set the target of all the call sites in the code they generate. Usual usage would be to create one class - * per language runtime to contain one linker instance as: + * The linker for {@link RelinkableCallSite} objects. Users of it (scripting + * frameworks and language runtimes) have to create a linker using the + * {@link DynamicLinkerFactory} and invoke its link method from the invokedynamic + * bootstrap methods to set the target of all the call sites in the code they + * generate. Usual usage would be to create one class per language runtime to + * contain one linker instance as: * *
  * class MyLanguageRuntime {
@@ -123,19 +125,27 @@
  *
  * Note how there are three components you will need to provide here:
  * 
    - *
  • You're expected to provide a {@link GuardingDynamicLinker} for your own language. If your runtime doesn't - * have its own language and/or object model (i.e. it's a generic scripting shell), you don't need to implement a - * dynamic linker; you would simply not invoke the {@code setPrioritizedLinker} method on the factory, or even better, - * simply use {@link DefaultBootstrapper}.
  • - *
  • The performance of the programs can depend on your choice of the class to represent call sites. The above - * example used {@link MonomorphicCallSite}, but you might want to use {@link ChainedCallSite} instead. You'll need to - * experiment and decide what fits your language runtime the best. You can subclass either of these or roll your own if - * you need to.
  • - *
  • You also need to provide {@link CallSiteDescriptor}s to your call sites. They are immutable objects that contain - * all the information about the call site: the class performing the lookups, the name of the method being invoked, and - * the method signature. The library has a default {@link CallSiteDescriptorFactory} for descriptors that you can use, - * or you can create your own descriptor classes, especially if you need to add further information (values passed in + * + *
  • You're expected to provide a {@link GuardingDynamicLinker} for your own + * language. If your runtime doesn't have its own language and/or object model + * (i.e., it's a generic scripting shell), you don't need to implement a dynamic + * linker; you would simply not invoke the {@code setPrioritizedLinker} method + * on the factory, or even better, simply use {@link DefaultBootstrapper}.
  • + * + *
  • The performance of the programs can depend on your choice of the class to + * represent call sites. The above example used {@link MonomorphicCallSite}, but + * you might want to use {@link ChainedCallSite} instead. You'll need to + * experiment and decide what fits your language runtime the best. You can + * subclass either of these or roll your own if you need to.
  • + * + *
  • You also need to provide {@link CallSiteDescriptor}s to your call sites. + * They are immutable objects that contain all the information about the call + * site: the class performing the lookups, the name of the method being invoked, + * and the method signature. The library has a default {@link CallSiteDescriptorFactory} + * for descriptors that you can use, or you can create your own descriptor + * classes, especially if you need to add further information (values passed in * additional parameters to the bootstrap method) to them.
  • + * *
* * @author Attila Szegedi @@ -176,11 +186,15 @@ } /** - * Links an invokedynamic call site. It will install a method handle into the call site that invokes the relinking - * mechanism of this linker. Next time the call site is invoked, it will be linked for the actual arguments it was - * invoked with. + * Links an invokedynamic call site. It will install a method handle into + * the call site that invokes the relinking mechanism of this linker. Next + * time the call site is invoked, it will be linked for the actual arguments + * it was invoked with. * + * @param the particular subclass of {@link RelinkableCallSite} for + * which to create a link. * @param callSite the call site to link. + * * @return the callSite, for easy call chaining. */ public T link(final T callSite) { @@ -189,10 +203,13 @@ } /** - * Returns the object representing the lower level linker services of this class that are normally exposed to - * individual language-specific linkers. While as a user of this class you normally only care about the - * {@link #link(RelinkableCallSite)} method, in certain circumstances you might want to use the lower level services - * directly; either to lookup specific method handles, to access the type converters, and so on. + * Returns the object representing the lower level linker services of this + * class that are normally exposed to individual language-specific linkers. + * While as a user of this class you normally only care about the + * {@link #link(RelinkableCallSite)} method, in certain circumstances you + * might want to use the lower level services directly; either to lookup + * specific method handles, to access the type converters, and so on. + * * @return the object representing the linker services of this class. */ public LinkerServices getLinkerServices() { @@ -218,7 +235,9 @@ * * @param callSite the call site itself * @param arguments arguments to the invocation + * * @return return the method handle for the invocation + * * @throws Exception rethrows any exception thrown by the linkers */ @SuppressWarnings("unused") @@ -272,11 +291,15 @@ } /** - * Returns a stack trace element describing the location of the call site currently being linked on the current - * thread. The operation internally creates a Throwable object and inspects its stack trace, so it's potentially - * expensive. The recommended usage for it is in writing diagnostics code. - * @return a stack trace element describing the location of the call site currently being linked, or null if it is - * not invoked while a call site is being linked. + * Returns a stack trace element describing the location of the call site + * currently being linked on the current thread. The operation internally + * creates a Throwable object and inspects its stack trace, so it's + * potentially expensive. The recommended usage for it is in writing + * diagnostics code. + * + * @return a stack trace element describing the location of the call site + * currently being linked, or null if it is not invoked while a call + * site is being linked. */ public static StackTraceElement getLinkedCallSiteLocation() { final StackTraceElement[] trace = new Throwable().getStackTrace(); @@ -290,8 +313,10 @@ } /** - * Deprecated because of not precise name. + * Deprecated because of imprecise name. + * * @deprecated Use {@link #getLinkedCallSiteLocation()} instead. + * * @return see non-deprecated method */ @Deprecated @@ -300,20 +325,26 @@ } /** - * Returns true if the frame represents {@code MethodHandleNatives.linkCallSite()}, the frame immediately on top of - * the call site frame when the call site is being linked for the first time. + * Returns {@code true} if the frame represents {@code MethodHandleNatives.linkCallSite()}, + * the frame immediately on top of the call site frame when the call site is + * being linked for the first time. + * * @param frame the frame - * @return true if this frame represents {@code MethodHandleNatives.linkCallSite()} + * + * @return {@code true} if this frame represents {@code MethodHandleNatives.linkCallSite()}. */ private static boolean isInitialLinkFrame(final StackTraceElement frame) { return testFrame(frame, INITIAL_LINK_METHOD_NAME, INITIAL_LINK_CLASS_NAME); } /** - * Returns true if the frame represents {@code DynamicLinker.relink()}, the frame immediately on top of the call - * site frame when the call site is being relinked (linked for second and subsequent times). + * Returns {@code true} if the frame represents {@code DynamicLinker.relink()}, + * the frame immediately on top of the call site frame when the call site is + * being relinked (linked for second and subsequent times). + * * @param frame the frame - * @return true if this frame represents {@code DynamicLinker.relink()} + * + * @return {@code true} if this frame represents {@code DynamicLinker.relink()}. */ private static boolean isRelinkFrame(final StackTraceElement frame) { return testFrame(frame, RELINK_METHOD_NAME, CLASS_NAME); diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/api/scripting/AbstractJSObject.java --- a/src/jdk/nashorn/api/scripting/AbstractJSObject.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/api/scripting/AbstractJSObject.java Wed Jun 17 21:57:59 2015 -0700 @@ -28,6 +28,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Set; +import jdk.nashorn.internal.runtime.JSONListAdapter; import jdk.nashorn.internal.runtime.JSType; /** @@ -282,6 +283,8 @@ public static Object getDefaultValue(final JSObject jsobj, final Class hint) { if (jsobj instanceof AbstractJSObject) { return ((AbstractJSObject)jsobj).getDefaultValue(hint); + } else if (jsobj instanceof JSONListAdapter) { + return ((JSONListAdapter)jsobj).getDefaultValue(hint); } return DefaultValueImpl.getDefaultValue(jsobj, hint); } diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/api/scripting/NashornScriptEngine.java --- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Wed Jun 17 21:57:59 2015 -0700 @@ -354,8 +354,7 @@ } }, CREATE_GLOBAL_ACC_CTXT); - nashornContext.initGlobal(newGlobal, this); - newGlobal.setScriptContext(ctxt); + nashornContext.initGlobal(newGlobal, this, ctxt); return newGlobal; } @@ -404,7 +403,7 @@ return evalImpl(script, ctxt, getNashornGlobalFrom(ctxt)); } - private static Object evalImpl(final Context.MultiGlobalCompiledScript mgcs, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException { + private Object evalImpl(final Context.MultiGlobalCompiledScript mgcs, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException { final Global oldGlobal = Context.getGlobal(); final boolean globalChanged = (oldGlobal != ctxtGlobal); try { @@ -413,8 +412,13 @@ } final ScriptFunction script = mgcs.getFunction(ctxtGlobal); + final ScriptContext oldCtxt = ctxtGlobal.getScriptContext(); ctxtGlobal.setScriptContext(ctxt); - return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal)); + try { + return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal)); + } finally { + ctxtGlobal.setScriptContext(oldCtxt); + } } catch (final Exception e) { throwAsScriptException(e, ctxtGlobal); throw new AssertionError("should not reach here"); @@ -425,7 +429,7 @@ } } - private static Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException { + private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException { if (script == null) { return null; } @@ -436,8 +440,13 @@ Context.setGlobal(ctxtGlobal); } + final ScriptContext oldCtxt = ctxtGlobal.getScriptContext(); ctxtGlobal.setScriptContext(ctxt); - return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal)); + try { + return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal)); + } finally { + ctxtGlobal.setScriptContext(oldCtxt); + } } catch (final Exception e) { throwAsScriptException(e, ctxtGlobal); throw new AssertionError("should not reach here"); diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java --- a/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java Wed Jun 17 21:57:59 2015 -0700 @@ -178,8 +178,7 @@ * denies {@code RuntimePermission("nashorn.setConfig")} */ public ScriptEngine getScriptEngine(final ClassFilter classFilter) { - Objects.requireNonNull(classFilter); - return newEngine(DEFAULT_OPTIONS, getAppClassLoader(), classFilter); + return newEngine(DEFAULT_OPTIONS, getAppClassLoader(), Objects.requireNonNull(classFilter)); } /** @@ -193,8 +192,7 @@ * denies {@code RuntimePermission("nashorn.setConfig")} */ public ScriptEngine getScriptEngine(final String... args) { - Objects.requireNonNull(args); - return newEngine(args, getAppClassLoader(), null); + return newEngine(Objects.requireNonNull(args), getAppClassLoader(), null); } /** @@ -209,8 +207,7 @@ * denies {@code RuntimePermission("nashorn.setConfig")} */ public ScriptEngine getScriptEngine(final String[] args, final ClassLoader appLoader) { - Objects.requireNonNull(args); - return newEngine(args, appLoader, null); + return newEngine(Objects.requireNonNull(args), appLoader, null); } /** @@ -226,9 +223,7 @@ * denies {@code RuntimePermission("nashorn.setConfig")} */ public ScriptEngine getScriptEngine(final String[] args, final ClassLoader appLoader, final ClassFilter classFilter) { - Objects.requireNonNull(args); - Objects.requireNonNull(classFilter); - return newEngine(args, appLoader, classFilter); + return newEngine(Objects.requireNonNull(args), appLoader, Objects.requireNonNull(classFilter)); } private ScriptEngine newEngine(final String[] args, final ClassLoader appLoader, final ClassFilter classFilter) { diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/api/scripting/ScriptObjectMirror.java --- a/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java Wed Jun 17 21:57:59 2015 -0700 @@ -47,6 +47,7 @@ import jdk.nashorn.internal.runtime.ConsString; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ECMAException; +import jdk.nashorn.internal.runtime.JSONListAdapter; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; @@ -72,6 +73,7 @@ private final ScriptObject sobj; private final Global global; private final boolean strict; + private final boolean jsonCompatible; @Override public boolean equals(final Object other) { @@ -110,9 +112,9 @@ } if (sobj instanceof ScriptFunction) { - final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args; - final Object self = globalChanged? wrap(thiz, oldGlobal) : thiz; - return wrap(ScriptRuntime.apply((ScriptFunction)sobj, unwrap(self, global), unwrapArray(modArgs, global)), global); + final Object[] modArgs = globalChanged? wrapArrayLikeMe(args, oldGlobal) : args; + final Object self = globalChanged? wrapLikeMe(thiz, oldGlobal) : thiz; + return wrapLikeMe(ScriptRuntime.apply((ScriptFunction)sobj, unwrap(self, global), unwrapArray(modArgs, global))); } throw new RuntimeException("not a function: " + toString()); @@ -140,8 +142,8 @@ } if (sobj instanceof ScriptFunction) { - final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args; - return wrap(ScriptRuntime.construct((ScriptFunction)sobj, unwrapArray(modArgs, global)), global); + final Object[] modArgs = globalChanged? wrapArrayLikeMe(args, oldGlobal) : args; + return wrapLikeMe(ScriptRuntime.construct((ScriptFunction)sobj, unwrapArray(modArgs, global))); } throw new RuntimeException("not a constructor: " + toString()); @@ -170,7 +172,7 @@ return Context.getContext(); } }, GET_CONTEXT_ACC_CTXT); - return wrap(context.eval(global, s, sobj, null, false), global); + return wrapLikeMe(context.eval(global, s, sobj, null)); } }); } @@ -193,8 +195,8 @@ final Object val = sobj.get(functionName); if (val instanceof ScriptFunction) { - final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args; - return wrap(ScriptRuntime.apply((ScriptFunction)val, sobj, unwrapArray(modArgs, global)), global); + final Object[] modArgs = globalChanged? wrapArrayLikeMe(args, oldGlobal) : args; + return wrapLikeMe(ScriptRuntime.apply((ScriptFunction)val, sobj, unwrapArray(modArgs, global))); } else if (val instanceof JSObject && ((JSObject)val).isFunction()) { return ((JSObject)val).call(sobj, args); } @@ -218,7 +220,7 @@ Objects.requireNonNull(name); return inGlobal(new Callable() { @Override public Object call() { - return wrap(sobj.get(name), global); + return wrapLikeMe(sobj.get(name)); } }); } @@ -227,7 +229,7 @@ public Object getSlot(final int index) { return inGlobal(new Callable() { @Override public Object call() { - return wrap(sobj.get(index), global); + return wrapLikeMe(sobj.get(index)); } }); } @@ -253,14 +255,12 @@ @Override public void removeMember(final String name) { - Objects.requireNonNull(name); - remove(name); + remove(Objects.requireNonNull(name)); } @Override public void setMember(final String name, final Object value) { - Objects.requireNonNull(name); - put(name, value); + put(Objects.requireNonNull(name), value); } @Override @@ -368,7 +368,7 @@ while (iter.hasNext()) { final String key = iter.next(); - final Object value = translateUndefined(wrap(sobj.get(key), global)); + final Object value = translateUndefined(wrapLikeMe(sobj.get(key))); entries.add(new AbstractMap.SimpleImmutableEntry<>(key, value)); } @@ -382,7 +382,7 @@ checkKey(key); return inGlobal(new Callable() { @Override public Object call() { - return translateUndefined(wrap(sobj.get(key), global)); + return translateUndefined(wrapLikeMe(sobj.get(key))); } }); } @@ -419,22 +419,22 @@ final boolean globalChanged = (oldGlobal != global); return inGlobal(new Callable() { @Override public Object call() { - final Object modValue = globalChanged? wrap(value, oldGlobal) : value; - return translateUndefined(wrap(sobj.put(key, unwrap(modValue, global), strict), global)); + final Object modValue = globalChanged? wrapLikeMe(value, oldGlobal) : value; + return translateUndefined(wrapLikeMe(sobj.put(key, unwrap(modValue, global), strict))); } }); } @Override public void putAll(final Map map) { - Objects.requireNonNull(map, "map is null"); + Objects.requireNonNull(map); final ScriptObject oldGlobal = Context.getGlobal(); final boolean globalChanged = (oldGlobal != global); inGlobal(new Callable() { @Override public Object call() { for (final Map.Entry entry : map.entrySet()) { final Object value = entry.getValue(); - final Object modValue = globalChanged? wrap(value, oldGlobal) : value; + final Object modValue = globalChanged? wrapLikeMe(value, oldGlobal) : value; final String key = entry.getKey(); checkKey(key); sobj.set(key, unwrap(modValue, global), getCallSiteFlags()); @@ -449,7 +449,7 @@ checkKey(key); return inGlobal(new Callable() { @Override public Object call() { - return translateUndefined(wrap(sobj.remove(key, strict), global)); + return translateUndefined(wrapLikeMe(sobj.remove(key, strict))); } }); } @@ -486,7 +486,7 @@ final Iterator iter = sobj.valueIterator(); while (iter.hasNext()) { - values.add(translateUndefined(wrap(iter.next(), global))); + values.add(translateUndefined(wrapLikeMe(iter.next()))); } return Collections.unmodifiableList(values); @@ -503,7 +503,7 @@ public Object getProto() { return inGlobal(new Callable() { @Override public Object call() { - return wrap(sobj.getProto(), global); + return wrapLikeMe(sobj.getProto()); } }); } @@ -532,7 +532,7 @@ public Object getOwnPropertyDescriptor(final String key) { return inGlobal(new Callable() { @Override public Object call() { - return wrap(sobj.getOwnPropertyDescriptor(key), global); + return wrapLikeMe(sobj.getOwnPropertyDescriptor(key)); } }); } @@ -661,16 +661,76 @@ * @return wrapped/converted object */ public static Object wrap(final Object obj, final Object homeGlobal) { + return wrap(obj, homeGlobal, false); + } + + /** + * Make a script object mirror on given object if needed. Also converts ConsString instances to Strings. The + * created wrapper will implement the Java {@code List} interface if {@code obj} is a JavaScript + * {@code Array} object; this is compatible with Java JSON libraries expectations. Arrays retrieved through its + * properties (transitively) will also implement the list interface. + * + * @param obj object to be wrapped/converted + * @param homeGlobal global to which this object belongs. Not used for ConsStrings. + * @return wrapped/converted object + */ + public static Object wrapAsJSONCompatible(final Object obj, final Object homeGlobal) { + return wrap(obj, homeGlobal, true); + } + + /** + * Make a script object mirror on given object if needed. Also converts ConsString instances to Strings. + * + * @param obj object to be wrapped/converted + * @param homeGlobal global to which this object belongs. Not used for ConsStrings. + * @param jsonCompatible if true, the created wrapper will implement the Java {@code List} interface if + * {@code obj} is a JavaScript {@code Array} object. Arrays retrieved through its properties (transitively) + * will also implement the list interface. + * @return wrapped/converted object + */ + private static Object wrap(final Object obj, final Object homeGlobal, final boolean jsonCompatible) { if(obj instanceof ScriptObject) { - return homeGlobal instanceof Global ? new ScriptObjectMirror((ScriptObject)obj, (Global)homeGlobal) : obj; - } - if(obj instanceof ConsString) { + if (!(homeGlobal instanceof Global)) { + return obj; + } + final ScriptObject sobj = (ScriptObject)obj; + final Global global = (Global)homeGlobal; + final ScriptObjectMirror mirror = new ScriptObjectMirror(sobj, global, jsonCompatible); + if (jsonCompatible && sobj.isArray()) { + return new JSONListAdapter(mirror, global); + } + return mirror; + } else if(obj instanceof ConsString) { return obj.toString(); + } else if (jsonCompatible && obj instanceof ScriptObjectMirror) { + // Since choosing JSON compatible representation is an explicit decision on user's part, if we're asked to + // wrap a mirror that was not JSON compatible, explicitly create its compatible counterpart following the + // principle of least surprise. + return ((ScriptObjectMirror)obj).asJSONCompatible(); } return obj; } /** + * Wraps the passed object with the same jsonCompatible flag as this mirror. + * @param obj the object + * @param homeGlobal the object's home global. + * @return a wrapper for the object. + */ + private Object wrapLikeMe(final Object obj, final Object homeGlobal) { + return wrap(obj, homeGlobal, jsonCompatible); + } + + /** + * Wraps the passed object with the same home global and jsonCompatible flag as this mirror. + * @param obj the object + * @return a wrapper for the object. + */ + private Object wrapLikeMe(final Object obj) { + return wrapLikeMe(obj, global); + } + + /** * Unwrap a script object mirror if needed. * * @param obj object to be unwrapped @@ -681,6 +741,8 @@ if (obj instanceof ScriptObjectMirror) { final ScriptObjectMirror mirror = (ScriptObjectMirror)obj; return (mirror.global == homeGlobal)? mirror.sobj : obj; + } else if (obj instanceof JSONListAdapter) { + return ((JSONListAdapter)obj).unwrap(homeGlobal); } return obj; @@ -694,6 +756,10 @@ * @return wrapped array */ public static Object[] wrapArray(final Object[] args, final Object homeGlobal) { + return wrapArray(args, homeGlobal, false); + } + + private static Object[] wrapArray(final Object[] args, final Object homeGlobal, final boolean jsonCompatible) { if (args == null || args.length == 0) { return args; } @@ -701,12 +767,16 @@ final Object[] newArgs = new Object[args.length]; int index = 0; for (final Object obj : args) { - newArgs[index] = wrap(obj, homeGlobal); + newArgs[index] = wrap(obj, homeGlobal, jsonCompatible); index++; } return newArgs; } + private Object[] wrapArrayLikeMe(final Object[] args, final Object homeGlobal) { + return wrapArray(args, homeGlobal, jsonCompatible); + } + /** * Unwrap an array of script object mirrors if needed. * @@ -748,12 +818,17 @@ // package-privates below this. ScriptObjectMirror(final ScriptObject sobj, final Global global) { + this(sobj, global, false); + } + + private ScriptObjectMirror(final ScriptObject sobj, final Global global, final boolean jsonCompatible) { assert sobj != null : "ScriptObjectMirror on null!"; assert global != null : "home Global is null"; this.sobj = sobj; this.global = global; this.strict = global.isStrictContext(); + this.jsonCompatible = jsonCompatible; } // accessors for script engine @@ -838,4 +913,11 @@ } }); } + + private ScriptObjectMirror asJSONCompatible() { + if (this.jsonCompatible) { + return this; + } + return new ScriptObjectMirror(sobj, global, true); + } } diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/api/scripting/URLReader.java --- a/src/jdk/nashorn/api/scripting/URLReader.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/api/scripting/URLReader.java Wed Jun 17 21:57:59 2015 -0700 @@ -78,8 +78,7 @@ * @throws NullPointerException if url is null */ public URLReader(final URL url, final Charset cs) { - Objects.requireNonNull(url); - this.url = url; + this.url = Objects.requireNonNull(url); this.cs = cs; } diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/codegen/ClassEmitter.java --- a/src/jdk/nashorn/internal/codegen/ClassEmitter.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/codegen/ClassEmitter.java Wed Jun 17 21:57:59 2015 -0700 @@ -100,7 +100,6 @@ * There is also a very nice debug interface that can emit formatted * bytecodes that have been written. This is enabled by setting the * environment "nashorn.codegen.debug" to true, or --log=codegen:{@literal } - *

* * @see Compiler */ @@ -144,7 +143,7 @@ /** * Constructor - only used internally in this class as it breaks - * abstraction towards ASM or other code generator below + * abstraction towards ASM or other code generator below. * * @param env script environment * @param cw ASM classwriter @@ -157,7 +156,8 @@ } /** - * Return the method names encountered + * Return the method names encountered. + * * @return method names */ public Set getMethodNames() { @@ -165,12 +165,13 @@ } /** - * Constructor + * Constructor. * * @param env script environment * @param className name of class to weave * @param superClassName super class name for class - * @param interfaceNames names of interfaces implemented by this class, or null if none + * @param interfaceNames names of interfaces implemented by this class, or + * {@code null} if none */ ClassEmitter(final Context context, final String className, final String superClassName, final String... interfaceNames) { this(context, new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS)); @@ -178,7 +179,7 @@ } /** - * Constructor from the compiler + * Constructor from the compiler. * * @param env Script environment * @param sourceName Source name @@ -217,7 +218,6 @@ } /** - * Returns the name of the compile unit class name. * @return the name of the compile unit class name. */ String getUnitClassName() { @@ -225,7 +225,8 @@ } /** - * Get the method count, including init and clinit methods + * Get the method count, including init and clinit methods. + * * @return method count */ public int getMethodCount() { @@ -233,7 +234,8 @@ } /** - * Get the clinit count + * Get the clinit count. + * * @return clinit count */ public int getClinitCount() { @@ -241,7 +243,8 @@ } /** - * Get the init count + * Get the init count. + * * @return init count */ public int getInitCount() { @@ -249,7 +252,8 @@ } /** - * Get the field count + * Get the field count. + * * @return field count */ public int getFieldCount() { @@ -260,6 +264,7 @@ * Convert a binary name to a package/class name. * * @param name Binary name. + * * @return Package/class name. */ private static String pathName(final String name) { @@ -268,6 +273,7 @@ /** * Define the static fields common in all scripts. + * * @param strictMode Should we generate this method in strict mode */ private void defineCommonStatics(final boolean strictMode) { @@ -284,8 +290,8 @@ } /** - * Define static utilities common needed in scripts. These are per compile unit - * and therefore have to be defined here and not in code gen. + * Define static utilities common needed in scripts. These are per compile + * unit and therefore have to be defined here and not in code gen. */ private void defineCommonUtilities() { assert unitClassName != null; @@ -333,7 +339,9 @@ } /** - * Constructs a primitive specific method for getting the ith entry from the constants table as an array. + * Constructs a primitive specific method for getting the ith entry from the + * constants table as an array. + * * @param clazz Array class. */ private void defineGetArrayMethod(final Class clazz) { @@ -356,7 +364,9 @@ /** * Generate the name of a get array from constant pool method. + * * @param clazz Name of array class. + * * @return Method name. */ static String getArrayMethodName(final Class clazz) { @@ -366,6 +376,7 @@ /** * Ensure a get constant method is issued for the class. + * * @param clazz Class of constant. */ void needGetConstantMethod(final Class clazz) { @@ -373,12 +384,12 @@ } /** - * Inspect class name and decide whether we are generating a ScriptObject class + * Inspect class name and decide whether we are generating a ScriptObject class. * * @param scriptPrefix the script class prefix for the current script * @param type the type to check * - * @return true if type is ScriptObject + * @return {@code true} if type is ScriptObject */ private static boolean isScriptObject(final String scriptPrefix, final String type) { if (type.startsWith(scriptPrefix)) { @@ -393,14 +404,14 @@ } /** - * Call at beginning of class emission + * Call at beginning of class emission. */ public void begin() { classStarted = true; } /** - * Call at end of class emission + * Call at end of class emission. */ public void end() { assert classStarted : "class not started for " + unitClassName; @@ -424,7 +435,9 @@ /** * Disassemble an array of byte code. + * * @param bytecode byte array representing bytecode + * * @return disassembly as human readable string */ static String disassemble(final byte[] bytecode) { @@ -446,7 +459,7 @@ } /** - * Call back from MethodEmitter for method start + * Call back from MethodEmitter for method start. * * @see MethodEmitter * @@ -458,7 +471,7 @@ } /** - * Call back from MethodEmitter for method end + * Call back from MethodEmitter for method end. * * @see MethodEmitter * @@ -470,7 +483,7 @@ } /** - * Add a new method to the class - defaults to public method + * Add a new method to the class - defaults to public method. * * @param methodName name of method * @param rtype return type of the method @@ -483,7 +496,7 @@ } /** - * Add a new method to the class - defaults to public method + * Add a new method to the class - defaults to public method. * * @param methodFlags access flags for the method * @param methodName name of method @@ -499,7 +512,7 @@ } /** - * Add a new method to the class - defaults to public method + * Add a new method to the class - defaults to public method. * * @param methodName name of method * @param descriptor descriptor of method @@ -511,7 +524,7 @@ } /** - * Add a new method to the class - defaults to public method + * Add a new method to the class - defaults to public method. * * @param methodFlags access flags for the method * @param methodName name of method @@ -526,9 +539,10 @@ } /** - * Add a new method to the class, representing a function node + * Add a new method to the class, representing a function node. * * @param functionNode the function node to generate a method for + * * @return method emitter to use for weaving this method */ MethodEmitter method(final FunctionNode functionNode) { @@ -546,9 +560,11 @@ } /** - * Add a new method to the class, representing a rest-of version of the function node + * Add a new method to the class, representing a rest-of version of the + * function node. * * @param functionNode the function node to generate a method for + * * @return method emitter to use for weaving this method */ MethodEmitter restOfMethod(final FunctionNode functionNode) { @@ -566,7 +582,7 @@ /** - * Start generating the method in the class + * Start generating the method in the class. * * @return method emitter to use for weaving */ @@ -576,7 +592,7 @@ } /** - * Start generating an ()V method in the class + * Start generating an ()V method in the class. * * @return method emitter to use for weaving ()V */ @@ -586,7 +602,7 @@ } /** - * Start generating an ()V method in the class + * Start generating an ()V method in the class. * * @param ptypes parameter types for constructor * @return method emitter to use for weaving ()V @@ -597,7 +613,7 @@ } /** - * Start generating an (...)V method in the class + * Start generating an (...)V method in the class. * * @param flags access flags for the constructor * @param ptypes parameter types for the constructor @@ -610,7 +626,7 @@ } /** - * Add a field to the class, initialized to a value + * Add a field to the class, initialized to a value. * * @param fieldFlags flags, e.g. should it be static or public etc * @param fieldName name of field @@ -625,7 +641,7 @@ } /** - * Add a field to the class + * Add a field to the class. * * @param fieldFlags access flags for the field * @param fieldName name of field @@ -638,7 +654,7 @@ } /** - * Add a field to the class - defaults to public + * Add a field to the class - defaults to public. * * @param fieldName name of field * @param fieldType type of field @@ -651,7 +667,8 @@ * Return a bytecode array from this ClassEmitter. The ClassEmitter must * have been ended (having its end function called) for this to work. * - * @return byte code array for generated class, null if class generation hasn't been ended with {@link ClassEmitter#end()} + * @return byte code array for generated class, {@code null} if class + * generation hasn't been ended with {@link ClassEmitter#end()}. */ byte[] toByteArray() { assert classEnded; @@ -663,13 +680,9 @@ } /** - * Abstraction for flags used in class emission - * - * We provide abstraction separating these from the underlying bytecode - * emitter. - * - * Flags are provided for method handles, protection levels, static/virtual - * fields/methods. + * Abstraction for flags used in class emission. We provide abstraction + * separating these from the underlying bytecode emitter. Flags are provided + * for method handles, protection levels, static/virtual fields/methods. */ static enum Flag { /** method handle with static access */ @@ -707,10 +720,12 @@ } /** - * Return the corresponding ASM flag value for an enum set of flags + * Return the corresponding ASM flag value for an enum set of flags. * * @param flags enum set of flags - * @return an integer value representing the flags intrinsic values or:ed together + * + * @return an integer value representing the flags intrinsic values + * or:ed together */ static int getValue(final EnumSet flags) { int v = 0; diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/codegen/CompilationPhase.java --- a/src/jdk/nashorn/internal/codegen/CompilationPhase.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/codegen/CompilationPhase.java Wed Jun 17 21:57:59 2015 -0700 @@ -363,7 +363,7 @@ //partial code generation final FunctionNode newFunctionNode = transformFunction(fn, new ReplaceCompileUnits() { @Override - CompileUnit getReplacement(CompileUnit original) { + CompileUnit getReplacement(final CompileUnit original) { return map.get(original); } diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/codegen/CompileUnit.java --- a/src/jdk/nashorn/internal/codegen/CompileUnit.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/codegen/CompileUnit.java Wed Jun 17 21:57:59 2015 -0700 @@ -122,8 +122,7 @@ * @param clazz class with code for this compile unit */ void setCode(final Class clazz) { - Objects.requireNonNull(clazz); - this.clazz = clazz; + this.clazz = Objects.requireNonNull(clazz); // Revisit this - refactor to avoid null-ed out non-final fields // null out emitter this.classEmitter = null; diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/codegen/SplitIntoFunctions.java --- a/src/jdk/nashorn/internal/codegen/SplitIntoFunctions.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/codegen/SplitIntoFunctions.java Wed Jun 17 21:57:59 2015 -0700 @@ -101,7 +101,7 @@ public SplitIntoFunctions(final Compiler compiler) { super(new BlockLexicalContext() { @Override - protected Block afterSetStatements(Block block) { + protected Block afterSetStatements(final Block block) { for(Statement stmt: block.getStatements()) { assert !(stmt instanceof SplitNode); } @@ -301,7 +301,7 @@ } @Override - public boolean enterVarNode(VarNode varNode) { + public boolean enterVarNode(final VarNode varNode) { if (!inSplitNode()) { return super.enterVarNode(varNode); } diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/ir/LexicalContext.java --- a/src/jdk/nashorn/internal/ir/LexicalContext.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/ir/LexicalContext.java Wed Jun 17 21:57:59 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -31,11 +31,13 @@ import jdk.nashorn.internal.runtime.Source; /** - * A class that tracks the current lexical context of node visitation as a stack of {@link Block} nodes. Has special - * methods to retrieve useful subsets of the context. + * A class that tracks the current lexical context of node visitation as a stack + * of {@link Block} nodes. Has special methods to retrieve useful subsets of the + * context. * - * This is implemented with a primitive array and a stack pointer, because it really makes a difference - * performance wise. None of the collection classes were optimal + * This is implemented with a primitive array and a stack pointer, because it + * really makes a difference performance-wise. None of the collection classes + * were optimal. */ public class LexicalContext { private LexicalContextNode[] stack; @@ -79,6 +81,7 @@ * {@link Block#NEEDS_SCOPE} because it atomically also sets the * {@link FunctionNode#HAS_SCOPE_BLOCK} flag on the block's containing * function. + * * @param block the block that needs to be marked as creating a scope. */ public void setBlockNeedsScope(final Block block) { @@ -97,8 +100,10 @@ } /** - * Get the flags for a lexical context node on the stack + * Get the flags for a lexical context node on the stack. + * * @param node node + * * @return the flags for the node */ public int getFlags(final LexicalContextNode node) { @@ -112,8 +117,10 @@ /** * Get the function body of a function node on the lexical context - * stack. This will trigger an assertion if node isn't present + * stack. This will trigger an assertion if node isn't present. + * * @param functionNode function node + * * @return body of function node */ public Block getFunctionBody(final FunctionNode functionNode) { @@ -126,15 +133,16 @@ } /** - * Return all nodes in the LexicalContext - * @return all nodes + * @return all nodes in the LexicalContext. */ public Iterator getAllNodes() { return new NodeIterator<>(LexicalContextNode.class); } /** - * Returns the outermost function in this context. It is either the program, or a lazily compiled function. + * Returns the outermost function in this context. It is either the program, + * or a lazily compiled function. + * * @return the outermost function in this context. */ public FunctionNode getOutermostFunction() { @@ -142,8 +150,12 @@ } /** - * Pushes a new block on top of the context, making it the innermost open block. + * Pushes a new block on top of the context, making it the innermost open + * block. + * + * @param the type of the new node * @param node the new node + * * @return the node that was pushed */ public T push(final T node) { @@ -168,25 +180,28 @@ /** * Is the context empty? - * @return true if empty + * + * @return {@code true} if empty */ public boolean isEmpty() { return sp == 0; } /** - * The depth of the lexical context - * @return depth + * @return the depth of the lexical context. */ public int size() { return sp; } /** - * Pops the innermost block off the context and all nodes that has been contributed - * since it was put there + * Pops the innermost block off the context and all nodes that has been + * contributed since it was put there. * - * @param node the node expected to be popped, used to detect unbalanced pushes/pops + * @param the type of the node to be popped + * @param node the node expected to be popped, used to detect unbalanced + * pushes/pops + * * @return the node that was popped */ @SuppressWarnings("unchecked") @@ -202,11 +217,17 @@ } /** - * Explicitly apply flags to the topmost element on the stack. This is only valid to use from a - * {@code NodeVisitor.leaveXxx()} method and only on the node being exited at the time. It is not mandatory to use, - * as {@link #pop(Node)} will apply the flags automatically, but this method can be used to apply them - * during the {@code leaveXxx()} method in case its logic depends on the value of the flags. - * @param node the node to apply the flags to. Must be the topmost node on the stack. + * Explicitly apply flags to the topmost element on the stack. This is only + * valid to use from a {@code NodeVisitor.leaveXxx()} method and only on the + * node being exited at the time. It is not mandatory to use, as + * {@link #pop(Node)} will apply the flags automatically, but this method + * can be used to apply them during the {@code leaveXxx()} method in case + * its logic depends on the value of the flags. + * + * @param the type of the node to apply the flags to. + * @param node the node to apply the flags to. Must be the topmost node on + * the stack. + * * @return the passed in node, or a modified node (if any flags were modified) */ public > T applyTopFlags(final T node) { @@ -215,7 +236,8 @@ } /** - * Return the top element in the context + * Return the top element in the context. + * * @return the node that was pushed last */ public LexicalContextNode peek() { @@ -223,9 +245,11 @@ } /** - * Check if a node is in the lexical context + * Check if a node is in the lexical context. + * * @param node node to check for - * @return true if in the context + * + * @return {@code true} if in the context */ public boolean contains(final LexicalContextNode node) { for (int i = 0; i < sp; i++) { @@ -242,6 +266,7 @@ * * @param oldNode old node * @param newNode new node + * * @return the new node */ public LexicalContextNode replace(final LexicalContextNode oldNode, final LexicalContextNode newNode) { @@ -256,7 +281,9 @@ } /** - * Returns an iterator over all blocks in the context, with the top block (innermost lexical context) first. + * Returns an iterator over all blocks in the context, with the top block + * (innermost lexical context) first. + * * @return an iterator over all blocks in the context. */ public Iterator getBlocks() { @@ -264,7 +291,9 @@ } /** - * Returns an iterator over all functions in the context, with the top (innermost open) function first. + * Returns an iterator over all functions in the context, with the top + * (innermost open) function first. + * * @return an iterator over all functions in the context. */ public Iterator getFunctions() { @@ -273,6 +302,7 @@ /** * Get the parent block for the current lexical context block + * * @return parent block */ public Block getParentBlock() { @@ -283,7 +313,9 @@ /** * Gets the label node of the current block. - * @return the label node of the current block, if it is labeled. Otherwise returns null. + * + * @return the label node of the current block, if it is labeled. Otherwise + * returns {@code null}. */ public LabelNode getCurrentBlockLabelNode() { assert stack[sp - 1] instanceof Block; @@ -294,21 +326,12 @@ return parent instanceof LabelNode ? (LabelNode)parent : null; } - - /* - public FunctionNode getProgram() { - final Iterator iter = getFunctions(); - FunctionNode last = null; - while (iter.hasNext()) { - last = iter.next(); - } - assert last != null; - return last; - }*/ - /** - * Returns an iterator over all ancestors block of the given block, with its parent block first. + * Returns an iterator over all ancestors block of the given block, with its + * parent block first. + * * @param block the block whose ancestors are returned + * * @return an iterator over all ancestors block of the given block. */ public Iterator getAncestorBlocks(final Block block) { @@ -323,8 +346,11 @@ } /** - * Returns an iterator over a block and all its ancestors blocks, with the block first. + * Returns an iterator over a block and all its ancestors blocks, with the + * block first. + * * @param block the block that is the starting point of the iteration. + * * @return an iterator over a block and all its ancestors. */ public Iterator getBlocks(final Block block) { @@ -352,7 +378,9 @@ /** * Get the function for this block. + * * @param block block for which to get function + * * @return function for block */ public FunctionNode getFunction(final Block block) { @@ -373,7 +401,6 @@ } /** - * Returns the innermost block in the context. * @return the innermost block in the context. */ public Block getCurrentBlock() { @@ -381,7 +408,6 @@ } /** - * Returns the innermost function in the context. * @return the innermost function in the context. */ public FunctionNode getCurrentFunction() { @@ -394,9 +420,12 @@ } /** - * Get the block in which a symbol is defined + * Get the block in which a symbol is defined. + * * @param symbol symbol - * @return block in which the symbol is defined, assert if no such block in context + * + * @return block in which the symbol is defined, assert if no such block in + * context. */ public Block getDefiningBlock(final Symbol symbol) { final String name = symbol.getName(); @@ -410,9 +439,12 @@ } /** - * Get the function in which a symbol is defined + * Get the function in which a symbol is defined. + * * @param symbol symbol - * @return function node in which this symbol is defined, assert if no such symbol exists in context + * + * @return function node in which this symbol is defined, assert if no such + * symbol exists in context. */ public FunctionNode getDefiningFunction(final Symbol symbol) { final String name = symbol.getName(); @@ -433,7 +465,8 @@ /** * Is the topmost lexical context element a function body? - * @return true if function body + * + * @return {@code true} if function body. */ public boolean isFunctionBody() { return getParentBlock() == null; @@ -441,16 +474,20 @@ /** * Is the topmost lexical context element body of a SplitNode? - * @return true if it's the body of a split node. + * + * @return {@code true} if it's the body of a split node. */ public boolean isSplitBody() { return sp >= 2 && stack[sp - 1] instanceof Block && stack[sp - 2] instanceof SplitNode; } /** - * Get the parent function for a function in the lexical context + * Get the parent function for a function in the lexical context. + * * @param functionNode function for which to get parent - * @return parent function of functionNode or null if none (e.g. if functionNode is the program) + * + * @return parent function of functionNode or {@code null} if none (e.g., if + * functionNode is the program). */ public FunctionNode getParentFunction(final FunctionNode functionNode) { final Iterator iter = new NodeIterator<>(FunctionNode.class); @@ -465,12 +502,16 @@ } /** - * Count the number of scopes until a given node. Note that this method is solely used to figure out the number of - * scopes that need to be explicitly popped in order to perform a break or continue jump within the current bytecode - * method. For this reason, the method returns 0 if it encounters a {@code SplitNode} between the current location - * and the break/continue target. - * @param until node to stop counting at. Must be within the current function - * @return number of with scopes encountered in the context + * Count the number of scopes until a given node. Note that this method is + * solely used to figure out the number of scopes that need to be explicitly + * popped in order to perform a break or continue jump within the current + * bytecode method. For this reason, the method returns 0 if it encounters a + * {@code SplitNode} between the current location and the break/continue + * target. + * + * @param until node to stop counting at. Must be within the current function. + * + * @return number of with scopes encountered in the context. */ public int getScopeNestingLevelTo(final LexicalContextNode until) { assert until != null; @@ -500,16 +541,17 @@ } /** - * Check whether the lexical context is currently inside a loop - * @return true if inside a loop + * Check whether the lexical context is currently inside a loop. + * + * @return {@code true} if inside a loop */ public boolean inLoop() { return getCurrentLoop() != null; } /** - * Returns the loop header of the current loop, or null if not inside a loop - * @return loop header + * @return the loop header of the current loop, or {@code null} if not + * inside a loop. */ public LoopNode getCurrentLoop() { final Iterator iter = new NodeIterator<>(LoopNode.class, getCurrentFunction()); @@ -518,9 +560,12 @@ /** * Find the breakable node corresponding to this label. - * @param labelName name of the label to search for. If null, the closest breakable node will be returned - * unconditionally, e.g. a while loop with no label - * @return closest breakable node + * + * @param labelName name of the label to search for. If {@code null}, the + * closest breakable node will be returned unconditionally, e.g., a + * while loop with no label. + * + * @return closest breakable node. */ public BreakableNode getBreakable(final String labelName) { if (labelName != null) { @@ -544,9 +589,12 @@ /** * Find the continue target node corresponding to this label. - * @param labelName label name to search for. If null the closest loop node will be returned unconditionally, e.g. a - * while loop with no label - * @return closest continue target node + * + * @param labelName label name to search for. If {@code null} the closest + * loop node will be returned unconditionally, e.g., a while loop + * with no label. + * + * @return closest continue target node. */ public LoopNode getContinueTo(final String labelName) { if (labelName != null) { @@ -566,8 +614,10 @@ /** * Find the inlined finally block node corresponding to this label. - * @param labelName label name to search for. Must not be null. - * @return closest inlined finally block with the given label + * + * @param labelName label name to search for. Must not be {@code null}. + * + * @return closest inlined finally block with the given label. */ public Block getInlinedFinally(final String labelName) { for (final NodeIterator iter = new NodeIterator<>(TryNode.class); iter.hasNext(); ) { @@ -581,7 +631,9 @@ /** * Find the try node for an inlined finally block corresponding to this label. - * @param labelName label name to search for. Must not be null. + * + * @param labelName label name to search for. Must not be {@code null}. + * * @return the try node to which the labelled inlined finally block belongs. */ public TryNode getTryNodeForInlinedFinally(final String labelName) { @@ -595,9 +647,11 @@ } /** - * Check the lexical context for a given label node by name - * @param name name of the label - * @return LabelNode if found, null otherwise + * Check the lexical context for a given label node by name. + * + * @param name name of the label. + * + * @return LabelNode if found, {@code null} otherwise. */ public LabelNode findLabel(final String name) { for (final Iterator iter = new NodeIterator<>(LabelNode.class, getCurrentFunction()); iter.hasNext(); ) { @@ -610,10 +664,13 @@ } /** - * Checks whether a given target is a jump destination that lies outside a given split node - * @param splitNode the split node - * @param target the target node - * @return true if target resides outside the split node + * Checks whether a given target is a jump destination that lies outside a + * given split node. + * + * @param splitNode the split node. + * @param target the target node. + * + * @return {@code true} if target resides outside the split node. */ public boolean isExternalTarget(final SplitNode splitNode, final BreakableNode target) { for (int i = sp; i-- > 0;) { @@ -634,8 +691,10 @@ } /** - * Checks whether the current context is inside a switch statement without explicit blocks (curly braces). - * @return true if in unprotected switch statement + * Checks whether the current context is inside a switch statement without + * explicit blocks (curly braces). + * + * @return {@code true} if in unprotected switch statement. */ public boolean inUnprotectedSwitchContext() { for (int i = sp; i > 0; i--) { diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/ir/SplitReturn.java --- a/src/jdk/nashorn/internal/ir/SplitReturn.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/ir/SplitReturn.java Wed Jun 17 21:57:59 2015 -0700 @@ -54,7 +54,7 @@ } @Override - public void toString(StringBuilder sb, boolean printType) { + public void toString(final StringBuilder sb, final boolean printType) { sb.append(":splitreturn;"); } diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/ir/TryNode.java --- a/src/jdk/nashorn/internal/ir/TryNode.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/ir/TryNode.java Wed Jun 17 21:57:59 2015 -0700 @@ -122,7 +122,7 @@ * @param visitor IR navigating visitor. */ @Override - public Node accept(final LexicalContext lc, NodeVisitor visitor) { + public Node accept(final LexicalContext lc, final NodeVisitor visitor) { if (visitor.enterTryNode(this)) { // Need to do finallybody first for termination analysis. TODO still necessary? final Block newFinallyBody = finallyBody == null ? null : (Block)finallyBody.accept(visitor); diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/ir/debug/NashornTextifier.java --- a/src/jdk/nashorn/internal/ir/debug/NashornTextifier.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/ir/debug/NashornTextifier.java Wed Jun 17 21:57:59 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -1109,7 +1109,7 @@ } final String ex = catches.get(node); if (ex != null) { - sb.append("*** CATCH: ").append(ex).append(" ***\n"); + sb.append("*** CATCH: ").append(ex).append(" ***\\l"); } sb.append(c); sb.append("\"]\n"); diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/objects/Global.java --- a/src/jdk/nashorn/internal/objects/Global.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/objects/Global.java Wed Jun 17 21:57:59 2015 -0700 @@ -928,9 +928,11 @@ private final Context context; // current ScriptContext to use - can be null. - private ScriptContext scontext; + private ThreadLocal scontext; // current ScriptEngine associated - can be null. private ScriptEngine engine; + // initial ScriptContext - can be null + private volatile ScriptContext initscontext; // ES6 global lexical scope. private final LexicalScope lexicalScope; @@ -940,10 +942,25 @@ /** * Set the current script context - * @param scontext script context + * @param ctxt script context */ - public void setScriptContext(final ScriptContext scontext) { - this.scontext = scontext; + public void setScriptContext(final ScriptContext ctxt) { + assert scontext != null; + scontext.set(ctxt); + } + + /** + * Get the current script context + * @return current script context + */ + public ScriptContext getScriptContext() { + assert scontext != null; + return scontext.get(); + } + + private ScriptContext currentContext() { + final ScriptContext sc = scontext != null? scontext.get() : null; + return sc == null? initscontext : sc; } @Override @@ -988,9 +1005,7 @@ * @return the global singleton */ public static Global instance() { - final Global global = Context.getGlobal(); - Objects.requireNonNull(global); - return global; + return Objects.requireNonNull(Context.getGlobal()); } private static Global instanceFrom(final Object self) { @@ -1055,17 +1070,21 @@ * as well as our extension builtin objects like "Java", "JSAdapter" as properties * of the global scope object. * - * @param engine ScriptEngine to initialize + * @param eng ScriptEngine to initialize + * @param ctxt ScriptContext to initialize */ - @SuppressWarnings("hiding") - public void initBuiltinObjects(final ScriptEngine engine) { + public void initBuiltinObjects(final ScriptEngine eng, final ScriptContext ctxt) { if (this.builtinObject != null) { // already initialized, just return return; } - this.engine = engine; - init(engine); + this.engine = eng; + this.initscontext = ctxt; + if (this.engine != null) { + this.scontext = new ThreadLocal<>(); + } + init(eng); } /** @@ -1393,7 +1412,7 @@ */ public static Object __noSuchProperty__(final Object self, final Object name) { final Global global = Global.instance(); - final ScriptContext sctxt = global.scontext; + final ScriptContext sctxt = global.currentContext(); final String nameStr = name.toString(); if (sctxt != null) { @@ -1432,7 +1451,7 @@ * @return the result of eval */ public static Object eval(final Object self, final Object str) { - return directEval(self, str, UNDEFINED, UNDEFINED, false); + return directEval(self, str, Global.instanceFrom(self), UNDEFINED, false); } /** @@ -1442,7 +1461,7 @@ * @param str Evaluated code * @param callThis "this" to be passed to the evaluated code * @param location location of the eval call - * @param strict is eval called a strict mode code? + * @param strict is eval called from a strict mode code? * * @return the return value of the eval * @@ -2485,7 +2504,7 @@ } @SuppressWarnings("hiding") - private void init(final ScriptEngine engine) { + private void init(final ScriptEngine eng) { assert Context.getGlobal() == this : "this global is not set as current"; final ScriptEnvironment env = getContext().getEnv(); @@ -2601,7 +2620,7 @@ addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments); } - if (engine != null) { + if (eng != null) { // default file name addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null); // __noSuchProperty__ hook for ScriptContext search of missing variables @@ -2692,6 +2711,14 @@ // Retrieve current state of ENV variables. final ScriptObject env = newObject(); env.putAll(System.getenv(), scriptEnv._strict); + + // Some platforms, e.g., Windows, do not define the PWD environment + // variable, so that the $ENV.PWD property needs to be explicitly + // set. + if (!env.containsKey(ScriptingFunctions.PWD_NAME)) { + env.put(ScriptingFunctions.PWD_NAME, System.getProperty("user.dir"), scriptEnv._strict); + } + addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env); } else { addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); @@ -2739,8 +2766,9 @@ } private Object printImpl(final boolean newLine, final Object... objects) { + final ScriptContext sc = currentContext(); @SuppressWarnings("resource") - final PrintWriter out = scontext != null? new PrintWriter(scontext.getWriter()) : getContext().getEnv().getOut(); + final PrintWriter out = sc != null? new PrintWriter(sc.getWriter()) : getContext().getEnv().getOut(); final StringBuilder sb = new StringBuilder(); for (final Object obj : objects) { diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/objects/NativeFunction.java --- a/src/jdk/nashorn/internal/objects/NativeFunction.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/objects/NativeFunction.java Wed Jun 17 21:57:59 2015 -0700 @@ -279,8 +279,8 @@ sb.append("})"); final Global global = Global.instance(); - - return (ScriptFunction)Global.directEval(global, sb.toString(), global, "", global.isStrictContext()); + final Context context = global.getContext(); + return (ScriptFunction)context.eval(global, sb.toString(), global, ""); } private static void checkFunctionParameters(final String params) { diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/objects/NativeJava.java --- a/src/jdk/nashorn/internal/objects/NativeJava.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/objects/NativeJava.java Wed Jun 17 21:57:59 2015 -0700 @@ -33,10 +33,12 @@ import java.util.Collection; import java.util.Deque; import java.util.List; +import java.util.Map; import java.util.Queue; import jdk.internal.dynalink.beans.StaticClass; import jdk.internal.dynalink.support.TypeUtilities; 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; @@ -656,4 +658,20 @@ public static Object _super(final Object self, final Object adapter) { return Bootstrap.createSuperAdapter(adapter); } + + /** + * Returns an object that is compatible with Java JSON libraries expectations; namely, that if it itself, or any + * object transitively reachable through it is a JavaScript array, then such objects will be exposed as + * {@link JSObject} that also implements the {@link List} interface for exposing the array elements. An explicit + * API is required as otherwise Nashorn exposes all objects externally as {@link JSObject}s that also implement the + * {@link Map} interface instead. By using this method, arrays will be exposed as {@link List}s and all other + * objects as {@link Map}s. + * @param self not used + * @param obj the object to be exposed in a Java JSON library compatible manner. + * @return a wrapper around the object that will enforce Java JSON library compatible exposure. + */ + @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) + public static Object asJSONCompatible(final Object self, final Object obj) { + return ScriptObjectMirror.wrapAsJSONCompatible(obj, Context.getGlobal()); + } } diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/objects/annotations/Constructor.java --- a/src/jdk/nashorn/internal/objects/annotations/Constructor.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/objects/annotations/Constructor.java Wed Jun 17 21:57:59 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -37,13 +37,15 @@ @Target(ElementType.METHOD) public @interface Constructor { /** - * Name of the constructor function. If empty, the name is inferred. + * @return the name of the constructor function. If empty, the name is + * inferred. */ public String name() default ""; /** - * The arity of the function. By default computed from the method signature. - * Note that -1 means varargs. So, -2 is used as invalid arity. + * @return the arity of the function. By default computed from the method + * signature. Note that -1 means varargs. So, -2 is used as invalid + * arity. */ public int arity() default -2; } diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/objects/annotations/Function.java --- a/src/jdk/nashorn/internal/objects/annotations/Function.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/objects/annotations/Function.java Wed Jun 17 21:57:59 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -41,22 +41,23 @@ @Target(ElementType.METHOD) public @interface Function { /** - * Name of the property. If empty, the name is inferred. + * @return the name of the property. If empty, the name is inferred. */ public String name() default ""; /** - * Attribute flags for this function. + * @return the attribute flags for this function. */ public int attributes() default DEFAULT_ATTRIBUTES; /** - * The arity of the function. By default computed from the method signature + * @return the arity of the function. By default computed from the method + * signature. */ public int arity() default -2; /** - * where this function lives + * @return where this function lives. */ public Where where() default Where.PROTOTYPE; } diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/objects/annotations/Getter.java --- a/src/jdk/nashorn/internal/objects/annotations/Getter.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/objects/annotations/Getter.java Wed Jun 17 21:57:59 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -39,17 +39,17 @@ @Target(ElementType.METHOD) public @interface Getter { /** - * Name of the property. If empty, the name is inferred. + * @return the name of the property. If empty, the name is inferred. */ public String name() default ""; /** - * Attribute flags for this setter. + * @return the attribute flags for this setter. */ public int attributes() default DEFAULT_ATTRIBUTES; /** - * Where this getter lives? + * @return where this getter lives. */ public Where where() default Where.INSTANCE; } diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/objects/annotations/ScriptClass.java --- a/src/jdk/nashorn/internal/objects/annotations/ScriptClass.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/objects/annotations/ScriptClass.java Wed Jun 17 21:57:59 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -37,8 +37,8 @@ @Target(ElementType.TYPE) public @interface ScriptClass { /** - * Name of the script class. By default, the name is derived from - * the Java class name. + * @return the name of the script class. By default, the name is derived + * from the Java class name. */ public String value() default ""; } diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/objects/annotations/Setter.java --- a/src/jdk/nashorn/internal/objects/annotations/Setter.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/objects/annotations/Setter.java Wed Jun 17 21:57:59 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -39,17 +39,17 @@ @Target(ElementType.METHOD) public @interface Setter { /** - * Name of the script property. If empty, the name is inferred. + * @return the name of the script property. If empty, the name is inferred. */ public String name() default ""; /** - * Attribute flags for this setter. + * @return the attribute flags for this setter. */ public int attributes() default DEFAULT_ATTRIBUTES; /** - * Where this setter lives? + * @return where this setter lives. */ public Where where() default Where.INSTANCE; } diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java --- a/src/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java Wed Jun 17 21:57:59 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -33,10 +33,11 @@ import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.linker.LinkRequest; import jdk.nashorn.internal.runtime.ScriptFunction; +import jdk.nashorn.internal.runtime.UnwarrantedOptimismException; /** * The SpecializedFunction annotation is used to flag more type specific - * functions than the standard one in the native objects + * functions than the standard one in the native objects. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @@ -45,23 +46,23 @@ /** * Functionality for testing if we are allowed to link a specialized * function the first time we encounter it. Then the guard will handle the - * rest of the invocations + * rest of the invocations. * - * This is the same for all callsites in Nashorn, the first time callsite is + * This is the same for all callsites in Nashorn; the first time a callsite is * linked, we have to manually check that the linkage is OK. Even if we add * a guard and it fails upon the first try, this is not good enough. - * (Symmetrical to how it works everywhere else in the Nashorn runtime). + * (Symmetrical to how it works everywhere else in the Nashorn runtime.) * * Here we abstract out a few of the most common link guard checks. */ public static abstract class LinkLogic { /** - * Empty link logic instance - this is the default + * Empty link logic instance - this is the default. * "no special linking or runtime guard behavior" */ public static final LinkLogic EMPTY_INSTANCE = new Empty(); - /** Empty link logic class - allow all linking, no guards */ + /** Empty link logic class - allow all linking, no guards. */ private static final class Empty extends LinkLogic { @Override public boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request) { @@ -75,7 +76,8 @@ } /** - * Get the class representing the empty link logic + * Get the class representing the empty link logic. + * * @return class representing empty link logic */ public static Class getEmptyLinkLogicClass() { @@ -83,31 +85,31 @@ } /** - * Should this callsite relink when an exception is thrown + * Should this callsite relink when an exception is thrown? * - * @return the relink exception, or null if none + * @return the relink exception, or {@code null} if none */ public Class getRelinkException() { return null; } /** - * Is this link logic class empty - i.e. no special linking logic - * supplied + * Is this link logic class empty - i.e., no special linking logic + * supplied? * * @param clazz class to check * - * @return true if this link logic is empty + * @return {@code true} if this link logic is empty */ public static boolean isEmpty(final Class clazz) { return clazz == Empty.class; } /** - * Is this link logic instance empty - i.e. no special linking logic - * supplied + * Is this link logic instance empty - i.e., no special linking logic + * supplied? * - * @return true if this link logic instance is empty + * @return {@code true} if this link logic instance is empty */ public boolean isEmpty() { return false; @@ -121,7 +123,7 @@ * @param desc callsite descriptor * @param request link request * - * @return true if we can link this callsite at this time + * @return {@code true} if we can link this callsite at this time */ public abstract boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request); @@ -131,7 +133,7 @@ * * @param self receiver * - * @return true if a guard is to be woven into the callsite + * @return {@code true} if a guard is to be woven into the callsite */ public boolean needsGuard(final Object self) { return true; @@ -139,13 +141,13 @@ /** * Given a callsite, and optional arguments, do we need an extra guard - * for specialization to go through - this guard can be a function of - * the arguments too + * for specialization to go through? This guard can be a function of + * the arguments too. * * @param self receiver * @param args arguments * - * @return true if a guard is to be woven into the callsite + * @return {@code true} if a guard is to be woven into the callsite */ public boolean needsGuard(final Object self, final Object... args) { return true; @@ -169,9 +171,9 @@ * @param self receiver * @param desc callsite descriptor * @param request link request - - * @return true if we can link, false otherwise - that means we have to - * pick a non specialized target + * + * @return {@code true} if we can link, {@code false} otherwise - that + * means we have to pick a non specialized target */ public boolean checkLinkable(final Object self, final CallSiteDescriptor desc, final LinkRequest request) { // check the link guard, if it says we can link, go ahead @@ -180,11 +182,11 @@ } /** - * name override for return value polymorphism, for example we can't have + * Name override for return value polymorphism, for example we can't have * pop(V)I and pop(V)D in the same Java class, so they need to be named, - * e.g. popInt(V)I and popDouble(V)D for disambiguation, however, their + * e.g., popInt(V)I and popDouble(V)D for disambiguation, however, their * names still need to resolve to "pop" to JavaScript so we can still - * specialize on return values and so that the linker can find them + * specialize on return values and so that the linker can find them. * * @return name, "" means no override, use the Java function name, e.g. * "push" @@ -199,16 +201,18 @@ Class linkLogic() default LinkLogic.Empty.class; /** - * Is this a specialized constructor? + * @return whether this is a specialized constructor. */ boolean isConstructor() default false; /** - * Can this function throw UnwarrantedOptimismExceptions? This works just - * like the normal functions, but we need the function to be + * Can this function throw {@link UnwarrantedOptimismException}s? This works + * just like the normal functions, but we need the function to be * immutable/non-state modifying, as we can't generate continuations for * native code. Luckily a lot of the methods we want to specialize have this - * property + * property. + * + * @return whether this function can throw {@link UnwarrantedOptimismException}. */ boolean isOptimistic() default false; } diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/parser/JSONParser.java --- a/src/jdk/nashorn/internal/parser/JSONParser.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/parser/JSONParser.java Wed Jun 17 21:57:59 2015 -0700 @@ -47,7 +47,8 @@ import static jdk.nashorn.internal.parser.TokenType.STRING; /** - * Parses JSON text and returns the corresponding IR node. This is derived from the objectLiteral production of the main parser. + * Parses JSON text and returns the corresponding IR node. This is derived from + * the objectLiteral production of the main parser. * * See: 15.12.1.2 The JSON Syntactic Grammar */ @@ -70,9 +71,11 @@ private static final int STATE_COMMA_PARSED = 2; /** - * Constructor - * @param source the source - * @param global the global object + * Constructor. + * + * @param source the source + * @param global the global object + * @param dualFields whether the parser should regard dual field representation */ public JSONParser(final String source, final Global global, final boolean dualFields) { this.source = source; @@ -82,8 +85,9 @@ } /** - * Implementation of the Quote(value) operation as defined in the ECMA script spec - * It wraps a String value in double quotes and escapes characters within in + * Implementation of the Quote(value) operation as defined in the ECMAscript + * spec. It wraps a String value in double quotes and escapes characters + * within. * * @param value string to quote * diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/parser/Parser.java --- a/src/jdk/nashorn/internal/parser/Parser.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/parser/Parser.java Wed Jun 17 21:57:59 2015 -0700 @@ -2635,8 +2635,12 @@ name = getIdent(); verifyStrictIdent(name, "function name"); } else if (isStatement) { - // Nashorn extension: anonymous function statements - if (env._no_syntax_extensions) { + // Nashorn extension: anonymous function statements. + // Do not allow anonymous function statement if extensions + // are now allowed. But if we are reparsing then anon function + // statement is possible - because it was used as function + // expression in surrounding code. + if (env._no_syntax_extensions && reparsedFunction == null) { expect(IDENT); } } diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/parser/TokenType.java --- a/src/jdk/nashorn/internal/parser/TokenType.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/parser/TokenType.java Wed Jun 17 21:57:59 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -222,9 +222,11 @@ /** * Determines if the token has greater precedence than other. + * * @param other Compare token. * @param isLeft Is to the left of the other. - * @return True if greater precedence. + * + * @return {@code true} if greater precedence. */ public boolean needsParens(final TokenType other, final boolean isLeft) { return other.precedence != 0 && @@ -234,16 +236,16 @@ /** * Determines if the type is a valid operator. - * @param noIn TRUE if IN operator should be ignored. - * @return TRUE if valid operator. + * + * @param noIn {@code true} if IN operator should be ignored. + * + * @return {@code true} if valid operator. */ public boolean isOperator(final boolean noIn) { return kind == BINARY && (!noIn || this != IN) && precedence != 0; } - /** - * Accessors. - */ + public int getLength() { assert name != null : "Token name not set"; return name.length(); diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/runtime/CompiledFunction.java --- a/src/jdk/nashorn/internal/runtime/CompiledFunction.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/runtime/CompiledFunction.java Wed Jun 17 21:57:59 2015 -0700 @@ -528,8 +528,9 @@ final int fnParamCountNoCallee = fnParamCount - thisThisIndex; final int minParams = Math.min(csParamCount - 1, fnParamCountNoCallee); // callSiteType always has callee, so subtract 1 - // We must match all incoming parameters, except "this". Starting from 1 to skip "this". - for(int i = 1; i < minParams; ++i) { + // We must match all incoming parameters, including "this". "this" will usually be Object, but there + // are exceptions, e.g. when calling functions with primitive "this" in strict mode or through call/apply. + for(int i = 0; i < minParams; ++i) { final Type fnType = Type.typeFor(type.parameterType(i + thisThisIndex)); final Type csType = csIsVarArg ? Type.OBJECT : Type.typeFor(other.parameterType(i + 1)); if(!fnType.isEquivalentTo(csType)) { diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/runtime/Context.java --- a/src/jdk/nashorn/internal/runtime/Context.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/runtime/Context.java Wed Jun 17 21:57:59 2015 -0700 @@ -66,6 +66,7 @@ import java.util.function.Consumer; import java.util.function.Supplier; import java.util.logging.Level; +import javax.script.ScriptContext; import javax.script.ScriptEngine; import jdk.internal.org.objectweb.asm.ClassReader; import jdk.internal.org.objectweb.asm.util.CheckClassAdapter; @@ -667,12 +668,11 @@ * @param string Evaluated code as a String * @param callThis "this" to be passed to the evaluated code * @param location location of the eval call - * @param strict is this {@code eval} call from a strict mode code? * @return the return value of the {@code eval} */ public Object eval(final ScriptObject initialScope, final String string, - final Object callThis, final Object location, final boolean strict) { - return eval(initialScope, string, callThis, location, strict, false); + final Object callThis, final Object location) { + return eval(initialScope, string, callThis, location, false, false); } /** @@ -691,14 +691,16 @@ final Object callThis, final Object location, final boolean strict, final boolean evalCall) { final String file = location == UNDEFINED || location == null ? "" : location.toString(); final Source source = sourceFor(file, string, evalCall); - final boolean directEval = location != UNDEFINED; // is this direct 'eval' call or indirectly invoked eval? + // is this direct 'eval' builtin call? + final boolean directEval = evalCall && (location != UNDEFINED); final Global global = Context.getGlobal(); ScriptObject scope = initialScope; // ECMA section 10.1.1 point 2 says eval code is strict if it begins // with "use strict" directive or eval direct call itself is made // from from strict mode code. We are passed with caller's strict mode. - boolean strictFlag = directEval && strict; + // Nashorn extension: any 'eval' is unconditionally strict when -strict is specified. + boolean strictFlag = strict || this._strict; Class clazz = null; try { @@ -739,7 +741,8 @@ if (directEval) { evalThis = (callThis != UNDEFINED && callThis != null) || strictFlag ? callThis : global; } else { - evalThis = global; + // either indirect evalCall or non-eval (Function, engine.eval, ScriptObjectMirror.eval..) + evalThis = callThis; } return ScriptRuntime.apply(func, evalThis); @@ -1095,16 +1098,17 @@ * * @param global the global * @param engine the associated ScriptEngine instance, can be null + * @param ctxt the initial ScriptContext, can be null * @return the initialized global scope object. */ - public Global initGlobal(final Global global, final ScriptEngine engine) { + public Global initGlobal(final Global global, final ScriptEngine engine, final ScriptContext ctxt) { // Need only minimal global object, if we are just compiling. if (!env._compile_only) { final Global oldGlobal = Context.getGlobal(); try { Context.setGlobal(global); // initialize global scope with builtin global objects - global.initBuiltinObjects(engine); + global.initBuiltinObjects(engine, ctxt); } finally { Context.setGlobal(oldGlobal); } @@ -1120,7 +1124,7 @@ * @return the initialized global scope object. */ public Global initGlobal(final Global global) { - return initGlobal(global, null); + return initGlobal(global, null, null); } /** diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/runtime/DebuggerSupport.java --- a/src/jdk/nashorn/internal/runtime/DebuggerSupport.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/runtime/DebuggerSupport.java Wed Jun 17 21:57:59 2015 -0700 @@ -156,7 +156,7 @@ final Context context = global.getContext(); try { - return context.eval(initialScope, string, callThis, ScriptRuntime.UNDEFINED, false); + return context.eval(initialScope, string, callThis, ScriptRuntime.UNDEFINED); } catch (final Throwable ex) { return returnException ? ex : null; } diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/runtime/JSONListAdapter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/nashorn/internal/runtime/JSONListAdapter.java Wed Jun 17 21:57:59 2015 -0700 @@ -0,0 +1,169 @@ +/* + * 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. 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.internal.runtime; + +import java.util.Collection; +import java.util.List; +import java.util.Set; +import jdk.nashorn.api.scripting.AbstractJSObject; +import jdk.nashorn.api.scripting.JSObject; +import jdk.nashorn.api.scripting.ScriptObjectMirror; +import jdk.nashorn.internal.objects.Global; + +/** + * A {@link ListAdapter} that also implements {@link JSObject}. Named {@code JSONListAdapter} as it is used as a + * {@code JSObject} implementing the {@link List} interface, which is the expected interface to be implemented by + * JSON-parsed arrays when they are handled in Java. We aren't implementing {@link JSObject} on {@link ListAdapter} + * directly since that'd have implications for other uses of list adapter (e.g. interferences of JSObject default + * value calculation vs. List's {@code toString()} etc.) + */ +public final class JSONListAdapter extends ListAdapter implements JSObject { + /** + * Creates a new JSON list adapter. + * @param obj the underlying object being exposed as a list. + * @param global the home global of the underlying object. + */ + public JSONListAdapter(final JSObject obj, final Global global) { + super(obj, global); + } + + /** + * Unwraps this adapter into its underlying non-JSObject representative. + * @param homeGlobal the home global for unwrapping + * @return either the unwrapped object or this if it should not be unwrapped in the specified global. + */ + public Object unwrap(final Object homeGlobal) { + final Object unwrapped = ScriptObjectMirror.unwrap(obj, homeGlobal); + return unwrapped != obj ? unwrapped : this; + } + + @Override + public Object call(final Object thiz, final Object... args) { + return obj.call(thiz, args); + } + + @Override + public Object newObject(final Object... args) { + return obj.newObject(args); + } + + @Override + public Object eval(final String s) { + return obj.eval(s); + } + + @Override + public Object getMember(final String name) { + return obj.getMember(name); + } + + @Override + public Object getSlot(final int index) { + return obj.getSlot(index); + } + + @Override + public boolean hasMember(final String name) { + return obj.hasMember(name); + } + + @Override + public boolean hasSlot(final int slot) { + return obj.hasSlot(slot); + } + + @Override + public void removeMember(final String name) { + obj.removeMember(name); + } + + @Override + public void setMember(final String name, final Object value) { + obj.setMember(name, value); + } + + @Override + public void setSlot(final int index, final Object value) { + obj.setSlot(index, value); + } + + @Override + public Set keySet() { + return obj.keySet(); + } + + @Override + public Collection values() { + return obj.values(); + } + + @Override + public boolean isInstance(final Object instance) { + return obj.isInstance(instance); + } + + @Override + public boolean isInstanceOf(final Object clazz) { + return obj.isInstanceOf(clazz); + } + + @Override + public String getClassName() { + return obj.getClassName(); + } + + @Override + public boolean isFunction() { + return obj.isFunction(); + } + + @Override + public boolean isStrictFunction() { + return obj.isStrictFunction(); + } + + @Override + public boolean isArray() { + return obj.isArray(); + } + + @Override @Deprecated + public double toNumber() { + return obj.toNumber(); + } + + /** + * Implements this object's {@code [[DefaultValue]]} method by returning its wrapped object's {@code [[DefaultValue]]}. + * + * @param hint the type hint. Should be either {@code null}, {@code Number.class} or {@code String.class}. + * @return the wrapped object's default value. + * @throws UnsupportedOperationException if the conversion can't be performed. The engine will convert this + * exception into a JavaScript {@code TypeError}. + */ + public Object getDefaultValue(final Class hint) { + return AbstractJSObject.getDefaultValue(obj, hint); + } +} diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/runtime/ListAdapter.java --- a/src/jdk/nashorn/internal/runtime/ListAdapter.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/runtime/ListAdapter.java Wed Jun 17 21:57:59 2015 -0700 @@ -36,6 +36,7 @@ import java.util.concurrent.Callable; import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.api.scripting.ScriptObjectMirror; +import jdk.nashorn.internal.objects.Global; import jdk.nashorn.internal.runtime.linker.Bootstrap; /** @@ -51,57 +52,43 @@ * operations respectively, while {@link #addLast(Object)} and {@link #removeLast()} will translate to {@code push} and * {@code pop}. */ -public final class ListAdapter extends AbstractList implements RandomAccess, Deque { +public class ListAdapter extends AbstractList implements RandomAccess, Deque { // Invoker creator for methods that add to the start or end of the list: PUSH and UNSHIFT. Takes fn, this, and value, returns void. private static final Callable ADD_INVOKER_CREATOR = invokerCreator(void.class, Object.class, JSObject.class, Object.class); - // PUSH adds to the end of the list + // PUSH adds to the start of the list private static final Object PUSH = new Object(); - private static MethodHandle getPushInvoker() { - return getDynamicInvoker(PUSH, ADD_INVOKER_CREATOR); - } - - // UNSHIFT adds to the start of the list + // UNSHIFT adds to the end of the list private static final Object UNSHIFT = new Object(); - private static MethodHandle getUnshiftInvoker() { - return getDynamicInvoker(UNSHIFT, ADD_INVOKER_CREATOR); - } // Invoker creator for methods that remove from the tail or head of the list: POP and SHIFT. Takes fn, this, returns Object. private static final Callable REMOVE_INVOKER_CREATOR = invokerCreator(Object.class, Object.class, JSObject.class); - // POP removes from the to the end of the list + // POP removes from the start of the list private static final Object POP = new Object(); - private static MethodHandle getPopInvoker() { - return getDynamicInvoker(POP, REMOVE_INVOKER_CREATOR); - } - - // SHIFT removes from the to the start of the list + // SHIFT removes from the end of the list private static final Object SHIFT = new Object(); - private static MethodHandle getShiftInvoker() { - return getDynamicInvoker(SHIFT, REMOVE_INVOKER_CREATOR); - } // SPLICE can be used to add a value in the middle of the list. private static final Object SPLICE_ADD = new Object(); private static final Callable SPLICE_ADD_INVOKER_CREATOR = invokerCreator(void.class, Object.class, JSObject.class, int.class, int.class, Object.class); - private static MethodHandle getSpliceAddInvoker() { - return getDynamicInvoker(SPLICE_ADD, SPLICE_ADD_INVOKER_CREATOR); - } // SPLICE can also be used to remove values from the middle of the list. private static final Object SPLICE_REMOVE = new Object(); private static final Callable SPLICE_REMOVE_INVOKER_CREATOR = invokerCreator(void.class, Object.class, JSObject.class, int.class, int.class); - private static MethodHandle getSpliceRemoveInvoker() { - return getDynamicInvoker(SPLICE_REMOVE, SPLICE_REMOVE_INVOKER_CREATOR); - } /** wrapped object */ - protected final JSObject obj; + final JSObject obj; + private final Global global; // allow subclasses only in this package - ListAdapter(final JSObject obj) { + ListAdapter(final JSObject obj, final Global global) { + if (global == null) { + throw new IllegalStateException(ECMAErrors.getMessage("list.adapter.null.global")); + } + this.obj = obj; + this.global = global; } /** @@ -111,12 +98,13 @@ * @return A ListAdapter wrapper object */ public static ListAdapter create(final Object obj) { - return new ListAdapter(getJSObject(obj)); + final Global global = Context.getGlobal(); + return new ListAdapter(getJSObject(obj, global), global); } - private static JSObject getJSObject(final Object obj) { + private static JSObject getJSObject(final Object obj, final Global global) { if (obj instanceof ScriptObject) { - return (JSObject)ScriptObjectMirror.wrap(obj, Context.getGlobal()); + return (JSObject)ScriptObjectMirror.wrap(obj, global); } else if (obj instanceof JSObject) { return (JSObject)obj; } @@ -166,7 +154,7 @@ @Override public final void addFirst(final Object e) { try { - getUnshiftInvoker().invokeExact(getFunction("unshift"), obj, e); + getDynamicInvoker(UNSHIFT, ADD_INVOKER_CREATOR).invokeExact(getFunction("unshift"), obj, e); } catch(RuntimeException | Error ex) { throw ex; } catch(final Throwable t) { @@ -177,7 +165,7 @@ @Override public final void addLast(final Object e) { try { - getPushInvoker().invokeExact(getFunction("push"), obj, e); + getDynamicInvoker(PUSH, ADD_INVOKER_CREATOR).invokeExact(getFunction("push"), obj, e); } catch(RuntimeException | Error ex) { throw ex; } catch(final Throwable t) { @@ -195,7 +183,7 @@ } else { final int size = size(); if(index < size) { - getSpliceAddInvoker().invokeExact(obj.getMember("splice"), obj, index, 0, e); + getDynamicInvoker(SPLICE_ADD, SPLICE_ADD_INVOKER_CREATOR).invokeExact(obj.getMember("splice"), obj, index, 0, e); } else if(index == size) { addLast(e); } else { @@ -287,7 +275,7 @@ private Object invokeShift() { try { - return getShiftInvoker().invokeExact(getFunction("shift"), obj); + return getDynamicInvoker(SHIFT, REMOVE_INVOKER_CREATOR).invokeExact(getFunction("shift"), obj); } catch(RuntimeException | Error ex) { throw ex; } catch(final Throwable t) { @@ -297,7 +285,7 @@ private Object invokePop() { try { - return getPopInvoker().invokeExact(getFunction("pop"), obj); + return getDynamicInvoker(POP, REMOVE_INVOKER_CREATOR).invokeExact(getFunction("pop"), obj); } catch(RuntimeException | Error ex) { throw ex; } catch(final Throwable t) { @@ -312,7 +300,7 @@ private void invokeSpliceRemove(final int fromIndex, final int count) { try { - getSpliceRemoveInvoker().invokeExact(getFunction("splice"), obj, fromIndex, count); + getDynamicInvoker(SPLICE_REMOVE, SPLICE_REMOVE_INVOKER_CREATOR).invokeExact(getFunction("splice"), obj, fromIndex, count); } catch(RuntimeException | Error ex) { throw ex; } catch(final Throwable t) { @@ -417,7 +405,7 @@ }; } - private static MethodHandle getDynamicInvoker(final Object key, final Callable creator) { - return Context.getGlobal().getDynamicInvoker(key, creator); + private MethodHandle getDynamicInvoker(final Object key, final Callable creator) { + return global.getDynamicInvoker(key, creator); } } diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java --- a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Wed Jun 17 21:57:59 2015 -0700 @@ -342,6 +342,9 @@ if (functionNode.isVarArg()) { flags |= IS_VARIABLE_ARITY; } + if (functionNode.getKind() == FunctionNode.Kind.GETTER || functionNode.getKind() == FunctionNode.Kind.SETTER) { + flags |= IS_PROPERTY_ACCESSOR; + } return flags; } @@ -382,7 +385,7 @@ parser.setReparsedFunction(this); final FunctionNode program = parser.parse(CompilerConstants.PROGRAM.symbolName(), descPosition, - Token.descLength(token), true); + Token.descLength(token), isPropertyAccessor()); // Parser generates a program AST even if we're recompiling a single function, so when we are only // recompiling a single function, extract it from the program. return (isProgram() ? program : extractFunctionFromScript(program)).setName(null, functionName); diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/runtime/ScriptFunctionData.java --- a/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Wed Jun 17 21:57:59 2015 -0700 @@ -80,24 +80,24 @@ private static final MethodHandle BIND_VAR_ARGS = findOwnMH("bindVarArgs", Object[].class, Object[].class, Object[].class); /** Is this a strict mode function? */ - public static final int IS_STRICT = 1 << 0; + public static final int IS_STRICT = 1 << 0; /** Is this a built-in function? */ - public static final int IS_BUILTIN = 1 << 1; + public static final int IS_BUILTIN = 1 << 1; /** Is this a constructor function? */ - public static final int IS_CONSTRUCTOR = 1 << 2; + public static final int IS_CONSTRUCTOR = 1 << 2; /** Does this function expect a callee argument? */ - public static final int NEEDS_CALLEE = 1 << 3; + public static final int NEEDS_CALLEE = 1 << 3; /** Does this function make use of the this-object argument? */ - public static final int USES_THIS = 1 << 4; + public static final int USES_THIS = 1 << 4; /** Is this a variable arity function? */ - public static final int IS_VARIABLE_ARITY = 1 << 5; + public static final int IS_VARIABLE_ARITY = 1 << 5; + /** Is this a object literal property getter or setter? */ + public static final int IS_PROPERTY_ACCESSOR = 1 << 6; /** Flag for strict or built-in functions */ public static final int IS_STRICT_OR_BUILTIN = IS_STRICT | IS_BUILTIN; /** Flag for built-in constructors */ public static final int IS_BUILTIN_CONSTRUCTOR = IS_BUILTIN | IS_CONSTRUCTOR; - /** Flag for strict constructors */ - public static final int IS_STRICT_CONSTRUCTOR = IS_STRICT | IS_CONSTRUCTOR; private static final long serialVersionUID = 4252901245508769114L; @@ -122,6 +122,10 @@ return (flags & IS_VARIABLE_ARITY) != 0; } + final boolean isPropertyAccessor() { + return (flags & IS_PROPERTY_ACCESSOR) != 0; + } + /** * Used from e.g. Native*$Constructors as an explicit call. TODO - make arity immutable and final * @param arity new arity diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/runtime/ScriptLoader.java --- a/src/jdk/nashorn/internal/runtime/ScriptLoader.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/runtime/ScriptLoader.java Wed Jun 17 21:57:59 2015 -0700 @@ -70,7 +70,6 @@ * @return Installed class. */ synchronized Class installClass(final String name, final byte[] data, final CodeSource cs) { - Objects.requireNonNull(cs); - return defineClass(name, data, 0, data.length, cs); + return defineClass(name, data, 0, data.length, Objects.requireNonNull(cs)); } } diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/runtime/ScriptObject.java --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java Wed Jun 17 21:57:59 2015 -0700 @@ -2582,7 +2582,7 @@ final int callCount = callType.parameterCount(); final boolean isCalleeVarArg = parameterCount > 0 && methodType.parameterType(parameterCount - 1).isArray(); - final boolean isCallerVarArg = callerVarArg != null ? callerVarArg.booleanValue() : callCount > 0 && + final boolean isCallerVarArg = callerVarArg != null ? callerVarArg : callCount > 0 && callType.parameterType(callCount - 1).isArray(); if (isCalleeVarArg) { diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/runtime/ScriptingFunctions.java --- a/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java Wed Jun 17 21:57:59 2015 -0700 @@ -39,8 +39,10 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; +import jdk.nashorn.internal.objects.NativeArray; /** * Global functions supported only in scripting mode. @@ -54,7 +56,7 @@ public static final MethodHandle READFULLY = findOwnMH("readFully", Object.class, Object.class, Object.class); /** Handle to implementation of {@link ScriptingFunctions#exec} - Nashorn extension */ - public static final MethodHandle EXEC = findOwnMH("exec", Object.class, Object.class, Object.class, Object.class); + public static final MethodHandle EXEC = findOwnMH("exec", Object.class, Object.class, Object[].class); /** EXEC name - special property used by $EXEC API. */ public static final String EXEC_NAME = "$EXEC"; @@ -71,7 +73,8 @@ /** Names of special properties used by $ENV API. */ public static final String ENV_NAME = "$ENV"; - private static final String PWD_NAME = "PWD"; + /** Name of the environment variable for the current working directory. */ + public static final String PWD_NAME = "PWD"; private ScriptingFunctions() { } @@ -125,19 +128,32 @@ * Nashorn extension: exec a string in a separate process. * * @param self self reference - * @param string string to execute - * @param input input + * @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 + * * @throws IOException if any stream access fails * @throws InterruptedException if execution is interrupted */ - public static Object exec(final Object self, final Object string, final Object input) throws IOException, InterruptedException { + public static Object exec(final Object self, final Object... args) throws IOException, InterruptedException { // Current global is need to fetch additional inputs and for additional results. final ScriptObject global = Context.getGlobal(); + final Object string = args.length > 0? args[0] : UNDEFINED; + final Object input = args.length > 1? args[1] : UNDEFINED; + final Object[] argv = (args.length > 2)? Arrays.copyOfRange(args, 2, args.length) : ScriptRuntime.EMPTY_ARRAY; + // Assemble command line, process additional arguments. + final List cmdLine = tokenizeString(JSType.toString(string)); + final Object[] additionalArgs = argv.length == 1 && argv[0] instanceof NativeArray ? + ((NativeArray) argv[0]).asObjectArray() : + argv; + for (Object arg : additionalArgs) { + cmdLine.add(JSType.toString(arg)); + } // Set up initial process. - final ProcessBuilder processBuilder = new ProcessBuilder(tokenizeCommandLine(JSType.toString(string))); + final ProcessBuilder processBuilder = new ProcessBuilder(cmdLine); // Current ENV property state. final Object env = global.get(ENV_NAME); @@ -237,23 +253,22 @@ } /** - * Break an exec string into tokens, honoring quoted arguments and escaped - * spaces. + * Break a string into tokens, honoring quoted arguments and escaped spaces. * - * @param execString a {@link String} with the command line to execute. + * @param str a {@link String} to tokenize. * @return a {@link List} of {@link String}s representing the tokens that - * constitute the command line. + * constitute the string. * @throws IOException in case {@link StreamTokenizer#nextToken()} raises it. */ - public static List tokenizeCommandLine(final String execString) throws IOException { - final StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(execString)); + public static List tokenizeString(final String str) throws IOException { + final StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(str)); tokenizer.resetSyntax(); tokenizer.wordChars(0, 255); tokenizer.whitespaceChars(0, ' '); tokenizer.commentChar('#'); tokenizer.quoteChar('"'); tokenizer.quoteChar('\''); - final List cmdList = new ArrayList<>(); + final List tokenList = new ArrayList<>(); final StringBuilder toAppend = new StringBuilder(); while (tokenizer.nextToken() != StreamTokenizer.TT_EOF) { final String s = tokenizer.sval; @@ -265,13 +280,13 @@ // omit trailing \, append space instead toAppend.append(s.substring(0, s.length() - 1)).append(' '); } else { - cmdList.add(toAppend.append(s).toString()); + tokenList.add(toAppend.append(s).toString()); toAppend.setLength(0); } } if (toAppend.length() != 0) { - cmdList.add(toAppend.toString()); + tokenList.add(toAppend.toString()); } - return cmdList; + return tokenList; } } diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/runtime/Source.java --- a/src/jdk/nashorn/internal/runtime/Source.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/runtime/Source.java Wed Jun 17 21:57:59 2015 -0700 @@ -910,14 +910,16 @@ start = 2; cs = StandardCharsets.UTF_16BE; } else if (bytes.length > 1 && bytes[0] == (byte) 0xFF && bytes[1] == (byte) 0xFE) { - start = 2; - cs = StandardCharsets.UTF_16LE; + if (bytes.length > 3 && bytes[2] == 0 && bytes[3] == 0) { + start = 4; + cs = Charset.forName("UTF-32LE"); + } else { + start = 2; + cs = StandardCharsets.UTF_16LE; + } } else if (bytes.length > 2 && bytes[0] == (byte) 0xEF && bytes[1] == (byte) 0xBB && bytes[2] == (byte) 0xBF) { start = 3; cs = StandardCharsets.UTF_8; - } else if (bytes.length > 3 && bytes[0] == (byte) 0xFF && bytes[1] == (byte) 0xFE && bytes[2] == 0 && bytes[3] == 0) { - start = 4; - cs = Charset.forName("UTF-32LE"); } else if (bytes.length > 3 && bytes[0] == 0 && bytes[1] == 0 && bytes[2] == (byte) 0xFE && bytes[3] == (byte) 0xFF) { start = 4; cs = Charset.forName("UTF-32BE"); diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Wed Jun 17 21:57:59 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -54,23 +54,28 @@ import jdk.nashorn.internal.runtime.ScriptObject; /** - *

A factory class that generates adapter classes. Adapter classes allow implementation of Java interfaces and - * extending of Java classes from JavaScript. For every combination of a superclass to extend and interfaces to - * implement (collectively: "original types"), exactly one adapter class is generated that extends the specified - * superclass and implements the specified interfaces. (But see the discussion of class-based overrides for exceptions.) - *

- * The adapter class is generated in a new secure class loader that inherits Nashorn's protection domain, and has either - * one of the original types' class loader or the Nashorn's class loader as its parent - the parent class loader - * is chosen so that all the original types and the Nashorn core classes are visible from it (as the adapter will have - * constant pool references to ScriptObject and ScriptFunction classes). In case none of the candidate class loaders has - * visibility of all the required types, an error is thrown. The class uses {@link JavaAdapterBytecodeGenerator} to - * generate the adapter class itself; see its documentation for details about the generated class. - *

- * You normally don't use this class directly, but rather either create adapters from script using - * {@link jdk.nashorn.internal.objects.NativeJava#extend(Object, Object...)}, using the {@code new} operator on abstract classes and interfaces (see - * {@link jdk.nashorn.internal.objects.NativeJava#type(Object, Object)}), or implicitly when passing script functions to Java methods expecting SAM - * types. - *

+ * A factory class that generates adapter classes. Adapter classes allow + * implementation of Java interfaces and extending of Java classes from + * JavaScript. For every combination of a superclass to extend and interfaces to + * implement (collectively: "original types"), exactly one adapter class is + * generated that extends the specified superclass and implements the specified + * interfaces. (But see the discussion of class-based overrides for exceptions.) + *

+ * The adapter class is generated in a new secure class loader that inherits + * Nashorn's protection domain, and has either one of the original types' class + * loader or the Nashorn's class loader as its parent - the parent class loader + * is chosen so that all the original types and the Nashorn core classes are + * visible from it (as the adapter will have constant pool references to + * ScriptObject and ScriptFunction classes). In case none of the candidate class + * loaders has visibility of all the required types, an error is thrown. The + * class uses {@link JavaAdapterBytecodeGenerator} to generate the adapter class + * itself; see its documentation for details about the generated class. + *

+ * You normally don't use this class directly, but rather either create adapters + * from script using {@link jdk.nashorn.internal.objects.NativeJava#extend(Object, Object...)}, + * using the {@code new} operator on abstract classes and interfaces (see + * {@link jdk.nashorn.internal.objects.NativeJava#type(Object, Object)}), or + * implicitly when passing script functions to Java methods expecting SAM types. */ @SuppressWarnings("javadoc") @@ -93,25 +98,39 @@ }; /** - * Returns an adapter class for the specified original types. The adapter class extends/implements the original - * class/interfaces. - * @param types the original types. The caller must pass at least one Java type representing either a public - * interface or a non-final public class with at least one public or protected constructor. If more than one type is - * specified, at most one can be a class and the rest have to be interfaces. The class can be in any position in the - * array. Invoking the method twice with exactly the same types in the same order will return the same adapter - * class, any reordering of types or even addition or removal of redundant types (i.e. interfaces that other types - * in the list already implement/extend, or {@code java.lang.Object} in a list of types consisting purely of - * interfaces) will result in a different adapter class, even though those adapter classes are functionally - * identical; we deliberately don't want to incur the additional processing cost of canonicalizing type lists. - * @param classOverrides a JavaScript object with functions serving as the class-level overrides and - * implementations. These overrides are defined for all instances of the class, and can be further overridden on a - * per-instance basis by passing additional objects in the constructor. - * @param lookup the lookup object identifying the caller class. The generated adapter class will have the - * protection domain of the caller class iff the lookup object is full-strength, otherwise it will be completely - * unprivileged. - * @return an adapter class. See this class' documentation for details on the generated adapter class. - * @throws ECMAException with a TypeError if the adapter class can not be generated because the original class is - * final, non-public, or has no public or protected constructors. + * Returns an adapter class for the specified original types. The adapter + * class extends/implements the original class/interfaces. + * + * @param types the original types. The caller must pass at least one Java + * type representing either a public interface or a non-final public + * class with at least one public or protected constructor. If more + * than one type is specified, at most one can be a class and the + * rest have to be interfaces. The class can be in any position in + * the array. Invoking the method twice with exactly the same types + * in the same order will return the same adapter class, any + * reordering of types or even addition or removal of redundant types + * (i.e., interfaces that other types in the list already + * implement/extend, or {@code java.lang.Object} in a list of types + * consisting purely of interfaces) will result in a different + * adapter class, even though those adapter classes are functionally + * identical; we deliberately don't want to incur the additional + * processing cost of canonicalizing type lists. + * @param classOverrides a JavaScript object with functions serving as the + * class-level overrides and implementations. These overrides are + * defined for all instances of the class, and can be further + * overridden on a per-instance basis by passing additional objects + * in the constructor. + * @param lookup the lookup object identifying the caller class. The + * generated adapter class will have the protection domain of the + * caller class iff the lookup object is full-strength, otherwise it + * will be completely unprivileged. + * + * @return an adapter class. See this class' documentation for details on + * the generated adapter class. + * + * @throws ECMAException with a TypeError if the adapter class can not be + * generated because the original class is final, non-public, or has + * no public or protected constructors. */ public static StaticClass getAdapterClassFor(final Class[] types, final ScriptObject classOverrides, final MethodHandles.Lookup lookup) { return getAdapterClassFor(types, classOverrides, getProtectionDomain(lookup)); @@ -148,15 +167,23 @@ } /** - * Returns a method handle representing a constructor that takes a single argument of the source type (which, - * really, should be one of {@link ScriptObject}, {@link ScriptFunction}, or {@link Object}, and returns an instance - * of the adapter for the target type. Used to implement the function autoconverters as well as the Nashorn's - * JSR-223 script engine's {@code getInterface()} method. - * @param sourceType the source type; should be either {@link ScriptObject}, {@link ScriptFunction}, or - * {@link Object}. In case of {@code Object}, it will return a method handle that dispatches to either the script - * object or function constructor at invocation based on the actual argument. + * Returns a method handle representing a constructor that takes a single + * argument of the source type (which, really, should be one of {@link ScriptObject}, + * {@link ScriptFunction}, or {@link Object}, and returns an instance of the + * adapter for the target type. Used to implement the function autoconverters + * as well as the Nashorn JSR-223 script engine's {@code getInterface()} + * method. + * + * @param sourceType the source type; should be either {@link ScriptObject}, + * {@link ScriptFunction}, or {@link Object}. In case of {@code Object}, + * it will return a method handle that dispatches to either the script + * object or function constructor at invocation based on the actual + * argument. * @param targetType the target type, for which adapter instances will be created + * @param lookup method handle lookup to use + * * @return the constructor method handle. + * * @throws Exception if anything goes wrong */ public static MethodHandle getConstructor(final Class sourceType, final Class targetType, final MethodHandles.Lookup lookup) throws Exception { @@ -168,13 +195,18 @@ } /** - * Returns whether an instance of the specified class/interface can be generated from a ScriptFunction. Returns true - * iff: the adapter for the class/interface can be created, it is abstract (this includes interfaces), it has at - * least one abstract method, all the abstract methods share the same name, and it has a public or protected default - * constructor. Note that invoking this class will most likely result in the adapter class being defined in the JVM - * if it hasn't been already. + * Returns whether an instance of the specified class/interface can be + * generated from a ScriptFunction. Returns {@code true} iff: the adapter + * for the class/interface can be created, it is abstract (this includes + * interfaces), it has at least one abstract method, all the abstract + * methods share the same name, and it has a public or protected default + * constructor. Note that invoking this class will most likely result in the + * adapter class being defined in the JVM if it hasn't been already. + * * @param clazz the inspected class - * @return true iff an instance of the specified class/interface can be generated from a ScriptFunction. + * + * @return {@code true} iff an instance of the specified class/interface can + * be generated from a ScriptFunction. */ static boolean isAutoConvertibleFromFunction(final Class clazz) { return getAdapterInfo(new Class[] { clazz }).autoConvertibleFromFunction; @@ -198,7 +230,9 @@ /** * For a given class, create its adapter class and associated info. + * * @param type the class for which the adapter is created + * * @return the adapter info for the class. */ private static AdapterInfo createAdapterInfo(final Class[] types, final ClassAndLoader definingClassAndLoader) { @@ -311,11 +345,14 @@ } /** - * Choose between the passed class loader and the class loader that defines the ScriptObject class, based on which - * of the two can see the classes in both. - * @param classAndLoader the loader and a representative class from it that will be used to add the generated - * adapter to its ADAPTER_INFO_MAPS. + * Choose between the passed class loader and the class loader that defines the + * ScriptObject class, based on which of the two can see the classes in both. + * + * @param classAndLoader the loader and a representative class from it that will + * be used to add the generated adapter to its ADAPTER_INFO_MAPS. + * * @return the class loader that sees both the specified class and Nashorn classes. + * * @throws IllegalStateException if no such class loader is found. */ private static ClassLoader findCommonLoader(final ClassAndLoader classAndLoader) throws AdaptationException { diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapter.java --- a/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapter.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapter.java Wed Jun 17 21:57:59 2015 -0700 @@ -36,8 +36,7 @@ private final Object adapter; JavaSuperAdapter(final Object adapter) { - Objects.requireNonNull(adapter); - this.adapter = adapter; + this.adapter = Objects.requireNonNull(adapter); } public Object getAdapter() { diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java --- a/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Wed Jun 17 21:57:59 2015 -0700 @@ -246,7 +246,7 @@ } @Override - public MethodHandle filterInternalObjects(MethodHandle target) { + public MethodHandle filterInternalObjects(final MethodHandle target) { return linkerServices.filterInternalObjects(target); } } diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/runtime/options/Options.java --- a/src/jdk/nashorn/internal/runtime/options/Options.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/runtime/options/Options.java Wed Jun 17 21:57:59 2015 -0700 @@ -136,6 +136,12 @@ return options.toString(); } + private static void checkPropertyName(final String name) { + if (! Objects.requireNonNull(name).startsWith("nashorn.")) { + throw new IllegalArgumentException(name); + } + } + /** * Convenience function for getting system properties in a safe way @@ -144,11 +150,7 @@ * @return true if set to true, default value if unset or set to false */ public static boolean getBooleanProperty(final String name, final Boolean defValue) { - Objects.requireNonNull(name); - if (!name.startsWith("nashorn.")) { - throw new IllegalArgumentException(name); - } - + checkPropertyName(name); return AccessController.doPrivileged( new PrivilegedAction() { @Override @@ -185,11 +187,7 @@ * @return string property if set or default value */ public static String getStringProperty(final String name, final String defValue) { - Objects.requireNonNull(name); - if (! name.startsWith("nashorn.")) { - throw new IllegalArgumentException(name); - } - + checkPropertyName(name); return AccessController.doPrivileged( new PrivilegedAction() { @Override @@ -212,11 +210,7 @@ * @return integer property if set or default value */ public static int getIntProperty(final String name, final int defValue) { - Objects.requireNonNull(name); - if (! name.startsWith("nashorn.")) { - throw new IllegalArgumentException(name); - } - + checkPropertyName(name); return AccessController.doPrivileged( new PrivilegedAction() { @Override diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java Wed Jun 17 21:57:59 2015 -0700 @@ -229,6 +229,11 @@ /** * @see http://www.geocities.jp/kosako3/oniguruma/doc/RE.txt + * + * @param code code + * @param ctype ctype + * + * @return isCodeCType */ public static boolean isCodeCType(final int code, final int ctype) { int type; diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java Wed Jun 17 21:57:59 2015 -0700 @@ -57,10 +57,10 @@ } } - /** - * OP - * - */ + // + // OP + // + protected boolean isOp(final int opm) { return (op & opm) != 0; } @@ -189,11 +189,10 @@ return isOp(OP_ESC_X_BRACE_HEX8); } + // + // OP2 + // - /** - * OP - * - */ protected boolean isOp2(final int opm) { return (op2 & opm) != 0; } @@ -278,10 +277,10 @@ return isOp2(OP2_INEFFECTIVE_ESCAPE); } - /** - * BEHAVIOR - * - */ + // + // BEHAVIOR + // + protected boolean isBehavior(final int bvm) { return (behavior & bvm) != 0; } diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/internal/runtime/resources/Messages.properties --- a/src/jdk/nashorn/internal/runtime/resources/Messages.properties Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/internal/runtime/resources/Messages.properties Wed Jun 17 21:57:59 2015 -0700 @@ -174,4 +174,4 @@ config.error.no.dest=no destination directory supplied uri.error.bad.uri=Bad URI "{0}" near offset {1} - +list.adapter.null.global=Attempted to create the adapter from outside a JavaScript execution context. diff -r 654ab44e8171 -r 219967ffe903 src/jdk/nashorn/tools/Shell.java --- a/src/jdk/nashorn/tools/Shell.java Wed Jun 10 23:17:34 2015 -0700 +++ b/src/jdk/nashorn/tools/Shell.java Wed Jun 17 21:57:59 2015 -0700 @@ -439,7 +439,7 @@ } try { - final Object res = context.eval(global, source, global, "", env._strict); + final Object res = context.eval(global, source, global, ""); if (res != ScriptRuntime.UNDEFINED) { err.println(JSType.toString(res)); } diff -r 654ab44e8171 -r 219967ffe903 test/script/basic/JDK-8066220.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8066220.js Wed Jun 17 21:57:59 2015 -0700 @@ -0,0 +1,38 @@ +/* + * 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-8066220: Fuzzing bug: MethodHandle bug (Object,Object) != (boolean)Object + * + * @test + * @run + */ + + +function f() {} +// Call f with primitive this first, then as constructor +f.call(1); +new f(); + +// Same as above in strict mode +eval('"use strict"; function e() { print(typeof this); } e.call(1); new e();'); diff -r 654ab44e8171 -r 219967ffe903 test/script/basic/JDK-8066220.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8066220.js.EXPECTED Wed Jun 17 21:57:59 2015 -0700 @@ -0,0 +1,2 @@ +number +object diff -r 654ab44e8171 -r 219967ffe903 test/script/basic/JDK-8066237.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8066237.js Wed Jun 17 21:57:59 2015 -0700 @@ -0,0 +1,38 @@ +/* + * 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-8066237: Fuzzing bug: Parser error on optimistic recompilation + * + * @test + * @run + */ + +try { + (function() { + eval("get, a") + })(); + fail("should have thrown"); +} catch (e) { + Assert.assertTrue(e.name === "ReferenceError"); +} diff -r 654ab44e8171 -r 219967ffe903 test/script/basic/JDK-8085802.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8085802.js Wed Jun 17 21:57:59 2015 -0700 @@ -0,0 +1,35 @@ +/* + * 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-8085802: Nashorn -nse option causes parse error on anonymous function definition + * + * @test + * @run + * @option -nse + */ + +// even with -nse passed, the following should run fine +// because anonymous function is used as expression here + +(function (){})() diff -r 654ab44e8171 -r 219967ffe903 test/script/basic/JDK-8087211.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8087211.js Wed Jun 17 21:57:59 2015 -0700 @@ -0,0 +1,63 @@ +/* + * 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-8087211: Indirect evals should be strict with -strict option + * + * @test + * @run + * @option -strict + */ + +var global = this; + +try { + // indirect eval call. + global.eval("x = 34;"); + throw new Error("should have thrown ReferenceError"); +} catch (e if e instanceof ReferenceError) { +} + + +function teststrict() { + "use strict"; + // strict caller, indirect eval. + global.eval('public = 1;'); +} + +try { + teststrict(); + throw new Error("should have thrown SyntaxError"); +} catch (e if e instanceof SyntaxError) { +} + +function testnonstrict() { + // non strict caller, indirect eval. + global.eval('public = 1;'); +} + +try { + testnonstrict(); + throw new Error("should have thrown SyntaxError"); +} catch (e if e instanceof SyntaxError) { +} diff -r 654ab44e8171 -r 219967ffe903 test/script/basic/JDK-8087211_2.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8087211_2.js Wed Jun 17 21:57:59 2015 -0700 @@ -0,0 +1,50 @@ +/* + * 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-8087211: Indirect evals should be strict with -strict option + * Make sure without -strict option, indirect evals are not strict. + * + * @test + * @run + */ + +var global = this; + +// indirect eval call. +global.eval("x = 34;"); + +function teststrict() { + "use strict"; + // strict caller, indirect eval. + global.eval('public = 1;'); +} + +teststrict(); + +function testnonstrict() { + // non strict caller, indirect eval. + global.eval('public = 1;'); +} + +testnonstrict(); diff -r 654ab44e8171 -r 219967ffe903 test/script/error/anon_func_stat_nse.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/error/anon_func_stat_nse.js Wed Jun 17 21:57:59 2015 -0700 @@ -0,0 +1,31 @@ +/* + * 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. + */ + +/** + * Anonymous function statement should result in error in -nse + * + * @option -nse + * @test/compile-error + */ + +function() {} diff -r 654ab44e8171 -r 219967ffe903 test/script/error/anon_func_stat_nse.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/error/anon_func_stat_nse.js.EXPECTED Wed Jun 17 21:57:59 2015 -0700 @@ -0,0 +1,3 @@ +test/script/error/anon_func_stat_nse.js:31:8 Expected ident but found ( +function() {} + ^ diff -r 654ab44e8171 -r 219967ffe903 test/script/error/backquote_string_nse.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/error/backquote_string_nse.js Wed Jun 17 21:57:59 2015 -0700 @@ -0,0 +1,32 @@ +/* + * 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. + */ + +/** + * Backquote string should result in error with -nse even with -scripting + * + * @option -nse + * @option -scripting + * @test/compile-error + */ + +`ls -l`; diff -r 654ab44e8171 -r 219967ffe903 test/script/error/backquote_string_nse.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/error/backquote_string_nse.js.EXPECTED Wed Jun 17 21:57:59 2015 -0700 @@ -0,0 +1,3 @@ +test/script/error/backquote_string_nse.js:32:0 Expected an operand but found error +`ls -l`; +^ diff -r 654ab44e8171 -r 219967ffe903 test/script/error/conditional_catch_nse.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/error/conditional_catch_nse.js Wed Jun 17 21:57:59 2015 -0700 @@ -0,0 +1,34 @@ +/* + * 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. + */ + +/** + * conditional catch should result in error with -nse + * + * @option -nse + * @test/compile-error + */ + +try { + func(); +} catch (e if e instanceof ReferenceError) { +} diff -r 654ab44e8171 -r 219967ffe903 test/script/error/conditional_catch_nse.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/error/conditional_catch_nse.js.EXPECTED Wed Jun 17 21:57:59 2015 -0700 @@ -0,0 +1,6 @@ +test/script/error/conditional_catch_nse.js:33:11 Expected ) but found if +} catch (e if e instanceof ReferenceError) { + ^ +test/script/error/conditional_catch_nse.js:34:0 Expected eof but found } +} +^ diff -r 654ab44e8171 -r 219967ffe903 test/script/error/expr_closure_nse.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/error/expr_closure_nse.js Wed Jun 17 21:57:59 2015 -0700 @@ -0,0 +1,31 @@ +/* + * 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. + */ + +/** + * Expression closures should result in error with -nse + * + * @option -nse + * @test/compile-error + */ + +function square(x) x*x; diff -r 654ab44e8171 -r 219967ffe903 test/script/error/expr_closure_nse.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/error/expr_closure_nse.js.EXPECTED Wed Jun 17 21:57:59 2015 -0700 @@ -0,0 +1,3 @@ +test/script/error/expr_closure_nse.js:31:19 Expected { but found x +function square(x) x*x; + ^ diff -r 654ab44e8171 -r 219967ffe903 test/script/error/for_each_nse.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/error/for_each_nse.js Wed Jun 17 21:57:59 2015 -0700 @@ -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. + */ + +/** + * for..each should result in error with -nse + * + * @option -nse + * @test/compile-error + */ + +for each (var x in [3, 454, 4]) { + print(x); +} diff -r 654ab44e8171 -r 219967ffe903 test/script/error/for_each_nse.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/error/for_each_nse.js.EXPECTED Wed Jun 17 21:57:59 2015 -0700 @@ -0,0 +1,6 @@ +test/script/error/for_each_nse.js:31:4 Expected ( but found each +for each (var x in [3, 454, 4]) { + ^ +test/script/error/for_each_nse.js:33:0 Expected eof but found } +} +^ diff -r 654ab44e8171 -r 219967ffe903 test/script/error/hash_comment_nse.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/error/hash_comment_nse.js Wed Jun 17 21:57:59 2015 -0700 @@ -0,0 +1,32 @@ +/* + * 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. + */ + +/** + * Hash comment should result in error with -nse even with -scripting + * + * @option -nse + * @option -scripting + * @test/compile-error + */ + +# this is a comment diff -r 654ab44e8171 -r 219967ffe903 test/script/error/hash_comment_nse.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/error/hash_comment_nse.js.EXPECTED Wed Jun 17 21:57:59 2015 -0700 @@ -0,0 +1,3 @@ +test/script/error/hash_comment_nse.js:32:0 Expected an operand but found error +# this is a comment +^ diff -r 654ab44e8171 -r 219967ffe903 test/script/error/heredoc_nse.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/error/heredoc_nse.js Wed Jun 17 21:57:59 2015 -0700 @@ -0,0 +1,35 @@ +/* + * 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. + */ + +/** + * Heredoc string should result in error with -nse even with -scripting + * + * @option -nse + * @option -scripting + * @test/compile-error + */ + +var str = < root = asMap(val); + final List x = asList(root.get("x")); + assertEquals(x.get(0), 1); + final Map x1 = asMap(x.get(1)); + final List y = asList(x1.get("y")); + assertEquals(y.get(0), 2); + final Map y1 = asMap(y.get(1)); + assertEquals(asList(y1.get("z")), Arrays.asList(3)); + assertEquals(asList(x.get(2)), Arrays.asList(4, 5)); + } + + /** + * Ensure that the old behaviour (every object is a Map) is unchanged. + */ + @Test + public void testNonWrapping() throws ScriptException { + final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine(); + final Object val = engine.eval("({x: [1, {y: [2, {z: [3]}]}, [4, 5]]})"); + final Map root = asMap(val); + final Map x = asMap(root.get("x")); + assertEquals(x.get("0"), 1); + final Map x1 = asMap(x.get("1")); + final Map y = asMap(x1.get("y")); + assertEquals(y.get("0"), 2); + final Map y1 = asMap(y.get("1")); + final Map z = asMap(y1.get("z")); + assertEquals(z.get("0"), 3); + final Map x2 = asMap(x.get("2")); + assertEquals(x2.get("0"), 4); + assertEquals(x2.get("1"), 5); + } + + @SuppressWarnings("unchecked") + private static List asList(final Object obj) { + assertJSObject(obj); + Assert.assertTrue(obj instanceof List); + return (List)obj; + } + + @SuppressWarnings("unchecked") + private static Map asMap(final Object obj) { + assertJSObject(obj); + Assert.assertTrue(obj instanceof Map); + return (Map)obj; + } + + private static void assertJSObject(final Object obj) { + assertTrue(obj instanceof JSObject); + } +} diff -r 654ab44e8171 -r 219967ffe903 test/src/jdk/nashorn/api/scripting/test/ScopeTest.java --- a/test/src/jdk/nashorn/api/scripting/test/ScopeTest.java Wed Jun 10 23:17:34 2015 -0700 +++ b/test/src/jdk/nashorn/api/scripting/test/ScopeTest.java Wed Jun 17 21:57:59 2015 -0700 @@ -31,10 +31,12 @@ import javax.script.Bindings; import javax.script.ScriptContext; import javax.script.ScriptEngine; +import javax.script.ScriptEngineFactory; import javax.script.ScriptEngineManager; import javax.script.ScriptException; import javax.script.SimpleBindings; import javax.script.SimpleScriptContext; +import jdk.nashorn.api.scripting.NashornScriptEngineFactory; import jdk.nashorn.api.scripting.ScriptObjectMirror; import jdk.nashorn.api.scripting.URLReader; import org.testng.Assert; @@ -778,4 +780,44 @@ throw new AssertionError("should have thrown NPE"); } catch (NullPointerException npe5) {} } + + public static class RecursiveEval { + private final ScriptEngineFactory factory = new NashornScriptEngineFactory(); + private final ScriptEngine engine = factory.getScriptEngine(); + private final Bindings engineBindings = engine.getBindings(ScriptContext.ENGINE_SCOPE); + + public void program() throws ScriptException { + ScriptContext sc = new SimpleScriptContext(); + Bindings global = new SimpleBindings(); + sc.setBindings(global, ScriptContext.GLOBAL_SCOPE); + sc.setBindings(engineBindings, ScriptContext.ENGINE_SCOPE); + global.put("text", "programText"); + String value = engine.eval("text", sc).toString(); + Assert.assertEquals(value, "programText"); + engine.put("program", this); + engine.eval("program.method()"); + // eval again from here! + value = engine.eval("text", sc).toString(); + Assert.assertEquals(value, "programText"); + } + + public void method() throws ScriptException { + // a context with a new global bindings, same engine bindings + final ScriptContext sc = new SimpleScriptContext(); + final Bindings global = new SimpleBindings(); + sc.setBindings(global, ScriptContext.GLOBAL_SCOPE); + sc.setBindings(engineBindings, ScriptContext.ENGINE_SCOPE); + global.put("text", "methodText"); + String value = engine.eval("text", sc).toString(); + Assert.assertEquals(value, "methodText"); + } + } + + // @bug 8081609: engine.eval call from a java method which + // was called from a previous engine.eval results in wrong + // ScriptContext being used. + @Test + public void recursiveEvalCallScriptContextTest() throws ScriptException { + new RecursiveEval().program(); + } } diff -r 654ab44e8171 -r 219967ffe903 test/src/jdk/nashorn/internal/runtime/test/AddAndRemoveOnListAdapterOutsideOfJavaScriptContextTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/src/jdk/nashorn/internal/runtime/test/AddAndRemoveOnListAdapterOutsideOfJavaScriptContextTest.java Wed Jun 17 21:57:59 2015 -0700 @@ -0,0 +1,102 @@ +/* + * 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. 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.internal.runtime.test; + +import static org.testng.Assert.assertEquals; + +import java.util.Arrays; +import java.util.Deque; +import java.util.List; +import javax.script.ScriptEngine; +import javax.script.ScriptException; +import jdk.nashorn.api.scripting.NashornScriptEngineFactory; +import org.testng.annotations.Test; + +/** + * @bug 8081204 + * @summary adding and removing elements to a ListAdapter outside of JS context should work. + */ +@SuppressWarnings("javadoc") +public class AddAndRemoveOnListAdapterOutsideOfJavaScriptContextTest { + + @SuppressWarnings("unchecked") + private static T getListAdapter() throws ScriptException { + final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine(); + return (T)engine.eval("Java.to([1, 2, 3, 4], 'java.util.List')"); + } + + @Test + public void testInvokePush() throws ScriptException { + final Deque l = getListAdapter(); + l.addLast(5); + assertEquals(l.size(), 5); + assertEquals(l.getLast(), 5); + assertEquals(l.getFirst(), 1); + } + + @Test + public void testPop() throws ScriptException { + final Deque l = getListAdapter(); + assertEquals(l.removeLast(), 4); + assertEquals(l.size(), 3); + assertEquals(l.getLast(), 3); + } + + @Test + public void testUnshift() throws ScriptException { + final Deque l = getListAdapter(); + l.addFirst(0); + assertEquals(l.getFirst(), 0); + assertEquals(l.getLast(), 4); + assertEquals(l.size(), 5); + } + + @Test + public void testShift() throws ScriptException { + final Deque l = getListAdapter(); + l.removeFirst(); + assertEquals(l.getFirst(), 2); + assertEquals(l.getLast(), 4); + assertEquals(l.size(), 3); + } + + @Test + public void testSpliceAdd() throws ScriptException { + final List l = getListAdapter(); + assertEquals(l, Arrays.asList(1, 2, 3, 4)); + l.add(2, "foo"); + assertEquals(l, Arrays.asList(1, 2, "foo", 3, 4)); + } + + + @Test + public void testSpliceRemove() throws ScriptException { + final List l = getListAdapter(); + assertEquals(l, Arrays.asList(1, 2, 3, 4)); + l.remove(2); + assertEquals(l, Arrays.asList(1, 2, 4)); + } +} diff -r 654ab44e8171 -r 219967ffe903 test/src/jdk/nashorn/internal/test/framework/TestFinder.java --- a/test/src/jdk/nashorn/internal/test/framework/TestFinder.java Wed Jun 10 23:17:34 2015 -0700 +++ b/test/src/jdk/nashorn/internal/test/framework/TestFinder.java Wed Jun 17 21:57:59 2015 -0700 @@ -225,7 +225,7 @@ boolean explicitOptimistic = false; String allContent = new String(Files.readAllBytes(testFile)); - Iterator scanner = ScriptingFunctions.tokenizeCommandLine(allContent).iterator(); + Iterator scanner = ScriptingFunctions.tokenizeString(allContent).iterator(); while (scanner.hasNext()) { // TODO: Scan for /ref=file qualifiers, etc, to determine run // behavior