Mercurial > hg > release > icedtea8-forest-3.0 > nashorn
changeset 908:2a866ca13bc6 icedtea-3.0.0pre02
Merge jdk8u20-b23
author | andrew |
---|---|
date | Tue, 19 Aug 2014 23:57:20 +0100 |
parents | 09162ba3f887 (current diff) ad36f9454ce3 (diff) |
children | ef23d8dd7745 |
files | .hgtags |
diffstat | 159 files changed, 6898 insertions(+), 522 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Mon Jun 02 18:51:26 2014 +0100 +++ b/.hgtags Tue Aug 19 23:57:20 2014 +0100 @@ -258,6 +258,20 @@ bc23b19e08eb1575663044902b6442ceaafa924f jdk8u5-b11 18b007062905dac9304605955a4b84eaf2a08553 jdk8u5-b12 e4fb85d69d6b33c9561b932ec5515f44c53c1017 jdk8u5-b13 +53cc5fda790e0f90dca53fb459c70517d76680bc jdk8u5-b31 +53cc5fda790e0f90dca53fb459c70517d76680bc jdk8u11-b01 +4dda2b1e51aa7977f53c261f983230fe505bbc3e jdk8u11-b02 +161f144c4e84037f655a2f6ebb0ba3057e8b18fa jdk8u11-b03 +2842beaa5db81731abe9d895181fbfceef720cf3 jdk8u11-b04 +7001e9f95b443a75e432205a29974c05b88e0fdc jdk8u11-b05 +daa414a4d8b712584d0818fab3fd31996e4cb645 jdk8u11-b06 +d9d482948b7c89161887b47e68e3367663d51b76 jdk8u11-b07 +a392513941025e2750acdcc45f9df2ec9080bde9 jdk8u11-b08 +dec6999877f39d3c17f7a092d8e2e17b676bb34b jdk8u11-b09 +d522ff5f53730cabd02c1863bb9d437c13bcc5e0 jdk8u11-b10 +3175dcbdd76ee9272276fa756247203dffb20596 jdk8u11-b11 +eea7f92c5fcc95310a6d946300ea47ac3e302cfe jdk8u11-b12 +b2c8eadc494bd32ed47d15d02cf942a8bd92c57f jdk8u11-b31 43a1183d2ab0ee3dbffd8bc47606e88dbe0c6116 jdk8u20-b02 9d69311869d513deecfebe767cc5f01502c9c01e jdk8u20-b03 e70dd55986e085185d976f2a78843a7d7eb87afd jdk8u20-b04 @@ -270,3 +284,16 @@ 2282c86cb1a954efd2fc5b7f22c173be19087c55 jdk8u20-b08 41f588adeb7a397d395233f00bd3402d0989934a jdk8u20-b09 fdcdffd5b5b1eb7d442096433d17466f023207f1 icedtea-3.0.0pre01 +fdcdffd5b5b1eb7d442096433d17466f023207f1 jdk8u20-b10 +c116e9229e096ffe841f2b4f79067378288d0d1d jdk8u20-b11 +c720454d2435be052fd941a789ece9468d1e8f74 jdk8u20-b12 +2ca464cf3093444f73e27ace78993629d2f15cb9 jdk8u20-b13 +2f6add5fefb37cfeeb9a7745e7144f0b6d96bbea jdk8u20-b14 +bb2d116675479fb2c9deaeeab6d4c41d41060693 jdk8u20-b15 +c89a4945404ce80e26cb94c90fc13adad6b114bf jdk8u20-b16 +046bf6509a1f3fcf8c9c8b5d09beec0400f704d1 jdk8u20-b17 +847387339a561e50353c0805a54ec14eca256d2a jdk8u20-b18 +b047df215de40cb8a87ff1e2bac0b57bb9e2e121 jdk8u20-b19 +ed3439dca4a73a2dd4a284f3457f0af216a3eb55 jdk8u20-b20 +f2925491b61b22ac42f8c30ee9c6723ffa401a4c jdk8u20-b21 +5332595fe7ba2a1fc5564cc2689f378b04a56eb4 jdk8u20-b22
--- a/make/build.xml Mon Jun 02 18:51:26 2014 +0100 +++ b/make/build.xml Tue Aug 19 23:57:20 2014 +0100 @@ -193,14 +193,16 @@ </jar> </target> - <target name="javadoc" depends="prepare"> - <javadoc destdir="${dist.javadoc.dir}" use="yes" overview="src/overview.html" windowtitle="${nashorn.product.name} ${nashorn.version}" additionalparam="-quiet" failonerror="true"> + <target name="javadoc" depends="jar"> + <javadoc destdir="${dist.javadoc.dir}" use="yes" overview="src/overview.html" + extdirs="${nashorn.ext.path}" windowtitle="${nashorn.product.name} ${nashorn.version}" + additionalparam="-quiet" failonerror="true"> <classpath> <pathelement location="${build.classes.dir}"/> </classpath> <fileset dir="${src.dir}" includes="**/*.java"/> <fileset dir="${jdk.asm.src.dir}" includes="**/*.java"/> - <link href="http://docs.oracle.com/javase/7/docs/api/"/> + <link href="http://docs.oracle.com/javase/8/docs/api/"/> <!-- The following tags are used only in ASM sources - just ignore these --> <tag name="label" description="label tag in ASM sources" enabled="false"/> <tag name="linked" description="linked tag in ASM sources" enabled="false"/> @@ -208,6 +210,19 @@ </javadoc> </target> + <!-- generate javadoc only for nashorn extension api classes --> + <target name="javadocapi" depends="jar"> + <javadoc destdir="${dist.javadoc.dir}" use="yes" extdirs="${nashorn.ext.path}" + windowtitle="${nashorn.product.name}" additionalparam="-quiet" failonerror="true"> + <classpath> + <pathelement location="${build.classes.dir}"/> + </classpath> + <fileset dir="${src.dir}" includes="jdk/nashorn/api/**/*.java"/> + <link href="http://docs.oracle.com/javase/8/docs/api/"/> + </javadoc> + </target> + + <!-- generate shell.html for shell tool documentation --> <target name="shelldoc" depends="jar"> <java classname="${nashorn.shell.tool}" dir="${basedir}" output="${dist.dir}/shell.html" failonerror="true" fork="true"> @@ -336,22 +351,58 @@ <echo message="WARNING: TestNG not available, will not run tests. Please copy testng.jar under test/lib directory."/> </target> - <target name="test" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available"> - <fileset id="test.classes" dir="${build.test.classes.dir}"> - <include name="**/api/javaaccess/*Test.class"/> - <include name="**/api/scripting/*Test.class"/> - <include name="**/codegen/*Test.class"/> - <include name="**/parser/*Test.class"/> - <include name="**/runtime/*Test.class"/> - <include name="**/runtime/regexp/*Test.class"/> - <include name="**/runtime/regexp/joni/*Test.class"/> - <include name="**/framework/*Test.class"/> + <!-- only to be invoked as dependency of "test" target --> + <target name="-test-classes-all" depends="jar" unless="test.class"> + <fileset id="test.classes" dir="${build.test.classes.dir}"> + <include name="**/api/javaaccess/*Test.class"/> + <include name="**/api/scripting/*Test.class"/> + <include name="**/codegen/*Test.class"/> + <include name="**/parser/*Test.class"/> + <include name="**/runtime/*Test.class"/> + <include name="**/runtime/regexp/*Test.class"/> + <include name="**/runtime/regexp/joni/*Test.class"/> + <include name="**/framework/*Test.class"/> + </fileset> + </target> + + <!-- only to be invoked as dependency of "test" target --> + <target name="-test-classes-single" depends="jar" if="test.class"> + <fileset id="test.classes" dir="${build.test.classes.dir}"> + <include name="${test.class}*"/> + </fileset> + </target> + + <!-- only to be invoked as dependency of "test" target --> + <target name="-test-nosecurity" unless="test.class"> + <fileset id="test.nosecurity.classes" dir="${build.test.classes.dir}"> + <include name="**/framework/ScriptTest.class"/> </fileset> + <testng outputdir="${build.nosecurity.test.results.dir}" classfilesetref="test.nosecurity.classes" + verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}"> + <jvmarg line="${ext.class.path}"/> + <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx}"/> + <propertyset> + <propertyref prefix="nashorn."/> + </propertyset> + <propertyset> + <propertyref prefix="test-sys-prop-no-security."/> + <mapper from="test-sys-prop-no-security.*" to="*" type="glob"/> + </propertyset> + <classpath> + <pathelement path="${run.test.classpath}"/> + </classpath> + </testng> + </target> + <!-- only to be invoked as dependency of "test" target --> + <target name="-test-security"> + <delete dir="${build.dir}/nashorn_code_cache"/> + <property name="debug.test.jvmargs" value=""/> <testng outputdir="${build.test.results.dir}" classfilesetref="test.classes" verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}"> <jvmarg line="${ext.class.path}"/> <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs}"/> + <jvmarg line="${debug.test.jvmargs}"/> <propertyset> <propertyref prefix="test-sys-prop."/> <mapper from="test-sys-prop.*" to="*" type="glob"/> @@ -363,6 +414,8 @@ </testng> </target> + <target name="test" depends="jar, -test-classes-all,-test-classes-single, check-testng, check-external-tests, compile-test, generate-policy-file, -test-security, -test-nosecurity" if="testng.available"/> + <target name="test-basicparallel" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file"> <!-- use just build.test.classes.dir to avoid referring to TestNG --> <java classname="${parallel.test.runner}" dir="${basedir}" classpath="${build.test.classes.dir}" failonerror="true" fork="true">
--- a/make/nbproject/ide-file-targets.xml Mon Jun 02 18:51:26 2014 +0100 +++ b/make/nbproject/ide-file-targets.xml Tue Aug 19 23:57:20 2014 +0100 @@ -22,38 +22,14 @@ questions. --> <project basedir=".." name="nashorn-IDE"> - <property file="nbproject/nbjdk.properties"/> - <property location="${netbeans.user}/build.properties" name="user.properties.file"/> - <property file="${user.properties.file}"/> - <import file="jdk.xml"/> - <import file="${basedir}/build-init.xml"/> - <!-- TODO: edit the following target according to your needs --> - <!-- (more info: http://www.netbeans.org/kb/articles/freeform-config.html#runsingle) --> - <target depends="-jdk-init, init" name="debug-selected-file-in-src"> - <fail unless="debug.class">Must set property 'debug.class'</fail> - <ant antfile="build.xml" inheritall="false" target="jar"/> + <target name="debug-selected-file-in-src"> + <fail unless="test.class">Must set property 'debug.class'</fail> <nbjpdastart addressproperty="jpda.address" name="nashorn" transport="dt_socket"> <classpath path="${run.test.classpath}"/> </nbjpdastart> - <java classname="${debug.class}" fork="false"> - <classpath path="${run.test.classpath}"/> - <jvmarg line="${boot.class.path}"/> - <jvmarg value="-Xdebug"/> - <jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/> - <jvmarg line="${run.test.jvmargs}"/> - <arg value="${debug.class}"/> - </java> - </target> - <!-- TODO: edit the following target according to your needs --> - <!-- (more info: http://www.netbeans.org/kb/articles/freeform-config.html#runsingle) --> - <target depends="-jdk-init, init" name="run-selected-file-in-src"> - <fail unless="run.class">Must set property 'run.class'</fail> - <ant antfile="build.xml" inheritall="false" target="jar"/> - <java classname="${run.class}" failonerror="true" fork="false"> - <classpath path="${run.test.classpath}"/> - <jvmarg line="${boot.class.path}"/> - <jvmarg line="${run.test.jvmargs}"/> - <arg value="${run.class}"/> - </java> + <ant antfile="build.xml" inheritall="false" target="test"> + <property name="test.class" value="${test.class}"/> + <property name="debug.test.jvmargs" value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/> + </ant> </target> </project>
--- a/make/nbproject/project.xml Mon Jun 02 18:51:26 2014 +0100 +++ b/make/nbproject/project.xml Tue Aug 19 23:57:20 2014 +0100 @@ -98,27 +98,27 @@ <script>nbproject/nbjdk.xml</script> <target>debug-nb</target> </action> - <action name="debug.single"> - <script>nbproject/ide-file-targets.xml</script> - <target>debug-selected-file-in-src</target> + <action name="run.single"> + <script>build.xml</script> + <target>test</target> <context> - <property>debug.class</property> - <folder>test/src</folder> + <property>test.class</property> + <folder>../test/src</folder> <pattern>\.java$</pattern> - <format>java-name</format> + <format>relative-path-noext</format> <arity> <one-file-only/> </arity> </context> </action> - <action name="run.single"> + <action name="debug.single"> <script>nbproject/ide-file-targets.xml</script> - <target>run-selected-file-in-src</target> + <target>debug-selected-file-in-src</target> <context> - <property>run.class</property> - <folder>test/src</folder> + <property>test.class</property> + <folder>../test/src</folder> <pattern>\.java$</pattern> - <format>java-name</format> + <format>relative-path-noext</format> <arity> <one-file-only/> </arity>
--- a/make/project.properties Mon Jun 02 18:51:26 2014 +0100 +++ b/make/project.properties Tue Aug 19 23:57:20 2014 +0100 @@ -59,6 +59,7 @@ # test results directory build.test.results.dir=${build.dir}/test/reports +build.nosecurity.test.results.dir=${build.dir}/test/nosecurity/reports # This directory is removed when the project is cleaned: dist.dir=dist @@ -110,6 +111,7 @@ # test scripts to run test.dir=test +test.nosecurity.dir=test/script/nosecurity test.script.dir=test/script test.basic.dir=test/script/basic test.maptests.dir=test/script/maptests @@ -127,8 +129,12 @@ test-sys-prop.es5conform.testcases.dir=${test.external.dir}/ES5Conform/TestCases test-sys-prop.test.basic.dir=${test.basic.dir} +test-sys-prop-no-security.test.dir=${test.dir} +test-sys-prop-no-security.test.js.roots=${test.nosecurity.dir} + # framework root for our script tests test-sys-prop.test.js.framework=${test.script.dir}/assert.js +test-sys-prop-no-security.test.js.framework=${test.script.dir}/assert.js # Control the verbosity of ParserTest test-sys-prop.parsertest.verbose=false @@ -245,7 +251,7 @@ test.src.dir=test/src # -Xmx is used for all tests, -Xms only for octane benchmark -run.test.xmx=3G +run.test.xmx=2G run.test.xms=2G run.test.user.language=tr
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/BufferArray.java Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2014, 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. + */ + +import jdk.nashorn.api.scripting.AbstractJSObject; +import java.nio.DoubleBuffer; + +/** + * Simple class demonstrating pluggable script object + * implementation. By implementing jdk.nashorn.api.scripting.JSObject + * (or extending AbstractJSObject which implements it), you + * can supply a friendly script object. Nashorn will call + * 'magic' methods on such a class on 'obj.foo, obj.foo = 33, + * obj.bar()' etc. from script. + * + * In this example, Java nio DoubleBuffer object is wrapped + * as a friendly script object that provides indexed acces + * to buffer content and also support array-like "length" + * readonly property to retrieve buffer's capacity. This class + * also demonstrates a function valued property called "buf". + * On 'buf' method, we return the underlying nio buffer object + * that is being wrapped. + */ +public class BufferArray extends AbstractJSObject { + // underlying nio buffer + private final DoubleBuffer buf; + + public BufferArray(int size) { + buf = DoubleBuffer.allocate(size); + } + + public BufferArray(DoubleBuffer buf) { + this.buf = buf; + } + + // called to check if indexed property exists + @Override + public boolean hasSlot(int index) { + return index > 0 && index < buf.capacity(); + } + + // get the value from that index + @Override + public Object getSlot(int index) { + return buf.get(index); + } + + // set the value at that index + @Override + public void setSlot(int index, Object value) { + buf.put(index, ((Number)value).doubleValue()); + } + + // do you have a property of that given name? + @Override + public boolean hasMember(String name) { + return "length".equals(name) || "buf".equals(name); + } + + // get the value of that named property + @Override + public Object getMember(String name) { + switch (name) { + case "length": + return buf.capacity(); + case "buf": + // return a 'function' value for this property + return new AbstractJSObject() { + @Override + public Object call(Object thiz, Object... args) { + return BufferArray.this.buf; + } + + // yes, I'm a function ! + @Override + public boolean isFunction() { + return true; + } + }; + } + return null; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/CastExample.java Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, 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. + */ + +// Simple java example with type casts. +// see javacastcounter.js. + +class CastExample { + public final static int I = (int)23.33; + public final String str = (String)"hello"; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/README Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,1 @@ +Simple Nashorn examples that can be run with "jjs" tool.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/array_mapreduce.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014, 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. + */ + +// Usage: jjs array_mapreduce.js + +// Many Array.prototype functions such as map, +// filter, reduce, reduceRight, every, some are generic. +// These functions accept ECMAScript array as well as +// many array-like objects including java arrays. +// So, you can do map/filter/reduce with Java streams or +// you can also use Array.prototype functions as below. +// See also http://en.wikipedia.org/wiki/MapReduce + +var DoubleArray = Java.type("double[]"); +var StringArray = Java.type("java.lang.String[]"); + +var map = Array.prototype.map; +var filter = Array.prototype.filter; +var reduce = Array.prototype.reduce; + +var jarr = new StringArray(5); +jarr[0] = "nashorn"; +jarr[1] = "ecmascript"; +jarr[2] = "javascript"; +jarr[3] = "js"; +jarr[4] = "scheme"; + +// sum of word lengths +print("Sum word length:", + reduce.call( + map.call(jarr, function(x) x.length), + function(x, y) x + y) +); + +// another array example involving numbers +jarr = new DoubleArray(10); +// make random array of numbers +for (var i = 0; i < jarr.length; i++) + jarr[i] = Math.random(); + +var forEach = Array.prototype.forEach; +// print numbers in the array +forEach.call(jarr, function(x) print(x)); + +// print sum of squares of the random numbers +print("Square sum:", + reduce.call( + map.call(jarr, function(x) x*x), + function(x, y) x + y) +);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/astviewer.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,98 @@ +#// Usage: jjs -scripting -fx astviewer.js -- <scriptfile> + +/* + * Copyright (c) 2014, 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. + */ + +if (!$OPTIONS._fx) { + print("Usage: jjs -scripting -fx astviewer.js -- <.js file>"); + exit(1); +} + +// Using JavaFX from Nashorn. See also: +// http://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/javafx.html + +// This example shows AST of a script file as a JavaFX +// tree view in a window. If no file is specified, AST of +// this script file is shown. This script demonstrates +// 'load' function, JavaFX support by -fx, readFully function +// in scripting mode. + +// JavaFX classes used +var StackPane = Java.type("javafx.scene.layout.StackPane"); +var Scene = Java.type("javafx.scene.Scene"); +var TreeItem = Java.type("javafx.scene.control.TreeItem"); +var TreeView = Java.type("javafx.scene.control.TreeView"); + +// Create a javafx TreeItem to view a AST node +function treeItemForASTNode(ast, name) { + var item = new TreeItem(name); + for (var prop in ast) { + var node = ast[prop]; + if (typeof node == 'object') { + if (node == null) { + // skip nulls + continue; + } + + if (Array.isArray(node) && node.length == 0) { + // skip empty arrays + continue; + } + + var subitem = treeItemForASTNode(node, prop); + } else { + var subitem = new TreeItem(prop + ": " + node); + } + item.children.add(subitem); + } + return item; +} + +// do we have a script file passed? if not, use current script +var sourceName = arguments.length == 0? __FILE__ : arguments[0]; + +// load parser.js from nashorn resources +load("nashorn:parser.js"); + +// read the full content of the file and parse it +// to get AST of the script specified +var ast = parse(readFully(sourceName)); + +// JavaFX start method +function start(stage) { + stage.title = "AST Viewer"; + var rootItem = treeItemForASTNode(ast, sourceName); + var tree = new TreeView(rootItem); + var root = new StackPane(); + root.children.add(tree); + stage.scene = new Scene(root, 300, 450); + stage.show(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/barchart_weather.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,116 @@ +#// Usage: jjs -fx barchart_weather.js + +/* + * Copyright (c) 2014, 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. + */ + +// Example that retrieves weather data from a URL in JSON +// format and draws bar chart using JavaFX + +// -fx check +if (! $OPTIONS._fx) { + print("Usage: jjs -fx barchart_weather.js"); + exit(1); +} + +// Java classes used +var URL = Java.type("java.net.URL"); +var BufferedReader = Java.type("java.io.BufferedReader"); +var InputStreamReader = Java.type("java.io.InputStreamReader"); + +// function to retrieve text content of the given URL +function readTextFromURL(url) { + var str = ''; + var u = new URL(url); + var reader = new BufferedReader( + new InputStreamReader(u.openStream())); + try { + reader.lines().forEach(function(x) str += x); + return str; + } finally { + reader.close(); + } +} + +// change URL for your city here! +var url = "http://api.openweathermap.org/data/2.5/forecast?q=chennai,india&units=metric&mode=json"; + +// download JSON document and parse +var json = readTextFromURL(url); +var weather = JSON.parse(json); + +// View JSON of this using site such as http://www.jsoneditoronline.org/ to know +// about the JSON data format used by this site + +// Extracted data from the json object +var temp = weather.list.map(function(x) x.main.temp); +var temp_min = weather.list.map(function(x) x.main.temp_min); +var temp_max = weather.list.map(function(x) x.main.temp_max); +var date = weather.list.map(function(x) x.dt_txt); + +// JavaFX classes used +var Scene = Java.type("javafx.scene.Scene"); +var BarChart = Java.type("javafx.scene.chart.BarChart"); +var CategoryAxis = Java.type("javafx.scene.chart.CategoryAxis"); +var NumberAxis = Java.type("javafx.scene.chart.NumberAxis"); +var XYChart = Java.type("javafx.scene.chart.XYChart"); + +function start(stage) { + stage.title="Chennai Weather Bar Chart"; + var xAxis = new CategoryAxis(); + xAxis.label = "date/time"; + var yAxis = new NumberAxis(); + yAxis.label = "temp in C"; + var bc = new BarChart(xAxis, yAxis); + + // 3 bars per datetime item - temp, min temp and max temp + var s1 = new XYChart.Series(); + s1.name = "temp"; + for (d in date) { + s1.data.add(new XYChart.Data(date[d], temp[d])); + } + + var s2 = new XYChart.Series(); + s2.name = "min temp"; + for (d in date) { + s2.data.add(new XYChart.Data(date[d], temp_min[d])); + } + + var s3 = new XYChart.Series(); + s3.name = "max temp"; + for (d in date) { + s3.data.add(new XYChart.Data(date[d], temp_max[d])); + } + + bc.data.addAll(s1, s2, s3); + + stage.scene = new Scene(bc, 800, 600); + stage.show(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/call_lambda.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014, 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. + */ + +// nashorn allows you treat every Java8 lambda as a function + +var JFunction = Java.type("java.util.function.Function"); +var obj = new JFunction() { + apply: function(x) { + print(x + ", lambda"); + } +}; + +// prints 'function' +print(typeof obj); + +// call it! +obj("hello");
--- a/samples/counters.js Mon Jun 02 18:51:26 2014 +0100 +++ b/samples/counters.js Tue Aug 19 23:57:20 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -33,7 +33,11 @@ * This file can be run along with any script you want to run * to print aggregate stat counters from nashorn. * - * Usage: jjs <your-file.js> counters.js + * Usage: jjs -J-Dnashorn.debug <your-file.js> counters.js */ -Debug.dumpCounters(); +if (java.lang.System.getProperty("nashorn.debug") == null) { + print("Usage: jjs -J-Dnashorn.debug <your-file.js> counters.js"); +} else { + Debug.dumpCounters(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/dirname.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, 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. + */ + +// __DIR__ variable is equivalent of `dirname $0` in +// shell scripts - expands to the directory where +// the current script is located. + +print("This script is in the directory: " + __DIR__);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/disassemble.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2014, 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. + */ + +// Usage: jjs disassemble.js -- <.class-file-path> + +// Simple .class disassembler that uses bundled ObjectWeb ASM +// classes in jdk8. WARNING: Bundled ObjectWeb ASM classes are +// not part of official jdk8 API. It can be changed/removed +// without notice. So, this script is brittle by design! + +// This example demonstrates passing arguments to script +// from jjs command line, nio and ASM usage. + +// classes used +var FileSystems = Java.type("java.nio.file.FileSystems"); +var Files = Java.type("java.nio.file.Files"); +var System = Java.type("java.lang.System"); +var PrintWriter = Java.type("java.io.PrintWriter"); + +// WARNING: uses non-API classes of jdk8! +var ClassReader = Java.type("jdk.internal.org.objectweb.asm.ClassReader"); +var TraceClassVisitor = Java.type("jdk.internal.org.objectweb.asm.util.TraceClassVisitor"); + +// convert file name to Path instance +function path(file) { + return FileSystems.default.getPath(file); +} + +// read all file content as a byte[] +function readAllBytes(file) { + return Files.readAllBytes(path(file)); +} + +// disassemble .class byte[] and prints output to stdout +function disassemble(bytecode) { + var pw = new PrintWriter(System.out); + new ClassReader(bytecode).accept(new TraceClassVisitor(pw), 0); +} + +// check for command line arg (for .class file name) +if (arguments.length == 0 || !arguments[0].endsWith('.class')) { + print("Usage: jjs disassemble -- <.class file>"); + exit(1); +} + +// disassemble the given .class file +disassemble(readAllBytes(arguments[0]));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/engine/README Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,1 @@ +Using javax.script engine API of nashorn from script!
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/engine/accessvar.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014, 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. + */ + +// Simple example showing global variable access from caller + +var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager"); +// create manager +var manager = new ScriptEngineManager(); +// create engine +var engine = manager.getEngineByName("js"); + +// eval code! +engine.eval("x = 'hello'"); + +// access global var from engine +print(engine.get('x'));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/engine/callfunc.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, 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. + */ + +// simple example showing how to call a global script +// function from caller + +var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager"); +// create manager +var manager = new ScriptEngineManager(); +// create engine +var engine = manager.getEngineByName("js"); + +// eval code! +engine.eval("function func(name) { print('I am func, hello ' + name) }"); + +// invoke functions, methods of code evaluated by engine +// from javax.script.Invocable interface. But, hey, +// calling code is JavaScript and don't worry about types :) + +engine.invokeFunction("func", "Nashorn");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/engine/callmethod.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,64 @@ +#// Usage: jjs -scripting callmethod.js + +/* + * Copyright (c) 2014, 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. + */ + +// simple example demonstrating calling a script object +// method from script engine user code + +var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager"); +// create manager +var manager = new ScriptEngineManager(); +// create engine +var engine = manager.getEngineByName("js"); + +// eval code - too many script escapes? +// use heredoc ! +engine.eval(<<CODE + var obj = { + func: function() { + print("I am func of " + this); + }, + + toString: function() { + return "Object 'obj'"; + } + }; +CODE); + +// invoke methods of an object in script world +// from javax.script.Invocable interface. But, hey, +// calling code is JavaScript and don't worry about types :) + +// get that script object on which to call a method +var scriptObj = engine.get("obj"); +// call 'func' method on object 'obj' +engine.invokeMethod(scriptObj, "func");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/engine/exposevar.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014, 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. + */ + +// Example showing how to expose a script global var from caller + +var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager"); +// create manager +var manager = new ScriptEngineManager(); +// create engine +var engine = manager.getEngineByName("js"); + +// expose variable to engine +engine.put("name", "Nashorn"); + +// access it from script +engine.eval("print('Hello, ' + name)");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/engine/foreignobject.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,71 @@ +#// Usage: jjs -scripting foreignobject.js + +/* + * Copyright (c) 2014, 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. + */ + +// cross nashorn engine scripting +// access script objects from other engines in natural syntax + +var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager"); +// create manager +var manager = new ScriptEngineManager(); +// create engine +var engine = manager.getEngineByName("js"); + +// eval code! +engine.eval(<<CODE + var obj = { + foo: 42, + func: function() { + print("func: " + this.foo); + } + }; +CODE); + +// Nashorn engine returns script objects as instance of +// the class jdk.nashorn.api.scripting.ScriptObjectMirror +// But nashorn's dynalink linker can treat these objects +// specially to support natural script syntax to access.. +// In Java code, you need to use ScriptObjectMirror's +// methods though. Once again, script world is simpler :-) + +var foreignObj = engine.get("obj"); +// access properties, functions of it +// with natural syntax +print(foreignObj.foo); +foreignObj.func(); +print(typeof foreignObj.func); + +// access engine's global +var foreignGlobal = engine.eval("this"); +// create objects in engine's world from here! +print(new foreignGlobal.Object()); +print(new foreignGlobal.Date());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/engine/hello.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014, 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. + */ + +// Simple hello world example showing create engine +// and eval simple script + +var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager"); +// create manager +var manager = new ScriptEngineManager(); +// create engine +var engine = manager.getEngineByName("js"); +// eval code! +engine.eval("print('hello world')");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/engine/interface.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,60 @@ +#// Usage: jjs -scripting interface.js + +/* + * Copyright (c) 2014, 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. + */ + +// Example demonstrating how to implement a Java interface +// whose methods are backed by global script functions + +var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager"); +// create manager +var manager = new ScriptEngineManager(); +// create engine +var engine = manager.getEngineByName("js"); + +// eval code - too many script escapes? +// use heredoc ! +engine.eval(<<CODE +function run() { + print("run global function called"); +} +CODE); + +// create Java interface object whose methods are +// implemented by script functions. This is from +// javax.script.Invocable. But we are in JS world, +// don't worry about types :) + +var Runnable = Java.type("java.lang.Runnable"); +var r = engine.getInterface(Runnable.class); +print(r.class); + +r.run();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/engine/interface2.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,63 @@ +#// Usage: jjs -scripting interface2.js + +/* + * Copyright (c) 2014, 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. + */ + +// Simple example demonstrating how to implement java interface +// whose methods are backed by script methods of a script object + +var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager"); +// create manager +var manager = new ScriptEngineManager(); +// create engine +var engine = manager.getEngineByName("js"); + +// eval code - too many script escapes? +// use heredoc ! +engine.eval(<<CODE + var obj = { + run: function() { + print("I am run method of 'obj'"); + } + }; +CODE); + +// create Java interface object whose methods are +// implemented by script methods of a script object +// This is from javax.script.Invocable. But we are +// in JS world, don't worry about types :) + +var Runnable = Java.type("java.lang.Runnable"); + +var scriptObj = engine.get("obj"); +var r = engine.getInterface(scriptObj, Runnable.class); +print(r.class); +r.run();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/engine/lambda_as_func.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, 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. + */ + +// Simple example demonstrating how to expose 'function's +// from embedding code. Any lambda object exposed to engine +// can be called as 'function' in script. + +var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager"); +// create manager +var manager = new ScriptEngineManager(); +// create engine +var engine = manager.getEngineByName("js"); + +// Any lambda (@FunctionalInterface annotated type) object can be +// be exposed from script embedding code. Script can call +// it as a function +engine.put("upper", new java.util.function.Function() { + apply: function(x) x.toUpperCase() +}); + +print(engine.eval("upper('hello')"));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/env.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,43 @@ +#// Usage: jjs -scripting env.js + +/* + * Copyright (c) 2014, 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. + */ + +// In nashorn -scripting mode, +// "$ENV" object exposes process +// environment variables + +print($ENV.PATH); +print($ENV.JAVA_HOME); + +for (i in $ENV) { + print(i, "->", $ENV[i]); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/expression_closure.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014, 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. + */ + +// nashorn supports expression closures extension of +// Mozilla JavaScript 1.8. See also +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/1.8 + +// leave {, } and 'return' keyword + +function sqr(x) x*x; + +// prints 289 (= 17*17) +print(sqr(17));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/filebrowser.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,100 @@ +#// Usage: jjs -fx filebrowser.js -- <start_dir> + +/* + * Copyright (c) 2014, 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. + */ + +// Uses -fx and javafx TreeView to visualize directories +if (!$OPTIONS._fx) { + print("Usage: jjs -fx filebrowser.js -- <start_dir>"); + exit(1); +} + +// Java classes used +var File = Java.type("java.io.File"); +var Files = Java.type("java.nio.file.Files"); + +// check directory argument, if passed +var dir = arguments.length > 0? new File(arguments[0]) : new File("."); +if (! dir.isDirectory()) { + print(dir + " is not a directory!"); + exit(2); +} + +// JavaFX classes used +var FXCollections = Java.type("javafx.collections.FXCollections"); +var Scene = Java.type("javafx.scene.Scene"); +var TreeItem = Java.type("javafx.scene.control.TreeItem"); +var TreeView = Java.type("javafx.scene.control.TreeView"); + +// create a subclass of JavaFX TreeItem class +var LazyTreeItem = Java.extend(TreeItem); + +// lazily filling children of a directory LazyTreeItem +function buildChildren(dir) { + var children = FXCollections.observableArrayList(); + var stream = Files.list(dir.toPath()); + stream.forEach(function(path) { + var file = path.toFile(); + var item = file.isDirectory()? + makeLazyTreeItem(file) : new TreeItem(file.name); + children.add(item); + }); + stream.close(); + return children; +} + +// create an instance LazyTreeItem with override methods +function makeLazyTreeItem(dir) { + var item = new LazyTreeItem(dir.name) { + expanded: false, + isLeaf: function() false, + getChildren: function() { + if (! this.expanded) { + // call super class (TreeItem) method + Java.super(item).getChildren().setAll(buildChildren(dir)); + this.expanded = true; + } + // call super class (TreeItem) method + return Java.super(item).getChildren(); + } + } + return item; +} + +// JavaFX start method +function start(stage) { + stage.title = dir.absolutePath; + var rootItem = makeLazyTreeItem(dir); + rootItem.expanded = true; + var tree = new TreeView(rootItem); + stage.scene = new Scene(tree, 300, 450); + stage.show(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/fileline.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014, 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. + */ + +// nashorn supports pseudo global variables __FILE__ +// and __LINE__ that expands to currently executed +// script file name and current script line number + +// prints current file and line number +print("executing " + __FILE__ + " @ " + __LINE__);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/fizzbuzz.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, 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. + */ + +// What is FizzBuzz? http://c2.com/cgi/wiki?FizzBuzzTest + +// Yet another FizzBuzz impl. using Java 8 lambda and stream +// but using Nashorn. This is ECMAScript port of @stuartmarks' +// Java implementation + +var IntStream = Java.type("java.util.stream.IntStream"); + +function ifmod(m, r, f) { + return function(i) { return i % m == 0? r : f(i); } +} + +// pass script function for lambda +IntStream.rangeClosed(1, 100). + mapToObj( + ifmod(15, "FizzBuzz", ifmod(5, "Buzz", ifmod(3, "Fizz", String)))) + .forEach(print);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/for_each.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2014, 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. + */ + +// nashorn supports for..each extension supported +// by Mozilla. See also +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for_each...in + +var strs = [ "hello", "world" ]; +for each (str in strs) + print(str); + +// create a java int[] object +var JArray = Java.type("int[]"); +var arr = new JArray(10); + +// store squares as values +for (i in arr) + arr[i] = i*i; + +// for .. each on java arrays +print("squares"); +for each (i in arr) + print(i); + +var System = Java.type("java.lang.System"); + +// for..each on java Iterables +// print System properties as name = value pairs +print("System properties"); +for each (p in System.properties.entrySet()) { + print(p.key, "=", p.value); +} + +// print process environment vars as name = value pairs +print("Process environment"); +for each (e in System.env.entrySet()) { + print(e.key, "=", e.value); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/gaussian_random.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014, 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. + */ + +// print 100 Guassian distributed numbers + +var Random = Java.type("java.util.Random"); +var DoubleStream = Java.type("java.util.stream.DoubleStream"); + +var r = new Random(); + +// expression closure (see expression_closure.js as well) +// passed as lambda double generator. "print" passed as +// double consumer lambda to 'forEach' method. + +DoubleStream + .generate(function() r.nextGaussian()) + .limit(100) + .forEach(print);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/gaussian_random_bind.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, 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. + */ + +// print 100 Guassian distributed numbers + +var Random = Java.type("java.util.Random"); +var DoubleStream = Java.type("java.util.stream.DoubleStream"); + +// function as lambda double generator. "print" passed as +// double consumer lambda to 'forEach' method. +// Function.prototype.bind used to attach 'state' for the +// generator function. + +DoubleStream + .generate( + function(r) { + return r.nextGaussian() + }.bind(this, new Random())) + .limit(100) + .forEach(print);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/gutenberg.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,142 @@ +#// Usage: jjs -scripting gutenberg.js + +/* + * Copyright (c) 2014, 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. + */ + +// Simple example that demonstrates reading XML Rss feed +// to generate a HTML file from script and show it by browser + +// Java classes used +var Characters = Java.type("javax.xml.stream.events.Characters"); +var Factory = Java.type("javax.xml.stream.XMLInputFactory"); +var File = Java.type("java.io.File"); +var FileWriter = Java.type("java.io.FileWriter"); +var PrintWriter = Java.type("java.io.PrintWriter"); +var URL = Java.type("java.net.URL"); + +// read Rss feed from a URL. Returns an array +// of objects having only title and link properties +function readRssFeed(url) { + var fac = Factory.newInstance(); + var reader = fac.createXMLEventReader(url.openStream()); + + // get text content from next event + function getChars() { + var result = ""; + var e = reader.nextEvent(); + if (e instanceof Characters) { + result = e.getData(); + } + return result; + } + + var items = []; + var title, link; + var inItem = false; + while (reader.hasNext()) { + var evt = reader.nextEvent(); + if (evt.isStartElement()) { + var local = evt.name.localPart; + if (local == "item") { + // capture title, description now + inItem = true; + } + + if (inItem) { + switch (local) { + case 'title': + title = getChars(); + break; + case 'link': + link = getChars(); + break; + } + } + } else if (evt.isEndElement()) { + var local = evt.name.localPart; + if (local == "item") { + // one item done, save it in result array + items.push({ title: title, link: link }); + inItem = false; + } + } + } + + return items; +} + +// generate simple HTML for an RSS feed +function getBooksHtml() { + var url = new URL("http://www.gutenberg.org/cache/epub/feeds/today.rss"); + var items = readRssFeed(url); + + var str = "<ul>"; + + // Nashorn's string interpolation and heredoc + // support is very handy in generating text content + // that is filled with elements from runtime objects. + // We insert title and link in <li> elements here. + for each (i in items) { + str += <<EOF +<li> + <a href="${i.link}">${i.title}</a> +</li> +EOF + } + str += "</ul>"; + return str; +} + +// write the string to the given file +function writeTo(file, str) { + var w = new PrintWriter(new FileWriter(file)); + try { + w.print(str); + } finally { + w.close(); + } +} + +// generate books HTML +var str = getBooksHtml(); + +// write to file. __DIR__ is directory where +// this script is stored. +var file = new File(__DIR__ + "books.html"); +writeTo(file, str); + +// show it by desktop browser +try { + var Desktop = Java.type("java.awt.Desktop"); + Desktop.desktop.browse(file.toURI()); +} catch (e) { + print(e); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/heredoc.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,51 @@ +#// Usage: jjs -scripting heredoc.js + +/* + * Copyright (c) 2014, 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. + */ + +// Nashorn supports Shell script like here-documents +// in -scripting mode. Here-docs are multi-line strings +// that are possibly interpolated with ${} expressions +// See also http://en.wikipedia.org/wiki/Here_document + +var sender = "Buffy the Vampire Slayer"; +var recipient = "Spike"; + +print(<<END + +Dear ${recipient}, + +I wish you to leave Sunnydale and never return. + +Not Quite Love, +${sender} + +END);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/interface_impl.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, 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. + */ + +// nashorn supports Java interface implementation +// by script using anonymous class-like syntax + +var Runnable = Java.type("java.lang.Runnable"); +var Thread = Java.type("java.lang.Thread"); +// use anonymous class-like new syntax +var r = new Runnable() { + run: function() { + print("I am a runnable " + Thread.currentThread()); + } +} + +r.run(); + +var t = new Thread(r); +t.start(); +t.join();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/javaastviewer.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,202 @@ +#// Usage: jjs -fx javaastviewer.js -- <.java files> + +/* + * Copyright (c) 2014, 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. + */ + +// This example demonstrates Java subclassing by Java.extend +// and javac Compiler and Tree API. This example also uses +// -fx and javafx TreeView to visualize Java AST as TreeView + +if (!$OPTIONS._fx || arguments.length == 0) { + print("Usage: jjs -fx javaastviewer.js -- <.java files>"); + exit(1); +} + +// Java types used +var Enum = Java.type("java.lang.Enum"); +var HashSet = Java.type("java.util.HashSet"); +var Name = Java.type("javax.lang.model.element.Name"); +var List = Java.type("java.util.List"); +var Set = Java.type("java.util.Set"); +var SimpleTreeVisitor = Java.type("com.sun.source.util.SimpleTreeVisitor"); +var StringArray = Java.type("java.lang.String[]"); +var ToolProvider = Java.type("javax.tools.ToolProvider"); +var Tree = Java.type("com.sun.source.tree.Tree"); + +function javaASTToScriptObject(args) { + // properties ignored (javac implementation class properties) in AST view. + // may not be exhaustive - any getAbc would become "abc" property or + // public field becomes a property of same name. + var ignoredProps = new HashSet(); + for each (var word in + ['extending', 'implementing', 'init', 'mods', 'clazz', 'defs', + 'expr', 'tag', 'preferredPosition', 'qualid', 'recvparam', + 'restype', 'params', 'startPosition', 'thrown', + 'tree', 'typarams', 'typetag', 'vartype']) { + ignoredProps.add(word); + } + + // get the system compiler tool + var compiler = ToolProvider.systemJavaCompiler; + + // get standard file manager + var fileMgr = compiler.getStandardFileManager(null, null, null); + + // make a list of compilation unit from command line argument file names + // Using Java.to convert script array (arguments) to a Java String[] + var compUnits = fileMgr.getJavaFileObjects(Java.to(args, StringArray)); + + // create a new compilation task + var task = compiler.getTask(null, fileMgr, null, null, null, compUnits); + + // subclass SimpleTreeVisitor - converts Java AST node to + // a simple script object by walking through it + var ConverterVisitor = Java.extend(SimpleTreeVisitor); + + var visitor = new ConverterVisitor() { + // convert java AST node to a friendly script object + // which can be viewed. Every node ends up in defaultAction + // method of SimpleTreeVisitor method. + + defaultAction: function (node, p) { + var resultObj = {}; + // Nashorn does not iterate properties and methods of Java objects + // But, we can bind properties of any object (including java objects) + // to a script object and iterate it! + var obj = {}; + Object.bindProperties(obj, node); + + // we don't want every property, method of java object + for (var prop in obj) { + var val = obj[prop]; + var type = typeof val; + // ignore 'method' members + if (type == 'function' || type == 'undefined') { + continue; + } + + // ignore properties from Javac implementation + // classes - hack by name!! + if (ignoredProps.contains(prop)) { + continue; + } + + // subtree - recurse it + if (val instanceof Tree) { + resultObj[prop] = visitor.visit(val, p); + } else if (val instanceof List) { + // List of trees - recurse each and make an array + var len = val.size(); + if (len != 0) { + var arr = []; + for (var j = 0; j < len; j++) { + var e = val[j]; + if (e instanceof Tree) { + arr.push(visitor.visit(e, p)); + } + } + resultObj[prop] = arr; + } + } else if (val instanceof Set) { + // Set - used for modifier flags + // make array + var len = val.size(); + if (len != 0) { + var arr = []; + for each (var e in val) { + if (e instanceof Enum || typeof e == 'string') { + arr.push(e.toString()); + } + } + resultObj[prop] = arr; + } + } else if (val instanceof Enum || val instanceof Name) { + // make string for any Enum or Name + resultObj[prop] = val.toString(); + } else if (type != 'object') { + // primitives 'as is' + resultObj[prop] = val; + } + } + return resultObj; + } + } + + // top level object with one property for each compilation unit + var scriptObj = {}; + for each (var cu in task.parse()) { + scriptObj[cu.sourceFile.name] = cu.accept(visitor, null); + } + + return scriptObj; +} + +// JavaFX classes used +var StackPane = Java.type("javafx.scene.layout.StackPane"); +var Scene = Java.type("javafx.scene.Scene"); +var TreeItem = Java.type("javafx.scene.control.TreeItem"); +var TreeView = Java.type("javafx.scene.control.TreeView"); + +// Create a javafx TreeItem to view a script object +function treeItemForObject(obj, name) { + var item = new TreeItem(name); + for (var prop in obj) { + var node = obj[prop]; + if (typeof node == 'object') { + if (node == null) { + // skip nulls + continue; + } + var subitem = treeItemForObject(node, prop); + } else { + var subitem = new TreeItem(prop + ": " + node); + } + item.children.add(subitem); + } + + item.expanded = true; + return item; +} + +var commandArgs = arguments; + +// JavaFX start method +function start(stage) { + var obj = javaASTToScriptObject(commandArgs); + stage.title = "Java AST Viewer" + var rootItem = treeItemForObject(obj, "AST"); + rootItem.expanded = true; + var tree = new TreeView(rootItem); + var root = new StackPane(); + root.children.add(tree); + stage.scene = new Scene(root, 300, 450); + stage.show(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/javacastcounter.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2014, 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. + */ + +// Usage: jjs javacastcounter.js -- <.java files> + +// This example demonstrates Nashorn Java.extend API +// to subclass a Java class from script. + +// This example uses Javac Compiler and Tree API +// to list type casts used in java source files. + +if (arguments.length == 0) { + print("Usage: jjs javacastcounter.js -- <.java files>"); + exit(1); +} + +// Java types used +var ToolProvider = Java.type("javax.tools.ToolProvider"); +var TreeScanner = Java.type("com.sun.source.util.TreeScanner"); +var Trees = Java.type("com.sun.source.util.Trees"); +var StringArray = Java.type("java.lang.String[]"); + +// get the system compiler tool +var compiler = ToolProvider.systemJavaCompiler; + +// get standard file manager +var fileMgr = compiler.getStandardFileManager(null, null, null); + +// make a list of compilation unit from command line argument file names +// Using Java.to convert script array (arguments) to a Java String[] +var compUnits = fileMgr.getJavaFileObjects(Java.to(arguments, StringArray)); + +// create a new compilation task +var task = compiler.getTask(null, fileMgr, null, null, null, compUnits); + +// SourcePositions object to get positions of AST nodes +var sourcePositions = Trees.instance(task).sourcePositions; + +// Subclass TreeScanner class +var CastCounter = Java.extend(TreeScanner); + +var counter = new CastCounter() { + // current CompilationUnitTree + compUnit: null, + // current LineMap (pos -> line, column) + lineMap: null, + // current compilation unit's file name + fileName: null, + + // overrides of TreeScanner methods + + visitCompilationUnit: function(node, p) { + // capture info about current Compilation unit + this.compUnit = node; + this.lineMap = node.lineMap; + this.fileName = node.sourceFile.name; + + // Using Java.super API to call super class method here + return Java.super(counter).visitCompilationUnit(node, p); + }, + + visitTypeCast: function(node, p) { + // print information on this type cast node + var pos = sourcePositions.getStartPosition(this.compUnit, node); + var line = this.lineMap.getLineNumber(pos); + var col = this.lineMap.getColumnNumber(pos); + print(node + " @ " + this.fileName + ":" + line + ":" + col); + + // count one more type cast + return 1; + }, + + reduce: function(r1, r2) { + return (r1 == null ? 0 : r1) + (r2 == null ? 0 : r2); + } +}; + +// print total number of type cast nodes seen +print("Total casts:", counter.scan(task.parse(), null));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/javaimporter.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014, 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. + */ + +// JavaImporter along with 'with' statement helps in +// localized Java class references + +function readTextFromURL(url) { + + // equivalent to + // + // import java.io.*; + // import java.net.*; + // import java.lang.StringBuffer; + // + // only inside the 'with' statement + with (new JavaImporter(java.io, + java.net, + java.lang.StringBuilder)) { + var buf = new StringBuilder(); + var u = new URL(url); + var reader = new BufferedReader( + new InputStreamReader(u.openStream())); + var line = null; + try { + while ((line = reader.readLine()) != null) + buf.append(line).append('\n'); + } finally { + reader.close(); + } + + return buf.toString(); + } +} + +print(readTextFromURL("https://twitter.com/"));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/javalist.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014, 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. + */ + +// Java List elements accessed/modified via +// array element access/update syntax + +var ArrayList = Java.type("java.util.ArrayList"); +var list = new ArrayList(); + +// add elements to list by List's add method calls +list.add("js"); +list.add("ecmascript"); +list.add("nashorn"); + +// get by List's get(int) method +print(list[0]); +print(list[1]); +print(list[2]); + +// access list elements by indexed access as well +print(list[0]); +print(list[1]); +print(list[2]); + +// assign to list elements by index as well +list[0] = list[0].toUpperCase(); +list[1] = list[1].toUpperCase(); +list[2] = list[2].toUpperCase(); + +print(list.get(0)); +print(list.get(1)); +print(list.get(2)); +print(list[0]); +print(list[1]); +print(list[2]);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/javamap.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014, 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. + */ + +// Java Map keys as properties + +// Demonstrating Java Map key/value can be accessed +// as property/value from script. + +var HashMap = Java.type("java.util.HashMap"); +var map = new HashMap(); + +// map key-value access by java get/put method calls +map.put('js', 'nashorn'); +print(map.get('js')); + +// access keys of map as properties +print(map['js']); +print(map.js); + +// also assign new key-value pair +// as 'property-value' +map['language'] = 'java'; +print(map.get("language")); +print(map.language); +print(map['language']); + +map.answer = 42; +print(map.get("answer")); +print(map.answer); +print(map['answer']);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/javashell.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,146 @@ +#// Usage: jjs -scripting javashell.js + +/* + * Copyright (c) 2014, 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. + */ + +// Simple Java "shell" with which you can try out +// your few liner Java code leaving imports, main etc. +// And you can leave even compilation as this script +// takes care boilerplate+compile step for you. + +// Java types used +var Arrays = Java.type("java.util.Arrays"); +var BufferedReader = Java.type("java.io.BufferedReader"); +var FileWriter = Java.type("java.io.FileWriter"); +var LocalDateTime = Java.type("java.time.LocalDateTime"); +var InputStreamReader = Java.type("java.io.InputStreamReader"); +var PrintWriter = Java.type("java.io.PrintWriter"); +var ProcessBuilder = Java.type("java.lang.ProcessBuilder"); +var System = Java.type("java.lang.System"); + +// read multiple lines of input from stdin till user +// enters an empty line +function input(endMarker, prompt) { + if (!endMarker) { + endMarker = ""; + } + + if (!prompt) { + prompt = " >> "; + } + + var str = ""; + var reader = new BufferedReader(new InputStreamReader(System.in)); + var line; + while (true) { + System.out.print(prompt); + line = reader.readLine(); + if (line == null || line == endMarker) { + break; + } + str += line + "\n"; + } + return str; +} + +// write the string to the given file +function writeTo(file, str) { + var w = new PrintWriter(new FileWriter(file)); + try { + w.print(str); + } finally { + w.close(); + } +} + +// generate Java code with user's input +// put inside generated main method +function generate(className) { + var usercode = input(); + if (usercode == "") { + return false; + } + + var fullcode = <<EOF +// userful imports, add more here if you want +// more imports. +import static java.lang.System.*; +import java.io.*; +import java.net.*; +import java.math.*; +import java.nio.file.*; +import java.time.*; +import java.time.chrono.*; +import java.time.format.*; +import java.time.temporal.*; +import java.time.zone.*; +import java.util.*; +import java.util.concurrent.*; +import java.util.function.*; +import java.util.stream.*; + +public class ${className} { + public static void main(String[] args) throws Exception { + ${usercode} + } +} +EOF + + writeTo("${className}.java", fullcode); + return true; +} + +// execute code command +function exec(args) { + // build child process and start it! + new ProcessBuilder(Arrays.asList(args.split(' '))) + .inheritIO() + .start() + .waitFor(); +} + +// generate unique name +function uniqueName() { + var now = LocalDateTime.now().toString(); + // replace unsafe chars with '_' + return "JavaShell" + now.replace(/-|:|\./g, '_'); +} + +// read-compile-run loop +while(true) { + var className = uniqueName(); + if (generate(className)) { + exec("javac ${className}.java"); + exec("java ${className}"); + } else { + break; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/jsadapter_dom.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,189 @@ +#// Usage: jjs -scripting jsadapter_dom.js + +/* + * Copyright (c) 2014, 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. + */ + +// Simple example that demonstrates reading XML Rss feed +// to generate a HTML file from script and show it by browser +// Uses XML DOM parser and DOM element wrapped by script +// "proxy" (JSAdapter constructor) + +// Java classes used +var DocBuilderFac = Java.type("javax.xml.parsers.DocumentBuilderFactory"); +var Node = Java.type("org.w3c.dom.Node"); +var File = Java.type("java.io.File"); +var FileWriter = Java.type("java.io.FileWriter"); +var PrintWriter = Java.type("java.io.PrintWriter"); + +// constants from Node class +var ELEMENT_NODE = Node.ELEMENT_NODE; +var TEXT_NODE = Node.TEXT_NODE; + +// parse XML from uri and return Document +function parseXML(uri) { + var docBuilder = DocBuilderFac.newInstance().newDocumentBuilder(); + return docBuilder["parse(java.lang.String)"](uri); +} + +// get child Elements of given name of the parent element given +function getChildElements(elem, name) { + var nodeList = elem.childNodes; + var childElems = []; + var len = nodeList.length; + for (var i = 0; i < len; i++) { + var node = nodeList.item(i); + if (node.nodeType == ELEMENT_NODE && + node.tagName == name) { + childElems.push(wrapElement(node)); + } + } + + return childElems; +} + +// get concatenated child text content of an Element +function getElemText(elem) { + var nodeList = elem.childNodes; + var len = nodeList.length; + var text = ''; + for (var i = 0; i < len; i++) { + var node = nodeList.item(i); + if (node.nodeType == TEXT_NODE) { + text += node.nodeValue; + } + } + + return text; +} + +// Wrap DOM Element object as a convenient script object +// using JSAdapter. JSAdapter is like java.lang.reflect.Proxy +// in that it allows property access, method calls be trapped +// by 'magic' methods like __get__, __call__. +function wrapElement(elem) { + if (! elem) { + return elem; + } + return new JSAdapter() { + // getter to expose child elements and attributes by name + __get__: function(name) { + if (typeof name == 'string') { + if (name.startsWith('@')) { + var attr = elem.getAttributeNode(name.substring(1)); + return !attr? undefined : attr.value; + } + + var arr = getChildElements(elem, name); + if (arr.length == 1) { + // single child element, expose as single element + return arr[0]; + } else { + // multiple children of given name, expose as array + return arr; + } + } + return undefined; + }, + + __call__: function(name) { + // toString override to get text content of this Element + if (name == 'toString' || name == 'valueOf') { + return getElemText(elem); + } + return undefined; + } + } +} + +// generate HTML using here-doc and string interpolation +function getBooksHtml() { + var doc = parseXML("http://www.gutenberg.org/cache/epub/feeds/today.rss"); + // wrap document root Element as script convenient object + var rss = wrapElement(doc.documentElement); + print("rss file version " + rss['@version']); + + var str = <<HEAD + +<html> +<title>${rss.channel.title}</title> +<body> +<h1>${rss.channel.description}</h1> +<p> +Published on ${rss.channel.pubDate} +</p> + +HEAD + + var items = rss.channel.item; + for each (var i in items) { + str += <<LIST + +<dl> +<dt><a href="${i.link}">${i.title}</a></dt> +<dd>${i.description}</dd> +</dl> + +LIST + } + str += <<END + +</body> +</html> + +END + return str; +} + +// write the string to the given file +function writeTo(file, str) { + var w = new PrintWriter(new FileWriter(file)); + try { + w.print(str); + } finally { + w.close(); + } +} + +// generate books HTML +var str = getBooksHtml(); + +// write to file. __DIR__ is directory where +// this script is stored. +var file = new File(__DIR__ + "books.html"); +writeTo(file, str); + +// show it by desktop browser +try { + var Desktop = Java.type("java.awt.Desktop"); + Desktop.desktop.browse(file.toURI()); +} catch (e) { + print(e); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/jsobject.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,75 @@ +#// Usage: jjs -scripting -cp . jsobject.js + +/* + * Copyright (c) 2014, 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. + */ + +// This sample demonstrats how to expose a +// script friendly object from your java code +// by implementing jdk.nashorn.api.scripting.JSObject + +// compile the java program +`javac BufferArray.java`; + +// print error, if any and exit +if ($ERR != '') { + print($ERR); + exit($EXIT); +} + +// create BufferArray +var BufferArray = Java.type("BufferArray"); +var bb = new BufferArray(10); + +// 'magic' methods called to retrieve set/get +// properties on BufferArray instance +var len = bb.length; +print("bb.length = " + len) +for (var i = 0; i < len; i++) { + bb[i] = i*i; +} + +for (var i = 0; i < len; i++) { + print(bb[i]); +} + +// get underlying buffer by calling a method +// on BufferArray magic object + +// 'buf' is a function member +print(typeof bb.buf); +var buf = bb.buf(); + +// use retrieved underlying nio buffer +var cap = buf.capacity(); +print("buf.capacity() = " + cap); +for (var i = 0; i < cap; i++) { + print(buf.get(i)); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/jsobject_mapreduce.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,62 @@ +#// Usage: jjs -scripting -cp . jsobject_mapreduce.js + +/* + * Copyright (c) 2014, 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. + */ + +// Many Array.prototype functions such as map, +// filter, reduce, reduceRight, every, some are generic. +// These functions accept ECMAScript array as well as +// many array-like objects including JSObjects. +// See also http://en.wikipedia.org/wiki/MapReduce + +`javac BufferArray.java`; + +var BufferArray = Java.type("BufferArray"); +var buf = new BufferArray(10); + +var map = Array.prototype.map; +var filter = Array.prototype.filter; +var reduce = Array.prototype.reduce; + +// make random list of numbers +for (var i = 0; i < 10; i++) + buf[i] = Math.random(); + +var forEach = Array.prototype.forEach; +// print numbers in the list +forEach.call(buf, function(x) print(x)); + +// print sum of squares of the random numbers +print("Square sum:", + reduce.call( + map.call(buf, function(x) x*x), + function(x, y) x + y) +);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/jsonviewer.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,120 @@ +#// Usage: jjs -fx jsonviewer.js +// or +// jjs -fx jsonviewer.js -- <url-of-json-doc> + +/* + * Copyright (c) 2014, 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. + */ + +if (! $OPTIONS._fx) { + print("Usage: jjs -fx jsonviewer.js -- <url-of-json-doc>"); + exit(1); +} + +// This example downloads a JSON file from a URL and +// shows the same as a JavaFX tree view. + +// Using JavaFX from Nashorn. See also: +// http://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/javafx.html + +// JavaFX classes used +var StackPane = Java.type("javafx.scene.layout.StackPane"); +var Scene = Java.type("javafx.scene.Scene"); +var TreeItem = Java.type("javafx.scene.control.TreeItem"); +var TreeView = Java.type("javafx.scene.control.TreeView"); + +// read text content of a URL +function readTextFromURL(url) { + // equivalent to + // + // import java.io.*; + // import java.net.*; + // import java.lang.StringBuffer; + // + // only inside the 'with' statement + with (new JavaImporter(java.io, + java.net, + java.lang.StringBuilder)) { + var buf = new StringBuilder(); + var u = new URL(url); + var reader = new BufferedReader( + new InputStreamReader(u.openStream())); + var line = null; + try { + while ((line = reader.readLine()) != null) + buf.append(line).append('\n'); + } finally { + reader.close(); + } + + return buf.toString(); + } +} + +// Create a javafx TreeItem to view a script object +function treeItemForObject(obj, name) { + var item = new TreeItem(name); + for (var prop in obj) { + var node = obj[prop]; + if (typeof node == 'object') { + if (node == null) { + // skip nulls + continue; + } + + if (Array.isArray(node) && node.length == 0) { + // skip empty arrays + continue; + } + + var subitem = treeItemForObject(node, prop); + } else { + var subitem = new TreeItem(prop + ": " + node); + } + item.children.add(subitem); + } + return item; +} + +var DEFAULT_URL = "http://api.openweathermap.org/data/2.5/forecast/daily?q=Chennai&mode=json&units=metric&cnt=7`"; + +var url = arguments.length == 0? DEFAULT_URL : arguments[0]; +var obj = JSON.parse(readTextFromURL(url)); + +// JavaFX start method +function start(stage) { + stage.title = "JSON Viewer"; + var rootItem = treeItemForObject(obj, url); + var tree = new TreeView(rootItem); + var root = new StackPane(); + root.children.add(tree); + stage.scene = new Scene(root, 300, 450); + stage.show(); +}
--- a/samples/letter.js Mon Jun 02 18:51:26 2014 +0100 +++ b/samples/letter.js Tue Aug 19 23:57:20 2014 +0100 @@ -1,3 +1,5 @@ +#// Usage: jjs -scripting letter.js -- <sender> <recipient> + /* * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. *
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/list_mapreduce.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2014, 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. + */ + +// Usage: jjs list_mapreduce.js + +// Many Array.prototype functions such as map, +// filter, reduce, reduceRight, every, some are generic. +// These functions accept ECMAScript array as well as +// many array-like objects including java.util.ArrayLists. +// So, you can do map/filter/reduce with Java streams or +// you can also use Array.prototype functions as below. +// See also http://en.wikipedia.org/wiki/MapReduce + +var ArrayList = Java.type("java.util.ArrayList"); +var list = new ArrayList(); +list.add("nashorn"); +list.add("ecmascript"); +list.add("javascript"); +list.add("js"); +list.add("scheme"); + +var map = Array.prototype.map; +var filter = Array.prototype.filter; +var reduce = Array.prototype.reduce; + +// sum of word lengths +print("Sum word length:", + reduce.call( + map.call(list, function(x) x.length), + function(x, y) x + y) +); + +// filter use to filter out "j*" and concatenate rest with ":" +// after uppercasing all strings +print( + reduce.call( + map.call( + filter.call(list, function(x) !x.startsWith("j")), + function(x) x.toUpperCase()), + function(x, y) x + ":" + y) +); + +// another list example involving numbers +list.clear(); +// make random list of numbers +for (var i = 0; i < 10; i++) + list.add(Math.random()); + +var forEach = Array.prototype.forEach; +// print numbers in the list +forEach.call(list, function(x) print(x)); + +// print sum of squares of the random numbers +print("Square sum:", + reduce.call( + map.call(list, function(x) x*x), + function(x, y) x + y) +);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/locales.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014, 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. + */ + +// Simple program that lists available locals. This is ECMAScript +// port of Java example by @brunoborges + +// Java classes used +var Arrays = Java.type("java.util.Arrays"); +var Collectors = Java.type("java.util.stream.Collectors"); +var JString = Java.type("java.lang.String"); +var Locale = Java.type("java.util.Locale"); + +var formatStr = "Country : %s \t\t\t\t:\t Country Code : %s"; + +// Nashorn allows script functions to be passed +// whereever Java8 lambdas are expected. + +// Nashorn also supports "expression closures" supported by +// Mozilla JavaScript 1.8 version. See also +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/1.8 + +// The following prints locales in (country) display name order +var list = Arrays.asList(Locale.getISOCountries()) + .stream() + .map(function(x) new Locale("", x)) + .sorted(function(c0, c1) c0.displayCountry.compareTo(c1.displayCountry)) + .map(function(l) JString.format(formatStr, l.displayCountry, l.country)) + .collect(Collectors.toList()); + +list.forEach(print);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/logisticmap.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,82 @@ +#// Usage: jjs -fx -scripting logisticmap.js -- <initial_x> <R> + +/* + * Copyright (c) 2014, 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. + */ + +// Logistic map viewer using Java8 Streams and JavaFX +// See also http://en.wikipedia.org/wiki/Logistic_map + +if (!$OPTIONS._fx || arguments.length < 2) { + print("Usage: jjs -fx -scripting logisticmap.js -- <initial_x> <R>"); + exit(1); +} + +// parameters for the logistic map +var x = parseFloat(arguments[0]); +var R = parseFloat(arguments[1]); +var NUM_POINTS = arguments.length > 2? parseFloat(arguments[2]) : 20; + +// Java classes used +var DoubleStream = Java.type('java.util.stream.DoubleStream'); +var LineChart = Java.type("javafx.scene.chart.LineChart"); +var NumberAxis = Java.type("javafx.scene.chart.NumberAxis"); +var Scene = Java.type("javafx.scene.Scene"); +var Stage = Java.type("javafx.stage.Stage"); +var XYChart = Java.type("javafx.scene.chart.XYChart"); + +function start(stage) { + stage.title = "Logistic Map: initial x = ${x}, R = ${R}"; + // make chart + var xAxis = new NumberAxis(); + var yAxis = new NumberAxis(); + var lineChart = new LineChart(xAxis, yAxis); + xAxis.setLabel("iteration"); + yAxis.setLabel("x"); + // make chart data series + var series = new XYChart.Series(); + var data = series.data; + // populate data using logistic iteration + var i = 0; + DoubleStream + .generate(function() x = R*x*(1-x)) + .limit(NUM_POINTS) + .forEach( + function(value) { + data.add(new XYChart.Data(i, value)); + i++; + } + ); + // add to stage + var scene = new Scene(lineChart, 800, 600); + lineChart.data.add(series); + stage.scene = scene; + stage.show(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/options.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,37 @@ +#// Usage: jjs -scripting options.js + +/* + * Copyright (c) 2014, 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. + */ + +// print all option names and values +for (i in $OPTIONS) { + print(i, '=', $OPTIONS[i]); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/readLine.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,38 @@ +#// Usage: jjs -scripting greeting.js + +/* + * Copyright (c) 2014, 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. + */ + +// readLine prints prompt and reads user response +var name = readLine("Your name please: "); + +// user name is interpolated within string +print("Hello ${name}");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/sam_function.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2014, 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. + */ + +// nashorn supports passing script functions whenever +// a SAM (single abstract method) type object is expected + +var System = Java.type("java.lang.System"); +var Timer = Java.type("java.util.Timer"); +var timer = new Timer(); + +// schedule method accepts java.util.TimerTask +// which is a single-abstract-method type. you +// can pass a script function and nashorn will +// wrap it as SAM implementor. + +timer.schedule(function() { + print("Hello World!"); +}, 1000); + +// wait for timer thread to print by +// reading from stdin. +print("press any key to exit after message from timer..."); +System.in.read();
--- a/samples/shell.js Mon Jun 02 18:51:26 2014 +0100 +++ b/samples/shell.js Tue Aug 19 23:57:20 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -29,50 +29,53 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * This is a simple shell tool in JavaScript. +// Usage: jjs shell.js + +/* This is a simple shell tool in JavaScript. * * Runs any operating system command using Java "exec". When "eval" command is * used, evaluates argument(s) as JavaScript code. */ -var imports = new JavaImporter(java.io, java.lang, java.util); - -function prompt() { - java.lang.System.out.print(">"); -} +(function() { + // Java classes used + var Arrays = Java.type("java.util.Arrays"); + var BufferedReader = Java.type("java.io.BufferedReader"); + var InputStreamReader = Java.type("java.io.InputStreamReader"); + var ProcessBuilder = Java.type("java.lang.ProcessBuilder"); + var System = Java.type("java.lang.System"); -with (imports) { - var reader = new BufferedReader(new InputStreamReader(System["in"])); - var line = null; + // print prompt + function prompt() { + System.out.print("> "); + } + + var reader = new BufferedReader(new InputStreamReader(System.in)); prompt(); - while ((line = reader.readLine()) != null) { - if (line != "") { - var args = line.split(" "); + // read and evaluate each line from stdin + reader.lines().forEach(function(line) { + if (! line.isEmpty()) { + var args = line.split(' '); try { - if (args[0] == "eval") { - var code = line.substring("eval".length); + // special 'eval' command to evaluate JS code + if (args[0] == 'eval') { + var code = line.substring('eval'.length); var res = eval(code); if (res != undefined) { print(res); } } else { - var argList = new ArrayList(); - for (i in args) { argList.add(args[i]); } - var procBuilder = new ProcessBuilder(argList); - procBuilder.redirectErrorStream(); - var proc = procBuilder.start(); - var out = new BufferedReader(new InputStreamReader(proc.getInputStream())); - var line = null; - while ((line = out.readLine()) != null) { - System.out.println(line); - } - proc.waitFor(); + // build child process and start it! + new ProcessBuilder(Arrays.asList(args)) + .inheritIO() + .start() + .waitFor(); } } catch (e) { + // print exception, if any print(e); } } prompt(); - } -} + }) +})()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/stack.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014, 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. + */ + +// nashorn supports 'stack' property on ECMAScript +// error objects. This property's value is a string +// that shows script stack trace. + +function g() { + throw new Error("wrong"); +} + +function f() { + g(); +} + +// Output looks something like: +// +// Error: wrong +// at g (stack.js:37) +// at f (stack.js:41) +// at <program> (stack.js:52) + +try { + f(); +} catch (e) { + print(e.stack); +}
--- a/samples/test.js Mon Jun 02 18:51:26 2014 +0100 +++ b/samples/test.js Tue Aug 19 23:57:20 2014 +0100 @@ -30,4 +30,3 @@ */ print("Hello World"); -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/uniform_random.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, 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. + */ + +// generate/print 100 uniformly distributed random values +// and print summary statistics on it + +var DoubleStream = Java.type("java.util.stream.DoubleStream"); + +// pass script function when a lambda is required +// Math.random passed here for double generator lambda +// print passed to forEach method + +DoubleStream + .generate(Math.random) + .limit(100) + .forEach(print); + +print(DoubleStream + .generate(Math.random) + .limit(100) + .summaryStatistics());
--- a/samples/uniq.js Mon Jun 02 18:51:26 2014 +0100 +++ b/samples/uniq.js Tue Aug 19 23:57:20 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -29,27 +29,28 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * Prints unique lines from a given file. - */ +// Usage: jjs uniq.js +// or: jjs uniq.js -- <file> + +// omit repeated lines and print unique lines -if (arguments.length != 1) { - print("Usage: jjs uniq.js -- <file>"); - java.lang.System.exit(1); -} +var BufferedReader = Java.type("java.io.BufferedReader"); +var FileReader = Java.type("java.io.FileReader"); +var InputStreamReader = Java.type("java.io.InputStreamReader"); +var System = Java.type("java.lang.System"); -var imports = new JavaImporter(java.io); - +// use object as set - but insertion order preserved var uniqueLines = {}; -with (imports) { - var reader = new BufferedReader(new FileReader(arguments[0])); - while ((line = reader.readLine()) != null) { - // using a JS object as a map... - uniqueLines[line] = true; - } +var reader = arguments.length > 0 ? + new FileReader(arguments[0]) : + new InputStreamReader(System.in); +reader = new BufferedReader(reader); + +// add unique lines +reader.lines().forEach(function(line) { + uniqueLines[line] = true; +}) + +for (line in uniqueLines) { + print(line); } - -// now print the collected lines -for (i in uniqueLines) { - print(i); -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/uniqs.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, 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. + */ + +// Usage: jjs uniqs.js -- <file> +// omit repeated lines and print unique lines +// But this version uses Stream API + +if (arguments.length < 1) { + print("Usage: jjs uniqs.js -- <file>"); + exit(1); +} + +var Files = Java.type("java.nio.file.Files"); +var FileSystems = Java.type("java.nio.file.FileSystems"); +print('Unique lines:', + Files + .lines(FileSystems.default.getPath(arguments[0])) + .distinct() + .peek(print) + .count());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/weather.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,63 @@ +#// usage: jjs -scripting weather.js + +/* + * Copyright (c) 2014, 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. + */ + +// Simple nashorn example showing back-quote exec process, +// JSON and Java8 streams + +var Arrays = Java.type("java.util.Arrays"); + +// use curl to download JSON weather data from the net +// use backquote -scripting mode syntax to exec a process + +`curl http://api.openweathermap.org/data/2.5/forecast/daily?q=Chennai&mode=json&units=metric&cnt=7`; + +// parse JSON +var weather = JSON.parse($OUT); + +// pull out humidity as array +var humidity = weather.list.map(function(curVal) { + return curVal.humidity; +}) + +// Stream API to print stat +print("Humidity"); +print(Arrays["stream(int[])"](humidity).summaryStatistics()); + +// pull maximum day time temperature +var temp = weather.list.map(function(curVal) { + return curVal.temp.max; +}); + +// Stream API to print stat +print("Max Temperature"); +print(Arrays["stream(double[])"](temp).summaryStatistics());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/word_histogram.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,53 @@ +#nashorn word histogram of a file + +/* + * Copyright (c) 2014, 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. + */ + +/* + * This example demonstrates how to print word histogram + * of a given text file using regex, array and JSON + * functions. + */ + +if (arguments.length < 1) { + print("Usage: jjs -scripting word_histogram.js -- <file>"); + exit(1); +} + +var obj = {}; + +readFully(arguments[0]). + split(/[^\w+]/). + forEach(function(x) + (x in obj? obj[x]++ : obj[x] = 1)); + +print(JSON.stringify(obj)); +
--- a/src/jdk/internal/dynalink/beans/BeanLinker.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/internal/dynalink/beans/BeanLinker.java Tue Aug 19 23:57:20 2014 +0100 @@ -113,6 +113,8 @@ // explicit property is beneficial for them. // REVISIT: is it maybe a code smell that "dyn:getLength" is not needed? setPropertyGetter("length", GET_ARRAY_LENGTH, ValidationType.IS_ARRAY); + } else if(List.class.isAssignableFrom(clazz)) { + setPropertyGetter("length", GET_COLLECTION_LENGTH, ValidationType.INSTANCE_OF); } }
--- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Tue Aug 19 23:57:20 2014 +0100 @@ -27,16 +27,14 @@ import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; +import static jdk.nashorn.internal.runtime.Source.sourceFor; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; import java.io.Reader; import java.lang.invoke.MethodHandles; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.URL; -import java.nio.charset.Charset; import java.security.AccessControlContext; import java.security.AccessController; import java.security.Permissions; @@ -124,21 +122,21 @@ } } - // load engine.js and return content as a char[] + // load engine.js @SuppressWarnings("resource") - private static char[] loadEngineJSSource() { + private static Source loadEngineJSSource() { final String script = "resources/engine.js"; try { - final InputStream is = AccessController.doPrivileged( - new PrivilegedExceptionAction<InputStream>() { + return AccessController.doPrivileged( + new PrivilegedExceptionAction<Source>() { @Override - public InputStream run() throws Exception { + public Source run() throws IOException { final URL url = NashornScriptEngine.class.getResource(script); - return url.openStream(); + return sourceFor(NashornException.ENGINE_SCRIPT_SOURCE_NAME, url); } - }); - return Source.readFully(new InputStreamReader(is)); - } catch (final PrivilegedActionException | IOException e) { + } + ); + } catch (final PrivilegedActionException e) { if (Context.DEBUG) { e.printStackTrace(); } @@ -147,7 +145,7 @@ } // Source object for engine.js - private static final Source ENGINE_SCRIPT_SRC = new Source(NashornException.ENGINE_SCRIPT_SOURCE_NAME, loadEngineJSSource()); + private static final Source ENGINE_SCRIPT_SRC = loadEngineJSSource(); NashornScriptEngine(final NashornScriptEngineFactory factory, final ClassLoader appLoader) { this(factory, DEFAULT_OPTIONS, appLoader); @@ -282,19 +280,14 @@ private static Source makeSource(final Reader reader, final ScriptContext ctxt) throws ScriptException { try { - if (reader instanceof URLReader) { - final URL url = ((URLReader)reader).getURL(); - final Charset cs = ((URLReader)reader).getCharset(); - return new Source(url.toString(), url, cs); - } - return new Source(getScriptName(ctxt), Source.readFully(reader)); - } catch (final IOException e) { + return sourceFor(getScriptName(ctxt), reader); + } catch (IOException e) { throw new ScriptException(e); } } private static Source makeSource(final String src, final ScriptContext ctxt) { - return new Source(getScriptName(ctxt), src); + return sourceFor(getScriptName(ctxt), src); } private static String getScriptName(final ScriptContext ctxt) { @@ -532,6 +525,31 @@ return evalImpl(script, ctxt, getNashornGlobalFrom(ctxt)); } + 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 { + if (globalChanged) { + Context.setGlobal(ctxtGlobal); + } + + final ScriptFunction script = mgcs.getFunction(ctxtGlobal); + + // set ScriptContext variables if ctxt is non-null + if (ctxt != null) { + setContextVariables(ctxtGlobal, ctxt); + } + return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal)); + } catch (final Exception e) { + throwAsScriptException(e, ctxtGlobal); + throw new AssertionError("should not reach here"); + } finally { + if (globalChanged) { + Context.setGlobal(oldGlobal); + } + } + } + private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException { if (script == null) { return null; @@ -578,18 +596,38 @@ } private CompiledScript asCompiledScript(final Source source) throws ScriptException { - final ScriptFunction func = compileImpl(source, context); + final Context.MultiGlobalCompiledScript mgcs; + final ScriptFunction func; + final Global oldGlobal = Context.getGlobal(); + final Global newGlobal = getNashornGlobalFrom(context); + final boolean globalChanged = (oldGlobal != newGlobal); + try { + if (globalChanged) { + Context.setGlobal(newGlobal); + } + + mgcs = nashornContext.compileScript(source); + func = mgcs.getFunction(newGlobal); + } catch (final Exception e) { + throwAsScriptException(e, newGlobal); + throw new AssertionError("should not reach here"); + } finally { + if (globalChanged) { + Context.setGlobal(oldGlobal); + } + } + return new CompiledScript() { @Override public Object eval(final ScriptContext ctxt) throws ScriptException { final Global globalObject = getNashornGlobalFrom(ctxt); - // Are we running the script in the correct global? + // Are we running the script in the same global in which it was compiled? if (func.getScope() == globalObject) { return evalImpl(func, ctxt, globalObject); } - // ScriptContext with a different global. Compile again! - // Note that we may still hit per-global compilation cache. - return evalImpl(compileImpl(source, ctxt), ctxt, globalObject); + + // different global + return evalImpl(mgcs, ctxt, globalObject); } @Override public ScriptEngine getEngine() {
--- a/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java Tue Aug 19 23:57:20 2014 +0100 @@ -496,7 +496,7 @@ public void setProto(final Object proto) { inGlobal(new Callable<Void>() { @Override public Void call() { - sobj.setProtoCheck(unwrap(proto, global)); + sobj.setPrototypeOf(unwrap(proto, global)); return null; } }); @@ -621,6 +621,7 @@ /** * Utilitity to convert this script object to the given type. * + * @param <T> destination type to convert to * @param type destination type to convert to * @return converted object */
--- a/src/jdk/nashorn/api/scripting/package-info.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/api/scripting/package-info.java Tue Aug 19 23:57:20 2014 +0100 @@ -32,7 +32,8 @@ * ScriptEngine nashornEngine = new ScriptEngineManager().getEngineByName("Nashorn"); * </pre> * <p>Nashorn script engines implement the optional {@link javax.script.Invocable} and {@link javax.script.Compilable} - * interfaces, allowing for efficient pre-compilation and repeated execution of scripts. See + * interfaces, allowing for efficient pre-compilation and repeated execution of scripts. In addition, + * this package provides nashorn specific extension classes, interfaces and methods. See * {@link jdk.nashorn.api.scripting.NashornScriptEngineFactory} for further details. */ package jdk.nashorn.api.scripting;
--- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java Tue Aug 19 23:57:20 2014 +0100 @@ -1451,7 +1451,10 @@ if (value == null) { hasGettersSetters = true; - } else if (key.equals(ScriptObject.PROTO_PROPERTY_NAME)) { + } else if (propertyNode.getKey() instanceof IdentNode && + key.equals(ScriptObject.PROTO_PROPERTY_NAME)) { + // ES6 draft compliant __proto__ inside object literal + // Identifier key and name is __proto__ protoNode = value; continue; } @@ -1497,7 +1500,9 @@ method.dup(); if (protoNode != null) { load(protoNode); - method.invoke(ScriptObject.SET_PROTO_CHECK); + // take care of { __proto__: 34 } or some such! + method.convert(Type.OBJECT); + method.invoke(ScriptObject.SET_PROTO_FROM_LITERAL); } else { globalObjectPrototype(); method.invoke(ScriptObject.SET_PROTO); @@ -3228,7 +3233,7 @@ final String className = SCRIPTFUNCTION_IMPL_OBJECT; final int fieldCount = ObjectClassGenerator.getPaddedFieldCount(functionNode.countThisProperties()); final String allocatorClassName = Compiler.binaryName(ObjectClassGenerator.getClassName(fieldCount)); - final PropertyMap allocatorMap = PropertyMap.newMap(null, 0, fieldCount, 0); + final PropertyMap allocatorMap = PropertyMap.newMap(null, allocatorClassName, 0, fieldCount, 0); method._new(className).dup(); loadConstant(new RecompilableScriptFunctionData(functionNode, compiler.getCodeInstaller(), allocatorClassName, allocatorMap));
--- a/src/jdk/nashorn/internal/codegen/Compiler.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/codegen/Compiler.java Tue Aug 19 23:57:20 2014 +0100 @@ -405,32 +405,8 @@ return newFunctionNode; } - private Class<?> install(final String className, final byte[] code) { - LOG.fine("Installing class ", className); - - final Class<?> clazz = installer.install(Compiler.binaryName(className), code); - - try { - final Object[] constants = getConstantData().toArray(); - // Need doPrivileged because these fields are private - AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { - @Override - public Void run() throws Exception { - //use reflection to write source and constants table to installed classes - final Field sourceField = clazz.getDeclaredField(SOURCE.symbolName()); - final Field constantsField = clazz.getDeclaredField(CONSTANTS.symbolName()); - sourceField.setAccessible(true); - constantsField.setAccessible(true); - sourceField.set(null, source); - constantsField.set(null, constants); - return null; - } - }); - } catch (final PrivilegedActionException e) { - throw new RuntimeException(e); - } - - return clazz; + private Class<?> install(final String className, final byte[] code, final Object[] constants) { + return installer.install(className, code, source, constants); } /** @@ -444,10 +420,15 @@ assert functionNode.hasState(CompilationState.EMITTED) : functionNode.getName() + " has no bytecode and cannot be installed"; final Map<String, Class<?>> installedClasses = new HashMap<>(); + final Object[] constants = getConstantData().toArray(); final String rootClassName = firstCompileUnitName(); final byte[] rootByteCode = bytecode.get(rootClassName); - final Class<?> rootClass = install(rootClassName, rootByteCode); + final Class<?> rootClass = install(rootClassName, rootByteCode, constants); + + if (!isLazy()) { + installer.storeCompiledScript(source, rootClassName, bytecode, constants); + } int length = rootByteCode.length; @@ -461,7 +442,7 @@ final byte[] code = entry.getValue(); length += code.length; - installedClasses.put(className, install(className, code)); + installedClasses.put(className, install(className, code, constants)); } for (final CompileUnit unit : compileUnits) {
--- a/src/jdk/nashorn/internal/codegen/MapCreator.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/codegen/MapCreator.java Tue Aug 19 23:57:20 2014 +0100 @@ -83,7 +83,7 @@ } } - return PropertyMap.newMap(properties, fieldCount, fieldMaximum, 0); + return PropertyMap.newMap(properties, structure.getName(), fieldCount, fieldMaximum, 0); } PropertyMap makeSpillMap(final boolean hasArguments) { @@ -100,7 +100,7 @@ } } - return PropertyMap.newMap(properties, 0, 0, spillIndex); + return PropertyMap.newMap(properties, structure.getName(), 0, 0, spillIndex); } /**
--- a/src/jdk/nashorn/internal/ir/annotations/Reference.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/ir/annotations/Reference.java Tue Aug 19 23:57:20 2014 +0100 @@ -32,9 +32,7 @@ * Reference node in AST, i.e. anything not a copy. Important for * AST traversal and cloning. Cloning currently as a rule uses * existingOrSame for references and otherwise existingOrCopy - * <p> */ - @Retention(value=RetentionPolicy.RUNTIME) public @interface Reference { // EMPTY
--- a/src/jdk/nashorn/internal/ir/debug/JSONWriter.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/ir/debug/JSONWriter.java Tue Aug 19 23:57:20 2014 +0100 @@ -25,6 +25,8 @@ package jdk.nashorn.internal.ir.debug; +import static jdk.nashorn.internal.runtime.Source.sourceFor; + import java.util.Arrays; import java.util.List; import java.util.ArrayList; @@ -88,7 +90,7 @@ * @return JSON string representation of AST of the supplied code */ public static String parse(final ScriptEnvironment env, final String code, final String name, final boolean includeLoc) { - final Parser parser = new Parser(env, new Source(name, code), new Context.ThrowErrorManager(), env._strict); + final Parser parser = new Parser(env, sourceFor(name, code), new Context.ThrowErrorManager(), env._strict); final JSONWriter jsonWriter = new JSONWriter(includeLoc); try { final FunctionNode functionNode = parser.parse(CompilerConstants.RUN_SCRIPT.symbolName());
--- a/src/jdk/nashorn/internal/objects/Global.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/objects/Global.java Tue Aug 19 23:57:20 2014 +0100 @@ -1906,6 +1906,13 @@ // Object.getPrototypeOf(Function.prototype) === Object.prototype anon.setInitialProto(ObjectPrototype); + // ES6 draft compliant __proto__ property of Object.prototype + // accessors on Object.prototype for "__proto__" + final ScriptFunction getProto = ScriptFunctionImpl.makeFunction("getProto", NativeObject.GET__PROTO__); + final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", NativeObject.SET__PROTO__); + ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto); + + // Function valued properties of Function.prototype were not properly // initialized. Because, these were created before global.function and // global.object were not initialized.
--- a/src/jdk/nashorn/internal/objects/NativeError.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/objects/NativeError.java Tue Aug 19 23:57:20 2014 +0100 @@ -327,7 +327,12 @@ final Object exception = ECMAException.getException(sobj); if (exception instanceof Throwable) { Object value = getScriptStackString(sobj, (Throwable)exception); - sobj.put(STACK, value, false); + if (sobj.hasOwnProperty(STACK)) { + sobj.put(STACK, value, false); + } else { + sobj.addOwnProperty(STACK, Attribute.NOT_ENUMERABLE, value); + } + return value; } @@ -346,7 +351,12 @@ public static Object setStack(final Object self, final Object value) { Global.checkObject(self); final ScriptObject sobj = (ScriptObject)self; - sobj.set(STACK, value, false); + if (sobj.hasOwnProperty(STACK)) { + sobj.put(STACK, value, false); + } else { + sobj.addOwnProperty(STACK, Attribute.NOT_ENUMERABLE, value); + } + return value; }
--- a/src/jdk/nashorn/internal/objects/NativeFunction.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/objects/NativeFunction.java Tue Aug 19 23:57:20 2014 +0100 @@ -27,6 +27,7 @@ import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; +import static jdk.nashorn.internal.runtime.Source.sourceFor; import java.util.List; @@ -257,7 +258,7 @@ } private static void checkFunctionParameters(final String params) { - final Source src = new Source("<function>", params); + final Source src = sourceFor("<function>", params); final Parser parser = new Parser(Global.getEnv(), src, new Context.ThrowErrorManager()); try { parser.parseFormalParameterList(); @@ -267,7 +268,7 @@ } private static void checkFunctionBody(final String funcBody) { - final Source src = new Source("<function>", funcBody); + final Source src = sourceFor("<function>", funcBody); final Parser parser = new Parser(Global.getEnv(), src, new Context.ThrowErrorManager()); try { parser.parseFunctionBody();
--- a/src/jdk/nashorn/internal/objects/NativeObject.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/objects/NativeObject.java Tue Aug 19 23:57:20 2014 +0100 @@ -25,6 +25,7 @@ package jdk.nashorn.internal.objects; +import static jdk.nashorn.internal.lookup.Lookup.MH; import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; @@ -74,6 +75,9 @@ */ @ScriptClass("Object") public final class NativeObject { + public static final MethodHandle GET__PROTO__ = findOwnMH("get__proto__", ScriptObject.class, Object.class); + public static final MethodHandle SET__PROTO__ = findOwnMH("set__proto__", Object.class, Object.class, Object.class); + private static final Object TO_STRING = new Object(); private static InvokeByName getTO_STRING() { @@ -86,6 +90,35 @@ }); } + @SuppressWarnings("unused") + private static ScriptObject get__proto__(final Object self) { + // See ES6 draft spec: B.2.2.1.1 get Object.prototype.__proto__ + // Step 1 Let O be the result of calling ToObject passing the this. + final Object obj = Global.toObject(self); + Global.checkObject(obj); + final ScriptObject sobj = (ScriptObject)obj; + return sobj.getProto(); + } + + @SuppressWarnings("unused") + private static Object set__proto__(final Object self, final Object proto) { + // See ES6 draft spec: B.2.2.1.2 set Object.prototype.__proto__ + // Step 1 + Global.checkObjectCoercible(self); + // Step 4 + if (! (self instanceof ScriptObject)) { + return UNDEFINED; + } + + final ScriptObject sobj = (ScriptObject)self; + // __proto__ assignment ignores non-nulls and non-objects + // step 3: If Type(proto) is neither Object nor Null, then return undefined. + if (proto == null || proto instanceof ScriptObject) { + sobj.setPrototypeOf(proto); + } + return UNDEFINED; + } + private static final MethodType MIRROR_GETTER_TYPE = MethodType.methodType(Object.class, ScriptObjectMirror.class); private static final MethodType MIRROR_SETTER_TYPE = MethodType.methodType(Object.class, ScriptObjectMirror.class, Object.class); @@ -160,7 +193,7 @@ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) public static Object setPrototypeOf(final Object self, final Object obj, final Object proto) { if (obj instanceof ScriptObject) { - ((ScriptObject)obj).setProtoCheck(proto); + ((ScriptObject)obj).setPrototypeOf(proto); return obj; } else if (obj instanceof ScriptObjectMirror) { ((ScriptObjectMirror)obj).setProto(proto); @@ -777,4 +810,8 @@ return new LinkRequestImpl(CallSiteDescriptorFactory.create(MethodHandles.publicLookup(), operation, methodType), false, source); } + + private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) { + return MH.findStatic(MethodHandles.lookup(), NativeObject.class, name, MH.type(rtype, types)); + } }
--- a/src/jdk/nashorn/internal/objects/NativeRegExp.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/objects/NativeRegExp.java Tue Aug 19 23:57:20 2014 +0100 @@ -731,6 +731,12 @@ if (nextChar == '$') { // Skip past $ cursor++; + if (cursor == replacement.length()) { + // nothing after "$" + sb.append('$'); + break; + } + nextChar = replacement.charAt(cursor); final int firstDigit = nextChar - '0';
--- a/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java Tue Aug 19 23:57:20 2014 +0100 @@ -89,6 +89,15 @@ } @Override + protected void setImpl(final int index, final long value) { + if (JSType.isRepresentableAsInt(value)) { + setImpl(index, (int)value); + } else { + buffer.getByteArray()[byteIndex(index)] = value > 0 ? (byte)0xff : 0; + } + } + + @Override protected void setImpl(final int key, final double value) { setImpl(key, (int)Math.rint(value)); }
--- a/src/jdk/nashorn/internal/parser/Parser.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/parser/Parser.java Tue Aug 19 23:57:20 2014 +0100 @@ -33,6 +33,7 @@ import static jdk.nashorn.internal.parser.TokenType.CATCH; import static jdk.nashorn.internal.parser.TokenType.COLON; import static jdk.nashorn.internal.parser.TokenType.COMMARIGHT; +import static jdk.nashorn.internal.parser.TokenType.CONST; import static jdk.nashorn.internal.parser.TokenType.DECPOSTFIX; import static jdk.nashorn.internal.parser.TokenType.DECPREFIX; import static jdk.nashorn.internal.parser.TokenType.ELSE; @@ -849,6 +850,11 @@ expect(SEMICOLON); break; default: + if (env._const_as_var && type == CONST) { + variableStatement(true); + break; + } + if (type == IDENT || isNonStrictModeIdent()) { if (T(k + 1) == COLON) { labelStatement(); @@ -1110,6 +1116,12 @@ case SEMICOLON: break; default: + if (env._const_as_var && type == CONST) { + // Var statements captured in for outer block. + vars = variableStatement(false); + break; + } + final Expression expression = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true); forNode = forNode.setInit(lc, expression); break;
--- a/src/jdk/nashorn/internal/parser/TokenType.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/parser/TokenType.java Tue Aug 19 23:57:20 2014 +0100 @@ -111,7 +111,7 @@ CATCH (KEYWORD, "catch"), // CHAR (FUTURE, "char"), CLASS (FUTURE, "class"), - CONST (FUTURE, "const"), + CONST (KEYWORD, "const"), CONTINUE (KEYWORD, "continue"), DEBUGGER (KEYWORD, "debugger"), DEFAULT (KEYWORD, "default"),
--- a/src/jdk/nashorn/internal/runtime/AccessorProperty.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/AccessorProperty.java Tue Aug 19 23:57:20 2014 +0100 @@ -39,6 +39,9 @@ import static jdk.nashorn.internal.lookup.Lookup.MH; import static jdk.nashorn.internal.lookup.MethodHandleFactory.stripName; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.Serializable; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -51,11 +54,12 @@ * An AccessorProperty is the most generic property type. An AccessorProperty is * represented as fields in a ScriptObject class. */ -public final class AccessorProperty extends Property { +public final class AccessorProperty extends Property implements Serializable { private static final MethodHandles.Lookup lookup = MethodHandles.lookup(); private static final MethodHandle REPLACE_MAP = findOwnMH("replaceMap", Object.class, Object.class, PropertyMap.class, String.class, Class.class, Class.class); private static final int NOOF_TYPES = getNumberOfAccessorTypes(); + private static final long serialVersionUID = 3371720170182154920L; /** * Properties in different maps for the same structure class will share their field getters and setters. This could @@ -71,7 +75,7 @@ }; /** Property getter cache */ - private MethodHandle[] getters = new MethodHandle[NOOF_TYPES]; + private transient MethodHandle[] getters = new MethodHandle[NOOF_TYPES]; private static final MethodType[] ACCESSOR_GETTER_TYPES = new MethodType[NOOF_TYPES]; private static final MethodType[] ACCESSOR_SETTER_TYPES = new MethodType[NOOF_TYPES]; @@ -122,16 +126,16 @@ } /** Seed getter for the primitive version of this field (in -Dnashorn.fields.dual=true mode) */ - private MethodHandle primitiveGetter; + private transient MethodHandle primitiveGetter; /** Seed setter for the primitive version of this field (in -Dnashorn.fields.dual=true mode) */ - private MethodHandle primitiveSetter; + private transient MethodHandle primitiveSetter; /** Seed getter for the Object version of this field */ - private MethodHandle objectGetter; + private transient MethodHandle objectGetter; /** Seed setter for the Object version of this field */ - private MethodHandle objectSetter; + private transient MethodHandle objectSetter; /** * Current type of this object, in object only mode, this is an Object.class. In dual-fields mode @@ -243,6 +247,12 @@ public AccessorProperty(final String key, final int flags, final Class<?> structure, final int slot) { super(key, flags, slot); + initGetterSetter(structure); + } + + private void initGetterSetter(final Class<?> structure) { + final int slot = getSlot(); + final String key = getKey(); /* * primitiveGetter and primitiveSetter are only used in dual fields mode. Setting them to null also * works in dual field mode, it only means that the property never has a primitive @@ -305,6 +315,12 @@ setCurrentType(property.getCurrentType()); } + private void readObject(final ObjectInputStream s) throws IOException, ClassNotFoundException { + s.defaultReadObject(); + // Restore getters array + getters = new MethodHandle[NOOF_TYPES]; + } + private static MethodHandle bindTo(final MethodHandle mh, final Object receiver) { if (mh == null) { return null; @@ -364,6 +380,16 @@ } @Override + void initMethodHandles(final Class<?> structure) { + if (!ScriptObject.class.isAssignableFrom(structure) || !StructureLoader.isStructureClass(structure.getName())) { + throw new IllegalArgumentException(); + } + if (!isSpill()) { + initGetterSetter(structure); + } + } + + @Override public MethodHandle getGetter(final Class<?> type) { final int i = getAccessorTypeIndex(type); ensureObjectGetter();
--- a/src/jdk/nashorn/internal/runtime/CodeInstaller.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/CodeInstaller.java Tue Aug 19 23:57:20 2014 +0100 @@ -25,6 +25,7 @@ package jdk.nashorn.internal.runtime; +import java.util.Map; import jdk.nashorn.internal.codegen.ClassEmitter; /** @@ -52,7 +53,7 @@ * @param bytecode bytecode * @return the installed class */ - public Class<?> install(final String className, final byte[] bytecode); + public Class<?> install(final String className, final byte[] bytecode, final Source source, final Object[] constants); /** * Verify generated bytecode before emission. This is called back from the @@ -74,4 +75,13 @@ * @return unique eval id */ public long getUniqueEvalId(); + + /** + * Store a compiled script for later reuse + * @param source the script source + * @param mainClassName the main class name + * @param classBytes map of class names to class bytes + * @param constants constants array + */ + public void storeCompiledScript(Source source, String mainClassName, Map<String, byte[]> classBytes, Object[] constants); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/nashorn/internal/runtime/CodeStore.java Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2010, 2014, 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.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.Base64; +import java.util.Map; + +/** + * A code cache for persistent caching of compiled scripts. + */ +final class CodeStore { + + private final File dir; + private final int minSize; + + // Message digest to file name encoder + private final static Base64.Encoder BASE64 = Base64.getUrlEncoder().withoutPadding(); + + // Default minimum size for storing a compiled script class + private final static int DEFAULT_MIN_SIZE = 1000; + + /** + * Constructor + * @param path directory to store code in + * @throws IOException + */ + public CodeStore(final String path) throws IOException { + this(path, DEFAULT_MIN_SIZE); + } + + /** + * Constructor + * @param path directory to store code in + * @param minSize minimum file size for caching scripts + * @throws IOException + */ + public CodeStore(final String path, final int minSize) throws IOException { + this.dir = checkDirectory(path); + this.minSize = minSize; + } + + private static File checkDirectory(final String path) throws IOException { + try { + return AccessController.doPrivileged(new PrivilegedExceptionAction<File>() { + @Override + public File run() throws IOException { + final File dir = new File(path).getAbsoluteFile(); + if (!dir.exists() && !dir.mkdirs()) { + throw new IOException("Could not create directory: " + dir); + } else if (!dir.isDirectory()) { + throw new IOException("Not a directory: " + dir); + } else if (!dir.canRead() || !dir.canWrite()) { + throw new IOException("Directory not readable or writable: " + dir); + } + return dir; + } + }); + } catch (PrivilegedActionException e) { + throw (IOException) e.getException(); + } + } + + /** + * Return a compiled script from the cache, or null if it isn't found. + * + * @param source the source + * @return the compiled script or null + * @throws IOException + * @throws ClassNotFoundException + */ + public CompiledScript getScript(final Source source) throws IOException, ClassNotFoundException { + if (source.getLength() < minSize) { + return null; + } + + final String digest = BASE64.encodeToString(source.getDigest()); + final File file = new File(dir, digest); + + try { + return AccessController.doPrivileged(new PrivilegedExceptionAction<CompiledScript>() { + @Override + public CompiledScript run() throws IOException, ClassNotFoundException { + if (!file.exists()) { + return null; + } + try (ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(new FileInputStream(file)))) { + CompiledScript compiledScript = (CompiledScript) in.readObject(); + compiledScript.setSource(source); + return compiledScript; + } + } + }); + } catch (PrivilegedActionException e) { + final Exception ex = e.getException(); + if (ex instanceof IOException) { + throw (IOException) ex; + } else if (ex instanceof ClassNotFoundException) { + throw (ClassNotFoundException) ex; + } + throw (new RuntimeException(ex)); + } + } + + /** + * Store a compiled script in the cache. + * + * @param source the source + * @param mainClassName the main class name + * @param classBytes a map of class bytes + * @param constants the constants array + * @throws IOException + */ + public void putScript(final Source source, final String mainClassName, final Map<String, byte[]> classBytes, final Object[] constants) + throws IOException { + if (source.getLength() < minSize) { + return; + } + for (final Object constant : constants) { + // Make sure all constant data is serializable + if (! (constant instanceof Serializable)) { + return; + } + } + + final String digest = BASE64.encodeToString(source.getDigest()); + final File file = new File(dir, digest); + final CompiledScript script = new CompiledScript(source, mainClassName, classBytes, constants); + + try { + AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { + @Override + public Void run() throws IOException { + try (ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file)))) { + out.writeObject(script); + } + return null; + } + }); + } catch (PrivilegedActionException e) { + throw (IOException) e.getException(); + } + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/nashorn/internal/runtime/CompiledScript.java Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2010, 2014, 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.io.Serializable; +import java.util.Arrays; +import java.util.Map; + +/** + * Class representing a compiled script. + */ +final class CompiledScript implements Serializable { + + /** Main class name. */ + private final String mainClassName; + + /** Map of class names to class bytes. */ + private final Map<String, byte[]> classBytes; + + /** Constants array. */ + private final Object[] constants; + + /** The source */ + private transient Source source; + + private static final long serialVersionUID = 2958227232195298340L; + + /** + * Constructor. + * + * @param mainClassName main class name + * @param classBytes map of class names to class bytes + * @param constants constants array + */ + CompiledScript(final Source source, final String mainClassName, final Map<String, byte[]> classBytes, final Object[] constants) { + this.source = source; + this.mainClassName = mainClassName; + this.classBytes = classBytes; + this.constants = constants; + } + + /** + * Returns the main class name. + * @return the main class name + */ + public String getMainClassName() { + return mainClassName; + } + + /** + * Returns a map of class names to class bytes. + * @return map of class bytes + */ + public Map<String, byte[]> getClassBytes() { + return classBytes; + } + + /** + * Returns the constants array. + * @return constants array + */ + public Object[] getConstants() { + return constants; + } + + /** + * Returns the source of this cached script. + * @return the source + */ + public Source getSource() { + return source; + } + + /** + * Sets the source of this cached script. + * @param source the source + */ + void setSource(final Source source) { + this.source = source; + } + + @Override + public int hashCode() { + int hash = mainClassName.hashCode(); + hash = 31 * hash + classBytes.hashCode(); + hash = 31 * hash + Arrays.hashCode(constants); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof CompiledScript)) { + return false; + } + + final CompiledScript cs = (CompiledScript) obj; + return mainClassName.equals(cs.mainClassName) + && classBytes.equals(cs.classBytes) + && Arrays.equals(constants, cs.constants); + } +}
--- a/src/jdk/nashorn/internal/runtime/Context.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/Context.java Tue Aug 19 23:57:20 2014 +0100 @@ -25,11 +25,14 @@ package jdk.nashorn.internal.runtime; +import static jdk.nashorn.internal.codegen.CompilerConstants.CONSTANTS; import static jdk.nashorn.internal.codegen.CompilerConstants.RUN_SCRIPT; +import static jdk.nashorn.internal.codegen.CompilerConstants.SOURCE; import static jdk.nashorn.internal.codegen.CompilerConstants.STRICT_MODE; import static jdk.nashorn.internal.lookup.Lookup.MH; import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; +import static jdk.nashorn.internal.runtime.Source.sourceFor; import java.io.File; import java.io.IOException; @@ -38,6 +41,7 @@ import java.lang.invoke.MethodHandles; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; +import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.concurrent.atomic.AtomicLong; import java.net.MalformedURLException; @@ -48,7 +52,10 @@ import java.security.CodeSource; import java.security.Permissions; import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; import java.security.ProtectionDomain; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; @@ -134,8 +141,32 @@ } @Override - public Class<?> install(final String className, final byte[] bytecode) { - return loader.installClass(className, bytecode, codeSource); + public Class<?> install(final String className, final byte[] bytecode, final Source source, final Object[] constants) { + Compiler.LOG.fine("Installing class ", className); + + final String binaryName = Compiler.binaryName(className); + final Class<?> clazz = loader.installClass(binaryName, bytecode, codeSource); + + try { + // Need doPrivileged because these fields are private + AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { + @Override + public Void run() throws Exception { + //use reflection to write source and constants table to installed classes + final Field sourceField = clazz.getDeclaredField(SOURCE.symbolName()); + final Field constantsField = clazz.getDeclaredField(CONSTANTS.symbolName()); + sourceField.setAccessible(true); + constantsField.setAccessible(true); + sourceField.set(null, source); + constantsField.set(null, constants); + return null; + } + }); + } catch (final PrivilegedActionException e) { + throw new RuntimeException(e); + } + + return clazz; } @Override @@ -152,6 +183,18 @@ public long getUniqueEvalId() { return context.getUniqueEvalId(); } + + @Override + public void storeCompiledScript(final Source source, final String mainClassName, + final Map<String, byte[]> classBytes, final Object[] constants) { + if (context.codeStore != null) { + try { + context.codeStore.putScript(source, mainClassName, classBytes, constants); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } + } } /** Is Context global debug mode enabled ? */ @@ -159,9 +202,12 @@ private static final ThreadLocal<Global> currentGlobal = new ThreadLocal<>(); - // class cache + // in-memory cache for loaded classes private ClassCache classCache; + // persistent code store + private CodeStore codeStore; + /** * Get the current global scope * @return the current global scope @@ -369,6 +415,19 @@ classCache = new ClassCache(cacheSize); } + if (env._persistent_cache) { + if (env._lazy_compilation || env._specialize_calls != null) { + getErr().println("Can not use persistent class caching with lazy compilation or call specialization."); + } else { + try { + final String cacheDir = Options.getStringProperty("nashorn.persistent.code.cache", "nashorn_code_cache"); + codeStore = new CodeStore(cacheDir); + } catch (IOException e) { + throw new RuntimeException("Error initializing code cache", e); + } + } + } + // print version info if asked. if (env._version) { getErr().println("nashorn " + Version.version()); @@ -432,6 +491,39 @@ } /** + * Interface to represent compiled code that can be re-used across many + * global scope instances + */ + public static interface MultiGlobalCompiledScript { + /** + * Obtain script function object for a specific global scope object. + * + * @param newGlobal global scope for which function object is obtained + * @return script function for script level expressions + */ + public ScriptFunction getFunction(final Global newGlobal); + } + + /** + * Compile a top level script. + * + * @param source the script source + * @return reusable compiled script across many global scopes. + */ + public MultiGlobalCompiledScript compileScript(final Source source) { + final Class<?> clazz = compile(source, this.errors, this._strict); + final MethodHandle runMethodHandle = getRunScriptHandle(clazz); + final boolean strict = isStrict(clazz); + + return new MultiGlobalCompiledScript() { + @Override + public ScriptFunction getFunction(final Global newGlobal) { + return Context.getGlobal().newScriptFunction(RUN_SCRIPT.symbolName(), runMethodHandle, newGlobal, strict); + } + }; + } + + /** * Entry point for {@code eval} * * @param initialScope The scope of this eval call @@ -444,7 +536,7 @@ */ public Object eval(final ScriptObject initialScope, final String string, final Object callThis, final Object location, final boolean strict) { final String file = (location == UNDEFINED || location == null) ? "<eval>" : location.toString(); - final Source source = new Source(file, string); + final Source source = sourceFor(file, string); final boolean directEval = location != UNDEFINED; // is this direct 'eval' call or indirectly invoked eval? final Global global = Context.getGlobal(); @@ -511,7 +603,7 @@ public Source run() { try { final URL resURL = Context.class.getResource(resource); - return (resURL != null)? new Source(srcStr, resURL) : null; + return (resURL != null)? sourceFor(srcStr, resURL) : null; } catch (final IOException exp) { return null; } @@ -543,7 +635,7 @@ final String srcStr = (String)src; if (srcStr.startsWith(LOAD_CLASSPATH)) { URL url = getResourceURL(srcStr.substring(LOAD_CLASSPATH.length())); - source = (url != null)? new Source(url.toString(), url) : null; + source = (url != null)? sourceFor(url.toString(), url) : null; } else { final File file = new File(srcStr); if (srcStr.indexOf(':') != -1) { @@ -556,31 +648,31 @@ } catch (final MalformedURLException e) { url = file.toURI().toURL(); } - source = new Source(url.toString(), url); + source = sourceFor(url.toString(), url); } } else if (file.isFile()) { - source = new Source(srcStr, file); + source = sourceFor(srcStr, file); } } } else if (src instanceof File && ((File)src).isFile()) { final File file = (File)src; - source = new Source(file.getName(), file); + source = sourceFor(file.getName(), file); } else if (src instanceof URL) { final URL url = (URL)src; - source = new Source(url.toString(), url); + source = sourceFor(url.toString(), url); } else if (src instanceof ScriptObject) { final ScriptObject sobj = (ScriptObject)src; if (sobj.has("script") && sobj.has("name")) { final String script = JSType.toString(sobj.get("script")); final String name = JSType.toString(sobj.get("name")); - source = new Source(name, script); + source = sourceFor(name, script); } } else if (src instanceof Map) { final Map<?,?> map = (Map<?,?>)src; if (map.containsKey("script") && map.containsKey("name")) { final String script = JSType.toString(map.get("script")); final String name = JSType.toString(map.get("name")); - source = new Source(name, script); + source = sourceFor(name, script); } } @@ -891,14 +983,8 @@ return ScriptRuntime.apply(script, thiz); } - private static ScriptFunction getRunScriptFunction(final Class<?> script, final ScriptObject scope) { - if (script == null) { - return null; - } - - // Get run method - the entry point to the script - final MethodHandle runMethodHandle = - MH.findStatic( + private static MethodHandle getRunScriptHandle(final Class<?> script) { + return MH.findStatic( MethodHandles.lookup(), script, RUN_SCRIPT.symbolName(), @@ -906,14 +992,24 @@ Object.class, ScriptFunction.class, Object.class)); + } - boolean strict; - + private static boolean isStrict(final Class<?> script) { try { - strict = script.getField(STRICT_MODE.symbolName()).getBoolean(null); + return script.getField(STRICT_MODE.symbolName()).getBoolean(null); } catch (final NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { - strict = false; + return false; } + } + + private static ScriptFunction getRunScriptFunction(final Class<?> script, final ScriptObject scope) { + if (script == null) { + return null; + } + + // Get run method - the entry point to the script + final MethodHandle runMethodHandle = getRunScriptHandle(script); + boolean strict = isStrict(script); // Package as a JavaScript function and pass function back to shell. return Context.getGlobal().newScriptFunction(RUN_SCRIPT.symbolName(), runMethodHandle, scope, strict); @@ -933,17 +1029,32 @@ return script; } - final FunctionNode functionNode = new Parser(env, source, errMan, strict).parse(); - if (errors.hasErrors()) { - return null; + CompiledScript compiledScript = null; + FunctionNode functionNode = null; + + if (!env._parse_only && codeStore != null) { + try { + compiledScript = codeStore.getScript(source); + } catch (IOException | ClassNotFoundException e) { + Compiler.LOG.warning("Error loading ", source, " from cache: ", e); + // Fall back to normal compilation + } } - if (env._print_ast) { - getErr().println(new ASTWriter(functionNode)); - } + if (compiledScript == null) { + functionNode = new Parser(env, source, errMan, strict).parse(); + + if (errors.hasErrors()) { + return null; + } - if (env._print_parse) { - getErr().println(new PrintVisitor(functionNode)); + if (env._print_ast) { + getErr().println(new ASTWriter(functionNode)); + } + + if (env._print_parse) { + getErr().println(new PrintVisitor(functionNode)); + } } if (env._parse_only) { @@ -955,12 +1066,15 @@ final CodeSource cs = new CodeSource(url, (CodeSigner[])null); final CodeInstaller<ScriptEnvironment> installer = new ContextCodeInstaller(this, loader, cs); - final Compiler compiler = new Compiler(installer, strict); + if (functionNode != null) { + final Compiler compiler = new Compiler(installer, strict); + final FunctionNode newFunctionNode = compiler.compile(functionNode); + script = compiler.install(newFunctionNode); + } else { + script = install(compiledScript, installer); + } - final FunctionNode newFunctionNode = compiler.compile(functionNode); - script = compiler.install(newFunctionNode); cacheClass(source, script); - return script; } @@ -982,6 +1096,42 @@ return uniqueScriptId.getAndIncrement(); } + + /** + * Install a previously compiled class from the code cache. + * + * @param compiledScript cached script containing class bytes and constants + * @return main script class + */ + private Class<?> install(final CompiledScript compiledScript, final CodeInstaller<ScriptEnvironment> installer) { + + final Map<String, Class<?>> installedClasses = new HashMap<>(); + final Source source = compiledScript.getSource(); + final Object[] constants = compiledScript.getConstants(); + final String rootClassName = compiledScript.getMainClassName(); + final byte[] rootByteCode = compiledScript.getClassBytes().get(rootClassName); + final Class<?> rootClass = installer.install(rootClassName, rootByteCode, source, constants); + + installedClasses.put(rootClassName, rootClass); + + for (final Map.Entry<String, byte[]> entry : compiledScript.getClassBytes().entrySet()) { + final String className = entry.getKey(); + if (className.equals(rootClassName)) { + continue; + } + final byte[] code = entry.getValue(); + + installedClasses.put(className, installer.install(className, code, source, constants)); + } + for (Object constant : constants) { + if (constant instanceof RecompilableScriptFunctionData) { + ((RecompilableScriptFunctionData) constant).setCodeAndSource(installedClasses, source); + } + } + + return rootClass; + } + /** * Cache for compiled script classes. */
--- a/src/jdk/nashorn/internal/runtime/DebuggerSupport.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/DebuggerSupport.java Tue Aug 19 23:57:20 2014 +0100 @@ -25,12 +25,20 @@ package jdk.nashorn.internal.runtime; +import static jdk.nashorn.internal.codegen.CompilerConstants.SOURCE; + +import java.lang.invoke.MethodHandle; +import java.lang.reflect.Field; +import java.net.URL; import java.util.HashSet; import java.util.Set; +import jdk.nashorn.internal.scripts.JS; /** * This class provides support for external debuggers. Its primary purpose is * is to simplify the debugger tasks and provide better performance. + * Even though the methods are not public, there are still part of the + * external debugger interface. */ final class DebuggerSupport { /** @@ -46,6 +54,11 @@ */ @SuppressWarnings("unused") DebuggerValueDesc forceLoad = new DebuggerValueDesc(null, false, null, null); + + // Hook to force the loading of the SourceInfo class + @SuppressWarnings("unused") + final + SourceInfo srcInfo = new SourceInfo(null, 0, null, null); } /** This class is used to send a bulk description of a value. */ @@ -70,6 +83,54 @@ } } + static class SourceInfo { + final String name; + final URL url; + final int hash; + final char[] content; + + SourceInfo(final String name, final int hash, final URL url, final char[] content) { + this.name = name; + this.hash = hash; + this.url = url; + this.content = content; + } + } + + /** + * Hook that is called just before invoking method handle + * from ScriptFunctionData via invoke, constructor method calls. + * + * @param mh script class method about to be invoked. + */ + static void notifyInvoke(final MethodHandle mh) { + // Do nothing here. This is placeholder method on which a + // debugger can place a breakpoint so that it can access the + // (script class) method handle that is about to be invoked. + // See ScriptFunctionData.invoke and ScriptFunctionData.construct. + } + + /** + * Return the script source info for the given script class. + * + * @param clazz compiled script class + * @return SourceInfo + */ + static SourceInfo getSourceInfo(final Class<?> clazz) { + if (JS.class.isAssignableFrom(clazz)) { + try { + final Field sourceField = clazz.getDeclaredField(SOURCE.symbolName()); + sourceField.setAccessible(true); + final Source src = (Source) sourceField.get(null); + return src.getSourceInfo(); + } catch (final IllegalAccessException | NoSuchFieldException ignored) { + return null; + } + } + + return null; + } + /** * Return the current context global. * @return context global. @@ -84,7 +145,7 @@ * @param self Receiver to use. * @param string String to evaluate. * @param returnException true if exceptions are to be returned. - * @return Result of eval as string, or, an exception or null depending on returnException. + * @return Result of eval, or, an exception or null depending on returnException. */ static Object eval(final ScriptObject scope, final Object self, final String string, final boolean returnException) { final ScriptObject global = Context.getGlobal(); @@ -235,7 +296,7 @@ * @param value Arbitrary value to be displayed by the debugger. * @return A string representation of the value or an array of DebuggerValueDesc. */ - private static String valueAsString(final Object value) { + static String valueAsString(final Object value) { final JSType type = JSType.of(value); switch (type) {
--- a/src/jdk/nashorn/internal/runtime/GlobalFunctions.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/GlobalFunctions.java Tue Aug 19 23:57:20 2014 +0100 @@ -459,5 +459,4 @@ private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) { return MH.findStatic(MethodHandles.lookup(), GlobalFunctions.class, name, MH.type(rtype, types)); } - }
--- a/src/jdk/nashorn/internal/runtime/JSONFunctions.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/JSONFunctions.java Tue Aug 19 23:57:20 2014 +0100 @@ -39,6 +39,8 @@ import jdk.nashorn.internal.runtime.arrays.ArrayIndex; import jdk.nashorn.internal.runtime.linker.Bootstrap; +import static jdk.nashorn.internal.runtime.Source.sourceFor; + /** * Utilities used by "JSON" object implementation. */ @@ -77,9 +79,7 @@ */ public static Object parse(final Object text, final Object reviver) { final String str = JSType.toString(text); - final JSONParser parser = new JSONParser( - new Source("<json>", str), - new Context.ThrowErrorManager()); + final JSONParser parser = new JSONParser(sourceFor("<json>", str), new Context.ThrowErrorManager()); Node node;
--- a/src/jdk/nashorn/internal/runtime/JSType.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/JSType.java Tue Aug 19 23:57:20 2014 +0100 @@ -438,7 +438,9 @@ // encode integer part from least significant digit, then reverse do { - sb.append(chars.charAt((int) (intPart % radix))); + final double remainder = intPart % radix; + sb.append(chars.charAt((int) remainder)); + intPart -= remainder; intPart /= radix; } while (intPart >= 1.0);
--- a/src/jdk/nashorn/internal/runtime/Property.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/Property.java Tue Aug 19 23:57:20 2014 +0100 @@ -29,6 +29,7 @@ import static jdk.nashorn.internal.runtime.PropertyDescriptor.ENUMERABLE; import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE; +import java.io.Serializable; import java.lang.invoke.MethodHandle; import java.util.Objects; import jdk.nashorn.internal.codegen.ObjectClassGenerator; @@ -43,7 +44,7 @@ * @see AccessorProperty * @see UserAccessorProperty */ -public abstract class Property { +public abstract class Property implements Serializable { /* * ECMA 8.6.1 Property Attributes * @@ -100,6 +101,8 @@ /** Property field number or spill slot. */ private final int slot; + private static final long serialVersionUID = 2099814273074501176L; + /** * Constructor * @@ -358,6 +361,13 @@ public abstract MethodHandle getGetter(final Class<?> type); /** + * Hook to initialize method handles after deserialization. + * + * @param structure the structure class + */ + abstract void initMethodHandles(final Class<?> structure); + + /** * Get the key for this property. This key is an ordinary string. The "name". * @return key for property */
--- a/src/jdk/nashorn/internal/runtime/PropertyMap.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/PropertyMap.java Tue Aug 19 23:57:20 2014 +0100 @@ -29,6 +29,10 @@ import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex; import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; import java.lang.invoke.SwitchPoint; import java.lang.ref.SoftReference; import java.util.Arrays; @@ -37,6 +41,7 @@ import java.util.Iterator; import java.util.NoSuchElementException; import java.util.WeakHashMap; +import jdk.nashorn.internal.scripts.JO; /** * Map of object properties. The PropertyMap is the "template" for JavaScript object @@ -47,7 +52,7 @@ * All property maps are immutable. If a property is added, modified or removed, the mutator * will return a new map. */ -public final class PropertyMap implements Iterable<Object> { +public final class PropertyMap implements Iterable<Object>, Serializable { /** Used for non extensible PropertyMaps, negative logic as the normal case is extensible. See {@link ScriptObject#preventExtensions()} */ public static final int NOT_EXTENSIBLE = 0b0000_0001; /** Does this map contain valid array keys? */ @@ -57,7 +62,7 @@ private int flags; /** Map of properties. */ - private final PropertyHashMap properties; + private transient PropertyHashMap properties; /** Number of fields in use. */ private int fieldCount; @@ -68,17 +73,22 @@ /** Length of spill in use. */ private int spillLength; + /** Structure class name */ + private String className; + /** {@link SwitchPoint}s for gets on inherited properties. */ - private HashMap<String, SwitchPoint> protoGetSwitches; + private transient HashMap<String, SwitchPoint> protoGetSwitches; /** History of maps, used to limit map duplication. */ - private WeakHashMap<Property, SoftReference<PropertyMap>> history; + private transient WeakHashMap<Property, SoftReference<PropertyMap>> history; /** History of prototypes, used to limit map duplication. */ - private WeakHashMap<PropertyMap, SoftReference<PropertyMap>> protoHistory; + private transient WeakHashMap<PropertyMap, SoftReference<PropertyMap>> protoHistory; /** property listeners */ - private PropertyListeners listeners; + private transient PropertyListeners listeners; + + private static final long serialVersionUID = -7041836752008732533L; /** * Constructor. @@ -89,8 +99,10 @@ * @param spillLength Number of spill slots used. * @param containsArrayKeys True if properties contain numeric keys */ - private PropertyMap(final PropertyHashMap properties, final int fieldCount, final int fieldMaximum, final int spillLength, final boolean containsArrayKeys) { + private PropertyMap(final PropertyHashMap properties, final String className, final int fieldCount, + final int fieldMaximum, final int spillLength, final boolean containsArrayKeys) { this.properties = properties; + this.className = className; this.fieldCount = fieldCount; this.fieldMaximum = fieldMaximum; this.spillLength = spillLength; @@ -145,7 +157,25 @@ if (Context.DEBUG) { duplicatedCount++; } - return new PropertyMap(this.properties, 0, 0, 0, containsArrayKeys()); + return new PropertyMap(this.properties, this.className, 0, 0, 0, containsArrayKeys()); + } + + private void writeObject(final ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + out.writeObject(properties.getProperties()); + } + + private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + + final Property[] props = (Property[]) in.readObject(); + this.properties = EMPTY_HASHMAP.immutableAdd(props); + + assert className != null; + final Class<?> structure = Context.forStructureClass(className); + for (Property prop : props) { + prop.initMethodHandles(structure); + } } /** @@ -160,9 +190,9 @@ * @param spillLength Number of used spill slots. * @return New {@link PropertyMap}. */ - public static PropertyMap newMap(final Collection<Property> properties, final int fieldCount, final int fieldMaximum, final int spillLength) { + public static PropertyMap newMap(final Collection<Property> properties, final String className, final int fieldCount, final int fieldMaximum, final int spillLength) { PropertyHashMap newProperties = EMPTY_HASHMAP.immutableAdd(properties); - return new PropertyMap(newProperties, fieldCount, fieldMaximum, spillLength, false); + return new PropertyMap(newProperties, className, fieldCount, fieldMaximum, spillLength, false); } /** @@ -175,7 +205,7 @@ * @return New {@link PropertyMap}. */ public static PropertyMap newMap(final Collection<Property> properties) { - return (properties == null || properties.isEmpty())? newMap() : newMap(properties, 0, 0, 0); + return (properties == null || properties.isEmpty())? newMap() : newMap(properties, JO.class.getName(), 0, 0, 0); } /** @@ -184,7 +214,7 @@ * @return New empty {@link PropertyMap}. */ public static PropertyMap newMap() { - return new PropertyMap(EMPTY_HASHMAP, 0, 0, 0, false); + return new PropertyMap(EMPTY_HASHMAP, JO.class.getName(), 0, 0, 0, false); } /**
--- a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Tue Aug 19 23:57:20 2014 +0100 @@ -27,14 +27,15 @@ import static jdk.nashorn.internal.lookup.Lookup.MH; +import java.io.Serializable; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; +import java.util.Map; import jdk.internal.dynalink.support.NameCodec; - import jdk.nashorn.internal.codegen.Compiler; import jdk.nashorn.internal.codegen.CompilerConstants; import jdk.nashorn.internal.codegen.FunctionSignature; @@ -43,6 +44,7 @@ import jdk.nashorn.internal.ir.FunctionNode.CompilationState; import jdk.nashorn.internal.parser.Token; import jdk.nashorn.internal.parser.TokenType; +import jdk.nashorn.internal.scripts.JS; /** * This is a subclass that represents a script function that may be regenerated, @@ -50,13 +52,19 @@ * The common denominator is that it can get new invokers during its lifespan, * unlike {@code FinalScriptFunctionData} */ -public final class RecompilableScriptFunctionData extends ScriptFunctionData { +public final class RecompilableScriptFunctionData extends ScriptFunctionData implements Serializable { /** FunctionNode with the code for this ScriptFunction */ - private FunctionNode functionNode; + private transient FunctionNode functionNode; /** Source from which FunctionNode was parsed. */ - private final Source source; + private transient Source source; + + /** The line number where this function begins. */ + private final int lineNumber; + + /** Allows us to retrieve the method handle for this function once the code is compiled */ + private MethodLocator methodLocator; /** Token of this function within the source. */ private final long token; @@ -65,13 +73,13 @@ private final PropertyMap allocatorMap; /** Code installer used for all further recompilation/specialization of this ScriptFunction */ - private CodeInstaller<ScriptEnvironment> installer; + private transient CodeInstaller<ScriptEnvironment> installer; /** Name of class where allocator function resides */ private final String allocatorClassName; /** lazily generated allocator */ - private MethodHandle allocator; + private transient MethodHandle allocator; private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); @@ -79,7 +87,7 @@ * Used for specialization based on runtime arguments. Whenever we specialize on * callsite parameter types at runtime, we need to use a parameter type guard to * ensure that the specialized version of the script function continues to be - * applicable for a particular callsite * + * applicable for a particular callsite. */ private static final MethodHandle PARAM_TYPE_GUARD = findOwnMH("paramTypeGuard", boolean.class, Type[].class, Object[].class); @@ -88,10 +96,12 @@ * (or java.lang.Number instance) to specialize the parameter to an integer, if the * parameter in question can be represented as one. The double typically only exists * because the compiler doesn't know any better than "a number type" and conservatively - * picks doubles when it can't prove that an integer addition wouldn't overflow + * picks doubles when it can't prove that an integer addition wouldn't overflow. */ private static final MethodHandle ENSURE_INT = findOwnMH("ensureInt", int.class, Object.class); + private static final long serialVersionUID = 4914839316174633726L; + /** * Constructor - public as scripts use it * @@ -104,13 +114,16 @@ super(functionName(functionNode), functionNode.getParameters().size(), getFlags(functionNode)); - this.functionNode = functionNode; this.source = functionNode.getSource(); + this.lineNumber = functionNode.getLineNumber(); this.token = tokenFor(functionNode); this.installer = installer; this.allocatorClassName = allocatorClassName; this.allocatorMap = allocatorMap; + if (!functionNode.isLazy()) { + methodLocator = new MethodLocator(functionNode); + } } @Override @@ -122,16 +135,19 @@ return "function " + (name == null ? "" : name) + "() { [native code] }"; } + public void setCodeAndSource(final Map<String, Class<?>> code, final Source source) { + this.source = source; + if (methodLocator != null) { + methodLocator.setClass(code.get(methodLocator.getClassName())); + } + } + @Override public String toString() { final StringBuilder sb = new StringBuilder(); if (source != null) { - sb.append(source.getName()); - if (functionNode != null) { - sb.append(':').append(functionNode.getLineNumber()); - } - sb.append(' '); + sb.append(source.getName()).append(':').append(lineNumber).append(' '); } return sb.toString() + super.toString(); @@ -204,8 +220,13 @@ functionNode = compiler.compile(functionNode); assert !functionNode.isLazy(); compiler.install(functionNode); + methodLocator = new MethodLocator(functionNode); flags = getFlags(functionNode); } + + if (functionNode != null) { + methodLocator.setClass(functionNode.getCompileUnit().getCode()); + } } @Override @@ -221,12 +242,13 @@ * eager compilation or from running a lazy compile on the lines above */ - assert functionNode.hasState(CompilationState.EMITTED) : functionNode.getName() + " " + functionNode.getState() + " " + Debug.id(functionNode); + assert functionNode == null || functionNode.hasState(CompilationState.EMITTED) : + functionNode.getName() + " " + functionNode.getState() + " " + Debug.id(functionNode); // code exists - look it up and add it into the automatically sorted invoker list addCode(functionNode); - if (! functionNode.canSpecialize()) { + if (functionNode != null && !functionNode.canSpecialize()) { // allow GC to claim IR stuff that is not needed anymore functionNode = null; installer = null; @@ -238,13 +260,9 @@ } private MethodHandle addCode(final FunctionNode fn, final MethodType runtimeType, final MethodHandle guard, final MethodHandle fallback) { - final MethodType targetType = new FunctionSignature(fn).getMethodType(); - MethodHandle target = - MH.findStatic( - LOOKUP, - fn.getCompileUnit().getCode(), - fn.getName(), - targetType); + assert methodLocator != null; + MethodHandle target = methodLocator.getMethodHandle(); + final MethodType targetType = methodLocator.getMethodType(); /* * For any integer argument. a double that is representable as an integer is OK. @@ -424,7 +442,6 @@ Compiler.LOG.info("Callsite specialized ", name, " runtimeType=", runtimeType, " parameters=", snapshot.getParameters(), " args=", Arrays.asList(args)); - assert snapshot != null; assert snapshot != functionNode; final Compiler compiler = new Compiler(installer); @@ -450,5 +467,45 @@ return MH.findStatic(MethodHandles.lookup(), RecompilableScriptFunctionData.class, name, MH.type(rtype, types)); } + /** + * Helper class that allows us to retrieve the method handle for this function once it has been generated. + */ + private static class MethodLocator implements Serializable { + private transient Class<?> clazz; + private final String className; + private final String methodName; + private final MethodType methodType; + + private static final long serialVersionUID = -5420835725902966692L; + + MethodLocator(final FunctionNode functionNode) { + this.className = functionNode.getCompileUnit().getUnitClassName(); + this.methodName = functionNode.getName(); + this.methodType = new FunctionSignature(functionNode).getMethodType(); + + assert className != null; + assert methodName != null; + } + + void setClass(final Class<?> clazz) { + if (!JS.class.isAssignableFrom(clazz)) { + throw new IllegalArgumentException(); + } + this.clazz = clazz; + } + + String getClassName() { + return className; + } + + MethodType getMethodType() { + return methodType; + } + + MethodHandle getMethodHandle() { + return MH.findStatic(LOOKUP, clazz, methodName, methodType); + } + } + }
--- a/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java Tue Aug 19 23:57:20 2014 +0100 @@ -62,6 +62,9 @@ /** Only compile script, do not run it or generate other ScriptObjects */ public final boolean _compile_only; + /** Accept "const" keyword and treat it as variable. Interim feature */ + public final boolean _const_as_var; + /** Accumulated callsite flags that will be used when bootstrapping script callsites */ public final int _callsite_flags; @@ -134,6 +137,9 @@ /** Only parse the source code, do not compile */ public final boolean _parse_only; + /** Enable disk cache for compiled scripts */ + public final boolean _persistent_cache; + /** Print the AST before lowering */ public final boolean _print_ast; @@ -197,6 +203,7 @@ _class_cache_size = options.getInteger("class.cache.size"); _compile_only = options.getBoolean("compile.only"); + _const_as_var = options.getBoolean("const.as.var"); _debug_lines = options.getBoolean("debug.lines"); _dest_dir = options.getString("d"); _dump_on_error = options.getBoolean("doe"); @@ -218,6 +225,7 @@ _no_syntax_extensions = options.getBoolean("no.syntax.extensions"); _no_typed_arrays = options.getBoolean("no.typed.arrays"); _parse_only = options.getBoolean("parse.only"); + _persistent_cache = options.getBoolean("persistent.code.cache"); _print_ast = options.getBoolean("print.ast"); _print_lower_ast = options.getBoolean("print.lower.ast"); _print_code = options.getBoolean("print.code");
--- a/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Tue Aug 19 23:57:20 2014 +0100 @@ -29,10 +29,10 @@ import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; +import java.io.Serializable; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; -import jdk.nashorn.internal.objects.Global; import jdk.nashorn.internal.runtime.linker.JavaAdapterFactory; /** @@ -40,7 +40,7 @@ * Instances of this class are created during codegen and stored in script classes' * constants array to reduce function instantiation overhead during runtime. */ -public abstract class ScriptFunctionData { +public abstract class ScriptFunctionData implements Serializable { /** Name of the function or "" for anonynous functions */ protected final String name; @@ -74,6 +74,8 @@ /** Flag for strict constructors */ public static final int IS_STRICT_CONSTRUCTOR = IS_STRICT | IS_CONSTRUCTOR; + private static final long serialVersionUID = 4252901245508769114L; + /** * Constructor * @@ -517,6 +519,8 @@ final Object selfObj = convertThisObject(self); final Object[] args = arguments == null ? ScriptRuntime.EMPTY_ARRAY : arguments; + DebuggerSupport.notifyInvoke(mh); + if (isVarArg(mh)) { if (needsCallee(mh)) { return mh.invokeExact(fn, selfObj, args); @@ -570,6 +574,8 @@ final MethodHandle mh = getGenericConstructor(); final Object[] args = arguments == null ? ScriptRuntime.EMPTY_ARRAY : arguments; + DebuggerSupport.notifyInvoke(mh); + if (isVarArg(mh)) { if (needsCallee(mh)) { return mh.invokeExact(fn, args);
--- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java Tue Aug 19 23:57:20 2014 +0100 @@ -91,7 +91,7 @@ */ public abstract class ScriptObject implements PropertyAccess { - /** __proto__ special property name */ + /** __proto__ special property name inside object literals. ES6 draft. */ public static final String PROTO_PROPERTY_NAME = "__proto__"; /** Search fall back routine name for "no such method" */ @@ -130,9 +130,9 @@ /** Indexed array data. */ private ArrayData arrayData; - static final MethodHandle GETPROTO = findOwnMH("getProto", ScriptObject.class); - static final MethodHandle SETPROTOCHECK = findOwnMH("setProtoCheck", void.class, Object.class); - static final MethodHandle MEGAMORPHIC_GET = findOwnMH("megamorphicGet", Object.class, String.class, boolean.class, boolean.class); + /** Method handle to retrive prototype of this object */ + public static final MethodHandle GETPROTO = findOwnMH("getProto", ScriptObject.class); + static final MethodHandle MEGAMORPHIC_GET = findOwnMH("megamorphicGet", Object.class, String.class, boolean.class); static final MethodHandle GLOBALFILTER = findOwnMH("globalFilter", Object.class, Object.class); static final MethodHandle SETFIELD = findOwnMH("setField", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, MethodHandle.class, Object.class, Object.class); @@ -158,7 +158,7 @@ public static final Call SET_PROTO = virtualCallNoLookup(ScriptObject.class, "setInitialProto", void.class, ScriptObject.class); /** Method handle for setting the proto of a ScriptObject after checking argument */ - public static final Call SET_PROTO_CHECK = virtualCallNoLookup(ScriptObject.class, "setProtoCheck", void.class, Object.class); + public static final Call SET_PROTO_FROM_LITERAL = virtualCallNoLookup(ScriptObject.class, "setProtoFromLiteral", void.class, Object.class); /** Method handle for setting the user accessors of a ScriptObject */ public static final Call SET_USER_ACCESSORS = virtualCall(MethodHandles.lookup(), ScriptObject.class, "setUserAccessors", void.class, String.class, ScriptFunction.class, ScriptFunction.class); @@ -1125,14 +1125,21 @@ /** * Set the __proto__ of an object with checks. + * This is the built-in operation [[SetPrototypeOf]] + * See ES6 draft spec: 9.1.2 [[SetPrototypeOf]] (V) + * * @param newProto Prototype to set. */ - public final void setProtoCheck(final Object newProto) { - if (!isExtensible()) { - throw typeError("__proto__.set.non.extensible", ScriptRuntime.safeToString(this)); - } - + public final void setPrototypeOf(final Object newProto) { if (newProto == null || newProto instanceof ScriptObject) { + if (!isExtensible()) { + // okay to set same proto again - even if non-extensible + if (newProto == getProto()) { + return; + } + throw typeError("__proto__.set.non.extensible", ScriptRuntime.safeToString(this)); + } + // check for circularity ScriptObject p = (ScriptObject)newProto; while (p != null) { @@ -1143,14 +1150,27 @@ } setProto((ScriptObject)newProto); } else { - final Global global = Context.getGlobal(); - final Object newProtoObject = JSType.toScriptObject(global, newProto); - - if (newProtoObject instanceof ScriptObject) { - setProto((ScriptObject)newProtoObject); - } else { - throw typeError(global, "cant.set.proto.to.non.object", ScriptRuntime.safeToString(this), ScriptRuntime.safeToString(newProto)); - } + throw typeError("cant.set.proto.to.non.object", ScriptRuntime.safeToString(this), ScriptRuntime.safeToString(newProto)); + } + } + + /** + * Set the __proto__ of an object from an object literal. + * See ES6 draft spec: B.3.1 __proto__ Property Names in + * Object Initializers. Step 6 handling of "__proto__". + * + * @param newProto Prototype to set. + */ + public final void setProtoFromLiteral(final Object newProto) { + if (newProto == null || newProto instanceof ScriptObject) { + setPrototypeOf(newProto); + } else { + // Some non-object, non-null. Then, we need to set + // Object.prototype as the new __proto__ + // + // var obj = { __proto__ : 34 }; + // print(obj.__proto__ === Object.prototype); // => true + setPrototypeOf(Global.objectPrototype()); } } @@ -1725,17 +1745,13 @@ protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) { final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); if (request.isCallSiteUnstable() || hasWithScope()) { - return findMegaMorphicGetMethod(desc, name, "getMethod".equals(operator), isScope() && NashornCallSiteDescriptor.isScope(desc)); + return findMegaMorphicGetMethod(desc, name, "getMethod".equals(operator)); } final FindProperty find = findProperty(name, true); MethodHandle methodHandle; if (find == null) { - if (PROTO_PROPERTY_NAME.equals(name)) { - return new GuardedInvocation(GETPROTO, NashornGuards.getScriptObjectGuard()); - } - if ("getProp".equals(operator)) { return noSuchProperty(desc, request); } else if ("getMethod".equals(operator)) { @@ -1772,22 +1788,19 @@ } private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name, - final boolean isMethod, final boolean isScope) { - final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod, isScope); + final boolean isMethod) { + final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod); final MethodHandle guard = getScriptObjectGuard(desc.getMethodType()); return new GuardedInvocation(invoker, guard); } @SuppressWarnings("unused") - private Object megamorphicGet(final String key, final boolean isMethod, final boolean isScope) { + private Object megamorphicGet(final String key, final boolean isMethod) { final FindProperty find = findProperty(key, true); if (find != null) { return find.getObjectValue(); } - if (isScope) { - throw referenceError("not.defined", key); - } return isMethod ? getNoSuchMethod(key) : invokeNoSuchProperty(key); } @@ -1890,9 +1903,7 @@ return createEmptySetMethod(desc, "property.not.writable", true); } } else { - if (PROTO_PROPERTY_NAME.equals(name)) { - return new GuardedInvocation(SETPROTOCHECK, NashornGuards.getScriptObjectGuard()); - } else if (! isExtensible()) { + if (! isExtensible()) { return createEmptySetMethod(desc, "object.non.extensible", false); } }
--- a/src/jdk/nashorn/internal/runtime/Source.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/Source.java Tue Aug 19 23:57:20 2014 +0100 @@ -27,27 +27,38 @@ import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOError; import java.io.IOException; import java.io.InputStream; import java.io.Reader; +import java.lang.ref.WeakReference; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; +import java.net.URLConnection; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.Objects; +import java.util.WeakHashMap; +import jdk.nashorn.api.scripting.URLReader; import jdk.nashorn.internal.parser.Token; /** * Source objects track the origin of JavaScript entities. - * */ public final class Source { + + private static final DebugLogger DEBUG = new DebugLogger("source"); + private static final int BUF_SIZE = 8 * 1024; + private static final Cache CACHE = new Cache(); + /** * Descriptive name of the source as supplied by the user. Used for error * reporting to the user. For example, SyntaxError will use this to print message. @@ -62,49 +73,311 @@ */ private final String base; - /** Cached source content. */ - private final char[] content; - - /** Length of source content. */ - private final int length; + /** Source content */ + private final Data data; /** Cached hash code */ private int hash; - /** Source URL if available */ - private final URL url; + /** Message digest */ + private byte[] digest; + + // Do *not* make this public, ever! Trusts the URL and content. + private Source(final String name, final String base, final Data data) { + this.name = name; + this.base = base; + this.data = data; + } + + private static synchronized Source sourceFor(final String name, final String base, final URLData data) throws IOException { + try { + final Source newSource = new Source(name, base, data); + final Source existingSource = CACHE.get(newSource); + if (existingSource != null) { + // Force any access errors + data.checkPermissionAndClose(); + return existingSource; + } else { + // All sources in cache must be fully loaded + data.load(); + CACHE.put(newSource, newSource); + return newSource; + } + } catch (RuntimeException e) { + final Throwable cause = e.getCause(); + if (cause instanceof IOException) { + throw (IOException) cause; + } + throw e; + } + } + + private static class Cache extends WeakHashMap<Source, WeakReference<Source>> { + public Source get(final Source key) { + final WeakReference<Source> ref = super.get(key); + return ref == null ? null : ref.get(); + } + + public void put(final Source key, final Source value) { + assert !(value.data instanceof RawData); + put(key, new WeakReference<>(value)); + } + } + + /* package-private */ + DebuggerSupport.SourceInfo getSourceInfo() { + return new DebuggerSupport.SourceInfo(getName(), data.hashCode(), data.url(), data.array()); + } + + // Wrapper to manage lazy loading + private static interface Data { + + URL url(); + + int length(); + + long lastModified(); + + char[] array(); + } + + private static class RawData implements Data { + private final char[] array; + private int hash; - private static final int BUFSIZE = 8 * 1024; + private RawData(final char[] array) { + this.array = Objects.requireNonNull(array); + } + + private RawData(final String source) { + this.array = Objects.requireNonNull(source).toCharArray(); + } + + private RawData(final Reader reader) throws IOException { + this(readFully(reader)); + } + + @Override + public int hashCode() { + int h = hash; + if (h == 0) { + h = hash = Arrays.hashCode(array); + } + return h; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof RawData) { + return Arrays.equals(array, ((RawData)obj).array); + } + return false; + } + + @Override + public String toString() { + return new String(array()); + } + + @Override + public URL url() { + return null; + } + + @Override + public int length() { + return array.length; + } + + @Override + public long lastModified() { + return 0; + } + + @Override + public char[] array() { + return array; + } + + + } + + private static class URLData implements Data { + private final URL url; + protected final Charset cs; + private int hash; + protected char[] array; + protected int length; + protected long lastModified; + + private URLData(final URL url, final Charset cs) { + this.url = Objects.requireNonNull(url); + this.cs = cs; + } - // Do *not* make this public ever! Trusts the URL and content. So has to be called - // from other public constructors. Note that this can not be some init method as - // we initialize final fields from here. - private Source(final String name, final String base, final char[] content, final URL url) { - this.name = name; - this.base = base; - this.content = content; - this.length = content.length; - this.url = url; + @Override + public int hashCode() { + int h = hash; + if (h == 0) { + h = hash = url.hashCode(); + } + return h; + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (!(other instanceof URLData)) { + return false; + } + + URLData otherData = (URLData) other; + + if (url.equals(otherData.url)) { + // Make sure both have meta data loaded + try { + if (isDeferred()) { + // Data in cache is always loaded, and we only compare to cached data. + assert !otherData.isDeferred(); + loadMeta(); + } else if (otherData.isDeferred()) { + otherData.loadMeta(); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + + // Compare meta data + return this.length == otherData.length && this.lastModified == otherData.lastModified; + } + return false; + } + + @Override + public String toString() { + return new String(array()); + } + + @Override + public URL url() { + return url; + } + + @Override + public int length() { + return length; + } + + @Override + public long lastModified() { + return lastModified; + } + + @Override + public char[] array() { + assert !isDeferred(); + return array; + } + + boolean isDeferred() { + return array == null; + } + + protected void checkPermissionAndClose() throws IOException { + try (InputStream in = url.openStream()) {} + debug("permission checked for ", url); + } + + protected void load() throws IOException { + if (array == null) { + final URLConnection c = url.openConnection(); + try (InputStream in = c.getInputStream()) { + array = cs == null ? readFully(in) : readFully(in, cs); + length = array.length; + lastModified = c.getLastModified(); + debug("loaded content for ", url); + } + } + } + + protected void loadMeta() throws IOException { + if (length == 0 && lastModified == 0) { + final URLConnection c = url.openConnection(); + length = c.getContentLength(); + lastModified = c.getLastModified(); + debug("loaded metadata for ", url); + } + } + } + + private static class FileData extends URLData { + private final File file; + + private FileData(final File file, final Charset cs) { + super(getURLFromFile(file), cs); + this.file = file; + + } + + @Override + protected void checkPermissionAndClose() throws IOException { + if (!file.canRead()) { + throw new FileNotFoundException(file + " (Permission Denied)"); + } + debug("permission checked for ", file); + } + + @Override + protected void loadMeta() { + if (length == 0 && lastModified == 0) { + length = (int) file.length(); + lastModified = file.lastModified(); + debug("loaded metadata for ", file); + } + } + + @Override + protected void load() throws IOException { + if (array == null) { + array = cs == null ? readFully(file) : readFully(file, cs); + length = array.length; + lastModified = file.lastModified(); + debug("loaded content for ", file); + } + } + } + + private static void debug(final Object... msg) { + DEBUG.info(msg); + } + + private char[] data() { + return data.array(); } /** - * Constructor + * Returns an instance * * @param name source name * @param content contents as char array */ - public Source(final String name, final char[] content) { - this(name, baseName(name, null), content, null); + public static Source sourceFor(final String name, final char[] content) { + return new Source(name, baseName(name), new RawData(content)); } /** - * Constructor + * Returns an instance * * @param name source name * @param content contents as string */ - public Source(final String name, final String content) { - this(name, content.toCharArray()); + public static Source sourceFor(final String name, final String content) { + return new Source(name, baseName(name), new RawData(content)); } /** @@ -115,8 +388,8 @@ * * @throws IOException if source cannot be loaded */ - public Source(final String name, final URL url) throws IOException { - this(name, baseURL(url, null), readFully(url), url); + public static Source sourceFor(final String name, final URL url) throws IOException { + return sourceFor(name, url, null); } /** @@ -128,8 +401,8 @@ * * @throws IOException if source cannot be loaded */ - public Source(final String name, final URL url, final Charset cs) throws IOException { - this(name, baseURL(url, null), readFully(url, cs), url); + public static Source sourceFor(final String name, final URL url, final Charset cs) throws IOException { + return sourceFor(name, baseURL(url), new URLData(url, cs)); } /** @@ -140,8 +413,8 @@ * * @throws IOException if source cannot be loaded */ - public Source(final String name, final File file) throws IOException { - this(name, dirName(file, null), readFully(file), getURLFromFile(file)); + public static Source sourceFor(final String name, final File file) throws IOException { + return sourceFor(name, file, null); } /** @@ -153,8 +426,25 @@ * * @throws IOException if source cannot be loaded */ - public Source(final String name, final File file, final Charset cs) throws IOException { - this(name, dirName(file, null), readFully(file, cs), getURLFromFile(file)); + public static Source sourceFor(final String name, final File file, final Charset cs) throws IOException { + final File absFile = file.getAbsoluteFile(); + return sourceFor(name, dirName(absFile, null), new FileData(file, cs)); + } + + /** + * Returns an instance + * + * @param name source name + * @param reader reader from which source can be loaded + * @throws IOException if source cannot be loaded + */ + public static Source sourceFor(final String name, final Reader reader) throws IOException { + // Extract URL from URLReader to defer loading and reuse cached data if available. + if (reader instanceof URLReader) { + final URLReader urlReader = (URLReader) reader; + return sourceFor(name, urlReader.getURL(), urlReader.getCharset()); + } + return new Source(name, baseName(name), new RawData(reader)); } @Override @@ -162,21 +452,18 @@ if (this == obj) { return true; } - if (!(obj instanceof Source)) { return false; } - - final Source src = (Source)obj; - // Only compare content as a last resort measure - return length == src.length && Objects.equals(url, src.url) && Objects.equals(name, src.name) && Arrays.equals(content, src.content); + final Source other = (Source) obj; + return Objects.equals(name, other.name) && data.equals(other.data); } @Override public int hashCode() { int h = hash; if (h == 0) { - h = hash = Arrays.hashCode(content) ^ Objects.hashCode(name); + h = hash = data.hashCode() ^ Objects.hashCode(name); } return h; } @@ -186,7 +473,7 @@ * @return Source content. */ public String getString() { - return new String(content, 0, length); + return data.toString(); } /** @@ -198,6 +485,14 @@ } /** + * Get the last modified time of this script. + * @return Last modified time. + */ + public long getLastModified() { + return data.lastModified(); + } + + /** * Get the "directory" part of the file or "base" of the URL. * @return base of file or URL. */ @@ -212,7 +507,7 @@ * @return Source content portion. */ public String getString(final int start, final int len) { - return new String(content, start, len); + return new String(data(), start, len); } /** @@ -223,7 +518,7 @@ public String getString(final long token) { final int start = Token.descPosition(token); final int len = Token.descLength(token); - return new String(content, start, len); + return new String(data(), start, len); } /** @@ -233,7 +528,7 @@ * @return URL source or null */ public URL getURL() { - return url; + return data.url(); } /** @@ -242,8 +537,9 @@ * @return Index of first character of line. */ private int findBOLN(final int position) { + final char[] data = data(); for (int i = position - 1; i > 0; i--) { - final char ch = content[i]; + final char ch = data[i]; if (ch == '\n' || ch == '\r') { return i + 1; @@ -259,8 +555,10 @@ * @return Index of last character of line. */ private int findEOLN(final int position) { - for (int i = position; i < length; i++) { - final char ch = content[i]; + final char[] data = data(); + final int length = data.length; + for (int i = position; i < length; i++) { + final char ch = data[i]; if (ch == '\n' || ch == '\r') { return i - 1; @@ -280,11 +578,12 @@ * @return Line number. */ public int getLine(final int position) { + final char[] data = data(); // Line count starts at 1. int line = 1; for (int i = 0; i < position; i++) { - final char ch = content[i]; + final char ch = data[i]; // Works for both \n and \r\n. if (ch == '\n') { line++; @@ -315,7 +614,7 @@ // Find end of this line. final int last = findEOLN(position); - return new String(content, first, last - first + 1); + return new String(data(), first, last - first + 1); } /** @@ -323,7 +622,7 @@ * @return content */ public char[] getContent() { - return content.clone(); + return data().clone(); } /** @@ -331,19 +630,18 @@ * @return length */ public int getLength() { - return length; + return data.length(); } /** * Read all of the source until end of file. Return it as char array * - * @param reader reader opened to source stream + * @param reader reader opened to source stream * @return source as content - * * @throws IOException if source could not be read */ public static char[] readFully(final Reader reader) throws IOException { - final char[] arr = new char[BUFSIZE]; + final char[] arr = new char[BUF_SIZE]; final StringBuilder sb = new StringBuilder(); try { @@ -361,9 +659,8 @@ /** * Read all of the source until end of file. Return it as char array * - * @param file source file + * @param file source file * @return source as content - * * @throws IOException if source could not be read */ public static char[] readFully(final File file) throws IOException { @@ -376,10 +673,9 @@ /** * Read all of the source until end of file. Return it as char array * - * @param file source file + * @param file source file * @param cs Charset used to convert bytes to chars * @return source as content - * * @throws IOException if source could not be read */ public static char[] readFully(final File file, final Charset cs) throws IOException { @@ -388,7 +684,7 @@ } final byte[] buf = Files.readAllBytes(file.toPath()); - return (cs != null)? new String(buf, cs).toCharArray() : byteToCharArray(buf); + return (cs != null) ? new String(buf, cs).toCharArray() : byteToCharArray(buf); } /** @@ -396,7 +692,6 @@ * * @param url URL to read content from * @return source as content - * * @throws IOException if source could not be read */ public static char[] readFully(final URL url) throws IOException { @@ -409,7 +704,6 @@ * @param url URL to read content from * @param cs Charset used to convert bytes to chars * @return source as content - * * @throws IOException if source could not be read */ public static char[] readFully(final URL url, final Charset cs) throws IOException { @@ -417,55 +711,85 @@ } /** + * Get a message digest for this source. + * + * @return a message digest for this source + */ + public synchronized byte[] getDigest() { + if (digest == null) { + final char[] content = data(); + final byte[] bytes = new byte[content.length * 2]; + + for (int i = 0; i < content.length; i++) { + bytes[i * 2] = (byte) (content[i] & 0x00ff); + bytes[i * 2 + 1] = (byte) ((content[i] & 0xff00) >> 8); + } + + try { + final MessageDigest md = MessageDigest.getInstance("SHA-1"); + if (name != null) { + md.update(name.getBytes(StandardCharsets.UTF_8)); + } + if (base != null) { + md.update(base.getBytes(StandardCharsets.UTF_8)); + } + if (getURL() != null) { + md.update(getURL().toString().getBytes(StandardCharsets.UTF_8)); + } + digest = md.digest(bytes); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + return digest; + } + + /** * Get the base url. This is currently used for testing only * @param url a URL * @return base URL for url */ public static String baseURL(final URL url) { - return baseURL(url, null); - } - - private static String baseURL(final URL url, final String defaultValue) { if (url.getProtocol().equals("file")) { try { final Path path = Paths.get(url.toURI()); final Path parent = path.getParent(); - return (parent != null) ? (parent + File.separator) : defaultValue; + return (parent != null) ? (parent + File.separator) : null; } catch (final SecurityException | URISyntaxException | IOError e) { - return defaultValue; + return null; } } // FIXME: is there a better way to find 'base' URL of a given URL? String path = url.getPath(); if (path.isEmpty()) { - return defaultValue; + return null; } path = path.substring(0, path.lastIndexOf('/') + 1); final int port = url.getPort(); try { return new URL(url.getProtocol(), url.getHost(), port, path).toString(); } catch (final MalformedURLException e) { - return defaultValue; + return null; } } - private static String dirName(final File file, final String defaultValue) { + private static String dirName(final File file, final String DEFAULT_BASE_NAME) { final String res = file.getParent(); - return (res != null)? (res + File.separator) : defaultValue; + return (res != null) ? (res + File.separator) : DEFAULT_BASE_NAME; } // fake directory like name - private static String baseName(final String name, final String defaultValue) { + private static String baseName(final String name) { int idx = name.lastIndexOf('/'); if (idx == -1) { idx = name.lastIndexOf('\\'); } - return (idx != -1)? name.substring(0, idx + 1) : defaultValue; + return (idx != -1) ? name.substring(0, idx + 1) : null; } private static char[] readFully(final InputStream is, final Charset cs) throws IOException { - return (cs != null)? new String(readBytes(is), cs).toCharArray() : readFully(is); + return (cs != null) ? new String(readBytes(is), cs).toCharArray() : readFully(is); } private static char[] readFully(final InputStream is) throws IOException { @@ -476,19 +800,19 @@ Charset cs = StandardCharsets.UTF_8; int start = 0; // BOM detection. - if (bytes.length > 1 && bytes[0] == (byte)0xFE && bytes[1] == (byte)0xFF) { + if (bytes.length > 1 && bytes[0] == (byte) 0xFE && bytes[1] == (byte) 0xFF) { start = 2; cs = StandardCharsets.UTF_16BE; - } else if (bytes.length > 1 && bytes[0] == (byte)0xFF && bytes[1] == (byte)0xFE) { + } else if (bytes.length > 1 && bytes[0] == (byte) 0xFF && bytes[1] == (byte) 0xFE) { start = 2; cs = StandardCharsets.UTF_16LE; - } else if (bytes.length > 2 && bytes[0] == (byte)0xEF && bytes[1] == (byte)0xBB && bytes[2] == (byte)0xBF) { + } 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) { + } 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) { + } 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"); } @@ -497,7 +821,7 @@ } static byte[] readBytes(final InputStream is) throws IOException { - final byte[] arr = new byte[BUFSIZE]; + final byte[] arr = new byte[BUF_SIZE]; try { try (ByteArrayOutputStream buf = new ByteArrayOutputStream()) { int numBytes;
--- a/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java Tue Aug 19 23:57:20 2014 +0100 @@ -187,6 +187,11 @@ } @Override + void initMethodHandles(final Class<?> structure) { + throw new UnsupportedOperationException(); + } + + @Override public ScriptFunction getGetterFunction(final ScriptObject obj) { final Object value = obj.getSpill(getterSlot); return (value instanceof ScriptFunction) ? (ScriptFunction) value : null;
--- a/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Tue Aug 19 23:57:20 2014 +0100 @@ -61,9 +61,17 @@ private static final DynamicLinker dynamicLinker; static { final DynamicLinkerFactory factory = new DynamicLinkerFactory(); - factory.setPrioritizedLinkers(new NashornLinker(), new NashornPrimitiveLinker(), new NashornStaticClassLinker(), - new BoundDynamicMethodLinker(), new JavaSuperAdapterLinker(), new JSObjectLinker(), new ReflectionCheckLinker()); - factory.setFallbackLinkers(new NashornBeansLinker(), new NashornBottomLinker()); + final NashornBeansLinker nashornBeansLinker = new NashornBeansLinker(); + final JSObjectLinker jsObjectLinker = new JSObjectLinker(nashornBeansLinker); + factory.setPrioritizedLinkers( + new NashornLinker(), + new NashornPrimitiveLinker(), + new NashornStaticClassLinker(), + new BoundDynamicMethodLinker(), + new JavaSuperAdapterLinker(), + jsObjectLinker, + new ReflectionCheckLinker()); + factory.setFallbackLinkers(nashornBeansLinker, new NashornBottomLinker()); factory.setSyncOnRelink(true); final int relinkThreshold = Options.getIntProperty("nashorn.unstable.relink.threshold", -1); if (relinkThreshold > -1) {
--- a/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java Tue Aug 19 23:57:20 2014 +0100 @@ -30,6 +30,7 @@ import java.lang.invoke.MethodType; import java.util.HashMap; import java.util.Map; +import javax.script.Bindings; import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.linker.GuardedInvocation; import jdk.internal.dynalink.linker.GuardedTypeConversion; @@ -48,14 +49,23 @@ * as ScriptObjects from other Nashorn contexts. */ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker, GuardingTypeConverterFactory { + private final NashornBeansLinker nashornBeansLinker; + + JSObjectLinker(final NashornBeansLinker nashornBeansLinker) { + this.nashornBeansLinker = nashornBeansLinker; + } + @Override public boolean canLinkType(final Class<?> type) { return canLinkTypeStatic(type); } static boolean canLinkTypeStatic(final Class<?> type) { - // can link JSObject - return JSObject.class.isAssignableFrom(type); + // can link JSObject also handles Map, Bindings to make + // sure those are not JSObjects. + return Map.class.isAssignableFrom(type) || + Bindings.class.isAssignableFrom(type) || + JSObject.class.isAssignableFrom(type); } @Override @@ -72,6 +82,11 @@ final GuardedInvocation inv; if (self instanceof JSObject) { inv = lookup(desc); + } else if (self instanceof Map || self instanceof Bindings) { + // guard to make sure the Map or Bindings does not turn into JSObject later! + final GuardedInvocation beanInv = nashornBeansLinker.getGuardedInvocation(request, linkerServices); + inv = new GuardedInvocation(beanInv.getInvocation(), + NashornGuards.combineGuards(beanInv.getGuard(), NashornGuards.getNotJSObjectGuard())); } else { throw new AssertionError(); // Should never reach here. }
--- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java Tue Aug 19 23:57:20 2014 +0100 @@ -131,7 +131,7 @@ * implemented securely. */ final class JavaAdapterBytecodeGenerator { - static final Type OBJECT_TYPE = Type.getType(Object.class); + static final Type OBJECT_TYPE = Type.getType(Object.class); static final String OBJECT_TYPE_NAME = OBJECT_TYPE.getInternalName(); @@ -139,6 +139,7 @@ static final String GLOBAL_FIELD_NAME = "global"; + // "global" is declared as Object instead of Global - avoid static references to internal Nashorn classes when possible. static final String GLOBAL_TYPE_DESCRIPTOR = OBJECT_TYPE.getDescriptor(); static final String SET_GLOBAL_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE, OBJECT_TYPE); @@ -642,7 +643,7 @@ mv.athrow(); } else { // If the super method is not abstract, delegate to it. - emitSuperCall(mv, name, methodDesc); + emitSuperCall(mv, method.getDeclaringClass(), name, methodDesc); } mv.visitLabel(handleDefined); @@ -671,7 +672,7 @@ // stack: [creatingGlobal, creatingGlobal, handle] // Emit code for switching to the creating global - // ScriptObject currentGlobal = Context.getGlobal(); + // Global currentGlobal = Context.getGlobal(); invokeGetGlobal(mv); mv.dup(); @@ -814,12 +815,12 @@ SUPER_PREFIX + name, methodDesc, null, getExceptionNames(method.getExceptionTypes()))); mv.visitCode(); - emitSuperCall(mv, name, methodDesc); + emitSuperCall(mv, method.getDeclaringClass(), name, methodDesc); endMethod(mv); } - private void emitSuperCall(final InstructionAdapter mv, final String name, final String methodDesc) { + private void emitSuperCall(final InstructionAdapter mv, final Class<?> owner, final String name, final String methodDesc) { mv.visitVarInsn(ALOAD, 0); int nextParam = 1; final Type methodType = Type.getMethodType(methodDesc); @@ -827,7 +828,13 @@ mv.load(nextParam, t); nextParam += t.getSize(); } - mv.invokespecial(superClassName, name, methodDesc, false); + + // default method - non-abstract, interface method + if (Modifier.isInterface(owner.getModifiers())) { + mv.invokespecial(Type.getInternalName(owner), name, methodDesc, false); + } else { + mv.invokespecial(superClassName, name, methodDesc, false); + } mv.areturn(methodType.getReturnType()); }
--- a/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java Tue Aug 19 23:57:20 2014 +0100 @@ -31,6 +31,7 @@ import java.lang.invoke.MethodHandles; import java.lang.ref.WeakReference; import jdk.internal.dynalink.CallSiteDescriptor; +import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.internal.codegen.ObjectClassGenerator; import jdk.nashorn.internal.objects.Global; import jdk.nashorn.internal.runtime.Property; @@ -43,6 +44,7 @@ */ public final class NashornGuards { private static final MethodHandle IS_SCRIPTOBJECT = findOwnMH("isScriptObject", boolean.class, Object.class); + private static final MethodHandle IS_NOT_JSOBJECT = findOwnMH("isNotJSObject", boolean.class, Object.class); private static final MethodHandle IS_SCRIPTFUNCTION = findOwnMH("isScriptFunction", boolean.class, Object.class); private static final MethodHandle IS_MAP = findOwnMH("isMap", boolean.class, Object.class, PropertyMap.class); private static final MethodHandle SAME_OBJECT = findOwnMH("sameObject", boolean.class, Object.class, WeakReference.class); @@ -61,6 +63,14 @@ } /** + * Get the guard that checks if an item is not a {@code JSObject} + * @return method handle for guard + */ + public static MethodHandle getNotJSObjectGuard() { + return IS_NOT_JSOBJECT; + } + + /** * Get the guard that checks if an item is a {@code ScriptFunction} * @return method handle for guard */ @@ -157,6 +167,11 @@ } @SuppressWarnings("unused") + private static boolean isNotJSObject(final Object self) { + return !(self instanceof JSObject); + } + + @SuppressWarnings("unused") private static boolean isScriptFunction(final Object self) { return self instanceof ScriptFunction; }
--- a/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java Tue Aug 19 23:57:20 2014 +0100 @@ -25,6 +25,7 @@ package jdk.nashorn.internal.runtime.linker; +import java.lang.reflect.Modifier; import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.beans.BeansLinker; import jdk.internal.dynalink.beans.StaticClass; @@ -65,10 +66,15 @@ return null; } final Class<?> receiverClass = ((StaticClass) self).getRepresentedClass(); + Bootstrap.checkReflectionAccess(receiverClass, true); final CallSiteDescriptor desc = request.getCallSiteDescriptor(); // We intercept "new" on StaticClass instances to provide additional capabilities if ("new".equals(desc.getNameToken(CallSiteDescriptor.OPERATOR))) { + if (! Modifier.isPublic(receiverClass.getModifiers())) { + throw ECMAErrors.typeError("new.on.nonpublic.javatype", receiverClass.getName()); + } + // make sure new is on accessible Class Context.checkPackageAccess(receiverClass);
--- a/src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java Tue Aug 19 23:57:20 2014 +0100 @@ -46,9 +46,6 @@ /** Java regexp pattern to use for match. We compile to one of these */ private Pattern pattern; - /** The matcher */ - private RegExpMatcher matcher; - /** * Construct a Regular expression from the given {@code source} and {@code flags} strings. * @@ -95,14 +92,7 @@ return null; // never matches or similar, e.g. a[] } - RegExpMatcher currentMatcher = this.matcher; - - if (currentMatcher == null || matcher.getInput() != str) { - currentMatcher = new DefaultMatcher(str); - this.matcher = currentMatcher; - } - - return currentMatcher; + return new DefaultMatcher(str); } class DefaultMatcher implements RegExpMatcher {
--- a/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java Tue Aug 19 23:57:20 2014 +0100 @@ -44,9 +44,6 @@ /** Compiled Joni Regex */ private Regex regex; - /** Matcher */ - private RegExpMatcher matcher; - /** * Construct a Regular expression from the given {@code pattern} and {@code flags} strings. * @@ -95,14 +92,7 @@ return null; } - RegExpMatcher currentMatcher = this.matcher; - - if (currentMatcher == null || input != currentMatcher.getInput()) { - currentMatcher = new JoniMatcher(input); - this.matcher = currentMatcher; - } - - return currentMatcher; + return new JoniMatcher(input); } /**
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/Analyser.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Analyser.java Tue Aug 19 23:57:20 2014 +0100 @@ -771,7 +771,7 @@ while (value < end) { int ovalue = value; - buf = Character.toLowerCase(chars[value++]); + buf = EncodingHelper.toLowerCase(chars[value++]); if (chars[ovalue] != buf) { @@ -779,7 +779,7 @@ System.arraycopy(chars, sn.p, sbuf, 0, ovalue - sn.p); value = ovalue; while (value < end) { - buf = Character.toLowerCase(chars[value++]); + buf = EncodingHelper.toLowerCase(chars[value++]); if (sp >= sbuf.length) { char[]tmp = new char[sbuf.length << 1]; System.arraycopy(sbuf, 0, tmp, 0, sbuf.length);
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFold.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFold.java Tue Aug 19 23:57:20 2014 +0100 @@ -20,70 +20,42 @@ package jdk.nashorn.internal.runtime.regexp.joni; import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode; -import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode; -import jdk.nashorn.internal.runtime.regexp.joni.ast.StringNode; final class ApplyCaseFold { // i_apply_case_fold - public void apply(int from, int[]to, int length, Object o) { + public void apply(int from, int to, Object o) { ApplyCaseFoldArg arg = (ApplyCaseFoldArg)o; ScanEnvironment env = arg.env; CClassNode cc = arg.cc; BitSet bs = cc.bs; - if (length == 1) { - boolean inCC = cc.isCodeInCC(from); + boolean inCC = cc.isCodeInCC(from); - if (Config.CASE_FOLD_IS_APPLIED_INSIDE_NEGATIVE_CCLASS) { - if ((inCC && !cc.isNot()) || (!inCC && cc.isNot())) { - if (to[0] >= BitSet.SINGLE_BYTE_SIZE) { - cc.addCodeRange(env, to[0], to[0]); - } else { - /* /(?i:[^A-C])/.match("a") ==> fail. */ - bs.set(to[0]); - } + if (Config.CASE_FOLD_IS_APPLIED_INSIDE_NEGATIVE_CCLASS) { + if ((inCC && !cc.isNot()) || (!inCC && cc.isNot())) { + if (to >= BitSet.SINGLE_BYTE_SIZE) { + cc.addCodeRange(env, to, to); + } else { + /* /(?i:[^A-C])/.match("a") ==> fail. */ + bs.set(to); } - } else { - if (inCC) { - if (to[0] >= BitSet.SINGLE_BYTE_SIZE) { - if (cc.isNot()) cc.clearNotFlag(); - cc.addCodeRange(env, to[0], to[0]); + } + } else { + if (inCC) { + if (to >= BitSet.SINGLE_BYTE_SIZE) { + if (cc.isNot()) cc.clearNotFlag(); + cc.addCodeRange(env, to, to); + } else { + if (cc.isNot()) { + bs.clear(to); } else { - if (cc.isNot()) { - bs.clear(to[0]); - } else { - bs.set(to[0]); - } + bs.set(to); } } - } // CASE_FOLD_IS_APPLIED_INSIDE_NEGATIVE_CCLASS - - } else { - if (cc.isCodeInCC(from) && (!Config.CASE_FOLD_IS_APPLIED_INSIDE_NEGATIVE_CCLASS || !cc.isNot())) { - StringNode node = null; - for (int i=0; i<length; i++) { - if (i == 0) { - node = new StringNode(); - /* char-class expanded multi-char only - compare with string folded at match time. */ - node.setAmbig(); - } - node.catCode(to[i]); - } - - ConsAltNode alt = ConsAltNode.newAltNode(node, null); - - if (arg.tail == null) { - arg.altRoot = alt; - } else { - arg.tail.setCdr(alt); - } - arg.tail = alt; } - - } + } // CASE_FOLD_IS_APPLIED_INSIDE_NEGATIVE_CCLASS }
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java Tue Aug 19 23:57:20 2014 +0100 @@ -58,8 +58,8 @@ int end1 = s1 + mbLen; while (s1 < end1) { - char c1 = Character.toLowerCase(chars[s1++]); - char c2 = Character.toLowerCase(chars[s2++]); + char c1 = EncodingHelper.toLowerCase(chars[s1++]); + char c2 = EncodingHelper.toLowerCase(chars[s2++]); if (c1 != c2) { return false; @@ -367,7 +367,7 @@ } private void opExact1IC() { - if (s >= range || code[ip] != Character.toLowerCase(chars[s++])) {opFail(); return;} + if (s >= range || code[ip] != EncodingHelper.toLowerCase(chars[s++])) {opFail(); return;} ip++; sprev = sbegin; // break; } @@ -380,10 +380,10 @@ char[] bs = regex.templates[code[ip++]]; int ps = code[ip++]; - while (tlen-- > 0) if (bs[ps++] != Character.toLowerCase(chars[s++])) {opFail(); return;} + while (tlen-- > 0) if (bs[ps++] != EncodingHelper.toLowerCase(chars[s++])) {opFail(); return;} } else { - while (tlen-- > 0) if (code[ip++] != Character.toLowerCase(chars[s++])) {opFail(); return;} + while (tlen-- > 0) if (code[ip++] != EncodingHelper.toLowerCase(chars[s++])) {opFail(); return;} } sprev = s - 1; }
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java Tue Aug 19 23:57:20 2014 +0100 @@ -93,43 +93,80 @@ return s; } - public static int mbcToCode(byte[] bytes, int p, int end) { - int code = 0; - for (int i = p; i < end; i++) { - code = (code << 8) | (bytes[i] & 0xff); - } - return code; - } - public static int mbcodeStartPosition() { return 0x80; } public static char[] caseFoldCodesByString(int flag, char c) { - if (Character.isUpperCase(c)) { - return new char[] {Character.toLowerCase(c)}; - } else if (Character.isLowerCase(c)) { - return new char[] {Character.toUpperCase(c)}; - } else { - return EMPTYCHARS; + char[] codes = EMPTYCHARS; + final char upper = toUpperCase(c); + + if (upper != toLowerCase(upper)) { + int count = 0; + char ch = 0; + + do { + final char u = toUpperCase(ch); + if (u == upper && ch != c) { + // Almost all characters will return array of length 1, very few 2 or 3, so growing by one is fine. + codes = count == 0 ? new char[1] : Arrays.copyOf(codes, count + 1); + codes[count++] = ch; + } + } while (ch++ < 0xffff); } + return codes; } public static void applyAllCaseFold(int flag, ApplyCaseFold fun, Object arg) { - int[] code = new int[1]; - for (int c = 0; c < 0xffff; c++) { - if (Character.getType(c) == Character.LOWERCASE_LETTER) { + if (Character.isLowerCase(c)) { + final int upper = toUpperCase(c); - int upper = code[0] = Character.toUpperCase(c); - fun.apply(c, code, 1, arg); + if (upper != c) { + fun.apply(c, upper, arg); + } + } + } - code[0] = c; - fun.apply(upper, code, 1, arg); + // Some characters have multiple lower case variants, hence we need to do a second run + for (int c = 0; c < 0xffff; c++) { + if (Character.isLowerCase(c)) { + final int upper = toUpperCase(c); + + if (upper != c) { + fun.apply(upper, c, arg); + } } } } + public static char toLowerCase(char c) { + return (char)toLowerCase((int)c); + } + + public static int toLowerCase(int c) { + if (c < 128) { + return ('A' <= c && c <= 'Z') ? (c + ('a' - 'A')) : c; + } + // Do not convert non-ASCII upper case character to ASCII lower case. + int lower = Character.toLowerCase(c); + return (lower < 128) ? c : lower; + + } + + public static char toUpperCase(char c) { + return (char)toUpperCase((int)c); + } + + public static int toUpperCase(int c) { + if (c < 128) { + return ('a' <= c && c <= 'z') ? c + ('A' - 'a') : c; + } + // Do not convert non-ASCII lower case character to ASCII upper case. + int upper = Character.toUpperCase(c); + return (upper < 128) ? c : upper; + } + public static int[] ctypeCodeRange(int ctype, IntHolder sbOut) { sbOut.value = 0x100; // use bitset for codes smaller than 256 int[] range = null;
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java Tue Aug 19 23:57:20 2014 +0100 @@ -131,12 +131,13 @@ this.warnings = null; } - public void compile() { + public synchronized MatcherFactory compile() { if (factory == null && analyser != null) { - Compiler compiler = new ArrayCompiler(analyser); + new ArrayCompiler(analyser).compile(); analyser = null; // only do this once - compiler.compile(); } + assert factory != null; + return factory; } public Matcher matcher(char[] chars) { @@ -144,8 +145,11 @@ } public Matcher matcher(char[] chars, int p, int end) { - compile(); - return factory.create(this, chars, p, end); + MatcherFactory matcherFactory = factory; + if (matcherFactory == null) { + matcherFactory = compile(); + } + return matcherFactory.create(this, chars, p, end); } public WarnCallback getWarnings() {
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/SearchAlgorithm.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/SearchAlgorithm.java Tue Aug 19 23:57:20 2014 +0100 @@ -168,7 +168,7 @@ char[] chars, int p, int end) { while (tP < tEnd) { - if (t[tP++] != Character.toLowerCase(chars[p++])) return false; + if (t[tP++] != EncodingHelper.toLowerCase(chars[p++])) return false; } return true; }
--- a/src/jdk/nashorn/internal/runtime/resources/Messages.properties Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/resources/Messages.properties Tue Aug 19 23:57:20 2014 +0100 @@ -138,6 +138,7 @@ type.error.method.not.constructor=Java method {0} can't be used as a constructor. type.error.env.not.object=$ENV must be an Object. type.error.unsupported.java.to.type=Unsupported Java.to target type {0}. +type.error.new.on.nonpublic.javatype=new cannot be used with non-public java type {0}. range.error.dataview.constructor.offset=Wrong offset or length in DataView constructor range.error.dataview.offset=Offset is outside the bounds of the DataView
--- a/src/jdk/nashorn/internal/runtime/resources/Options.properties Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/internal/runtime/resources/Options.properties Tue Aug 19 23:57:20 2014 +0100 @@ -102,6 +102,13 @@ type=Boolean \ } +nashorn.option.const.as.var = { \ + name="--const-as-var", \ + is_undocumented=true, \ + desc="Replace 'const' with 'var'.", \ + type=Boolean \ +} + nashorn.option.d = { \ name="--dump-debug-dir", \ short_name="-d", \ @@ -230,6 +237,14 @@ desc="Parse without compiling." \ } +nashorn.option.persistent.code.cache = { \ + name="--persistent-code-cache", \ + short_name="-pcc", \ + desc="Enable disk cache for compiled scripts.", \ + is_undocumented=true, \ + default=false \ +} + nashorn.option.profile.callsites = { \ name="--profile-callsites", \ short_name="-pcs", \
--- a/src/jdk/nashorn/tools/Shell.java Mon Jun 02 18:51:26 2014 +0100 +++ b/src/jdk/nashorn/tools/Shell.java Tue Aug 19 23:57:20 2014 +0100 @@ -25,6 +25,8 @@ package jdk.nashorn.tools; +import static jdk.nashorn.internal.runtime.Source.sourceFor; + import java.io.BufferedReader; import java.io.File; import java.io.FileReader; @@ -50,7 +52,6 @@ import jdk.nashorn.internal.runtime.Property; import jdk.nashorn.internal.runtime.ScriptEnvironment; import jdk.nashorn.internal.runtime.ScriptFunction; -import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.Source; import jdk.nashorn.internal.runtime.options.Options; @@ -244,7 +245,7 @@ // For each file on the command line. for (final String fileName : files) { - final FunctionNode functionNode = new Parser(env, new Source(fileName, new File(fileName)), errors).parse(); + final FunctionNode functionNode = new Parser(env, sourceFor(fileName, new File(fileName)), errors).parse(); if (errors.getNumberOfErrors() != 0) { return COMPILATION_ERROR; @@ -302,7 +303,7 @@ } final File file = new File(fileName); - final ScriptFunction script = context.compileScript(new Source(fileName, file.toURI().toURL()), global); + final ScriptFunction script = context.compileScript(sourceFor(fileName, file), global); if (script == null || errors.getNumberOfErrors() != 0) { return COMPILATION_ERROR; } @@ -405,7 +406,7 @@ // initialize with "shell.js" script try { - final Source source = new Source("<shell.js>", Shell.class.getResource("resources/shell.js")); + final Source source = sourceFor("<shell.js>", Shell.class.getResource("resources/shell.js")); context.eval(global, source.getString(), global, "<shell.js>", false); } catch (final Exception e) { err.println(e); @@ -452,7 +453,7 @@ } } finally { if (globalChanged) { - Context.setGlobal(global); + Context.setGlobal(oldGlobal); } }
--- a/test/script/basic/JDK-8008448.js Mon Jun 02 18:51:26 2014 +0100 +++ b/test/script/basic/JDK-8008448.js Tue Aug 19 23:57:20 2014 +0100 @@ -26,6 +26,7 @@ * Ensure that all parseable files can be parsed using parser API. * * @test + * @option --const-as-var * @option -scripting * @run */
--- a/test/script/basic/JDK-8024120.js Mon Jun 02 18:51:26 2014 +0100 +++ b/test/script/basic/JDK-8024120.js Tue Aug 19 23:57:20 2014 +0100 @@ -32,10 +32,6 @@ obj.__proto__ = null; -if (obj.__proto__ !== null || typeof(obj.__proto__) != 'object') { - fail("obj.__proto__ is expected to be null"); -} - var p = Object.getPrototypeOf(obj); if (p !== null || typeof(p) != 'object') { fail("Object.getPrototypeOf(obj) is expected to be null");
--- a/test/script/basic/JDK-8024174.js Mon Jun 02 18:51:26 2014 +0100 +++ b/test/script/basic/JDK-8024174.js Tue Aug 19 23:57:20 2014 +0100 @@ -46,6 +46,6 @@ __proto__: null }; -if (obj2.__proto__ !== null || Object.getPrototypeOf(obj2) !== null) { +if (Object.getPrototypeOf(obj2) !== null) { fail("obj2.__proto__ was not set to null inside literal"); }
--- a/test/script/basic/JDK-8026161.js Mon Jun 02 18:51:26 2014 +0100 +++ b/test/script/basic/JDK-8026161.js Tue Aug 19 23:57:20 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2014, 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 @@ -28,5 +28,5 @@ * @run */ -print(new java.awt.Color(1, 1, 1)) // creates Color[r=1,g=1,b=1] -print(new java.awt.Color(1.0, 1.0, 1.0)) // Color[r=255,g=255,b=255] +print(Java.type("jdk.nashorn.test.models.IntFloatOverloadSelection").overloadedMethod(1)) +print(Java.type("jdk.nashorn.test.models.IntFloatOverloadSelection").overloadedMethod(1.0))
--- a/test/script/basic/JDK-8026161.js.EXPECTED Mon Jun 02 18:51:26 2014 +0100 +++ b/test/script/basic/JDK-8026161.js.EXPECTED Tue Aug 19 23:57:20 2014 +0100 @@ -1,2 +1,2 @@ -java.awt.Color[r=1,g=1,b=1] -java.awt.Color[r=255,g=255,b=255] +int +float
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8027933.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, 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-8027933: Add const.as.var option + * + * @test + * @option --const-as-var + * @run + */ + +const THE_ANSWER = 42; +print("Answer to all questions: " + THE_ANSWER); + +print((function () { + const FORTY_TWO = 42; + return FORTY_TWO +})())
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8027933.js.EXPECTED Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,2 @@ +Answer to all questions: 42 +42
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8030199.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2010, 2014, 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-8030199: Nashorn: Uint8ClampedArray - Incorrect ToUint8Clamp implementation + * + * @test + * @run + */ + +function testTypedArray(ArrayType) { + print(ArrayType.BYTES_PER_ELEMENT); + var a = new ArrayType(7); + a[0] = 4294967296; + a[1] = -4294967295; + a[2] = 4294967298; + a[3] = -4294967298; + a[4] = Infinity; + a[5] = -Infinity; + a[6] = NaN; + print(Array.prototype.join.call(a)); +} + +testTypedArray(Uint8ClampedArray); +testTypedArray(Uint8Array); +testTypedArray(Int8Array); +testTypedArray(Uint16Array); +testTypedArray(Int16Array); +testTypedArray(Uint32Array); +testTypedArray(Int32Array);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8030199.js.EXPECTED Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,14 @@ +1 +255,0,255,0,255,0,0 +1 +0,1,2,254,0,0,0 +1 +0,1,2,-2,0,0,0 +2 +0,1,2,65534,0,0,0 +2 +0,1,2,-2,0,0,0 +4 +0,1,2,4294967294,0,0,0 +4 +0,1,2,-2,0,0,0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8030200.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2010, 2014, 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-8030200: Wrong result for Number.prototype.toString() for certain radix/inputs + * + * @test + * @run + */ + +var n = 0x8000000000000800; +print(n); +var s = n.toString(5); +var m = parseInt(s, 5); +print(m === n); +print(n);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8030200.js.EXPECTED Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,3 @@ +9223372036854778000 +true +9223372036854778000
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8030202.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2010, 2014, 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-8030202: Nashorn: Multiple RegExp#ignoreCase issues + * + * @test + * @run + */ + +print(/\u2160/i.test("\u2170")); +print(/[\u2160]/i.test("\u2170")); +print(/\u2170/i.test("\u2160")); +print(/[\u2170]/i.test("\u2160")); + +print(/\u0130/i.test("\u0069")); +print(/[\u0130]/i.test("\u0069")); +print(/\u0069/i.test("\u0130")); +print(/[\u0069]/i.test("\u0130")); + +print(/\u1e9e/i.test("\u00df")); +print(/[\u1e9e]/i.test("\u00df")); +print(/\u00df/i.test("\u1e9e")); +print(/[\u00df]/i.test("\u1e9e")); + +print(/[^\u1e9e]/i.test("\u00df")); +print(/[^\u00df]/i.test("\u1e9e")); + +print(/\u0345{4}/i.test("\u0345\u0399\u03b9\u1fbe")); +print(/\u0399{4}/i.test("\u0345\u0399\u03b9\u1fbe")); +print(/\u03b9{4}/i.test("\u0345\u0399\u03b9\u1fbe")); +print(/\u1fbe{4}/i.test("\u0345\u0399\u03b9\u1fbe")); + +print(/[\u0345]{4}/i.test("\u0345\u0399\u03b9\u1fbe")); +print(/[\u0399]{4}/i.test("\u0345\u0399\u03b9\u1fbe")); +print(/[\u03b9]{4}/i.test("\u0345\u0399\u03b9\u1fbe")); +print(/[\u1fbe]{4}/i.test("\u0345\u0399\u03b9\u1fbe"));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8030202.js.EXPECTED Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,22 @@ +true +true +true +true +false +false +false +false +false +false +false +false +true +true +true +true +true +true +true +true +true +true
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8039387.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014, 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-8039387: Nashorn supports indexed access of List elements, but length property is not supported + * + * @test + * @run + */ + +var ArrayList = Java.type("java.util.ArrayList") +var list = new ArrayList(3) +list.add("nashorn") +list.add("js") +list.add("ecmascript") +var len = list.length +print("length = " + len) +for (var i = 0; i < len; i++) + print(list[i])
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8039387.js.EXPECTED Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,4 @@ +length = 3 +nashorn +js +ecmascript
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8041998.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2010, 2014, 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-8041998: RegExp implementation is not thread-safe + * + * @test + * @run + */ + +var Thread = java.lang.Thread; + +function run() { + var line = 'content-type: text/html'; + for (var i = 0; i < 300; i++) { + Thread.sleep(1); + line.split(/: /); + } + print("done"); +} + +var threads = []; + +for (var i = 0; i < 4; i++) { + var thread = new Thread(run); + thread.start(); + threads.push(thread); +} + +for (var i = 0; i < 4; i++) { + threads[i].join(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8041998.js.EXPECTED Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,4 @@ +done +done +done +done
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8042364.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2014, 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-8042364: Make __proto__ ES6 draft compliant + * + * @test + * @run + */ + +// check for Object.prototype.__proto__ accessor property +print("Object.prototype has __proto__?", + Object.prototype.hasOwnProperty("__proto__")) + +var desc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__") +print("descriptor"); +print(JSON.stringify(desc)) +print("getter", desc.get) +print("setter", desc.set) + +// no computed "__proto__" name, only identifier! +var p = {} +var obj = { + "__proto__" : p +} + +if (Object.getPrototypeOf(obj) === p) { + fail("obj has wrong __proto__, allows computed __proto__!") +} + +if (obj.__proto__ !== p) { + fail("__proto__ not created as normal property!") +} + +if (Object.getPrototypeOf(obj) !== Object.prototype) { + fail("obj has wrong __proto__") +} + +var obj2 = { + __proto__: p +} + +if (Object.getPrototypeOf(obj2) !== p) { + fail("can't set __proto__ in object literal") +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8042364.js.EXPECTED Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,5 @@ +Object.prototype has __proto__? true +descriptor +{"configurable":true,"enumerable":false} +getter function getProto() { [native code] } +setter function setProto() { [native code] }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8043930.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8043930: TypeError when attemping to create an instance of non-public class could be better + * + * @test + * @run + */ + +var NonPublicClass = Java.type("jdk.nashorn.test.models.NonPublicClass"); +try { + var obj = new NonPublicClass(); + fail("Expected TypeError to be thrown!"); +} catch (e) { + print(e); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8043930.js.EXPECTED Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,1 @@ +TypeError: new cannot be used with non-public java type jdk.nashorn.test.models.NonPublicClass.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8044520.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2014, 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-8044520: Nashorn cannot execute node.js's express module + * + * @test + * @run + */ + +function checkNullProto() { + var obj = {}; + obj.__proto__ = null; + var proto = Object.getPrototypeOf(obj); + if (typeof proto != 'object' || proto !== null) { + fail("__proto__ can't be set to null!"); + } +} + +checkNullProto(); + +function checkSetProto(proto) { + var obj = {}; + obj.__proto__ = proto; + if (Object.getPrototypeOf(obj) !== Object.prototype) { + fail("obj.__proto__ set not ignored for " + proto); + } +} + +checkSetProto(undefined); +checkSetProto(42); +checkSetProto(false); +checkSetProto("hello"); + +function checkLiteralSetProto(proto) { + var obj = { __proto__: proto }; + if (obj.__proto__ !== Object.prototype) { + fail("object literal _proto__ set not ignored for " + proto); + } +} + +checkLiteralSetProto(undefined); +checkLiteralSetProto(34); +checkLiteralSetProto(true); +checkLiteralSetProto("world"); + +function checkNullProtoFromLiteral() { + var obj = { __proto__: null }; + var proto = Object.getPrototypeOf(obj); + if (typeof proto != 'object' || proto !== null) { + fail("__proto__ can't be set to null!"); + } +} + +checkNullProtoFromLiteral(); + +function checkSetPrototypeOf(proto) { + try { + Object.setPrototypeOf({}, proto); + fail("should have thrown error for " + proto); + } catch (e) { + if (! (e instanceof TypeError)) { + fail("should have thrown TypeError, got " + e); + } + } +} + +checkSetPrototypeOf(undefined); +checkSetPrototypeOf(43); +checkSetPrototypeOf(false); +checkSetPrototypeOf("nashorn"); + +function checkNullSetPrototypeOf() { + var obj = { }; + Object.setPrototypeOf(obj, null); + var proto = Object.getPrototypeOf(obj); + if (typeof proto != 'object' || proto !== null) { + fail("__proto__ can't be set to null!"); + } +} + +checkNullSetPrototypeOf(); + +var desc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__"); + +function checkProtoGetterOnPrimitive(value) { + // call __proto__ getter on primitive - check ToObject + // is called on 'this' value as per draft spec + if (desc.get.call(value) !== Object(value).__proto__) { + fail("can't call __proto__ getter on " + value); + } +} + +checkProtoGetterOnPrimitive(32); +checkProtoGetterOnPrimitive(false); +checkProtoGetterOnPrimitive("great!"); + +function checkProtoSetterOnNonObjectThis(self) { + try { + desc.set.call(self); + fail("should have thrown TypeError"); + } catch (e) { + if (! (e instanceof TypeError)) { + fail("should throw TypeError on non-object self, got " +e); + } + } +} + +checkProtoSetterOnNonObjectThis(undefined); +checkProtoSetterOnNonObjectThis(null); + +function checkProtoSetterReturnValue(obj, p) { + if (typeof desc.set.call(obj, p) != "undefined") { + fail("__proto__ setter does not return undefined: " + obj + " " + p); + } +} + +// try non-object 'this'. setter is expected to return undefined. +checkProtoSetterReturnValue(23); +checkProtoSetterReturnValue(false); +checkProtoSetterReturnValue("foo"); + +// set proper __proto__. Still return value is undefined. +checkProtoSetterReturnValue({}, {}); +checkProtoSetterReturnValue({}, null);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8044612.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014, 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-8044612: StringIndexOutOfBoundException in NativeRegExp.appendReplacement + * + * @test + * @run + */ + +if ("hello".replace("h", "$") != "$ello") { + fail("String.prototype.replace failed to handle '$' as replacement"); +} + +if ("hello".replace("o", "$x") != "hell$x") { + fail("String.prototype.replace failed to handle '$x' as replacement"); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8044695.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014, 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-8044695: __stack__ becomes visible in Error properties + * + * @test + * @run + */ + +var e = new Error(); +// access stack to force __stack__ +e.stack; +var jsonStr = JSON.stringify(e); +if (jsonStr != "{}") { + fail("JSON string is not {}, it is " + jsonStr); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8044750.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014, 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-8044750: megamorphic getter for scope objects does not call __noSuchProperty__ hook + * + * @test + * @run + */ + +__noSuchProperty__ = function(name) { + return 1; +} + +function func(obj) { + with(obj) { + // this "foo" getter site becomes megamorphic + // due to different 'with' scope objects. + foo; + } +} + +for (var i = 0; i < 20; i++) { + var obj = {}; + obj.foo = i; + obj[i] = i; + func(obj); +} + +// pass a 'with' scope object that does not have 'foo'. +// callsite inside func should see __noSuchProperty__ +// hook on global scope object. +func({});
--- a/test/script/basic/NASHORN-173.js.EXPECTED Mon Jun 02 18:51:26 2014 +0100 +++ b/test/script/basic/NASHORN-173.js.EXPECTED Tue Aug 19 23:57:20 2014 +0100 @@ -132,7 +132,7 @@ 2.3423446609034533e+21 2.3423446609034533e+21 11111101111101010001111111010101101000101011011001001000000000000000000 -2224143002343343220233144213324 +2224143002343343220233044213324 375752177255053311000000 73b92b9962990aa44400 7efa8fead15b240000
--- a/test/script/basic/list.js Mon Jun 02 18:51:26 2014 +0100 +++ b/test/script/basic/list.js Tue Aug 19 23:57:20 2014 +0100 @@ -33,7 +33,7 @@ l.add("foo") l.add("bar") -print("l.length=" + l.length) // doesn't work, returns undefined +print("l.length=" + l.length) // works, maps to l.size() print("l.size()=" + l.size()) // this will work print("l[0]=" + l[0])
--- a/test/script/basic/list.js.EXPECTED Mon Jun 02 18:51:26 2014 +0100 +++ b/test/script/basic/list.js.EXPECTED Tue Aug 19 23:57:20 2014 +0100 @@ -1,5 +1,5 @@ l.class.name=java.util.ArrayList -l.length=undefined +l.length=2 l.size()=2 l[0]=foo l[1]=bar
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/error/JDK-8027933.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2014, 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-8027933: Add const.as.var option + * + * @test/compile-error + */ + +// without --const-as-var the following should fail to compile +const THE_ANSWER = 42;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/error/JDK-8027933.js.EXPECTED Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,3 @@ +test/script/error/JDK-8027933.js:31:0 Expected an operand but found const +const THE_ANSWER = 42; +^
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/nosecurity/JDK-8044798.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2014, 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-8044798: API for debugging Nashorn + * + * @test + * @run + */ + +// basic API exercise checks + +var Arrays = Java.type("java.util.Arrays"); +var CharArray = Java.type("char[]"); +var DebuggerSupport = Java.type("jdk.nashorn.internal.runtime.DebuggerSupport"); +var DebuggerValueDesc = Java.type("jdk.nashorn.internal.runtime.DebuggerSupport.DebuggerValueDesc"); + +var valueDescFields = DebuggerValueDesc.class.declaredFields; +Arrays.sort(valueDescFields, function(f1, f2) f1.name.compareTo(f2.name)); +var keyField; +for each (var f in valueDescFields) { + if (f.name == "key") { + keyField = f; + } + f.accessible = true; +} + +var debuggerSupportMethods = DebuggerSupport.class.declaredMethods; + +// methods of DebuggerSupport that we use +var evalMethod, valueInfoMethod, valueInfosMethod; +var getSourceInfoMethod, valueAsStringMethod; + +for each (var m in debuggerSupportMethods) { + m.accessible = true; + switch (m.name) { + case "eval": + evalMethod = m; + break; + case "valueInfo": + if (m.parameterCount == 3) { + valueInfoMethod = m; + } + break; + case "valueInfos": + valueInfosMethod = m; + break; + case "valueAsString": + valueAsStringMethod = m; + break; + case "getSourceInfo": + getSourceInfoMethod = m; + break; + } +} + +// eval +var value = evalMethod.invoke(null, null, null, "33 + 55", false); +print(value); + +// valueInfo +var info = valueInfoMethod.invoke(null, "apply", Function, true); +for each (var f in valueDescFields) { + print(f.name, "=", f.get(info)); +} + +// valueInfo - user defined object +var info = valueInfoMethod.invoke(null, "foo", { foo: 343 }, true); +for each (var f in valueDescFields) { + print(f.name, "=", f.get(info)); +} + +// valueInfos +var infos = valueInfosMethod.invoke(null, Object, true); +Arrays.sort(infos, function (i1, i2) keyField.get(i1).compareTo(keyField.get(i2))); + +for each (var info in infos) { + for each (var f in valueDescFields) { + print(f.name, "=", f.get(info)); + } +} + +// valueInfos - user defined object +var infos = valueInfosMethod.invoke(null, { foo: 34, bar: "hello" }, true); +Arrays.sort(infos, function (i1, i2) keyField.get(i1).compareTo(keyField.get(i2))); + +for each (var info in infos) { + for each (var f in valueDescFields) { + print(f.name, "=", f.get(info)); + } +} + +// valueAsString +function printValue(value) { + print(valueAsStringMethod.invoke(null, value)); +} + +printValue(undefined); +printValue(null); +printValue("hello"); +printValue(Math.PI); +printValue(this); + +// The below are not part of DebuggerSupport. But we need these to +// test DebuggerSupport.getSourceInfo etc. which need compiled script class + +var Source = Java.type("jdk.nashorn.internal.runtime.Source"); +var Context = Java.type("jdk.nashorn.internal.runtime.Context"); +var sourceCls = Source.class; +var errorMgrCls = Java.type("jdk.nashorn.internal.runtime.ErrorManager").class; +var booleanCls = Java.type("java.lang.Boolean").TYPE; + +// private compile method of Context class +var compileMethod = Context.class.getDeclaredMethod("compile", + sourceCls, errorMgrCls, booleanCls); +compileMethod.accessible = true; + +var scriptCls = compileMethod.invoke(Context.context, + Source.sourceFor("test", "print('hello')"), + new Context.ThrowErrorManager(), false); + +var SCRIPT_CLASS_NAME_PREFIX = "jdk.nashorn.internal.scripts.Script$"; +print("script class name pattern satisfied? " + + scriptCls.name.startsWith(SCRIPT_CLASS_NAME_PREFIX)); + +var srcInfo = getSourceInfoMethod.invoke(null, scriptCls); +var srcInfoFields = srcInfo.class.declaredFields; +Arrays.sort(srcInfoFields, function(f1, f2) f1.name.compareTo(f2.name)); + +print("Source info"); +for each (var f in srcInfoFields) { + f.accessible = true; + var fieldValue = f.get(srcInfo); + if (fieldValue instanceof CharArray) { + fieldValue = new java.lang.String(fieldValue); + } + + print(f.name, "=", fieldValue); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/nosecurity/JDK-8044798.js.EXPECTED Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,104 @@ +88 +expandable = false +key = apply +valueAsObject = function Function() { [native code] } +valueAsString = function Function() { [native code] } +expandable = true +key = foo +valueAsObject = [object Object] +valueAsString = {foo: 343} +expandable = false +key = bindProperties +valueAsObject = function bindProperties() { [native code] } +valueAsString = function bindProperties() { [native code] } +expandable = false +key = create +valueAsObject = function create() { [native code] } +valueAsString = function create() { [native code] } +expandable = false +key = defineProperties +valueAsObject = function defineProperties() { [native code] } +valueAsString = function defineProperties() { [native code] } +expandable = false +key = defineProperty +valueAsObject = function defineProperty() { [native code] } +valueAsString = function defineProperty() { [native code] } +expandable = false +key = freeze +valueAsObject = function freeze() { [native code] } +valueAsString = function freeze() { [native code] } +expandable = false +key = getOwnPropertyDescriptor +valueAsObject = function getOwnPropertyDescriptor() { [native code] } +valueAsString = function getOwnPropertyDescriptor() { [native code] } +expandable = false +key = getOwnPropertyNames +valueAsObject = function getOwnPropertyNames() { [native code] } +valueAsString = function getOwnPropertyNames() { [native code] } +expandable = false +key = getPrototypeOf +valueAsObject = function getPrototypeOf() { [native code] } +valueAsString = function getPrototypeOf() { [native code] } +expandable = false +key = isExtensible +valueAsObject = function isExtensible() { [native code] } +valueAsString = function isExtensible() { [native code] } +expandable = false +key = isFrozen +valueAsObject = function isFrozen() { [native code] } +valueAsString = function isFrozen() { [native code] } +expandable = false +key = isSealed +valueAsObject = function isSealed() { [native code] } +valueAsString = function isSealed() { [native code] } +expandable = false +key = keys +valueAsObject = function keys() { [native code] } +valueAsString = function keys() { [native code] } +expandable = false +key = length +valueAsObject = 1 +valueAsString = 1 +expandable = false +key = name +valueAsObject = Object +valueAsString = "Object" +expandable = false +key = preventExtensions +valueAsObject = function preventExtensions() { [native code] } +valueAsString = function preventExtensions() { [native code] } +expandable = false +key = prototype +valueAsObject = [object Object] +valueAsString = {toString: function toString() { [native code] }, toLocaleString: function toLocaleString() { [native code] }, valueOf: function valueOf() { [native code] }, hasOwnProperty: function hasOwnProperty() { [native code] }, isPrototypeOf: function isPrototypeOf() { [native code] }, propertyIsEnumerable: function propertyIsEnumerable() { [native code] }, constructor: function Object() { [native code] }, __proto__: null} +expandable = false +key = seal +valueAsObject = function seal() { [native code] } +valueAsString = function seal() { [native code] } +expandable = false +key = setIndexedPropertiesToExternalArrayData +valueAsObject = function setIndexedPropertiesToExternalArrayData() { [native code] } +valueAsString = function setIndexedPropertiesToExternalArrayData() { [native code] } +expandable = false +key = setPrototypeOf +valueAsObject = function setPrototypeOf() { [native code] } +valueAsString = function setPrototypeOf() { [native code] } +expandable = false +key = bar +valueAsObject = hello +valueAsString = "hello" +expandable = false +key = foo +valueAsObject = 34 +valueAsString = 34 +undefined +null +"hello" +3.141592653589793 +[object global] +script class name pattern satisfied? true +Source info +content = print('hello') +hash = 1655359881 +name = test +url = null
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/nosecurity/debuggersupportapi.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2014, 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-8044798: API for debugging Nashorn + * + * @test + * @run + */ + +// Basic API class, method, field existence checks. + +// The following classes and the associated methods and fields are used as +// private debugger interface. Though private/implementation defined, nashorn +// code should not be changed to remove these classes, fields and methods. +// The test takes signatures of debugger interface and stores in .EXPECTED file. +// If any incompatible change is made to nashorn to break any of these, this +// test will fail. + +var Arrays = Java.type("java.util.Arrays"); +var DebuggerSupport = Java.type("jdk.nashorn.internal.runtime.DebuggerSupport"); + +print(DebuggerSupport.class); +print(); +var methods = DebuggerSupport.class.declaredMethods; +Arrays.sort(methods, function(m1, m2) m1.name.compareTo(m2.name)); +for each (var mth in methods) { + switch (mth.name) { + case "eval": + case "notifyInvoke": + case "getSourceInfo": + case "valueAsString": + case "valueInfos": + print(mth); + break; + case "valueInfo": + if (mth.parameterCount == 3) { + print(mth); + } + break; + } +} +print(); + +var DebuggerValueDesc = Java.type("jdk.nashorn.internal.runtime.DebuggerSupport.DebuggerValueDesc"); +print(DebuggerValueDesc.class); +print(); +var fields = DebuggerValueDesc.class.declaredFields; +Arrays.sort(fields, function(f1, f2) f1.name.compareTo(f2.name)); +for each (var fld in fields) { + switch (fld.name) { + case "key": + case "expandable": + case "valueAsObject": + case "valueAsString": + print(fld); + } +} +print(); + +var SourceInfo = Java.type("jdk.nashorn.internal.runtime.DebuggerSupport.SourceInfo"); +print(SourceInfo.class); +print(); +var fields = SourceInfo.class.declaredFields; +Arrays.sort(fields, function(f1, f2) f1.name.compareTo(f2.name)); +for each (var fld in fields) { + switch (fld.name) { + case "name": + case "hash": + case "url": + case "content": + print(fld); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/nosecurity/debuggersupportapi.js.EXPECTED Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,22 @@ +class jdk.nashorn.internal.runtime.DebuggerSupport + +static java.lang.Object jdk.nashorn.internal.runtime.DebuggerSupport.eval(jdk.nashorn.internal.runtime.ScriptObject,java.lang.Object,java.lang.String,boolean) +static jdk.nashorn.internal.runtime.DebuggerSupport$SourceInfo jdk.nashorn.internal.runtime.DebuggerSupport.getSourceInfo(java.lang.Class) +static void jdk.nashorn.internal.runtime.DebuggerSupport.notifyInvoke(java.lang.invoke.MethodHandle) +static java.lang.String jdk.nashorn.internal.runtime.DebuggerSupport.valueAsString(java.lang.Object) +static jdk.nashorn.internal.runtime.DebuggerSupport$DebuggerValueDesc jdk.nashorn.internal.runtime.DebuggerSupport.valueInfo(java.lang.String,java.lang.Object,boolean) +static jdk.nashorn.internal.runtime.DebuggerSupport$DebuggerValueDesc[] jdk.nashorn.internal.runtime.DebuggerSupport.valueInfos(java.lang.Object,boolean) + +class jdk.nashorn.internal.runtime.DebuggerSupport$DebuggerValueDesc + +final boolean jdk.nashorn.internal.runtime.DebuggerSupport$DebuggerValueDesc.expandable +final java.lang.String jdk.nashorn.internal.runtime.DebuggerSupport$DebuggerValueDesc.key +final java.lang.Object jdk.nashorn.internal.runtime.DebuggerSupport$DebuggerValueDesc.valueAsObject +final java.lang.String jdk.nashorn.internal.runtime.DebuggerSupport$DebuggerValueDesc.valueAsString + +class jdk.nashorn.internal.runtime.DebuggerSupport$SourceInfo + +final char[] jdk.nashorn.internal.runtime.DebuggerSupport$SourceInfo.content +final int jdk.nashorn.internal.runtime.DebuggerSupport$SourceInfo.hash +final java.lang.String jdk.nashorn.internal.runtime.DebuggerSupport$SourceInfo.name +final java.net.URL jdk.nashorn.internal.runtime.DebuggerSupport$SourceInfo.url
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/nosecurity/nosecurity.js Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2014, 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. + */ + +/** + * 8043443: Test framework changes to run script tests without security manager + * @test + * @run + */ + +var System = Java.type("java.lang.System"); + +if (System.securityManager != null) { + fail("SecurityManager is set!"); +}
--- a/test/script/trusted/JDK-8006529.js Mon Jun 02 18:51:26 2014 +0100 +++ b/test/script/trusted/JDK-8006529.js Tue Aug 19 23:57:20 2014 +0100 @@ -113,7 +113,7 @@ var getContextMethod = Context.class.getMethod("getContext") var getEnvMethod = Context.class.getMethod("getEnv") -var SourceConstructor = Source.class.getConstructor(java.lang.String.class, java.lang.String.class) +var sourceForMethod = Source.class.getMethod("sourceFor", java.lang.String.class, java.lang.String.class) var ParserConstructor = Parser.class.getConstructor(ScriptEnvironment.class, Source.class, ErrorManager.class) var CompilerConstructor = Compiler.class.getConstructor(ScriptEnvironment.class) @@ -121,7 +121,7 @@ // source code, returns a jdk.nashorn.internal.ir.FunctionNode object // representing it. function compile(source) { - var source = SourceConstructor.newInstance("<no name>", source); + var source = sourceForMethod.invoke(null, "<no name>", source); var env = getEnvMethod.invoke(getContextMethod.invoke(null))
--- a/test/src/jdk/nashorn/api/scripting/ScopeTest.java Mon Jun 02 18:51:26 2014 +0100 +++ b/test/src/jdk/nashorn/api/scripting/ScopeTest.java Tue Aug 19 23:57:20 2014 +0100 @@ -510,6 +510,23 @@ assertEquals(e.eval("x", newCtxt), 2); } + // @bug 8044750: megamorphic getter for scope objects does not call __noSuchProperty__ hook + @Test + public static void testMegamorphicGetInGlobal() throws Exception { + final ScriptEngineManager m = new ScriptEngineManager(); + final ScriptEngine engine = m.getEngineByName("nashorn"); + final String script = "foo"; + // "foo" is megamorphic because of different global scopes. + // Make sure ScriptContext variable search works even after + // it becomes megamorphic. + for (int index = 0; index < 25; index++) { + final Bindings bindings = new SimpleBindings(); + bindings.put("foo", index); + final Number value = (Number)engine.eval(script, bindings); + assertEquals(index, value.intValue()); + } + } + /** * Test "slow" scopes involving {@code with} and {@code eval} statements for shared script classes with multiple globals. */
--- a/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java Mon Jun 02 18:51:26 2014 +0100 +++ b/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java Tue Aug 19 23:57:20 2014 +0100 @@ -29,6 +29,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.script.Bindings; +import javax.script.ScriptContext; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; @@ -276,4 +278,31 @@ "({ toString: function() { return 'foo' } })"); assertEquals("foo", obj.to(String.class)); } + + // @bug 8044000: Access to undefined property yields "null" instead of "undefined" + @Test + public void mapScriptObjectMirrorCallsiteTest() throws ScriptException { + final ScriptEngineManager m = new ScriptEngineManager(); + final ScriptEngine engine = m.getEngineByName("nashorn"); + final String TEST_SCRIPT = "typeof obj.foo"; + + final Bindings global = engine.getContext().getBindings(ScriptContext.ENGINE_SCOPE); + engine.eval("var obj = java.util.Collections.emptyMap()"); + // this will drive callsite "obj.foo" of TEST_SCRIPT + // to use "obj instanceof Map" as it's guard + engine.eval(TEST_SCRIPT, global); + // redefine 'obj' to be a script object + engine.eval("obj = {}"); + + final Bindings newGlobal = engine.createBindings(); + // transfer 'obj' from default global to new global + // new global will get a ScriptObjectMirror wrapping 'obj' + newGlobal.put("obj", global.get("obj")); + + // Every ScriptObjectMirror is a Map! If callsite "obj.foo" + // does not see the new 'obj' is a ScriptObjectMirror, it'll + // continue to use Map's get("obj.foo") instead of ScriptObjectMirror's + // getMember("obj.foo") - thereby getting null instead of undefined + assertEquals("undefined", engine.eval(TEST_SCRIPT, newGlobal)); + } }
--- a/test/src/jdk/nashorn/internal/codegen/CompilerTest.java Mon Jun 02 18:51:26 2014 +0100 +++ b/test/src/jdk/nashorn/internal/codegen/CompilerTest.java Tue Aug 19 23:57:20 2014 +0100 @@ -25,6 +25,9 @@ package jdk.nashorn.internal.codegen; +import static jdk.nashorn.internal.runtime.Source.sourceFor; +import static jdk.nashorn.internal.runtime.Source.readFully; + import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; @@ -32,7 +35,6 @@ import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ErrorManager; import jdk.nashorn.internal.runtime.ScriptFunction; -import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.Source; import jdk.nashorn.internal.runtime.options.Options; import org.testng.Assert; @@ -69,6 +71,7 @@ options.set("print.ast", true); options.set("print.parse", true); options.set("scripting", true); + options.set("const.as.var", true); final ErrorManager errors = new ErrorManager() { @Override @@ -151,7 +154,7 @@ final boolean globalChanged = (oldGlobal != global); try { - final char[] buffer = Source.readFully(file); + final char[] buffer = readFully(file); boolean excluded = false; if (filter != null) { @@ -170,7 +173,7 @@ if (globalChanged) { Context.setGlobal(global); } - final Source source = new Source(file.getAbsolutePath(), buffer); + final Source source = sourceFor(file.getAbsolutePath(), buffer); final ScriptFunction script = context.compileScript(source, global); if (script == null || context.getErrorManager().getNumberOfErrors() > 0) { log("Compile failed: " + file.getAbsolutePath());
--- a/test/src/jdk/nashorn/internal/parser/ParserTest.java Mon Jun 02 18:51:26 2014 +0100 +++ b/test/src/jdk/nashorn/internal/parser/ParserTest.java Tue Aug 19 23:57:20 2014 +0100 @@ -25,6 +25,9 @@ package jdk.nashorn.internal.parser; +import static jdk.nashorn.internal.runtime.Source.sourceFor; +import static jdk.nashorn.internal.runtime.Source.readFully; + import java.io.File; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ErrorManager; @@ -62,6 +65,7 @@ options.set("anon.functions", true); options.set("parse.only", true); options.set("scripting", true); + options.set("const.as.var", true); ErrorManager errors = new ErrorManager(); this.context = new Context(options, errors, Thread.currentThread().getContextClassLoader()); @@ -131,7 +135,7 @@ } try { - final char[] buffer = Source.readFully(file); + final char[] buffer = readFully(file); boolean excluded = false; if (filter != null) { final String content = new String(buffer); @@ -153,7 +157,7 @@ } }; errors.setLimit(0); - final Source source = new Source(file.getAbsolutePath(), buffer); + final Source source = sourceFor(file.getAbsolutePath(), buffer); new Parser(context.getEnv(), source, errors).parse(); if (errors.getNumberOfErrors() > 0) { log("Parse failed: " + file.getAbsolutePath());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/src/jdk/nashorn/internal/runtime/CodeStoreAndPathTest.java Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2014, 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.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.DirectoryStream; +import java.nio.file.Path; +import java.nio.file.FileSystems; +import javax.script.ScriptException; +import org.testng.annotations.Test; +import javax.script.ScriptEngine; +import jdk.nashorn.api.scripting.NashornScriptEngineFactory; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertEquals; + +/** + * @test + * @bug 8039185 8039403 + * @summary Test for persistent code cache and path handling + * @run testng jdk.nashorn.internal.runtime.CodeStoreAndPathTest + */ + +public class CodeStoreAndPathTest { + + final String code1 = "var code1; var x = 'Hello Script'; var x1 = 'Hello Script'; " + + "var x2 = 'Hello Script'; var x3 = 'Hello Script'; " + + "var x4 = 'Hello Script'; var x5 = 'Hello Script';" + + "var x6 = 'Hello Script'; var x7 = 'Hello Script'; " + + "var x8 = 'Hello Script'; var x9 = 'Hello Script'; " + + "var x10 = 'Hello Script';" + + "function f() {x ='Bye Script'; x1 ='Bye Script'; x2='Bye Script';" + + "x3='Bye Script'; x4='Bye Script'; x5='Bye Script'; x6='Bye Script';" + + "x7='Bye Script'; x8='Bye Script'; var x9 = 'Hello Script'; " + + "var x10 = 'Hello Script';}" + + "function g() {x ='Bye Script'; x1 ='Bye Script'; x2='Bye Script';" + + "x3='Bye Script'; x4='Bye Script'; x5='Bye Script'; x6='Bye Script';" + + "x7='Bye Script'; x8='Bye Script'; var x9 = 'Hello Script'; " + + "var x10 = 'Hello Script';}" + + "function h() {x ='Bye Script'; x1 ='Bye Script'; x2='Bye Script';" + + "x3='Bye Script'; x4='Bye Script'; x5='Bye Script'; x6='Bye Script';" + + "x7='Bye Script'; x8='Bye Script'; var x9 = 'Hello Script'; " + + "var x10 = 'Hello Script';}" + + "function i() {x ='Bye Script'; x1 ='Bye Script'; x2='Bye Script';" + + "x3='Bye Script'; x4='Bye Script'; x5='Bye Script'; x6='Bye Script';" + + "x7='Bye Script'; x8='Bye Script'; var x9 = 'Hello Script'; " + + "var x10 = 'Hello Script';}"; + final String code2 = "var code2; var x = 'Hello Script'; var x1 = 'Hello Script'; " + + "var x2 = 'Hello Script'; var x3 = 'Hello Script'; " + + "var x4 = 'Hello Script'; var x5 = 'Hello Script';" + + "var x6 = 'Hello Script'; var x7 = 'Hello Script'; " + + "var x8 = 'Hello Script'; var x9 = 'Hello Script'; " + + "var x10 = 'Hello Script';" + + "function f() {x ='Bye Script'; x1 ='Bye Script'; x2='Bye Script';" + + "x3='Bye Script'; x4='Bye Script'; x5='Bye Script'; x6='Bye Script';" + + "x7='Bye Script'; x8='Bye Script'; var x9 = 'Hello Script'; " + + "var x10 = 'Hello Script';}" + + "function g() {x ='Bye Script'; x1 ='Bye Script'; x2='Bye Script';" + + "x3='Bye Script'; x4='Bye Script'; x5='Bye Script'; x6='Bye Script';" + + "x7='Bye Script'; x8='Bye Script'; var x9 = 'Hello Script'; " + + "var x10 = 'Hello Script';}" + + "function h() {x ='Bye Script'; x1 ='Bye Script'; x2='Bye Script';" + + "x3='Bye Script'; x4='Bye Script'; x5='Bye Script'; x6='Bye Script';" + + "x7='Bye Script'; x8='Bye Script'; var x9 = 'Hello Script'; " + + "var x10 = 'Hello Script';}" + + "function i() {x ='Bye Script'; x1 ='Bye Script'; x2='Bye Script';" + + "x3='Bye Script'; x4='Bye Script'; x5='Bye Script'; x6='Bye Script';" + + "x7='Bye Script'; x8='Bye Script'; var x9 = 'Hello Script'; " + + "var x10 = 'Hello Script';}"; + // Script size < Default minimum size for storing a compiled script class + final String code3 = "var code3; var x = 'Hello Script'; var x1 = 'Hello Script'; "; + final String codeCache = "build/nashorn_code_cache"; + final String oldUserDir = System.getProperty("user.dir"); + + public void checkCompiledScripts(DirectoryStream<Path> stream, int numberOfScripts) throws IOException { + for (Path file : stream) { + numberOfScripts--; + } + stream.close(); + assertEquals(numberOfScripts,0); + } + + @Test + public void pathHandlingTest() throws ScriptException, IOException { + System.setProperty("nashorn.persistent.code.cache", codeCache); + String[] options = new String[]{"--persistent-code-cache"}; + NashornScriptEngineFactory fac = new NashornScriptEngineFactory(); + ScriptEngine e = fac.getScriptEngine(options); + Path expectedCodeCachePath = FileSystems.getDefault().getPath(oldUserDir + File.separator + codeCache); + Path actualCodeCachePath = FileSystems.getDefault().getPath(System.getProperty( + "nashorn.persistent.code.cache")).toAbsolutePath(); + // Check that nashorn code cache is created in current working directory + assertEquals(actualCodeCachePath, expectedCodeCachePath); + // Check that code cache dir exists and it's not empty + File file = new File(actualCodeCachePath.toUri()); + assertFalse(!file.isDirectory(), "No code cache directory was created!"); + assertFalse(file.list().length == 0, "Code cache directory is empty!"); + } + + @Test + public void changeUserDirTest() throws ScriptException, IOException { + System.setProperty("nashorn.persistent.code.cache", codeCache); + String[] options = new String[]{"--persistent-code-cache"}; + NashornScriptEngineFactory fac = new NashornScriptEngineFactory(); + ScriptEngine e = fac.getScriptEngine(options); + Path codeCachePath = FileSystems.getDefault().getPath(System.getProperty( + "nashorn.persistent.code.cache")).toAbsolutePath(); + String newUserDir = "build/newUserDir"; + // Now changing current working directory + System.setProperty("user.dir", System.getProperty("user.dir") + File.separator + newUserDir); + // Check that a new compiled script is stored in exisitng code cache + e.eval(code1); + DirectoryStream<Path> stream = Files.newDirectoryStream(codeCachePath); + // Already one compiled script has been stored in the cache during initialization + checkCompiledScripts(stream, 2); + // Setting to default current working dir + System.setProperty("user.dir", oldUserDir); + } + + @Test + public void codeCacheTest() throws ScriptException, IOException { + System.setProperty("nashorn.persistent.code.cache", codeCache); + String[] options = new String[]{"--persistent-code-cache"}; + NashornScriptEngineFactory fac = new NashornScriptEngineFactory(); + ScriptEngine e = fac.getScriptEngine(options); + Path codeCachePath = FileSystems.getDefault().getPath(System.getProperty( + "nashorn.persistent.code.cache")).toAbsolutePath(); + e.eval(code1); + e.eval(code2); + e.eval(code3);// less than minimum size for storing + // Already one compiled script has been stored in the cache during initialization + // adding code1 and code2. + DirectoryStream<Path> stream = Files.newDirectoryStream(codeCachePath); + checkCompiledScripts(stream, 3); + } +}
--- a/test/src/jdk/nashorn/internal/runtime/ContextTest.java Mon Jun 02 18:51:26 2014 +0100 +++ b/test/src/jdk/nashorn/internal/runtime/ContextTest.java Tue Aug 19 23:57:20 2014 +0100 @@ -25,6 +25,7 @@ package jdk.nashorn.internal.runtime; +import static jdk.nashorn.internal.runtime.Source.sourceFor; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; @@ -107,7 +108,7 @@ } private Object eval(final Context cx, final String name, final String code) { - final Source source = new Source(name, code); + final Source source = sourceFor(name, code); final ScriptObject global = Context.getGlobal(); final ScriptFunction func = cx.compileScript(source, global); return func != null ? ScriptRuntime.apply(func, global) : null;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/src/jdk/nashorn/internal/runtime/NoPersistenceCachingTest.java Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2014, 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.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import static org.testng.Assert.fail; +import org.testng.annotations.Test; + +import javax.script.ScriptContext; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineFactory; +import javax.script.ScriptEngineManager; +import javax.script.SimpleScriptContext; +import jdk.nashorn.api.scripting.NashornScriptEngineFactory; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeTest; + +/** + * @test + * @bug 8037378 + * @summary Sanity tests for no persistence caching + * @run testng/othervm jdk.nashorn.internal.runtime.NoPersistenceCachingTest + */ +public class NoPersistenceCachingTest { + + private ScriptEngine engine; + private ScriptContext context1, context2, context3; + private ByteArrayOutputStream stderr; + private PrintStream prevStderr; + + @BeforeTest + public void setupTest() { + stderr = new ByteArrayOutputStream(); + prevStderr = System.err; + System.setErr(new PrintStream(stderr)); + NashornScriptEngineFactory nashornFactory = null; + ScriptEngineManager sm = new ScriptEngineManager(); + for (ScriptEngineFactory fac : sm.getEngineFactories()) { + if (fac instanceof NashornScriptEngineFactory) { + nashornFactory = (NashornScriptEngineFactory) fac; + break; + } + } + if (nashornFactory == null) { + fail("Cannot find nashorn factory!"); + } + String[] options = new String[]{"--log=compiler:finest"}; + engine = nashornFactory.getScriptEngine(options); + context1 = engine.getContext(); + context2 = new SimpleScriptContext(); + context2.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE); + context3 = new SimpleScriptContext(); + context3.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE); + } + + @AfterTest + public void setErrTest() { + System.setErr(prevStderr); + } + + public void runTest(int numberOfContext, String expectedOutputPattern, + int expectedPatternOccurrence) { + + try { + switch (numberOfContext) { + case 2: + String scriptTwoContexts = "print('HelloTwoContexts')"; + engine.eval(scriptTwoContexts, context1); + engine.eval(scriptTwoContexts, context2); + break; + case 3: + String scriptThreeContexts = "print('HelloThreeContexts')"; + engine.eval(scriptThreeContexts, context1); + engine.eval(scriptThreeContexts, context2); + engine.eval(scriptThreeContexts, context3); + break; + } + } catch (final Exception se) { + se.printStackTrace(); + fail(se.getMessage()); + } + Pattern deoptimizing = Pattern.compile(expectedOutputPattern); + Matcher matcher = deoptimizing.matcher(stderr.toString()); + int matches = 0; + while (matcher.find()) { + matches++; + } + if (matches != expectedPatternOccurrence) { + fail("Number of cache hit is not correct, expected: " + + expectedPatternOccurrence + " and found: " + matches + "\n" + + stderr); + } + stderr.reset(); + } + + private static String getCodeCachePattern() { + return ("\\[compiler\\]\\sCode\\scache\\shit\\sfor\\s<eval>\\savoiding\\srecompile."); + } + + @Test + public void twoContextTest() { + runTest(2, getCodeCachePattern(), 1); + + } + + @Test + public void threeContextTest() { + runTest(3, getCodeCachePattern(), 2); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/src/jdk/nashorn/internal/runtime/SourceTest.java Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2010, 2014, 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 jdk.nashorn.api.scripting.URLReader; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.URL; +import java.util.Arrays; + +import static jdk.nashorn.internal.runtime.Source.sourceFor; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; + +/** + * Tests different Source representations. + */ +public class SourceTest { + + final private static String SOURCE_NAME = "source.js"; + final private static String SOURCE_STRING = "var x = 1;"; + final private static char[] SOURCE_CHARS = SOURCE_STRING.toCharArray(); + final private static String RESOURCE_PATH = "resources/load_test.js"; + final private static File SOURCE_FILE = new File("build/test/classes/jdk/nashorn/internal/runtime/" + RESOURCE_PATH); + final private static URL SOURCE_URL = SourceTest.class.getResource(RESOURCE_PATH); + + + @Test + public void testStringSource() { + testSources(sourceFor(SOURCE_NAME, SOURCE_STRING), sourceFor(SOURCE_NAME, SOURCE_STRING)); + testSources(sourceFor(SOURCE_NAME, SOURCE_STRING), sourceFor(SOURCE_NAME, SOURCE_CHARS)); + } + + @Test + public void testCharArraySource() { + testSources(sourceFor(SOURCE_NAME, SOURCE_CHARS), sourceFor(SOURCE_NAME, SOURCE_CHARS)); + testSources(sourceFor(SOURCE_NAME, SOURCE_CHARS), sourceFor(SOURCE_NAME, SOURCE_STRING)); + } + + @Test + public void testURLSource() { + try { + testSources(sourceFor(SOURCE_NAME, SOURCE_URL), sourceFor(SOURCE_NAME, SOURCE_URL)); + testSources(sourceFor(SOURCE_NAME, SOURCE_URL), sourceFor(SOURCE_NAME, new URLReader(SOURCE_URL))); + + } catch (final IOException e) { + fail(e.toString()); + } + } + + @Test + public void testURLReaderSource() { + try { + System.err.println(SourceTest.class.getResource("")); + testSources(sourceFor(SOURCE_NAME, new URLReader(SOURCE_URL)), sourceFor(SOURCE_NAME, new URLReader(SOURCE_URL))); + testSources(sourceFor(SOURCE_NAME, new URLReader(SOURCE_URL)), sourceFor(SOURCE_NAME, SOURCE_URL)); + } catch (final IOException e) { + fail(e.toString()); + } + } + + @Test + public void testReaderSource() { + try { + testSources(sourceFor(SOURCE_NAME, getReader(RESOURCE_PATH)), sourceFor(SOURCE_NAME, getReader(RESOURCE_PATH))); + } catch (final IOException e) { + fail(e.toString()); + } + } + + @Test + public void testFileSource() { + try { + testSources(sourceFor(SOURCE_NAME, SOURCE_FILE), sourceFor(SOURCE_NAME, SOURCE_FILE)); + } catch (final IOException e) { + fail(e.toString()); + } + } + + private Reader getReader(final String path) { + return new InputStreamReader(SourceTest.class.getResourceAsStream(path)); + } + + private void testSources(final Source source1, final Source source2) { + final char[] chars1 = source1.getContent(); + final char[] chars2 = source2.getContent(); + final String str1 = source1.getString(); + final String str2 = source2.getString(); + assertTrue(Arrays.equals(chars1, chars2)); + assertEquals(str1, str2); + assertEquals(source1.hashCode(), source2.hashCode()); + assertTrue(source1.equals(source2)); + // Test for immutability + Arrays.fill(source1.getContent(), (char)0); + Arrays.fill(source2.getContent(), (char)1); + assertTrue(Arrays.equals(source1.getContent(), str1.toCharArray())); + assertTrue(Arrays.equals(source1.getContent(), chars1)); + assertTrue(Arrays.equals(source1.getContent(), source2.getContent())); + } +}
--- a/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java Mon Jun 02 18:51:26 2014 +0100 +++ b/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java Tue Aug 19 23:57:20 2014 +0100 @@ -220,4 +220,19 @@ // bar should be visible in default context assertTrue(e.eval("typeof bar").equals("function")); } + + + @Test public void nashornSwallowsConstKeyword() throws Exception { + final NashornScriptEngineFactory f = new NashornScriptEngineFactory(); + final String[] args = new String[] { "--const-as-var" }; + final ScriptEngine engine = f.getScriptEngine(args); + + final Object ret = engine.eval("" + + "(function() {\n" + + " const x = 10;\n" + + " return x;\n" + + "})();" + ); + assertEquals(ret, 10, "Parsed and executed OK"); + } }
--- a/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java Mon Jun 02 18:51:26 2014 +0100 +++ b/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java Tue Aug 19 23:57:20 2014 +0100 @@ -25,6 +25,7 @@ package jdk.nashorn.internal.test.framework; +import static jdk.nashorn.internal.runtime.Source.sourceFor; import static jdk.nashorn.tools.Shell.COMPILATION_ERROR; import static jdk.nashorn.tools.Shell.RUNTIME_ERROR; import static jdk.nashorn.tools.Shell.SUCCESS; @@ -39,7 +40,6 @@ import jdk.nashorn.internal.runtime.ErrorManager; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptRuntime; -import jdk.nashorn.internal.runtime.Source; import jdk.nashorn.internal.runtime.options.Options; /** @@ -125,7 +125,7 @@ continue; } final File file = new File(fileName); - ScriptFunction script = context.compileScript(new Source(fileName, file.toURI().toURL()), global); + ScriptFunction script = context.compileScript(sourceFor(fileName, file.toURI().toURL()), global); if (script == null || errors.getNumberOfErrors() != 0) { return COMPILATION_ERROR;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/src/jdk/nashorn/test/models/IntFloatOverloadSelection.java Tue Aug 19 23:57:20 2014 +0100 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, 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.test.models; + +public class IntFloatOverloadSelection { + + public static String overloadedMethod(int i) { + return "int"; + } + + public static String overloadedMethod(float f) { + return "float"; + } +}
--- a/test/src/jdk/nashorn/test/models/SourceHelper.java Mon Jun 02 18:51:26 2014 +0100 +++ b/test/src/jdk/nashorn/test/models/SourceHelper.java Tue Aug 19 23:57:20 2014 +0100 @@ -46,7 +46,7 @@ } public static String readFully(final URL url) throws IOException { - return new Source(url.toString(), url).getString(); + return Source.sourceFor(url.toString(), url).getString(); } public static String readFully(final Reader reader) throws IOException {