Mercurial > hg > openjdk > jdk9 > nashorn
changeset 868:f44ec6545b9a
Merge
line wrap: on
line diff
--- a/.hgtags Wed May 28 13:58:46 2014 +0200 +++ b/.hgtags Wed May 28 16:53:43 2014 +0200 @@ -237,3 +237,13 @@ 65347535840f045f2cd4341d7466c51009b1b06f jdk9-b01 b3517e51f40477f10db8bc30a557aa0ea712c274 jdk9-b02 832f89ff25d903c45cfc994553f1ade8821a4398 jdk9-b03 +3f6ef92cd7823372c45e79125adba4cbf1c9f7b2 jdk9-b04 +2a1cac93c33317d828d4a5b81239204a9927cc4a jdk9-b05 +1f75bcbe74e315470dc0b75b7d5bcd209e287c39 jdk9-b06 +9a34d2a0a5bdaf0bf0d81d6fe6324aa0cfb35bfe jdk9-b07 +4764920fd81d631915b13ba03b5d962ab14a50c4 jdk9-b08 +27f6ea87dcbd52c4b59e34a9f18d5b3321d53fa7 jdk9-b09 +0eaa55c7abe5d96023a4b38a326f411209c43f49 jdk9-b10 +4d60c3292e14aac90dc3b8232496ba4af4254cc3 jdk9-b11 +282e9a675e079cc84dbfaa4c10050f08397faab0 jdk9-b12 +be4580ae56e2ef0ce521d3f840753eaa83cacf33 jdk9-b13
--- a/README Wed May 28 13:58:46 2014 +0200 +++ b/README Wed May 28 16:53:43 2014 +0200 @@ -81,13 +81,13 @@ After that, you can run the tests using: cd make - ant test + ant clean test You can also run the ECMA-262 test suite with Nashorn. In order to do that, you will need to get a copy of it and put it in test/script/external/test262 directory. A convenient way to do it is: - hg clone http://hg.ecmascript.org/tests/test262/ test/script/external/test262 + git clone https://github.com/tc39/test262 test/script/external/test262 Alternatively, you can check it out elsewhere and make test/script/external/test262 a symbolic link to that directory. After @@ -95,6 +95,11 @@ cd nashorn~jdk8/nashorn/make ant test262 + +Ant target to get/update external test suites: + + ant externals + ant update-externals These tests take time, so we have a parallelized runner for them that takes advantage of all processor cores on the computer:
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java Wed May 28 13:58:46 2014 +0200 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java Wed May 28 16:53:43 2014 +0200 @@ -22,40 +22,62 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - package jdk.nashorn.internal.tools.nasgen; import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_ARRAY_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTOBJECT_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.STRING_DESC; import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Type; import jdk.nashorn.internal.objects.annotations.Where; +import jdk.nashorn.internal.runtime.ScriptObject; /** * Details about a Java method or field annotated with any of the field/method * annotations from the jdk.nashorn.internal.objects.annotations package. */ public final class MemberInfo implements Cloneable { + // class loader of this class + private static ClassLoader myLoader = MemberInfo.class.getClassLoader(); + /** * The different kinds of available class annotations */ public static enum Kind { - /** This is a script class */ + + /** + * This is a script class + */ SCRIPT_CLASS, - /** This is a constructor */ + /** + * This is a constructor + */ CONSTRUCTOR, - /** This is a function */ + /** + * This is a function + */ FUNCTION, - /** This is a getter */ + /** + * This is a getter + */ GETTER, - /** This is a setter */ + /** + * This is a setter + */ SETTER, - /** This is a property */ + /** + * This is a property + */ PROPERTY, - /** This is a specialized version of a function */ + /** + * This is a specialized version of a function + */ SPECIALIZED_FUNCTION, - /** This is a specialized version of a constructor */ + /** + * This is a specialized version of a constructor + */ SPECIALIZED_CONSTRUCTOR } @@ -194,6 +216,7 @@ /** * Check whether this MemberInfo is a getter that resides in the instance + * * @return true if instance setter */ boolean isInstanceSetter() { @@ -245,92 +268,200 @@ } void verify() { - if (kind == Kind.CONSTRUCTOR) { - final Type returnType = Type.getReturnType(javaDesc); - if (! returnType.toString().equals(OBJECT_DESC)) { - error("return value should be of Object type, found " + returnType); - } - final Type[] argTypes = Type.getArgumentTypes(javaDesc); - if (argTypes.length < 2) { - error("constructor methods should have at least 2 args"); - } - if (! argTypes[0].equals(Type.BOOLEAN_TYPE)) { - error("first argument should be of boolean type, found " + argTypes[0]); - } - if (! argTypes[1].toString().equals(OBJECT_DESC)) { - error("second argument should be of Object type, found " + argTypes[0]); - } + switch (kind) { + case CONSTRUCTOR: { + final Type returnType = Type.getReturnType(javaDesc); + if (!isJSObjectType(returnType)) { + error("return value of a @Constructor method should be of Object type, found " + returnType); + } + final Type[] argTypes = Type.getArgumentTypes(javaDesc); + if (argTypes.length < 2) { + error("@Constructor methods should have at least 2 args"); + } + if (!argTypes[0].equals(Type.BOOLEAN_TYPE)) { + error("first argument of a @Constructor method should be of boolean type, found " + argTypes[0]); + } + if (!isJavaLangObject(argTypes[1])) { + error("second argument of a @Constructor method should be of Object type, found " + argTypes[0]); + } - if (argTypes.length > 2) { - for (int i = 2; i < argTypes.length - 1; i++) { - if (! argTypes[i].toString().equals(OBJECT_DESC)) { - error(i + "'th argument should be of Object type, found " + argTypes[i]); + if (argTypes.length > 2) { + for (int i = 2; i < argTypes.length - 1; i++) { + if (!isJavaLangObject(argTypes[i])) { + error(i + "'th argument of a @Constructor method should be of Object type, found " + argTypes[i]); + } + } + + final String lastArgTypeDesc = argTypes[argTypes.length - 1].getDescriptor(); + final boolean isVarArg = lastArgTypeDesc.equals(OBJECT_ARRAY_DESC); + if (!lastArgTypeDesc.equals(OBJECT_DESC) && !isVarArg) { + error("last argument of a @Constructor method is neither Object nor Object[] type: " + lastArgTypeDesc); + } + + if (isVarArg && argTypes.length > 3) { + error("vararg of a @Constructor method has more than 3 arguments"); } } - - final String lastArgType = argTypes[argTypes.length - 1].toString(); - final boolean isVarArg = lastArgType.equals(OBJECT_ARRAY_DESC); - if (!lastArgType.equals(OBJECT_DESC) && !isVarArg) { - error("last argument is neither Object nor Object[] type: " + lastArgType); + } + break; + case SPECIALIZED_CONSTRUCTOR: { + final Type returnType = Type.getReturnType(javaDesc); + if (!isJSObjectType(returnType)) { + error("return value of a @SpecializedConstructor method should be a valid JS type, found " + returnType); } - - if (isVarArg && argTypes.length > 3) { - error("vararg constructor has more than 3 arguments"); + final Type[] argTypes = Type.getArgumentTypes(javaDesc); + for (int i = 0; i < argTypes.length; i++) { + if (!isValidJSType(argTypes[i])) { + error(i + "'th argument of a @SpecializedConstructor method is not valid JS type, found " + argTypes[i]); + } } } - } else if (kind == Kind.FUNCTION) { - final Type[] argTypes = Type.getArgumentTypes(javaDesc); - if (argTypes.length < 1) { - error("function methods should have at least 1 arg"); - } - if (! argTypes[0].toString().equals(OBJECT_DESC)) { - error("first argument should be of Object type, found " + argTypes[0]); - } - - if (argTypes.length > 1) { - for (int i = 1; i < argTypes.length - 1; i++) { - if (! argTypes[i].toString().equals(OBJECT_DESC)) { - error(i + "'th argument should be of Object type, found " + argTypes[i]); - } + break; + case FUNCTION: { + final Type returnType = Type.getReturnType(javaDesc); + if (!(isValidJSType(returnType) || Type.VOID_TYPE == returnType)) { + error("return value of a @Function method should be a valid JS type, found " + returnType); } - - final String lastArgType = argTypes[argTypes.length - 1].toString(); - final boolean isVarArg = lastArgType.equals(OBJECT_ARRAY_DESC); - if (!lastArgType.equals(OBJECT_DESC) && !isVarArg) { - error("last argument is neither Object nor Object[] type: " + lastArgType); + final Type[] argTypes = Type.getArgumentTypes(javaDesc); + if (argTypes.length < 1) { + error("@Function methods should have at least 1 arg"); + } + if (!isJavaLangObject(argTypes[0])) { + error("first argument of a @Function method should be of Object type, found " + argTypes[0]); } - if (isVarArg && argTypes.length > 2) { - error("vararg function has more than 2 arguments"); + if (argTypes.length > 1) { + for (int i = 1; i < argTypes.length - 1; i++) { + if (!isJavaLangObject(argTypes[i])) { + error(i + "'th argument of a @Function method should be of Object type, found " + argTypes[i]); + } + } + + final String lastArgTypeDesc = argTypes[argTypes.length - 1].getDescriptor(); + final boolean isVarArg = lastArgTypeDesc.equals(OBJECT_ARRAY_DESC); + if (!lastArgTypeDesc.equals(OBJECT_DESC) && !isVarArg) { + error("last argument of a @Function method is neither Object nor Object[] type: " + lastArgTypeDesc); + } + + if (isVarArg && argTypes.length > 2) { + error("vararg @Function method has more than 2 arguments"); + } + } + } + break; + case SPECIALIZED_FUNCTION: { + final Type returnType = Type.getReturnType(javaDesc); + if (!(isValidJSType(returnType) || Type.VOID_TYPE == returnType)) { + error("return value of a @SpecializedFunction method should be a valid JS type, found " + returnType); + } + final Type[] argTypes = Type.getArgumentTypes(javaDesc); + for (int i = 0; i < argTypes.length; i++) { + if (!isValidJSType(argTypes[i])) { + error(i + "'th argument of a @SpecializedFunction method is not valid JS type, found " + argTypes[i]); + } } } - } else if (kind == Kind.GETTER) { - final Type[] argTypes = Type.getArgumentTypes(javaDesc); - if (argTypes.length != 1) { - error("getter methods should have one argument"); - } - if (! argTypes[0].toString().equals(OBJECT_DESC)) { - error("first argument of getter should be of Object type, found: " + argTypes[0]); - } - if (Type.getReturnType(javaDesc).equals(Type.VOID_TYPE)) { - error("return type of getter should not be void"); + break; + case GETTER: { + final Type[] argTypes = Type.getArgumentTypes(javaDesc); + if (argTypes.length != 1) { + error("@Getter methods should have one argument"); + } + if (!isJavaLangObject(argTypes[0])) { + error("first argument of a @Getter method should be of Object type, found: " + argTypes[0]); + } + + if (Type.getReturnType(javaDesc).equals(Type.VOID_TYPE)) { + error("return type of getter should not be void"); + } } - } else if (kind == Kind.SETTER) { - final Type[] argTypes = Type.getArgumentTypes(javaDesc); - if (argTypes.length != 2) { - error("setter methods should have two arguments"); + break; + case SETTER: { + final Type[] argTypes = Type.getArgumentTypes(javaDesc); + if (argTypes.length != 2) { + error("@Setter methods should have two arguments"); + } + if (!isJavaLangObject(argTypes[0])) { + error("first argument of a @Setter method should be of Object type, found: " + argTypes[0]); + } + if (!Type.getReturnType(javaDesc).toString().equals("V")) { + error("return type of of a @Setter method should be void, found: " + Type.getReturnType(javaDesc)); + } } - if (! argTypes[0].toString().equals(OBJECT_DESC)) { - error("first argument of setter should be of Object type, found: " + argTypes[0]); - } - if (!Type.getReturnType(javaDesc).toString().equals("V")) { - error("return type of setter should be void, found: " + Type.getReturnType(javaDesc)); + break; + case PROPERTY: { + if (where == Where.CONSTRUCTOR) { + if (isStatic()) { + if (!isFinal()) { + error("static Where.CONSTRUCTOR @Property should be final"); + } + + if (!isJSPrimitiveType(Type.getType(javaDesc))) { + error("static Where.CONSTRUCTOR @Property should be a JS primitive"); + } + } + } else if (where == Where.PROTOTYPE) { + if (isStatic()) { + if (!isFinal()) { + error("static Where.PROTOTYPE @Property should be final"); + } + + if (!isJSPrimitiveType(Type.getType(javaDesc))) { + error("static Where.PROTOTYPE @Property should be a JS primitive"); + } + } + } } } } + private static boolean isValidJSType(final Type type) { + return isJSPrimitiveType(type) || isJSObjectType(type); + } + + private static boolean isJSPrimitiveType(final Type type) { + switch (type.getSort()) { + case Type.BOOLEAN: + case Type.INT: + case Type.LONG: + case Type.DOUBLE: + return true; + default: + return false; + } + } + + private static boolean isJSObjectType(final Type type) { + return isJavaLangObject(type) || isJavaLangString(type) || isScriptObject(type); + } + + private static boolean isJavaLangObject(final Type type) { + return type.getDescriptor().equals(OBJECT_DESC); + } + + private static boolean isJavaLangString(final Type type) { + return type.getDescriptor().equals(STRING_DESC); + } + + private static boolean isScriptObject(final Type type) { + if (type.getDescriptor().equals(SCRIPTOBJECT_DESC)) { + return true; + } + + if (type.getSort() == Type.OBJECT) { + try { + final Class clazz = Class.forName(type.getClassName(), false, myLoader); + return ScriptObject.class.isAssignableFrom(clazz); + } catch (final ClassNotFoundException cnfe) { + return false; + } + } + + return false; + } + private void error(final String msg) { - throw new RuntimeException(javaName + javaDesc + " : " + msg); + throw new RuntimeException(javaName + " of type " + javaDesc + " : " + msg); } /**
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java Wed May 28 13:58:46 2014 +0200 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java Wed May 28 16:53:43 2014 +0200 @@ -60,6 +60,8 @@ static final String METHODHANDLE_TYPE = TYPE_METHODHANDLE.getInternalName(); static final String OBJECT_TYPE = TYPE_OBJECT.getInternalName(); static final String OBJECT_DESC = TYPE_OBJECT.getDescriptor(); + static final String STRING_TYPE = TYPE_STRING.getInternalName(); + static final String STRING_DESC = TYPE_STRING.getDescriptor(); static final String OBJECT_ARRAY_DESC = Type.getDescriptor(Object[].class); static final String ARRAYLIST_TYPE = TYPE_ARRAYLIST.getInternalName(); static final String COLLECTION_TYPE = TYPE_COLLECTION.getInternalName(); @@ -128,6 +130,7 @@ // ScriptObject static final String SCRIPTOBJECT_TYPE = TYPE_SCRIPTOBJECT.getInternalName(); + static final String SCRIPTOBJECT_DESC = TYPE_SCRIPTOBJECT.getDescriptor(); static final String SCRIPTOBJECT_INIT_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_PROPERTYMAP); static final String GETTER_PREFIX = "G$";
--- a/make/build.xml Wed May 28 13:58:46 2014 +0200 +++ b/make/build.xml Wed May 28 16:53:43 2014 +0200 @@ -42,6 +42,9 @@ <condition property="hg.executable" value="/usr/local/bin/hg" else="hg"> <available file="/usr/local/bin/hg"/> </condition> + <condition property="git.executable" value="/usr/local/bin/git" else="git"> + <available file="/usr/local/bin/git"/> + </condition> <!-- check if JDK already has ASM classes --> <available property="asm.available" classname="jdk.internal.org.objectweb.asm.Type"/> <!-- check if testng.jar is avaiable --> @@ -355,8 +358,30 @@ <include name="**/runtime/regexp/*Test.class"/> <include name="**/runtime/regexp/joni/*Test.class"/> <include name="**/framework/*Test.class"/> + <exclude name="jdk/nashorn/internal/runtime/CodeStoreAndPathTest.class"/> </fileset> + <fileset id="test.nosecurity.classes" dir="${build.test.classes.dir}"> + <include name="**/framework/ScriptTest.class"/> + </fileset> + + <fileset id="test.nooptimistic.classes" dir="${build.test.classes.dir}"> + <include name="jdk/nashorn/internal/runtime/CodeStoreAndPathTest.class"/> + </fileset> + + <testng outputdir="${build.nooptimistic.test.results.dir}" classfilesetref="test.nooptimistic.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}"/> + <sysproperty key="nashorn.optimistic" value="false"/> + <propertyset> + <propertyref prefix="nashorn."/> + </propertyset> + <classpath> + <pathelement path="${run.test.classpath}"/> + </classpath> + </testng> + <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}"/> @@ -373,6 +398,22 @@ <pathelement path="${run.test.classpath}"/> </classpath> </testng> + + <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> <target name="check-jemmy.jfx.testng" unless="jemmy.jfx.testng.available"> @@ -515,18 +556,17 @@ <!-- test262 test suite --> <target name="get-test262" depends="init" unless="${test-sys-prop.external.test262}"> - <!-- clone test262 mercurial repo --> - <exec executable="${hg.executable}"> + <!-- clone test262 git repo --> + <exec executable="${git.executable}"> <arg value="clone"/> - <arg value="http://hg.ecmascript.org/tests/test262"/> + <arg value="https://github.com/tc39/test262"/> <arg value="${test.external.dir}/test262"/> </exec> </target> <target name="update-test262" depends="init" if="${test-sys-prop.external.test262}"> - <!-- update test262 mercurial repo --> - <exec executable="${hg.executable}" dir="${test.external.dir}/test262"> + <!-- update test262 git repo --> + <exec executable="${git.executable}" dir="${test.external.dir}/test262"> <arg value="pull"/> - <arg value="-u"/> </exec> </target>
--- a/make/project.properties Wed May 28 13:58:46 2014 +0200 +++ b/make/project.properties Wed May 28 16:53:43 2014 +0200 @@ -60,6 +60,8 @@ # test results directory build.test.results.dir=${build.dir}/test/reports +build.nosecurity.test.results.dir=${build.dir}/test/nosecurity/reports +build.nooptimistic.test.results.dir=${build.dir}/test/nooptimistic/reports # This directory is removed when the project is cleaned: dist.dir=dist @@ -114,6 +116,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 @@ -132,8 +135,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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/BufferArray.java Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 13:58:46 2014 +0200 +++ b/samples/counters.js Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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/fileline.js Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 13:58:46 2014 +0200 +++ b/samples/letter.js Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 13:58:46 2014 +0200 +++ b/samples/shell.js Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 13:58:46 2014 +0200 +++ b/samples/test.js Wed May 28 16:53:43 2014 +0200 @@ -30,4 +30,3 @@ */ print("Hello World"); -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/uniform_random.js Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 13:58:46 2014 +0200 +++ b/samples/uniq.js Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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());
--- a/src/jdk/internal/dynalink/beans/AccessibleMembersLookup.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/internal/dynalink/beans/AccessibleMembersLookup.java Wed May 28 16:53:43 2014 +0200 @@ -211,7 +211,8 @@ if(!CheckRestrictedPackage.isRestrictedClass(clazz)) { searchSuperTypes = false; for(Method method: clazz.getMethods()) { - if(instance != Modifier.isStatic(method.getModifiers())) { + final boolean isStatic = Modifier.isStatic(method.getModifiers()); + if(instance != isStatic) { final MethodSignature sig = new MethodSignature(method); if(!methods.containsKey(sig)) { final Class<?> declaringClass = method.getDeclaringClass(); @@ -228,7 +229,10 @@ //generate the said synthetic delegators. searchSuperTypes = true; } else { - methods.put(sig, method); + // don't allow inherited static + if (!isStatic || clazz == declaringClass) { + methods.put(sig, method); + } } } } @@ -245,7 +249,8 @@ searchSuperTypes = true; } - if(searchSuperTypes) { + // don't need to search super types for static methods + if(instance && searchSuperTypes) { // If we reach here, the class is either not public, or it is in a restricted package. Alternatively, it is // public, but some of its methods claim that their declaring class is non-public. We'll try superclasses // and implemented interfaces then looking for public ones.
--- a/src/jdk/internal/dynalink/beans/BeanLinker.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/internal/dynalink/beans/BeanLinker.java Wed May 28 16:53:43 2014 +0200 @@ -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/internal/dynalink/beans/FacetIntrospector.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/internal/dynalink/beans/FacetIntrospector.java Wed May 28 16:53:43 2014 +0200 @@ -136,7 +136,13 @@ final Field[] fields = clazz.getFields(); final Collection<Field> cfields = new ArrayList<>(fields.length); for(Field field: fields) { - if(instance != Modifier.isStatic(field.getModifiers()) && isAccessible(field)) { + final boolean isStatic = Modifier.isStatic(field.getModifiers()); + if(isStatic && clazz != field.getDeclaringClass()) { + // ignore inherited static fields + continue; + } + + if(instance != isStatic && isAccessible(field)) { cfields.add(field); } }
--- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Wed May 28 16:53:43 2014 +0200 @@ -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; @@ -125,20 +123,20 @@ } } - // load engine.js and return content as a char[] - private static char[] loadEngineJSSource() { + // load engine.js + 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/internal/codegen/CodeGenerator.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java Wed May 28 16:53:43 2014 +0200 @@ -1826,7 +1826,7 @@ * doing an on-demand ("just-in-time") compilation, then we aren't generating code for inner functions. */ private boolean compileOutermostOnly() { - return RecompilableScriptFunctionData.LAZY_COMPILATION || compiler.isOnDemandCompilation(); + return compiler.isOnDemandCompilation() || compiler.getScriptEnvironment()._lazy_compilation; } @Override @@ -2296,7 +2296,10 @@ if (value == null) { gettersSetters.add(propertyNode); - } 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; }
--- a/src/jdk/nashorn/internal/codegen/CompilationPhase.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/codegen/CompilationPhase.java Wed May 28 16:53:43 2014 +0200 @@ -25,8 +25,6 @@ package jdk.nashorn.internal.codegen; -import static jdk.nashorn.internal.codegen.CompilerConstants.CONSTANTS; -import static jdk.nashorn.internal.codegen.CompilerConstants.SOURCE; import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.BUILTINS_TRANSFORMED; import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.BYTECODE_GENERATED; import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.BYTECODE_INSTALLED; @@ -42,10 +40,6 @@ import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote; import java.io.PrintWriter; -import java.lang.reflect.Field; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.util.ArrayList; import java.util.EnumSet; import java.util.HashMap; @@ -53,22 +47,21 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; -import java.util.Map.Entry; -import java.util.function.Consumer; - import jdk.nashorn.internal.codegen.Compiler.CompilationPhases; import jdk.nashorn.internal.ir.FunctionNode; +import jdk.nashorn.internal.ir.FunctionNode.CompilationState; import jdk.nashorn.internal.ir.LexicalContext; -import jdk.nashorn.internal.ir.FunctionNode.CompilationState; +import jdk.nashorn.internal.ir.LiteralNode; import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit; -import jdk.nashorn.internal.ir.LiteralNode; import jdk.nashorn.internal.ir.Node; import jdk.nashorn.internal.ir.SplitNode; import jdk.nashorn.internal.ir.debug.ASTWriter; import jdk.nashorn.internal.ir.debug.PrintVisitor; import jdk.nashorn.internal.ir.visitor.NodeVisitor; +import jdk.nashorn.internal.runtime.CodeInstaller; import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData; import jdk.nashorn.internal.runtime.ScriptEnvironment; import jdk.nashorn.internal.runtime.logging.DebugLogger; @@ -496,13 +489,17 @@ Class<?> rootClass = null; long length = 0L; - for (final Entry<String, byte[]> entry : compiler.getBytecode().entrySet()) { + final CodeInstaller<?> codeInstaller = compiler.getCodeInstaller(); + + final Map<String, byte[]> bytecode = compiler.getBytecode(); + + for (final Entry<String, byte[]> entry : bytecode.entrySet()) { final String className = entry.getKey(); //assert !first || className.equals(compiler.getFirstCompileUnit().getUnitClassName()) : "first=" + first + " className=" + className + " != " + compiler.getFirstCompileUnit().getUnitClassName(); final byte[] code = entry.getValue(); length += code.length; - final Class<?> clazz = compiler.getCodeInstaller().install(Compiler.binaryName(className), code); + final Class<?> clazz = codeInstaller.install(className, code); if (first) { rootClass = clazz; first = false; @@ -514,46 +511,12 @@ throw new CompilationException("Internal compiler error: root class not found!"); } - // do these in parallel, this significantly reduces class installation overhead - // however - it still means that every thread needs a separate doPrivileged final Object[] constants = compiler.getConstantData().toArray(); - installedClasses.entrySet().parallelStream().forEach( - new Consumer<Entry<String, Class<?>>>() { - @Override - public void accept(final Entry<String, Class<?>> entry) { - try { - AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { - @Override - public Void run() { - try { - final Class<?> clazz = entry.getValue(); - log.fine("Initializing source for ", clazz); - //use reflection to write source and constants table to installed classes - final Field sourceField = clazz.getDeclaredField(SOURCE.symbolName()); - sourceField.setAccessible(true); - sourceField.set(null, compiler.getSource()); - - log.fine("Initializing constants for ", clazz); - final Field constantsField = clazz.getDeclaredField(CONSTANTS.symbolName()); - constantsField.setAccessible(true); - constantsField.set(null, constants); - } catch (final IllegalAccessException | NoSuchFieldException e) { - throw new RuntimeException(e); - } - return null; - } - }); - } catch (final PrivilegedActionException e) { - throw new RuntimeException(e); - } - } - }); - log.fine("Done"); - log.fine("Done"); + codeInstaller.initialize(installedClasses.values(), compiler.getSource(), constants); // index recompilable script function datas in the constant pool final Map<RecompilableScriptFunctionData, RecompilableScriptFunctionData> rfns = new IdentityHashMap<>(); - for (final Object constant: compiler.getConstantData().getConstants()) { + for (final Object constant: constants) { if (constant instanceof RecompilableScriptFunctionData) { final RecompilableScriptFunctionData rfn = (RecompilableScriptFunctionData)constant; rfns.put(rfn, rfn); @@ -566,6 +529,10 @@ unit.initializeFunctionsCode(); } + if (!compiler.isOnDemandCompilation()) { + codeInstaller.storeCompiledScript(compiler.getSource(), compiler.getFirstCompileUnit().getUnitClassName(), bytecode, constants); + } + // remove installed bytecode from table in case compiler is reused for (final String className : installedClasses.keySet()) { log.fine("Removing installed class ", quote(className), " from bytecode table...");
--- a/src/jdk/nashorn/internal/codegen/CompileUnit.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/codegen/CompileUnit.java Wed May 28 16:53:43 2014 +0200 @@ -29,7 +29,6 @@ import java.util.LinkedHashSet; import java.util.Set; import java.util.TreeSet; - import jdk.nashorn.internal.ir.FunctionNode; import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData; @@ -38,7 +37,7 @@ */ public final class CompileUnit implements Comparable<CompileUnit> { /** Current class name */ - private String className; + private final String className; /** Current class generator */ private ClassEmitter classEmitter; @@ -173,14 +172,6 @@ return className; } - /** - * Reset the class name for this compile unit - * @param className new class name - */ - public void setUnitClassName(final String className) { - this.className = className; - } - private static String shortName(final String name) { return name.lastIndexOf('/') == -1 ? name : name.substring(name.lastIndexOf('/') + 1); }
--- a/src/jdk/nashorn/internal/codegen/ConstantData.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/codegen/ConstantData.java Wed May 28 16:53:43 2014 +0200 @@ -27,12 +27,9 @@ import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; - import jdk.nashorn.internal.runtime.Property; import jdk.nashorn.internal.runtime.PropertyMap; @@ -209,10 +206,6 @@ return index; } - Collection<Object> getConstants() { - return Collections.unmodifiableList(constants); - } - Object[] toArray() { return constants.toArray(); }
--- a/src/jdk/nashorn/internal/codegen/FindScopeDepths.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/codegen/FindScopeDepths.java Wed May 28 16:53:43 2014 +0200 @@ -210,9 +210,8 @@ // Generate the object class and property map in case this function is ever used as constructor final int fieldCount = getPaddedFieldCount(newFunctionNode.getThisProperties()); final String allocatorClassName = Compiler.binaryName(getClassName(fieldCount)); - final PropertyMap allocatorMap = PropertyMap.newMap(null, 0, fieldCount, 0); + final PropertyMap allocatorMap = PropertyMap.newMap(null, allocatorClassName, 0, fieldCount, 0); final RecompilableScriptFunctionData data = new RecompilableScriptFunctionData( - compiler.getContext(), newFunctionNode, compiler.getCodeInstaller(), allocatorClassName,
--- a/src/jdk/nashorn/internal/codegen/MapCreator.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/codegen/MapCreator.java Wed May 28 16:53:43 2014 +0200 @@ -90,7 +90,7 @@ } } - return PropertyMap.newMap(properties, fieldCount, fieldMaximum, 0); + return PropertyMap.newMap(properties, structure.getName(), fieldCount, fieldMaximum, 0); } PropertyMap makeSpillMap(final boolean hasArguments) { @@ -113,7 +113,7 @@ } } - return PropertyMap.newMap(properties, 0, 0, spillIndex); + return PropertyMap.newMap(properties, structure.getName(), 0, 0, spillIndex); } /**
--- a/src/jdk/nashorn/internal/ir/BinaryNode.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/ir/BinaryNode.java Wed May 28 16:53:43 2014 +0200 @@ -242,6 +242,12 @@ case INSTANCEOF: { return Type.BOOLEAN; } + case COMMALEFT: { + return lhs.getType(localVariableTypes); + } + case COMMARIGHT: { + return rhs.getType(localVariableTypes); + } default: if (isComparison()) { return Type.BOOLEAN;
--- a/src/jdk/nashorn/internal/ir/debug/JSONWriter.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/ir/debug/JSONWriter.java Wed May 28 16:53:43 2014 +0200 @@ -25,6 +25,8 @@ package jdk.nashorn.internal.ir.debug; +import static jdk.nashorn.internal.runtime.Source.sourceFor; + import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -88,7 +90,7 @@ * @return JSON string representation of AST of the supplied code */ public static String parse(final Context context, final String code, final String name, final boolean includeLoc) { - final Parser parser = new Parser(context.getEnv(), new Source(name, code), new Context.ThrowErrorManager(), context.getEnv()._strict, context.getLogger(Parser.class)); + final Parser parser = new Parser(context.getEnv(), sourceFor(name, code), new Context.ThrowErrorManager(), context.getEnv()._strict, context.getLogger(Parser.class)); final JSONWriter jsonWriter = new JSONWriter(includeLoc); try { final FunctionNode functionNode = parser.parse(); //symbol name is ":program", default
--- a/src/jdk/nashorn/internal/lookup/Lookup.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/lookup/Lookup.java Wed May 28 16:53:43 2014 +0200 @@ -146,6 +146,9 @@ if (from == int.class) { //fallthru } else if (from == long.class) { + if (to == int.class) { + return MH.filterArguments(mh, n, JSType.TO_INT32_L.methodHandle()); + } //fallthru } else if (from == double.class) { if (to == int.class) { @@ -169,7 +172,7 @@ } //use a standard cast - we don't need to check JavaScript special cases - return MH.explicitCastArguments(mh, mh.type().changeParameterType(2, to)); + return MH.explicitCastArguments(mh, mh.type().changeParameterType(n, from)); } /** @@ -189,6 +192,9 @@ if (retType == int.class) { //fallthru } else if (retType == long.class) { + if (type == int.class) { + return MH.filterReturnValue(mh, JSType.TO_INT32_L.methodHandle()); + } //fallthru } else if (retType == double.class) { if (type == int.class) {
--- a/src/jdk/nashorn/internal/objects/ArrayBufferView.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/ArrayBufferView.java Wed May 28 16:53:43 2014 +0200 @@ -95,7 +95,7 @@ } @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE) - public static Object byteOffset(final Object self) { + public static int byteOffset(final Object self) { return ((ArrayBufferView)self).byteOffset; } @@ -244,7 +244,7 @@ return (int)(length & Integer.MAX_VALUE); } - protected static Object subarrayImpl(final Object self, final Object begin0, final Object end0) { + protected static ScriptObject subarrayImpl(final Object self, final Object begin0, final Object end0) { final ArrayBufferView arrayView = (ArrayBufferView)self; final int byteOffset = arrayView.byteOffset; final int bytesPerElement = arrayView.bytesPerElement();
--- a/src/jdk/nashorn/internal/objects/Global.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/Global.java Wed May 28 16:53:43 2014 +0200 @@ -1973,6 +1973,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", ScriptObject.GETPROTO); + final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", ScriptObject.SETPROTOCHECK); + 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/NativeArray.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeArray.java Wed May 28 16:53:43 2014 +0200 @@ -29,6 +29,7 @@ import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import static jdk.nashorn.internal.runtime.PropertyDescriptor.VALUE; import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE; +import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex; import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.arrayLikeIterator; import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.reverseArrayLikeIterator; @@ -387,6 +388,27 @@ } /** + * Spec. mentions use of [[DefineOwnProperty]] for indexed properties in + * certain places (eg. Array.prototype.map, filter). We can not use ScriptObject.set + * method in such cases. This is because set method uses inherited setters (if any) + * from any object in proto chain such as Array.prototype, Object.prototype. + * This method directly sets a particular element value in the current object. + * + * @param index key for property + * @param value value to define + */ + @Override + public final void defineOwnProperty(final int index, final Object value) { + assert isValidArrayIndex(index) : "invalid array index"; + final long longIndex = ArrayIndex.toLongIndex(index); + if (longIndex >= getArray().length()) { + // make array big enough to hold.. + setArray(getArray().ensure(longIndex)); + } + setArray(getArray().set(index, value, false)); + } + + /** * Return the array contents upcasted as an ObjectArray, regardless of * representation * @@ -404,8 +426,8 @@ * @return true if argument is an array */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) - public static Object isArray(final Object self, final Object arg) { - return isArray(arg) || arg instanceof JSObject && ((JSObject)arg).isArray(); + public static boolean isArray(final Object self, final Object arg) { + return isArray(arg) || (arg instanceof JSObject && ((JSObject)arg).isArray()); } /** @@ -516,7 +538,7 @@ * @return locale specific string representation for array */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object toLocaleString(final Object self) { + public static String toLocaleString(final Object self) { final StringBuilder sb = new StringBuilder(); final Iterator<Object> iter = arrayLikeIterator(self, true); @@ -562,7 +584,7 @@ * @return the new NativeArray */ @Constructor(arity = 1) - public static Object construct(final boolean newObj, final Object self, final Object... args) { + public static NativeArray construct(final boolean newObj, final Object self, final Object... args) { switch (args.length) { case 0: return new NativeArray(0); @@ -615,7 +637,7 @@ * @return the new NativeArray */ @SpecializedConstructor - public static Object construct(final boolean newObj, final Object self) { + public static NativeArray construct(final boolean newObj, final Object self) { return new NativeArray(0); } @@ -645,7 +667,7 @@ * @return the new NativeArray */ @SpecializedConstructor - public static Object construct(final boolean newObj, final Object self, final int length) { + public static NativeArray construct(final boolean newObj, final Object self, final int length) { if (length >= 0) { return new NativeArray(length); } @@ -664,7 +686,7 @@ * @return the new NativeArray */ @SpecializedConstructor - public static Object construct(final boolean newObj, final Object self, final long length) { + public static NativeArray construct(final boolean newObj, final Object self, final long length) { if (length >= 0L && length <= JSType.MAX_UINT) { return new NativeArray(length); } @@ -683,7 +705,7 @@ * @return the new NativeArray */ @SpecializedConstructor - public static Object construct(final boolean newObj, final Object self, final double length) { + public static NativeArray construct(final boolean newObj, final Object self, final double length) { final long uint32length = JSType.toUint32(length); if (uint32length == length) { @@ -701,7 +723,7 @@ * @return resulting NativeArray */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) - public static Object concat(final Object self, final Object... args) { + public static NativeArray concat(final Object self, final Object... args) { final ArrayList<Object> list = new ArrayList<>(); concatToList(list, Global.toObject(self)); @@ -748,7 +770,7 @@ * @return string representation after join */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object join(final Object self, final Object separator) { + public static String join(final Object self, final Object separator) { final StringBuilder sb = new StringBuilder(); final Iterator<Object> iter = arrayLikeIterator(self, true); final String sep = separator == ScriptRuntime.UNDEFINED ? "," : JSType.toString(separator); @@ -1095,7 +1117,7 @@ * @return sorted array */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object sort(final Object self, final Object comparefn) { + public static ScriptObject sort(final Object self, final Object comparefn) { try { final ScriptObject sobj = (ScriptObject) self; final long len = JSType.toUint32(sobj.getLength()); @@ -1299,7 +1321,7 @@ * @return index of element, or -1 if not found */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) - public static Object indexOf(final Object self, final Object searchElement, final Object fromIndex) { + public static long indexOf(final Object self, final Object searchElement, final Object fromIndex) { try { final ScriptObject sobj = (ScriptObject)Global.toObject(self); final long len = JSType.toUint32(sobj.getLength()); @@ -1335,7 +1357,7 @@ * @return index of element, or -1 if not found */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) - public static Object lastIndexOf(final Object self, final Object... args) { + public static long lastIndexOf(final Object self, final Object... args) { try { final ScriptObject sobj = (ScriptObject)Global.toObject(self); final long len = JSType.toUint32(sobj.getLength()); @@ -1370,7 +1392,7 @@ * @return true if callback function return true for every element in the array, false otherwise */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) - public static Object every(final Object self, final Object callbackfn, final Object thisArg) { + public static boolean every(final Object self, final Object callbackfn, final Object thisArg) { return applyEvery(Global.toObject(self), callbackfn, thisArg); } @@ -1394,7 +1416,7 @@ * @return true if callback function returned true for any element in the array, false otherwise */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) - public static Object some(final Object self, final Object callbackfn, final Object thisArg) { + public static boolean some(final Object self, final Object callbackfn, final Object thisArg) { return new IteratorAction<Boolean>(Global.toObject(self), callbackfn, thisArg, false) { private final MethodHandle someInvoker = getSOME_CALLBACK_INVOKER(); @@ -1435,7 +1457,7 @@ * @return array with elements transformed by map function */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) - public static Object map(final Object self, final Object callbackfn, final Object thisArg) { + public static NativeArray map(final Object self, final Object callbackfn, final Object thisArg) { return new IteratorAction<NativeArray>(Global.toObject(self), callbackfn, thisArg, null) { private final MethodHandle mapInvoker = getMAP_CALLBACK_INVOKER(); @@ -1464,7 +1486,7 @@ * @return filtered array */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) - public static Object filter(final Object self, final Object callbackfn, final Object thisArg) { + public static NativeArray filter(final Object self, final Object callbackfn, final Object thisArg) { return new IteratorAction<NativeArray>(Global.toObject(self), callbackfn, thisArg, new NativeArray()) { private long to = 0; private final MethodHandle filterInvoker = getFILTER_CALLBACK_INVOKER();
--- a/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java Wed May 28 16:53:43 2014 +0200 @@ -95,7 +95,7 @@ * @return new NativeArrayBuffer */ @Constructor(arity = 1) - public static Object constructor(final boolean newObj, final Object self, final Object... args) { + public static NativeArrayBuffer constructor(final boolean newObj, final Object self, final Object... args) { if (!newObj) { throw typeError("constructor.requires.new", "ArrayBuffer"); } @@ -145,7 +145,7 @@ * @return new array buffer, sliced */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object slice(final Object self, final Object begin0, final Object end0) { + public static NativeArrayBuffer slice(final Object self, final Object begin0, final Object end0) { final NativeArrayBuffer arrayBuffer = (NativeArrayBuffer)self; final int byteLength = arrayBuffer.getByteLength(); final int begin = adjustIndex(JSType.toInt32(begin0), byteLength); @@ -213,11 +213,9 @@ ByteBuffer getBuffer(final int offset) { return (ByteBuffer)nb.duplicate().position(offset); -// return ByteBuffer.wrap(buffer, offset, buffer.length - offset); } ByteBuffer getBuffer(final int offset, final int length) { return (ByteBuffer)getBuffer(offset).limit(length); - //return ByteBuffer.wrap(buffer, offset, length); } }
--- a/src/jdk/nashorn/internal/objects/NativeBoolean.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeBoolean.java Wed May 28 16:53:43 2014 +0200 @@ -110,7 +110,7 @@ * @return string representation of this boolean */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object toString(final Object self) { + public static String toString(final Object self) { return getBoolean(self).toString(); } @@ -121,7 +121,7 @@ * @return value of this boolean */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object valueOf(final Object self) { + public static boolean valueOf(final Object self) { return getBoolean(self); }
--- a/src/jdk/nashorn/internal/objects/NativeDataView.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeDataView.java Wed May 28 16:53:43 2014 +0200 @@ -131,7 +131,7 @@ * @return newly constructed DataView object */ @Constructor(arity = 1) - public static Object constructor(final boolean newObj, final Object self, final Object... args) { + public static NativeDataView constructor(final boolean newObj, final Object self, final Object... args) { if (args.length == 0 || !(args[0] instanceof NativeArrayBuffer)) { throw typeError("not.an.arraybuffer.in.dataview"); } @@ -157,7 +157,7 @@ * @return newly constructed DataView object */ @SpecializedConstructor - public static Object constructor(final boolean newObj, final Object self, final Object arrBuf, final int offset) { + public static NativeDataView constructor(final boolean newObj, final Object self, final Object arrBuf, final int offset) { if (!(arrBuf instanceof NativeArrayBuffer)) { throw typeError("not.an.arraybuffer.in.dataview"); } @@ -175,7 +175,7 @@ * @return newly constructed DataView object */ @SpecializedConstructor - public static Object constructor(final boolean newObj, final Object self, final Object arrBuf, final int offset, final int length) { + public static NativeDataView constructor(final boolean newObj, final Object self, final Object arrBuf, final int offset, final int length) { if (!(arrBuf instanceof NativeArrayBuffer)) { throw typeError("not.an.arraybuffer.in.dataview"); } @@ -434,7 +434,7 @@ @SpecializedFunction public static long getUint32(final Object self, final int byteOffset) { try { - return 0xFFFFFFFFL & getBuffer(self, false).getInt(JSType.toInt32(byteOffset)); + return JSType.MAX_UINT & getBuffer(self, false).getInt(JSType.toInt32(byteOffset)); } catch (final IllegalArgumentException iae) { throw rangeError(iae, "dataview.offset"); } @@ -451,7 +451,7 @@ @SpecializedFunction public static long getUint32(final Object self, final int byteOffset, final boolean littleEndian) { try { - return 0xFFFFFFFFL & getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset)); + return JSType.MAX_UINT & getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset)); } catch (final IllegalArgumentException iae) { throw rangeError(iae, "dataview.offset"); }
--- a/src/jdk/nashorn/internal/objects/NativeDate.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeDate.java Wed May 28 16:53:43 2014 +0200 @@ -226,7 +226,7 @@ * @return Date interpreted from the string, or NaN for illegal values */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) - public static Object parse(final Object self, final Object string) { + public static double parse(final Object self, final Object string) { return parseDateString(JSType.toString(string)); } @@ -238,7 +238,7 @@ * @return a time clip according to the ECMA specification */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 7, where = Where.CONSTRUCTOR) - public static Object UTC(final Object self, final Object... args) { + public static double UTC(final Object self, final Object... args) { final NativeDate nd = new NativeDate(0); final double[] d = convertCtorArgs(args); final double time = d == null ? Double.NaN : timeClip(makeDate(d)); @@ -253,8 +253,8 @@ * @return a Date that points to the current moment in time */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) - public static Object now(final Object self) { - return (double)System.currentTimeMillis(); + public static long now(final Object self) { + return System.currentTimeMillis(); } /** @@ -264,7 +264,7 @@ * @return string value that represents the Date in the current time zone */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object toString(final Object self) { + public static String toString(final Object self) { return toStringImpl(self, FORMAT_DATE_TIME); } @@ -275,7 +275,7 @@ * @return string value with the "date" part of the Date in the current time zone */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object toDateString(final Object self) { + public static String toDateString(final Object self) { return toStringImpl(self, FORMAT_DATE); } @@ -286,7 +286,7 @@ * @return string value with "time" part of Date in the current time zone */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object toTimeString(final Object self) { + public static String toTimeString(final Object self) { return toStringImpl(self, FORMAT_TIME); } @@ -297,7 +297,7 @@ * @return string value that represents the Data in the current time zone and locale */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object toLocaleString(final Object self) { + public static String toLocaleString(final Object self) { return toStringImpl(self, FORMAT_LOCAL_DATE_TIME); } @@ -308,7 +308,7 @@ * @return string value with the "date" part of the Date in the current time zone and locale */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object toLocaleDateString(final Object self) { + public static String toLocaleDateString(final Object self) { return toStringImpl(self, FORMAT_LOCAL_DATE); } @@ -319,7 +319,7 @@ * @return string value with the "time" part of Date in the current time zone and locale */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object toLocaleTimeString(final Object self) { + public static String toLocaleTimeString(final Object self) { return toStringImpl(self, FORMAT_LOCAL_TIME); } @@ -330,7 +330,7 @@ * @return valueOf - a number which is this time value */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object valueOf(final Object self) { + public static double valueOf(final Object self) { final NativeDate nd = getNativeDate(self); return (nd != null) ? nd.getTime() : Double.NaN; } @@ -342,7 +342,7 @@ * @return time */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object getTime(final Object self) { + public static double getTime(final Object self) { final NativeDate nd = getNativeDate(self); return (nd != null) ? nd.getTime() : Double.NaN; } @@ -365,7 +365,7 @@ * @return UTC full year */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object getUTCFullYear(final Object self) { + public static double getUTCFullYear(final Object self) { return getUTCField(self, YEAR); } @@ -376,7 +376,7 @@ * @return year */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object getYear(final Object self) { + public static double getYear(final Object self) { final NativeDate nd = getNativeDate(self); return (nd != null && nd.isValidDate()) ? (yearFromTime(nd.getLocalTime()) - 1900) : Double.NaN; } @@ -388,7 +388,7 @@ * @return month */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object getMonth(final Object self) { + public static double getMonth(final Object self) { return getField(self, MONTH); } @@ -399,7 +399,7 @@ * @return UTC month */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object getUTCMonth(final Object self) { + public static double getUTCMonth(final Object self) { return getUTCField(self, MONTH); } @@ -410,7 +410,7 @@ * @return date */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object getDate(final Object self) { + public static double getDate(final Object self) { return getField(self, DAY); } @@ -421,7 +421,7 @@ * @return UTC Date */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object getUTCDate(final Object self) { + public static double getUTCDate(final Object self) { return getUTCField(self, DAY); } @@ -432,7 +432,7 @@ * @return day */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object getDay(final Object self) { + public static double getDay(final Object self) { final NativeDate nd = getNativeDate(self); return (nd != null && nd.isValidDate()) ? weekDay(nd.getLocalTime()) : Double.NaN; } @@ -444,7 +444,7 @@ * @return UTC day */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object getUTCDay(final Object self) { + public static double getUTCDay(final Object self) { final NativeDate nd = getNativeDate(self); return (nd != null && nd.isValidDate()) ? weekDay(nd.getTime()) : Double.NaN; } @@ -456,7 +456,7 @@ * @return hours */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object getHours(final Object self) { + public static double getHours(final Object self) { return getField(self, HOUR); } @@ -467,7 +467,7 @@ * @return UTC hours */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object getUTCHours(final Object self) { + public static double getUTCHours(final Object self) { return getUTCField(self, HOUR); } @@ -478,7 +478,7 @@ * @return minutes */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object getMinutes(final Object self) { + public static double getMinutes(final Object self) { return getField(self, MINUTE); } @@ -489,7 +489,7 @@ * @return UTC minutes */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object getUTCMinutes(final Object self) { + public static double getUTCMinutes(final Object self) { return getUTCField(self, MINUTE); } @@ -500,7 +500,7 @@ * @return seconds */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object getSeconds(final Object self) { + public static double getSeconds(final Object self) { return getField(self, SECOND); } @@ -511,7 +511,7 @@ * @return UTC seconds */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object getUTCSeconds(final Object self) { + public static double getUTCSeconds(final Object self) { return getUTCField(self, SECOND); } @@ -522,7 +522,7 @@ * @return milliseconds */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object getMilliseconds(final Object self) { + public static double getMilliseconds(final Object self) { return getField(self, MILLISECOND); } @@ -533,7 +533,7 @@ * @return UTC milliseconds */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object getUTCMilliseconds(final Object self) { + public static double getUTCMilliseconds(final Object self) { return getUTCField(self, MILLISECOND); } @@ -544,7 +544,7 @@ * @return time zone offset or NaN if N/A */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object getTimezoneOffset(final Object self) { + public static double getTimezoneOffset(final Object self) { final NativeDate nd = getNativeDate(self); if (nd != null && nd.isValidDate()) { final long msec = (long) nd.getTime(); @@ -561,7 +561,7 @@ * @return time */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object setTime(final Object self, final Object time) { + public static double setTime(final Object self, final Object time) { final NativeDate nd = getNativeDate(self); final double num = timeClip(JSType.toNumber(time)); nd.setTime(num); @@ -576,7 +576,7 @@ * @return time */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) - public static Object setMilliseconds(final Object self, final Object... args) { + public static double setMilliseconds(final Object self, final Object... args) { final NativeDate nd = getNativeDate(self); setFields(nd, MILLISECOND, args, true); return nd.getTime(); @@ -590,7 +590,7 @@ * @return time */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) - public static Object setUTCMilliseconds(final Object self, final Object... args) { + public static double setUTCMilliseconds(final Object self, final Object... args) { final NativeDate nd = getNativeDate(self); setFields(nd, MILLISECOND, args, false); return nd.getTime(); @@ -604,7 +604,7 @@ * @return time */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2) - public static Object setSeconds(final Object self, final Object... args) { + public static double setSeconds(final Object self, final Object... args) { final NativeDate nd = getNativeDate(self); setFields(nd, SECOND, args, true); return nd.getTime(); @@ -618,7 +618,7 @@ * @return time */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2) - public static Object setUTCSeconds(final Object self, final Object... args) { + public static double setUTCSeconds(final Object self, final Object... args) { final NativeDate nd = getNativeDate(self); setFields(nd, SECOND, args, false); return nd.getTime(); @@ -632,7 +632,7 @@ * @return time */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 3) - public static Object setMinutes(final Object self, final Object... args) { + public static double setMinutes(final Object self, final Object... args) { final NativeDate nd = getNativeDate(self); setFields(nd, MINUTE, args, true); return nd.getTime(); @@ -646,7 +646,7 @@ * @return time */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 3) - public static Object setUTCMinutes(final Object self, final Object... args) { + public static double setUTCMinutes(final Object self, final Object... args) { final NativeDate nd = getNativeDate(self); setFields(nd, MINUTE, args, false); return nd.getTime(); @@ -660,7 +660,7 @@ * @return time */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 4) - public static Object setHours(final Object self, final Object... args) { + public static double setHours(final Object self, final Object... args) { final NativeDate nd = getNativeDate(self); setFields(nd, HOUR, args, true); return nd.getTime(); @@ -674,7 +674,7 @@ * @return time */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 4) - public static Object setUTCHours(final Object self, final Object... args) { + public static double setUTCHours(final Object self, final Object... args) { final NativeDate nd = getNativeDate(self); setFields(nd, HOUR, args, false); return nd.getTime(); @@ -688,7 +688,7 @@ * @return time */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) - public static Object setDate(final Object self, final Object... args) { + public static double setDate(final Object self, final Object... args) { final NativeDate nd = getNativeDate(self); setFields(nd, DAY, args, true); return nd.getTime(); @@ -702,7 +702,7 @@ * @return time */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) - public static Object setUTCDate(final Object self, final Object... args) { + public static double setUTCDate(final Object self, final Object... args) { final NativeDate nd = getNativeDate(self); setFields(nd, DAY, args, false); return nd.getTime(); @@ -716,7 +716,7 @@ * @return time */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2) - public static Object setMonth(final Object self, final Object... args) { + public static double setMonth(final Object self, final Object... args) { final NativeDate nd = getNativeDate(self); setFields(nd, MONTH, args, true); return nd.getTime(); @@ -730,7 +730,7 @@ * @return time */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2) - public static Object setUTCMonth(final Object self, final Object... args) { + public static double setUTCMonth(final Object self, final Object... args) { final NativeDate nd = ensureNativeDate(self); setFields(nd, MONTH, args, false); return nd.getTime(); @@ -744,7 +744,7 @@ * @return time */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 3) - public static Object setFullYear(final Object self, final Object... args) { + public static double setFullYear(final Object self, final Object... args) { final NativeDate nd = ensureNativeDate(self); if (nd.isValidDate()) { setFields(nd, YEAR, args, true); @@ -767,7 +767,7 @@ * @return time */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 3) - public static Object setUTCFullYear(final Object self, final Object... args) { + public static double setUTCFullYear(final Object self, final Object... args) { final NativeDate nd = ensureNativeDate(self); if (nd.isValidDate()) { setFields(nd, YEAR, args, false); @@ -786,7 +786,7 @@ * @return NativeDate */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object setYear(final Object self, final Object year) { + public static double setYear(final Object self, final Object year) { final NativeDate nd = getNativeDate(self); if (isNaN(nd.getTime())) { nd.setTime(utc(0, nd.getTimeZone())); @@ -813,7 +813,7 @@ * @return string representation of date */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object toUTCString(final Object self) { + public static String toUTCString(final Object self) { return toGMTStringImpl(self); } @@ -826,7 +826,7 @@ * @return string representation of date */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object toGMTString(final Object self) { + public static String toGMTString(final Object self) { return toGMTStringImpl(self); } @@ -837,7 +837,7 @@ * @return string representation of date */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object toISOString(final Object self) { + public static String toISOString(final Object self) { return toISOStringImpl(self); } @@ -1282,14 +1282,14 @@ } } - private static Object getField(final Object self, final int field) { + private static double getField(final Object self, final int field) { final NativeDate nd = getNativeDate(self); - return (nd != null && nd.isValidDate()) ? valueFromTime(field, nd.getLocalTime()) : Double.NaN; + return (nd != null && nd.isValidDate()) ? (double)valueFromTime(field, nd.getLocalTime()) : Double.NaN; } - private static Object getUTCField(final Object self, final int field) { + private static double getUTCField(final Object self, final int field) { final NativeDate nd = getNativeDate(self); - return (nd != null && nd.isValidDate()) ? valueFromTime(field, nd.getTime()) : Double.NaN; + return (nd != null && nd.isValidDate()) ? (double)valueFromTime(field, nd.getTime()) : Double.NaN; } private static void setFields(final NativeDate nd, final int fieldId, final Object[] args, final boolean local) { @@ -1344,5 +1344,4 @@ private TimeZone getTimeZone() { return timezone; } - }
--- a/src/jdk/nashorn/internal/objects/NativeDebug.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeDebug.java Wed May 28 16:53:43 2014 +0200 @@ -30,7 +30,6 @@ import java.io.PrintWriter; import java.util.LinkedList; import java.util.Objects; - import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Function; import jdk.nashorn.internal.objects.annotations.ScriptClass; @@ -105,7 +104,7 @@ * @return true if reference identity */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) - public static Object identical(final Object self, final Object obj1, final Object obj2) { + public static boolean identical(final Object self, final Object obj1, final Object obj2) { return obj1 == obj2; } @@ -158,7 +157,7 @@ * @return return {@link Object#equals(Object)} for objects. */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) - public static Object equals(final Object self, final Object obj1, final Object obj2) { + public static boolean equals(final Object self, final Object obj1, final Object obj2) { return Objects.equals(obj1, obj2); } @@ -170,7 +169,7 @@ * @return Java string representation of {@code obj} */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) - public static Object toJavaString(final Object self, final Object obj) { + public static String toJavaString(final Object self, final Object obj) { return Objects.toString(obj); } @@ -182,7 +181,7 @@ * @return string representation */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) - public static Object toIdentString(final Object self, final Object obj) { + public static String toIdentString(final Object self, final Object obj) { if (obj == null) { return "null"; } @@ -199,7 +198,7 @@ * @return listener count */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) - public static Object getListenerCount(final Object self, final Object obj) { + public static int getListenerCount(final Object self, final Object obj) { return (obj instanceof ScriptObject) ? PropertyListeners.getListenerCount((ScriptObject) obj) : 0; } @@ -334,7 +333,7 @@ * @return array of events */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) - public static RuntimeEvent<?>[] getRuntimeEvents(final Object self) { + public static Object getRuntimeEvents(final Object self) { final LinkedList<RuntimeEvent<?>> q = getEventQueue(self); return q.toArray(new RuntimeEvent<?>[q.size()]); } @@ -345,7 +344,7 @@ * @return the freshest event, null if queue is empty */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) - public static RuntimeEvent<?> getLastRuntimeEvent(final Object self) { + public static Object getLastRuntimeEvent(final Object self) { final LinkedList<RuntimeEvent<?>> q = getEventQueue(self); return q.isEmpty() ? null : q.getLast(); }
--- a/src/jdk/nashorn/internal/objects/NativeError.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeError.java Wed May 28 16:53:43 2014 +0200 @@ -126,7 +126,7 @@ * @return NativeError instance */ @Constructor - public static Object constructor(final boolean newObj, final Object self, final Object msg) { + public static NativeError constructor(final boolean newObj, final Object self, final Object msg) { return new NativeError(msg); }
--- a/src/jdk/nashorn/internal/objects/NativeEvalError.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeEvalError.java Wed May 28 16:53:43 2014 +0200 @@ -98,7 +98,7 @@ * @return new EvalError */ @Constructor(name = "EvalError") - public static Object constructor(final boolean newObj, final Object self, final Object msg) { + public static NativeEvalError constructor(final boolean newObj, final Object self, final Object msg) { return new NativeEvalError(msg); } }
--- a/src/jdk/nashorn/internal/objects/NativeFloat32Array.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeFloat32Array.java Wed May 28 16:53:43 2014 +0200 @@ -31,7 +31,6 @@ import java.lang.invoke.MethodHandles; import java.nio.ByteBuffer; import java.nio.FloatBuffer; - import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; import jdk.nashorn.internal.objects.annotations.Function; @@ -174,8 +173,8 @@ * @return new typed array */ @Constructor(arity = 1) - public static Object constructor(final boolean newObj, final Object self, final Object... args) { - return constructorImpl(newObj, args, FACTORY); + public static NativeFloat32Array constructor(final boolean newObj, final Object self, final Object... args) { + return (NativeFloat32Array)constructorImpl(newObj, args, FACTORY); } NativeFloat32Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) { @@ -225,8 +224,8 @@ * @return sub array */ @Function(attributes = Attribute.NOT_ENUMERABLE) - protected static Object subarray(final Object self, final Object begin, final Object end) { - return ArrayBufferView.subarrayImpl(self, begin, end); + protected static NativeFloat32Array subarray(final Object self, final Object begin, final Object end) { + return (NativeFloat32Array)ArrayBufferView.subarrayImpl(self, begin, end); } @Override
--- a/src/jdk/nashorn/internal/objects/NativeFloat64Array.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeFloat64Array.java Wed May 28 16:53:43 2014 +0200 @@ -31,7 +31,6 @@ import java.lang.invoke.MethodHandles; import java.nio.ByteBuffer; import java.nio.DoubleBuffer; - import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; import jdk.nashorn.internal.objects.annotations.Function; @@ -174,8 +173,8 @@ * @return new typed array */ @Constructor(arity = 1) - public static Object constructor(final boolean newObj, final Object self, final Object... args) { - return constructorImpl(newObj, args, FACTORY); + public static NativeFloat64Array constructor(final boolean newObj, final Object self, final Object... args) { + return (NativeFloat64Array)constructorImpl(newObj, args, FACTORY); } NativeFloat64Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) { @@ -225,8 +224,8 @@ * @return sub array */ @Function(attributes = Attribute.NOT_ENUMERABLE) - protected static Object subarray(final Object self, final Object begin, final Object end) { - return ArrayBufferView.subarrayImpl(self, begin, end); + protected static NativeFloat64Array subarray(final Object self, final Object begin, final Object end) { + return (NativeFloat64Array)ArrayBufferView.subarrayImpl(self, begin, end); } @Override
--- a/src/jdk/nashorn/internal/objects/NativeFunction.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeFunction.java Wed May 28 16:53:43 2014 +0200 @@ -28,6 +28,7 @@ import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError; 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.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -47,7 +48,6 @@ import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; -import jdk.nashorn.internal.runtime.Source; /** * ECMA 15.3 Function Objects @@ -78,7 +78,7 @@ * @return string representation of Function */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object toString(final Object self) { + public static String toString(final Object self) { if (!(self instanceof ScriptFunction)) { throw typeError("not.a.function", ScriptRuntime.safeToString(self)); } @@ -204,7 +204,7 @@ * @return function with bound arguments */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) - public static Object bind(final Object self, final Object... args) { + public static ScriptFunction bind(final Object self, final Object... args) { if (!(self instanceof ScriptFunction)) { throw typeError("not.a.function", ScriptRuntime.safeToString(self)); } @@ -229,7 +229,7 @@ * @return source for function */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object toSource(final Object self) { + public static String toSource(final Object self) { if (!(self instanceof ScriptFunction)) { throw typeError("not.a.function", ScriptRuntime.safeToString(self)); } @@ -247,7 +247,7 @@ * @return new NativeFunction */ @Constructor(arity = 1) - public static Object function(final boolean newObj, final Object self, final Object... args) { + public static ScriptFunction function(final boolean newObj, final Object self, final Object... args) { final StringBuilder sb = new StringBuilder(); sb.append("(function ("); @@ -283,13 +283,11 @@ final Global global = Global.instance(); - return Global.directEval(global, sb.toString(), global, "<function>", global.isStrictContext()); + return (ScriptFunction)Global.directEval(global, sb.toString(), global, "<function>", global.isStrictContext()); } private static void checkFunctionParameters(final String params) { - final Source src = new Source("<function>", params); - final ScriptEnvironment env = Global.getEnv(); - final Parser parser = new Parser(env, src, new Context.ThrowErrorManager(), env._strict, null); + final Parser parser = getParser(params); try { parser.parseFormalParameterList(); } catch (final ParserException pe) { @@ -298,13 +296,16 @@ } private static void checkFunctionBody(final String funcBody) { - final Source src = new Source("<function>", funcBody); - final ScriptEnvironment env = Global.getEnv(); - final Parser parser = new Parser(env, src, new Context.ThrowErrorManager(), env._strict, null); + final Parser parser = getParser(funcBody); try { parser.parseFunctionBody(); } catch (final ParserException pe) { pe.throwAsEcmaException(); } } + + private static Parser getParser(final String sourceText) { + final ScriptEnvironment env = Global.getEnv(); + return new Parser(env, sourceFor("<function>", sourceText), new Context.ThrowErrorManager(), env._strict, null); + } }
--- a/src/jdk/nashorn/internal/objects/NativeInt16Array.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeInt16Array.java Wed May 28 16:53:43 2014 +0200 @@ -31,7 +31,6 @@ import java.lang.invoke.MethodHandles; import java.nio.ByteBuffer; import java.nio.ShortBuffer; - import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; import jdk.nashorn.internal.objects.annotations.Function; @@ -167,8 +166,8 @@ * @return new typed array */ @Constructor(arity = 1) - public static Object constructor(final boolean newObj, final Object self, final Object... args) { - return constructorImpl(newObj, args, FACTORY); + public static NativeInt16Array constructor(final boolean newObj, final Object self, final Object... args) { + return (NativeInt16Array)constructorImpl(newObj, args, FACTORY); } NativeInt16Array(final NativeArrayBuffer buffer, final int byteOffset, final int byteLength) { @@ -213,8 +212,8 @@ * @return sub array */ @Function(attributes = Attribute.NOT_ENUMERABLE) - protected static Object subarray(final Object self, final Object begin, final Object end) { - return ArrayBufferView.subarrayImpl(self, begin, end); + protected static NativeInt16Array subarray(final Object self, final Object begin, final Object end) { + return (NativeInt16Array)ArrayBufferView.subarrayImpl(self, begin, end); } @Override
--- a/src/jdk/nashorn/internal/objects/NativeInt32Array.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeInt32Array.java Wed May 28 16:53:43 2014 +0200 @@ -31,7 +31,6 @@ import java.lang.invoke.MethodHandles; import java.nio.ByteBuffer; import java.nio.IntBuffer; - import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; import jdk.nashorn.internal.objects.annotations.Function; @@ -165,8 +164,8 @@ * @return new typed array */ @Constructor(arity = 1) - public static Object constructor(final boolean newObj, final Object self, final Object... args) { - return constructorImpl(newObj, args, FACTORY); + public static NativeInt32Array constructor(final boolean newObj, final Object self, final Object... args) { + return (NativeInt32Array)constructorImpl(newObj, args, FACTORY); } NativeInt32Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) { @@ -211,8 +210,8 @@ * @return sub array */ @Function(attributes = Attribute.NOT_ENUMERABLE) - protected static Object subarray(final Object self, final Object begin, final Object end) { - return ArrayBufferView.subarrayImpl(self, begin, end); + protected static NativeInt32Array subarray(final Object self, final Object begin, final Object end) { + return (NativeInt32Array)ArrayBufferView.subarrayImpl(self, begin, end); } @Override
--- a/src/jdk/nashorn/internal/objects/NativeInt8Array.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeInt8Array.java Wed May 28 16:53:43 2014 +0200 @@ -30,7 +30,6 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.nio.ByteBuffer; - import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; import jdk.nashorn.internal.objects.annotations.Function; @@ -166,8 +165,8 @@ * @return new typed array */ @Constructor(arity = 1) - public static Object constructor(final boolean newObj, final Object self, final Object... args) { - return constructorImpl(newObj, args, FACTORY); + public static NativeInt8Array constructor(final boolean newObj, final Object self, final Object... args) { + return (NativeInt8Array)constructorImpl(newObj, args, FACTORY); } NativeInt8Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) { @@ -212,8 +211,8 @@ * @return sub array */ @Function(attributes = Attribute.NOT_ENUMERABLE) - protected static Object subarray(final Object self, final Object begin, final Object end) { - return ArrayBufferView.subarrayImpl(self, begin, end); + protected static NativeInt8Array subarray(final Object self, final Object begin, final Object end) { + return (NativeInt8Array)ArrayBufferView.subarrayImpl(self, begin, end); } @Override
--- a/src/jdk/nashorn/internal/objects/NativeJSAdapter.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeJSAdapter.java Wed May 28 16:53:43 2014 +0200 @@ -537,7 +537,7 @@ * @return new NativeJSAdapter */ @Constructor - public static Object construct(final boolean isNew, final Object self, final Object... args) { + public static NativeJSAdapter construct(final boolean isNew, final Object self, final Object... args) { Object proto = UNDEFINED; Object overrides = UNDEFINED; Object adaptee;
--- a/src/jdk/nashorn/internal/objects/NativeJava.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeJava.java Wed May 28 16:53:43 2014 +0200 @@ -75,7 +75,7 @@ * @see #type(Object, Object) */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) - public static Object isType(final Object self, final Object type) { + public static boolean isType(final Object self, final Object type) { return type instanceof StaticClass; } @@ -338,7 +338,7 @@ * null. */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) - public static Object from(final Object self, final Object objArray) { + public static NativeArray from(final Object self, final Object objArray) { if (objArray == null) { return null; } else if (objArray instanceof Collection) {
--- a/src/jdk/nashorn/internal/objects/NativeJavaImporter.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeJavaImporter.java Wed May 28 16:53:43 2014 +0200 @@ -89,7 +89,7 @@ * @return NativeJavaImporter instance */ @Constructor(arity = 1) - public static Object constructor(final boolean isNew, final Object self, final Object... args) { + public static NativeJavaImporter constructor(final boolean isNew, final Object self, final Object... args) { return new NativeJavaImporter(args); }
--- a/src/jdk/nashorn/internal/objects/NativeNumber.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeNumber.java Wed May 28 16:53:43 2014 +0200 @@ -156,7 +156,7 @@ * @return number in decimal fixed point notation */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object toFixed(final Object self, final Object fractionDigits) { + public static String toFixed(final Object self, final Object fractionDigits) { return toFixed(self, JSType.toInteger(fractionDigits)); } @@ -169,7 +169,7 @@ * @return number in decimal fixed point notation */ @SpecializedFunction - public static Object toFixed(final Object self, final int fractionDigits) { + public static String toFixed(final Object self, final int fractionDigits) { if (fractionDigits < 0 || fractionDigits > 20) { throw rangeError("invalid.fraction.digits", "toFixed"); } @@ -200,7 +200,7 @@ * @return number in decimal exponential notation */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object toExponential(final Object self, final Object fractionDigits) { + public static String toExponential(final Object self, final Object fractionDigits) { final double x = getNumberValue(self); final boolean trimZeros = fractionDigits == UNDEFINED; final int f = trimZeros ? 16 : JSType.toInteger(fractionDigits); @@ -228,7 +228,7 @@ * @return number in decimal exponentiation notation or decimal fixed notation depending on {@code precision} */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object toPrecision(final Object self, final Object precision) { + public static String toPrecision(final Object self, final Object precision) { final double x = getNumberValue(self); if (precision == UNDEFINED) { return JSType.toString(x); @@ -245,11 +245,11 @@ * @return number in decimal exponentiation notation or decimal fixed notation depending on {@code precision} */ @SpecializedFunction - public static Object toPrecision(Object self, final int precision) { + public static String toPrecision(Object self, final int precision) { return toPrecision(getNumberValue(self), precision); } - private static Object toPrecision(final double x, final int p) { + private static String toPrecision(final double x, final int p) { if (Double.isNaN(x)) { return "NaN"; } else if (Double.isInfinite(x)) { @@ -276,7 +276,7 @@ * @return string representation of this Number in the given radix */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object toString(final Object self, final Object radix) { + public static String toString(final Object self, final Object radix) { if (radix != UNDEFINED) { final int intRadix = JSType.toInteger(radix); if (intRadix != 10) { @@ -297,7 +297,7 @@ * @return localized string for this Number */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object toLocaleString(final Object self) { + public static String toLocaleString(final Object self) { return JSType.toString(getNumberValue(self)); } @@ -306,10 +306,10 @@ * ECMA 15.7.4.4 Number.prototype.valueOf ( ) * * @param self self reference - * @return boxed number value for this Number + * @return number value for this Number */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object valueOf(final Object self) { + public static double valueOf(final Object self) { return getNumberValue(self); }
--- a/src/jdk/nashorn/internal/objects/NativeObject.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeObject.java Wed May 28 16:53:43 2014 +0200 @@ -111,7 +111,7 @@ * @return the 'obj' object */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) - public static Object setIndexedPropertiesToExternalArrayData(final Object self, final Object obj, final Object buf) { + public static ScriptObject setIndexedPropertiesToExternalArrayData(final Object self, final Object obj, final Object buf) { Global.checkObject(obj); final ScriptObject sobj = (ScriptObject)obj; if (buf instanceof ByteBuffer) { @@ -203,7 +203,7 @@ * @return array of property names */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) - public static Object getOwnPropertyNames(final Object self, final Object obj) { + public static ScriptObject getOwnPropertyNames(final Object self, final Object obj) { if (obj instanceof ScriptObject) { return new NativeArray(((ScriptObject)obj).getOwnKeys(true)); } else if (obj instanceof ScriptObjectMirror) { @@ -222,7 +222,7 @@ * @return object created */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) - public static Object create(final Object self, final Object proto, final Object props) { + public static ScriptObject create(final Object self, final Object proto, final Object props) { if (proto != null) { Global.checkObject(proto); } @@ -248,9 +248,10 @@ * @return object */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) - public static Object defineProperty(final Object self, final Object obj, final Object prop, final Object attr) { - Global.checkObject(obj).defineOwnProperty(JSType.toString(prop), attr, true); - return obj; + public static ScriptObject defineProperty(final Object self, final Object obj, final Object prop, final Object attr) { + final ScriptObject sobj = Global.checkObject(obj); + sobj.defineOwnProperty(JSType.toString(prop), attr, true); + return sobj; } /** @@ -262,7 +263,7 @@ * @return object */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) - public static Object defineProperties(final Object self, final Object obj, final Object props) { + public static ScriptObject defineProperties(final Object self, final Object obj, final Object props) { final ScriptObject sobj = Global.checkObject(obj); final Object propsObj = Global.toObject(props); @@ -339,7 +340,7 @@ * @return true if sealed, false otherwise */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) - public static Object isSealed(final Object self, final Object obj) { + public static boolean isSealed(final Object self, final Object obj) { if (obj instanceof ScriptObject) { return ((ScriptObject)obj).isSealed(); } else if (obj instanceof ScriptObjectMirror) { @@ -357,7 +358,7 @@ * @return true if object is frozen, false otherwise */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) - public static Object isFrozen(final Object self, final Object obj) { + public static boolean isFrozen(final Object self, final Object obj) { if (obj instanceof ScriptObject) { return ((ScriptObject)obj).isFrozen(); } else if (obj instanceof ScriptObjectMirror) { @@ -375,7 +376,7 @@ * @return true if object is extensible, false otherwise */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) - public static Object isExtensible(final Object self, final Object obj) { + public static boolean isExtensible(final Object self, final Object obj) { if (obj instanceof ScriptObject) { return ((ScriptObject)obj).isExtensible(); } else if (obj instanceof ScriptObjectMirror) { @@ -393,7 +394,7 @@ * @return array of keys in object */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) - public static Object keys(final Object self, final Object obj) { + public static ScriptObject keys(final Object self, final Object obj) { if (obj instanceof ScriptObject) { final ScriptObject sobj = (ScriptObject)obj; return new NativeArray(sobj.getOwnKeys(false)); @@ -449,7 +450,7 @@ * @return ToString of object */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object toString(final Object self) { + public static String toString(final Object self) { return ScriptRuntime.builtinObjectToString(self); } @@ -502,7 +503,7 @@ * @return true if property exists in object */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object hasOwnProperty(final Object self, final Object v) { + public static boolean hasOwnProperty(final Object self, final Object v) { // Convert ScriptObjects to primitive with String.class hint // but no need to convert other primitives to string. final Object key = JSType.toPrimitive(v, String.class); @@ -519,7 +520,7 @@ * @return true if object is prototype of v */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object isPrototypeOf(final Object self, final Object v) { + public static boolean isPrototypeOf(final Object self, final Object v) { if (!(v instanceof ScriptObject)) { return false; } @@ -545,7 +546,7 @@ * @return true if property is enumerable */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object propertyIsEnumerable(final Object self, final Object v) { + public static boolean propertyIsEnumerable(final Object self, final Object v) { final String str = JSType.toString(v); final Object obj = Global.toObject(self);
--- a/src/jdk/nashorn/internal/objects/NativeRangeError.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeRangeError.java Wed May 28 16:53:43 2014 +0200 @@ -98,7 +98,7 @@ * @return new RangeError */ @Constructor(name = "RangeError") - public static Object constructor(final boolean newObj, final Object self, final Object msg) { + public static NativeRangeError constructor(final boolean newObj, final Object self, final Object msg) { return new NativeRangeError(msg); } }
--- a/src/jdk/nashorn/internal/objects/NativeReferenceError.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeReferenceError.java Wed May 28 16:53:43 2014 +0200 @@ -98,7 +98,7 @@ * @return new ReferenceError */ @Constructor(name = "ReferenceError") - public static Object constructor(final boolean newObj, final Object self, final Object msg) { + public static NativeReferenceError constructor(final boolean newObj, final Object self, final Object msg) { return new NativeReferenceError(msg); } }
--- a/src/jdk/nashorn/internal/objects/NativeRegExp.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeRegExp.java Wed May 28 16:53:43 2014 +0200 @@ -124,7 +124,7 @@ * @return new NativeRegExp */ @Constructor(arity = 2) - public static Object constructor(final boolean isNew, final Object self, final Object... args) { + public static NativeRegExp constructor(final boolean isNew, final Object self, final Object... args) { if (args.length > 1) { return newRegExp(args[0], args[1]); } else if (args.length > 0) { @@ -144,7 +144,7 @@ * @return new NativeRegExp */ @SpecializedConstructor - public static Object constructor(final boolean isNew, final Object self) { + public static NativeRegExp constructor(final boolean isNew, final Object self) { return new NativeRegExp("", ""); } @@ -159,7 +159,7 @@ * @return new NativeRegExp */ @SpecializedConstructor - public static Object constructor(final boolean isNew, final Object self, final Object pattern) { + public static NativeRegExp constructor(final boolean isNew, final Object self, final Object pattern) { return newRegExp(pattern, UNDEFINED); } @@ -175,7 +175,7 @@ * @return new NativeRegExp */ @SpecializedConstructor - public static Object constructor(final boolean isNew, final Object self, final Object pattern, final Object flags) { + public static NativeRegExp constructor(final boolean isNew, final Object self, final Object pattern, final Object flags) { return newRegExp(pattern, flags); } @@ -285,7 +285,7 @@ * @return new NativeRegExp */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object compile(final Object self, final Object pattern, final Object flags) { + public static ScriptObject compile(final Object self, final Object pattern, final Object flags) { final NativeRegExp regExp = checkRegExp(self); final NativeRegExp compiled = newRegExp(pattern, flags); // copy over regexp to 'self' @@ -304,7 +304,7 @@ * @return array containing the matches or {@code null} if no match */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object exec(final Object self, final Object string) { + public static ScriptObject exec(final Object self, final Object string) { return checkRegExp(self).exec(JSType.toString(string)); } @@ -316,7 +316,7 @@ * @return true if matches found, false otherwise */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object test(final Object self, final Object string) { + public static boolean test(final Object self, final Object string) { return checkRegExp(self).test(JSType.toString(string)); } @@ -327,7 +327,7 @@ * @return string version of regexp */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object toString(final Object self) { + public static String toString(final Object self) { return checkRegExp(self).toString(); } @@ -620,7 +620,7 @@ * @param string String to match. * @return NativeArray of matches, string or null. */ - public Object exec(final String string) { + public NativeRegExpExecResult exec(final String string) { final RegExpResult match = execInner(string); if (match == null) { @@ -637,7 +637,7 @@ * @param string String to match. * @return True if a match is found. */ - public Object test(final String string) { + public boolean test(final String string) { return execInner(string) != null; } @@ -651,7 +651,7 @@ * @param replacement Replacement string. * @return String with substitutions. */ - Object replace(final String string, final String replacement, final ScriptFunction function) throws Throwable { + String replace(final String string, final String replacement, final ScriptFunction function) throws Throwable { final RegExpMatcher matcher = regexp.match(string); if (matcher == null) { @@ -820,7 +820,7 @@ * @param limit Split limit. * @return Array of substrings. */ - Object split(final String string, final long limit) { + NativeArray split(final String string, final long limit) { if (limit == 0L) { return new NativeArray(); } @@ -883,7 +883,7 @@ * @param string String to match. * @return Index of match. */ - Object search(final String string) { + int search(final String string) { final RegExpResult match = execInner(string); if (match == null) {
--- a/src/jdk/nashorn/internal/objects/NativeString.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeString.java Wed May 28 16:53:43 2014 +0200 @@ -424,7 +424,7 @@ * @return string with arguments translated to charcodes */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1, where = Where.CONSTRUCTOR) - public static Object fromCharCode(final Object self, final Object... args) { + public static String fromCharCode(final Object self, final Object... args) { final char[] buf = new char[args.length]; int index = 0; for (final Object arg : args) { @@ -454,7 +454,7 @@ * @return string with one charcode */ @SpecializedFunction - public static Object fromCharCode(final Object self, final int value) { + public static String fromCharCode(final Object self, final int value) { return Character.toString((char)(value & 0xffff)); } @@ -493,7 +493,7 @@ * @return string with one charcode */ @SpecializedFunction - public static Object fromCharCode(final Object self, final int ch1, final int ch2, final int ch3, final int ch4) { + public static String fromCharCode(final Object self, final int ch1, final int ch2, final int ch3, final int ch4) { return Character.toString((char)(ch1 & 0xffff)) + Character.toString((char)(ch2 & 0xffff)) + Character.toString((char)(ch3 & 0xffff)) + Character.toString((char)(ch4 & 0xffff)); } @@ -504,7 +504,7 @@ * @return string with one charcode */ @SpecializedFunction - public static Object fromCharCode(final Object self, final double value) { + public static String fromCharCode(final Object self, final double value) { return Character.toString((char)JSType.toUint16(value)); } @@ -514,7 +514,7 @@ * @return self as string */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object toString(final Object self) { + public static String toString(final Object self) { return getString(self); } @@ -524,7 +524,7 @@ * @return self as string */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object valueOf(final Object self) { + public static String valueOf(final Object self) { return getString(self); } @@ -535,7 +535,7 @@ * @return string representing the char at the given position */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object charAt(final Object self, final Object pos) { + public static String charAt(final Object self, final Object pos) { return charAtImpl(checkObjectToString(self), JSType.toInteger(pos)); } @@ -572,7 +572,7 @@ * @return number representing charcode at position */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object charCodeAt(final Object self, final Object pos) { + public static double charCodeAt(final Object self, final Object pos) { return charCodeAtImpl(checkObjectToString(self), JSType.toInteger(pos)); } @@ -627,7 +627,7 @@ * @return position of first match or -1 */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) - public static Object indexOf(final Object self, final Object search, final Object pos) { + public static int indexOf(final Object self, final Object search, final Object pos) { final String str = checkObjectToString(self); return str.indexOf(JSType.toString(search), JSType.toInteger(pos)); } @@ -675,7 +675,7 @@ * @return last position of match or -1 */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) - public static Object lastIndexOf(final Object self, final Object search, final Object pos) { + public static int lastIndexOf(final Object self, final Object search, final Object pos) { final String str = checkObjectToString(self); final String searchStr = JSType.toString(search); @@ -706,7 +706,7 @@ * @return result of locale sensitive comparison operation between {@code self} and {@code that} */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object localeCompare(final Object self, final Object that) { + public static double localeCompare(final Object self, final Object that) { final String str = checkObjectToString(self); final Collator collator = Collator.getInstance(Global.getEnv()._locale); @@ -714,7 +714,7 @@ collator.setStrength(Collator.IDENTICAL); collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION); - return (double)collator.compare(str, JSType.toString(that)); + return collator.compare(str, JSType.toString(that)); } /** @@ -724,7 +724,7 @@ * @return array of regexp matches */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object match(final Object self, final Object regexp) { + public static ScriptObject match(final Object self, final Object regexp) { final String str = checkObjectToString(self); @@ -772,7 +772,7 @@ * @throws Throwable if replacement fails */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object replace(final Object self, final Object string, final Object replacement) throws Throwable { + public static String replace(final Object self, final Object string, final Object replacement) throws Throwable { final String str = checkObjectToString(self); @@ -798,7 +798,7 @@ * @return offset where match occurred */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object search(final Object self, final Object string) { + public static int search(final Object self, final Object string) { final String str = checkObjectToString(self); final NativeRegExp nativeRegExp = Global.toRegExp(string == UNDEFINED ? "" : string); @@ -815,7 +815,7 @@ * @return sliced out substring */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object slice(final Object self, final Object start, final Object end) { + public static String slice(final Object self, final Object start, final Object end) { final String str = checkObjectToString(self); if (end == UNDEFINED) { @@ -832,7 +832,7 @@ * @return sliced out substring */ @SpecializedFunction - public static Object slice(final Object self, final int start) { + public static String slice(final Object self, final int start) { final String str = checkObjectToString(self); final int from = start < 0 ? Math.max(str.length() + start, 0) : Math.min(start, str.length()); @@ -847,7 +847,7 @@ * @return sliced out substring */ @SpecializedFunction - public static Object slice(final Object self, final double start) { + public static String slice(final Object self, final double start) { return slice(self, (int)start); } @@ -860,7 +860,7 @@ * @return sliced out substring */ @SpecializedFunction - public static Object slice(final Object self, final int start, final int end) { + public static String slice(final Object self, final int start, final int end) { final String str = checkObjectToString(self); final int len = str.length(); @@ -880,7 +880,7 @@ * @return sliced out substring */ @SpecializedFunction - public static Object slice(final Object self, final double start, final double end) { + public static String slice(final Object self, final double start, final double end) { return slice(self, (int)start, (int)end); } @@ -893,7 +893,7 @@ * @return array object in which splits have been placed */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object split(final Object self, final Object separator, final Object limit) { + public static ScriptObject split(final Object self, final Object separator, final Object limit) { final String str = checkObjectToString(self); final long lim = limit == UNDEFINED ? JSType.MAX_UINT : JSType.toUint32(limit); @@ -909,7 +909,7 @@ return splitString(str, JSType.toString(separator), lim); } - private static Object splitString(String str, String separator, long limit) { + private static ScriptObject splitString(String str, String separator, long limit) { if (separator.isEmpty()) { final int length = (int) Math.min(str.length(), limit); final Object[] array = new Object[length]; @@ -950,7 +950,7 @@ * @return substring given start and length of section */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object substr(final Object self, final Object start, final Object length) { + public static String substr(final Object self, final Object start, final Object length) { final String str = JSType.toString(self); final int strLength = str.length(); @@ -973,7 +973,7 @@ * @return substring given start and end indexes */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object substring(final Object self, final Object start, final Object end) { + public static String substring(final Object self, final Object start, final Object end) { final String str = checkObjectToString(self); if (end == UNDEFINED) { @@ -1053,7 +1053,7 @@ * @return string to lower case */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object toLowerCase(final Object self) { + public static String toLowerCase(final Object self) { return checkObjectToString(self).toLowerCase(Locale.ROOT); } @@ -1063,7 +1063,7 @@ * @return string to locale sensitive lower case */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object toLocaleLowerCase(final Object self) { + public static String toLocaleLowerCase(final Object self) { return checkObjectToString(self).toLowerCase(Global.getEnv()._locale); } @@ -1073,7 +1073,7 @@ * @return string to upper case */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object toUpperCase(final Object self) { + public static String toUpperCase(final Object self) { return checkObjectToString(self).toUpperCase(Locale.ROOT); } @@ -1083,7 +1083,7 @@ * @return string to locale sensitive upper case */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object toLocaleUpperCase(final Object self) { + public static String toLocaleUpperCase(final Object self) { return checkObjectToString(self).toUpperCase(Global.getEnv()._locale); } @@ -1093,7 +1093,7 @@ * @return string trimmed from whitespace */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object trim(final Object self) { + public static String trim(final Object self) { final String str = checkObjectToString(self); int start = 0; @@ -1115,7 +1115,7 @@ * @return string trimmed left from whitespace */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object trimLeft(final Object self) { + public static String trimLeft(final Object self) { final String str = checkObjectToString(self); int start = 0; @@ -1134,7 +1134,7 @@ * @return string trimmed right from whitespace */ @Function(attributes = Attribute.NOT_ENUMERABLE) - public static Object trimRight(final Object self) { + public static String trimRight(final Object self) { final String str = checkObjectToString(self); final int start = 0; @@ -1147,7 +1147,7 @@ return str.substring(start, end + 1); } - private static Object newObj(final CharSequence str) { + private static ScriptObject newObj(final CharSequence str) { return new NativeString(str); }
--- a/src/jdk/nashorn/internal/objects/NativeSyntaxError.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeSyntaxError.java Wed May 28 16:53:43 2014 +0200 @@ -94,7 +94,7 @@ * @return new SyntaxError */ @Constructor(name = "SyntaxError") - public static Object constructor(final boolean newObj, final Object self, final Object msg) { + public static NativeSyntaxError constructor(final boolean newObj, final Object self, final Object msg) { return new NativeSyntaxError(msg); } }
--- a/src/jdk/nashorn/internal/objects/NativeTypeError.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeTypeError.java Wed May 28 16:53:43 2014 +0200 @@ -94,7 +94,7 @@ * @return new TypeError */ @Constructor(name = "TypeError") - public static Object constructor(final boolean newObj, final Object self, final Object msg) { + public static NativeTypeError constructor(final boolean newObj, final Object self, final Object msg) { return new NativeTypeError(msg); } }
--- a/src/jdk/nashorn/internal/objects/NativeURIError.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeURIError.java Wed May 28 16:53:43 2014 +0200 @@ -93,7 +93,7 @@ * @return new URIError */ @Constructor(name = "URIError") - public static Object constructor(final boolean newObj, final Object self, final Object msg) { + public static NativeURIError constructor(final boolean newObj, final Object self, final Object msg) { return new NativeURIError(msg); } }
--- a/src/jdk/nashorn/internal/objects/NativeUint16Array.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeUint16Array.java Wed May 28 16:53:43 2014 +0200 @@ -31,7 +31,6 @@ import java.lang.invoke.MethodHandles; import java.nio.ByteBuffer; import java.nio.CharBuffer; - import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; import jdk.nashorn.internal.objects.annotations.Function; @@ -171,8 +170,8 @@ * @return new typed array */ @Constructor(arity = 1) - public static Object constructor(final boolean newObj, final Object self, final Object... args) { - return constructorImpl(newObj, args, FACTORY); + public static NativeUint16Array constructor(final boolean newObj, final Object self, final Object... args) { + return (NativeUint16Array)constructorImpl(newObj, args, FACTORY); } NativeUint16Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) { @@ -217,8 +216,8 @@ * @return sub array */ @Function(attributes = Attribute.NOT_ENUMERABLE) - protected static Object subarray(final Object self, final Object begin, final Object end) { - return ArrayBufferView.subarrayImpl(self, begin, end); + protected static NativeUint16Array subarray(final Object self, final Object begin, final Object end) { + return (NativeUint16Array)ArrayBufferView.subarrayImpl(self, begin, end); } @Override
--- a/src/jdk/nashorn/internal/objects/NativeUint32Array.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeUint32Array.java Wed May 28 16:53:43 2014 +0200 @@ -32,7 +32,6 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.IntBuffer; - import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; import jdk.nashorn.internal.objects.annotations.Function; @@ -180,8 +179,8 @@ * @return new typed array */ @Constructor(arity = 1) - public static Object constructor(final boolean newObj, final Object self, final Object... args) { - return constructorImpl(newObj, args, FACTORY); + public static NativeUint32Array constructor(final boolean newObj, final Object self, final Object... args) { + return (NativeUint32Array)constructorImpl(newObj, args, FACTORY); } NativeUint32Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) { @@ -226,8 +225,8 @@ * @return sub array */ @Function(attributes = Attribute.NOT_ENUMERABLE) - protected static Object subarray(final Object self, final Object begin, final Object end) { - return ArrayBufferView.subarrayImpl(self, begin, end); + protected static NativeUint32Array subarray(final Object self, final Object begin, final Object end) { + return (NativeUint32Array)ArrayBufferView.subarrayImpl(self, begin, end); } @Override
--- a/src/jdk/nashorn/internal/objects/NativeUint8Array.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeUint8Array.java Wed May 28 16:53:43 2014 +0200 @@ -30,7 +30,6 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.nio.ByteBuffer; - import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; import jdk.nashorn.internal.objects.annotations.Function; @@ -172,12 +171,12 @@ * @return new typed array */ @Constructor(arity = 1) - public static Object constructor(final boolean newObj, final Object self, final Object... args) { - return constructorImpl(newObj, args, FACTORY); + public static NativeUint8Array constructor(final boolean newObj, final Object self, final Object... args) { + return (NativeUint8Array)constructorImpl(newObj, args, FACTORY); } - NativeUint8Array(NativeArrayBuffer buffer, int byteOffset, int elementLength) { - super(buffer, byteOffset, elementLength); + NativeUint8Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) { + super(buffer, byteOffset, length); } @Override @@ -218,8 +217,8 @@ * @return sub array */ @Function(attributes = Attribute.NOT_ENUMERABLE) - protected static Object subarray(final Object self, final Object begin, final Object end) { - return ArrayBufferView.subarrayImpl(self, begin, end); + protected static NativeUint8Array subarray(final Object self, final Object begin, final Object end) { + return (NativeUint8Array)ArrayBufferView.subarrayImpl(self, begin, end); } @Override
--- a/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java Wed May 28 16:53:43 2014 +0200 @@ -25,14 +25,13 @@ package jdk.nashorn.internal.objects; +import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall; -import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; import static jdk.nashorn.internal.lookup.Lookup.MH; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.nio.ByteBuffer; - import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; import jdk.nashorn.internal.objects.annotations.Function; @@ -82,6 +81,7 @@ private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "getElem", int.class, int.class).methodHandle(); private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "setElem", void.class, int.class, int.class).methodHandle(); private static final MethodHandle RINT = staticCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "rint", double.class, double.class).methodHandle(); + private static final MethodHandle CLAMP_LONG = staticCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "clampLong", long.class, long.class).methodHandle(); private Uint8ClampedArrayData(final ByteBuffer nb, final int start, final int end) { super(((ByteBuffer)nb.position(start).limit(end)).slice(), end - start); @@ -108,8 +108,12 @@ @Override public MethodHandle getElementSetter(final Class<?> elementType) { final MethodHandle setter = super.getElementSetter(elementType); //getContinuousElementSetter(getClass(), setElem(), elementType); - if (setter != null && elementType == double.class) { - return MH.filterArguments(setter, 2, RINT); + if (setter != null) { + if (elementType == double.class) { + return MH.filterArguments(setter, 2, RINT); + } else if (elementType == long.class) { + return MH.filterArguments(setter, 2, CLAMP_LONG); + } } return setter; } @@ -186,6 +190,15 @@ return (int)Math.rint(rint); } + @SuppressWarnings("unused") + private static long clampLong(final long l) { + if(l < 0L) { + return 0L; + } else if(l > 0xffL) { + return 0xffL; + } + return l; + } } /** @@ -198,8 +211,8 @@ * @return new typed array */ @Constructor(arity = 1) - public static Object constructor(final boolean newObj, final Object self, final Object... args) { - return constructorImpl(newObj, args, FACTORY); + public static NativeUint8ClampedArray constructor(final boolean newObj, final Object self, final Object... args) { + return (NativeUint8ClampedArray)constructorImpl(newObj, args, FACTORY); } NativeUint8ClampedArray(final NativeArrayBuffer buffer, final int byteOffset, final int length) { @@ -244,8 +257,8 @@ * @return sub array */ @Function(attributes = Attribute.NOT_ENUMERABLE) - protected static Object subarray(final Object self, final Object begin, final Object end) { - return ArrayBufferView.subarrayImpl(self, begin, end); + protected static NativeUint8ClampedArray subarray(final Object self, final Object begin, final Object end) { + return (NativeUint8ClampedArray)ArrayBufferView.subarrayImpl(self, begin, end); } @Override
--- a/src/jdk/nashorn/internal/parser/Parser.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/parser/Parser.java Wed May 28 16:53:43 2014 +0200 @@ -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; @@ -926,6 +927,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(); @@ -1211,6 +1217,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; @@ -1801,9 +1813,11 @@ // ECMA 12.4.1 strict mode restrictions verifyStrictIdent(exception, "catch argument"); - // Check for conditional catch. + // Nashorn extension: catch clause can have optional + // condition. So, a single try can have more than one + // catch clause each with it's own condition. final Expression ifExpression; - if (type == IF) { + if (!env._no_syntax_extensions && type == IF) { next(); // Get the exception condition. ifExpression = expression();
--- a/src/jdk/nashorn/internal/parser/TokenType.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/parser/TokenType.java Wed May 28 16:53:43 2014 +0200 @@ -112,7 +112,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 Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/AccessorProperty.java Wed May 28 16:53:43 2014 +0200 @@ -37,6 +37,8 @@ import static jdk.nashorn.internal.runtime.JSType.getNumberOfAccessorTypes; import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; +import java.io.IOException; +import java.io.ObjectInputStream; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.SwitchPoint; @@ -60,6 +62,7 @@ private static final SwitchPoint NO_CHANGE_CALLBACK = new SwitchPoint(); 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 @@ -133,16 +136,16 @@ } /** Seed getter for the primitive version of this field (in -Dnashorn.fields.dual=true mode) */ - protected final MethodHandle primitiveGetter; + private transient MethodHandle primitiveGetter; /** Seed setter for the primitive version of this field (in -Dnashorn.fields.dual=true mode) */ - protected final MethodHandle primitiveSetter; + private transient MethodHandle primitiveSetter; /** Seed getter for the Object version of this field */ - protected final MethodHandle objectGetter; + private transient MethodHandle objectGetter; /** Seed setter for the Object version of this field */ - protected final MethodHandle objectSetter; + private transient MethodHandle objectSetter; /** * Current type of this object, in object only mode, this is an Object.class. In dual-fields mode @@ -263,6 +266,11 @@ 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(); /* * 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 @@ -369,6 +377,12 @@ setCurrentType(OBJECT_FIELDS_ONLY ? Object.class : null); } + private void readObject(final ObjectInputStream s) throws IOException, ClassNotFoundException { + s.defaultReadObject(); + // Restore getters array + GETTER_CACHE = new MethodHandle[NOOF_TYPES]; + } + private static MethodHandle bindTo(final MethodHandle mh, final Object receiver) { if (mh == null) { return null; @@ -516,6 +530,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);
--- a/src/jdk/nashorn/internal/runtime/CodeInstaller.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/CodeInstaller.java Wed May 28 16:53:43 2014 +0200 @@ -25,6 +25,8 @@ package jdk.nashorn.internal.runtime; +import java.util.Collection; +import java.util.Map; import jdk.nashorn.internal.codegen.ClassEmitter; /** @@ -47,7 +49,7 @@ public T getOwner(); /** - * Install a class + * Install a class. * @param className name of the class with / separation * @param bytecode bytecode * @return the installed class @@ -55,6 +57,14 @@ public Class<?> install(final String className, final byte[] bytecode); /** + * Initialize already installed classes. + * @param classes the class to initialize + * @param source the source object for the classes + * @param constants the runtime constants for the classes + */ + public void initialize(final Collection<Class<?>> classes, final Source source, final Object[] constants); + + /** * Verify generated bytecode before emission. This is called back from the * {@link ClassEmitter} or the {@link Compiler}. If the "--verify-code" parameter * hasn't been given, this is a nop @@ -74,4 +84,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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/Context.java Wed May 28 16:53:43 2014 +0200 @@ -25,10 +25,13 @@ package jdk.nashorn.internal.runtime; +import static jdk.nashorn.internal.codegen.CompilerConstants.CONSTANTS; import static jdk.nashorn.internal.codegen.CompilerConstants.CREATE_PROGRAM_FUNCTION; +import static jdk.nashorn.internal.codegen.CompilerConstants.SOURCE; import static jdk.nashorn.internal.codegen.CompilerConstants.STRICT_MODE; 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; @@ -36,6 +39,7 @@ import java.lang.invoke.MethodHandle; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; +import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Modifier; import java.net.MalformedURLException; @@ -46,14 +50,17 @@ 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.Collection; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Consumer; import java.util.function.Supplier; import java.util.logging.Level; - import jdk.internal.org.objectweb.asm.ClassReader; import jdk.internal.org.objectweb.asm.util.CheckClassAdapter; import jdk.nashorn.api.scripting.ScriptObjectMirror; @@ -70,8 +77,8 @@ import jdk.nashorn.internal.runtime.logging.DebugLogger; import jdk.nashorn.internal.runtime.logging.Loggable; import jdk.nashorn.internal.runtime.logging.Logger; +import jdk.nashorn.internal.runtime.options.LoggingOption.LoggerInfo; import jdk.nashorn.internal.runtime.options.Options; -import jdk.nashorn.internal.runtime.options.LoggingOption.LoggerInfo; /** * This class manages the global state of execution. Context is immutable. @@ -144,7 +151,42 @@ @Override public Class<?> install(final String className, final byte[] bytecode) { - return loader.installClass(className, bytecode, codeSource); + final String binaryName = Compiler.binaryName(className); + return loader.installClass(binaryName, bytecode, codeSource); + } + + @Override + public void initialize(final Collection<Class<?>> classes, final Source source, final Object[] constants) { + // do these in parallel, this significantly reduces class installation overhead + // however - it still means that every thread needs a separate doPrivileged + classes.parallelStream().forEach( + new Consumer<Class<?>>() { + @Override + public void accept(final Class<?> clazz) { + try { + AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { + @Override + public Void run() { + try { + //use reflection to write source and constants table to installed classes + final Field sourceField = clazz.getDeclaredField(SOURCE.symbolName()); + sourceField.setAccessible(true); + sourceField.set(null, source); + + final Field constantsField = clazz.getDeclaredField(CONSTANTS.symbolName()); + constantsField.setAccessible(true); + constantsField.set(null, constants); + } catch (final IllegalAccessException | NoSuchFieldException e) { + throw new RuntimeException(e); + } + return null; + } + }); + } catch (final PrivilegedActionException e) { + throw new RuntimeException(e); + } + } + }); } @Override @@ -161,6 +203,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 ? */ @@ -168,9 +222,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 @@ -382,6 +439,19 @@ classCache = new ClassCache(cacheSize); } + if (env._persistent_cache) { + if (env._lazy_compilation || ScriptEnvironment.globalOptimistic()) { + getErr().println("Can not use persistent class caching with lazy compilation or optimistic compilation."); + } else { + try { + final String cacheDir = Options.getStringProperty("nashorn.persistent.code.cache", "nashorn_code_cache"); + codeStore = new CodeStore(cacheDir); + } catch (final IOException e) { + throw new RuntimeException("Error initializing code cache", e); + } + } + } + // print version info if asked. if (env._version) { getErr().println("nashorn " + Version.version()); @@ -447,6 +517,37 @@ } /** + * 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); + + return new MultiGlobalCompiledScript() { + @Override + public ScriptFunction getFunction(final Global newGlobal) { + return getProgramFunction(clazz, newGlobal); + } + }; + } + + /** * Entry point for {@code eval} * * @param initialScope The scope of this eval call @@ -459,7 +560,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(); ScriptObject scope = initialScope; @@ -525,7 +626,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; } @@ -557,7 +658,7 @@ final String srcStr = (String)src; if (srcStr.startsWith(LOAD_CLASSPATH)) { final 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) { @@ -570,31 +671,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); } } @@ -861,6 +962,11 @@ return ((ScriptObject)Context.getGlobal()).getContext(); } + static Context getContextTrustedOrNull() { + final Global global = Context.getGlobal(); + return global == null ? null : ((ScriptObject)global).getContext(); + } + /** * Try to infer Context instance from the Class. If we cannot, * then get it from the thread local variable. @@ -932,17 +1038,32 @@ return script; } - final FunctionNode functionNode = new Parser(env, source, errMan, strict, getLogger(Parser.class)).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) { + getLogger(Compiler.class).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, getLogger(Parser.class)).parse(); + + if (errors.hasErrors()) { + return null; + } - if (env._print_parse) { - getErr().println(new PrintVisitor(functionNode, true, false)); + if (env._print_ast) { + getErr().println(new ASTWriter(functionNode)); + } + + if (env._print_parse) { + getErr().println(new PrintVisitor(functionNode, true, false)); + } } if (env._parse_only) { @@ -954,19 +1075,23 @@ final CodeSource cs = new CodeSource(url, (CodeSigner[])null); final CodeInstaller<ScriptEnvironment> installer = new ContextCodeInstaller(this, loader, cs); - final CompilationPhases phases = Compiler.CompilationPhases.COMPILE_ALL; + if (functionNode != null) { + final CompilationPhases phases = Compiler.CompilationPhases.COMPILE_ALL; - final Compiler compiler = new Compiler( - this, - env, - installer, - source, - functionNode.getSourceURL(), - strict | functionNode.isStrict()); + final Compiler compiler = new Compiler( + this, + env, + installer, + source, + functionNode.getSourceURL(), + strict | functionNode.isStrict()); - script = compiler.compile(functionNode, phases).getRootClass(); + script = compiler.compile(functionNode, phases).getRootClass(); + } else { + script = install(compiledScript, installer); + } + cacheClass(source, script); - return script; } @@ -988,6 +1113,45 @@ 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 static 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); + + 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)); + } + + installer.initialize(installedClasses.values(), 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/FinalScriptFunctionData.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java Wed May 28 16:53:43 2014 +0200 @@ -94,11 +94,6 @@ // is too conservative a check. However, isConstructor(mh) always implies isConstructor param assert isConstructor(); code.add(CompiledFunction.createBuiltInConstructor(mh)); -/*======= - final MethodHandle invoker = MH.insertArguments(mh, 0, false); - final MethodHandle constructor = composeConstructor(MH.insertArguments(mh, 0, true)); - code.add(new CompiledFunction(mh.type(), invoker, constructor)); ->>>>>>> theirs*/ } else { code.add(new CompiledFunction(mh)); }
--- a/src/jdk/nashorn/internal/runtime/JSONFunctions.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/JSONFunctions.java Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/JSType.java Wed May 28 16:53:43 2014 +0200 @@ -651,7 +651,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 Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/Property.java Wed May 28 16:53:43 2014 +0200 @@ -29,10 +29,10 @@ 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.lang.invoke.SwitchPoint; import java.util.Objects; - import jdk.nashorn.internal.codegen.ObjectClassGenerator; /** @@ -44,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 +100,8 @@ /** SwitchPoint that is invalidated when property is changed, optional */ protected SwitchPoint changeCallback; + private static final long serialVersionUID = 2099814273074501176L; + /** * Constructor * @@ -394,6 +396,13 @@ public abstract MethodHandle getOptimisticGetter(final Class<?> type, final int programPoint); /** + * 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 Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/PropertyMap.java Wed May 28 16:53:43 2014 +0200 @@ -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) { final 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 Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Wed May 28 16:53:43 2014 +0200 @@ -27,6 +27,8 @@ import static jdk.nashorn.internal.lookup.Lookup.MH; +import java.io.IOException; +import java.io.Serializable; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -34,7 +36,6 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; - import jdk.internal.dynalink.support.NameCodec; import jdk.nashorn.internal.codegen.CompileUnit; import jdk.nashorn.internal.codegen.Compiler; @@ -54,6 +55,7 @@ import jdk.nashorn.internal.runtime.logging.Loggable; import jdk.nashorn.internal.runtime.logging.Logger; import jdk.nashorn.internal.runtime.options.Options; +import jdk.nashorn.internal.scripts.JS; /** * This is a subclass that represents a script function that may be regenerated, @@ -79,10 +81,14 @@ // Source object. private final String sourceURL; + /** The line number where this function begins. */ private final int lineNumber; /** Source from which FunctionNode was parsed. */ - private final Source source; + private transient Source source; + + /** 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; @@ -91,13 +97,13 @@ private final PropertyMap allocatorMap; /** Code installer used for all further recompilation/specialization of this ScriptFunction */ - private final 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 final Map<Integer, RecompilableScriptFunctionData> nestedFunctions; @@ -110,20 +116,19 @@ private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); - private final DebugLogger log; + private transient DebugLogger log; private final Map<String, Integer> externalScopeDepths; private final Set<String> internalSymbols; - private final Context context; + private static final int GET_SET_PREFIX_LENGTH = "*et ".length(); - private static final int GET_SET_PREFIX_LENGTH = "*et ".length(); + private static final long serialVersionUID = 4914839316174633726L; /** * Constructor - public as scripts use it * - * @param context context * @param functionNode functionNode that represents this function code * @param installer installer for code regeneration versions of this function * @param allocatorClassName name of our allocator class, will be looked up dynamically if used as a constructor @@ -134,7 +139,6 @@ * @param internalSymbols internal symbols to method, defined in its scope */ public RecompilableScriptFunctionData( - final Context context, final FunctionNode functionNode, final CodeInstaller<ScriptEnvironment> installer, final String allocatorClassName, @@ -148,7 +152,6 @@ Math.min(functionNode.getParameters().size(), MAX_ARITY), getFlags(functionNode)); - this.context = context; this.functionName = functionNode.getName(); this.lineNumber = functionNode.getLineNumber(); this.isDeclared = functionNode.isDeclared(); @@ -163,14 +166,14 @@ this.allocatorMap = allocatorMap; this.nestedFunctions = nestedFunctions; this.externalScopeDepths = externalScopeDepths; - this.internalSymbols = internalSymbols; + this.internalSymbols = new HashSet<>(internalSymbols); for (final RecompilableScriptFunctionData nfn : nestedFunctions.values()) { assert nfn.getParent() == null; nfn.setParent(this); } - this.log = initLogger(context); + createLogger(); } @Override @@ -237,6 +240,13 @@ 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() { return super.toString() + '@' + functionNodeId; @@ -336,6 +346,7 @@ final boolean isProgram = functionNodeId == FunctionNode.FIRST_FUNCTION_ID; // NOTE: If we aren't recompiling the top-level program, we decrease functionNodeId 'cause we'll have a synthetic program node final int descPosition = Token.descPosition(token); + final Context context = Context.getContextTrusted(); final Parser parser = new Parser( context.getEnv(), source, @@ -378,6 +389,7 @@ } Compiler getCompiler(final FunctionNode functionNode, final MethodType actualCallSiteType, final ScriptObject runtimeScope, final Map<Integer, Type> ipp, final int[] cep) { + final Context context = Context.getContextTrusted(); return new Compiler( context, context.getEnv(), @@ -406,10 +418,6 @@ return getCompiler(fn, actualCallSiteType, runtimeScope).compile(fn, CompilationPhases.COMPILE_ALL); } - Context getContext() { - return context; - } - private MethodType explicitParams(final MethodType callSiteType) { if (CompiledFunction.isVarArgsType(callSiteType)) { return null; @@ -481,6 +489,7 @@ throw new IllegalStateException(functionNode.getName() + " id=" + functionNode.getId()); } addCode(functionNode); + methodLocator = new MethodLocator(functionNode); } private CompiledFunction addCode(final MethodHandle target, final int fnFlags) { @@ -542,7 +551,12 @@ synchronized (code) { CompiledFunction existingBest = super.getBest(callSiteType, runtimeScope); if (existingBest == null) { - existingBest = addCode(compileTypeSpecialization(callSiteType, runtimeScope), callSiteType); + if(code.isEmpty() && methodLocator != null) { + // This is a deserialized object, reconnect from method handle + existingBest = addCode(methodLocator.getMethodHandle(), methodLocator.getFunctionFlags()); + } else { + existingBest = addCode(compileTypeSpecialization(callSiteType, runtimeScope), callSiteType); + } } assert existingBest != null; @@ -653,4 +667,55 @@ return true; } + + /** + * 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 final int functionFlags; + + 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(); + this.functionFlags = functionNode.getFlags(); + + 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; + } + + MethodHandle getMethodHandle() { + return MH.findStatic(LOOKUP, clazz, methodName, methodType); + } + + int getFunctionFlags() { + return functionFlags; + } + } + + private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + createLogger(); + } + + private void createLogger() { + log = initLogger(Context.getContextTrusted()); + } }
--- a/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java Wed May 28 16:53:43 2014 +0200 @@ -33,7 +33,6 @@ import java.util.StringTokenizer; import java.util.TimeZone; import java.util.logging.Level; - import jdk.nashorn.internal.codegen.Namespace; import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; import jdk.nashorn.internal.runtime.options.KeyValueOption; @@ -65,6 +64,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; @@ -132,6 +134,9 @@ */ public final FunctionStatementBehavior _function_statement; + /** Should lazy compilation take place */ + public final boolean _lazy_compilation; + /** Create a new class loaded for each compilation */ public final boolean _loader_per_compile; @@ -147,6 +152,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; @@ -219,6 +227,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"); @@ -234,11 +243,13 @@ } _fx = options.getBoolean("fx"); _global_per_engine = options.getBoolean("global.per.engine"); + _lazy_compilation = options.getBoolean("lazy.compilation"); _loader_per_compile = options.getBoolean("loader.per.compile"); _no_java = options.getBoolean("no.java"); _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.getString("print.code") != null;
--- a/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Wed May 28 16:53:43 2014 +0200 @@ -29,17 +29,21 @@ import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; +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; import jdk.nashorn.internal.runtime.linker.LinkerCallSite; + /** * A container for data needed to instantiate a specific {@link ScriptFunction} at runtime. * 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 { static final int MAX_ARITY = LinkerCallSite.ARGLIMIT; static { // Assert it fits in a byte, as that's what we store it in. It's just a size optimization though, so if needed @@ -52,7 +56,7 @@ /** All versions of this function that have been generated to code */ // TODO: integrate it into ScriptFunctionData; there's not much reason for this to be in its own class. - protected final CompiledFunctions code; + protected transient CompiledFunctions code; /** Function flags */ protected int flags; @@ -93,6 +97,8 @@ /** Flag for strict constructors */ public static final int IS_STRICT_CONSTRUCTOR = IS_STRICT | IS_CONSTRUCTOR; + private static final long serialVersionUID = 4252901245508769114L; + /** * Constructor * @@ -793,4 +799,9 @@ volatile MethodHandle invoker; volatile MethodHandle constructor; } + + private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + code = new CompiledFunctions(name); + } }
--- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java Wed May 28 16:53:43 2014 +0200 @@ -99,7 +99,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" */ @@ -153,8 +153,11 @@ /** Indexed array data. */ private ArrayData arrayData; - static final MethodHandle GETPROTO = findOwnMH_V("getProto", ScriptObject.class); - static final MethodHandle SETPROTOCHECK = findOwnMH_V("setProtoCheck", void.class, Object.class); + /** Method handle to retrieve prototype of this object */ + public static final MethodHandle GETPROTO = findOwnMH_V("getProto", ScriptObject.class); + /** Method handle to set prototype of this object */ + public static final MethodHandle SETPROTOCHECK = findOwnMH_V("setProtoCheck", void.class, Object.class); + static final MethodHandle MEGAMORPHIC_GET = findOwnMH_V("megamorphicGet", Object.class, String.class, boolean.class, boolean.class); static final MethodHandle GLOBALFILTER = findOwnMH_S("globalFilter", Object.class, Object.class); @@ -680,22 +683,16 @@ } /** - * Spec. mentions use of [[DefineOwnProperty]] for indexed properties in - * certain places (eg. Array.prototype.map, filter). We can not use ScriptObject.set - * method in such cases. This is because set method uses inherited setters (if any) - * from any object in proto chain such as Array.prototype, Object.prototype. - * This method directly sets a particular element value in the current object. + * Almost like defineOwnProperty(int,Object) for arrays this one does + * not add 'gap' elements (like the array one does). * * @param index key for property * @param value value to define */ - public final void defineOwnProperty(final int index, final Object value) { + public void defineOwnProperty(final int index, final Object value) { assert isValidArrayIndex(index) : "invalid array index"; final long longIndex = ArrayIndex.toLongIndex(index); - if (longIndex >= getArray().length()) { - // make array big enough to hold.. - setArray(getArray().ensure(longIndex)); - } + doesNotHaveEnsureDelete(longIndex, getArray().length(), false); setArray(getArray().set(index, value, false)); } @@ -1915,17 +1912,6 @@ MethodHandle mh; if (find == null) { - if (PROTO_PROPERTY_NAME.equals(name)) { - return new GuardedInvocation( - GETPROTO, - explicitInstanceOfCheck ? - getScriptObjectGuard(desc.getMethodType(), explicitInstanceOfCheck) : - null, - (SwitchPoint)null, - explicitInstanceOfCheck ? - null : ClassCastException.class); - } - switch (operator) { case "getProp": return noSuchProperty(desc, request); @@ -2116,13 +2102,7 @@ return createEmptySetMethod(desc, explicitInstanceOfCheck, "property.not.writable", true); } } else { - if (PROTO_PROPERTY_NAME.equals(name)) { - return new GuardedInvocation( - SETPROTOCHECK, - getScriptObjectGuard(desc.getMethodType(), explicitInstanceOfCheck), - (SwitchPoint)null, - explicitInstanceOfCheck ? null : ClassCastException.class); - } else if (!isExtensible()) { + if (!isExtensible()) { return createEmptySetMethod(desc, explicitInstanceOfCheck, "object.non.extensible", false); } }
--- a/src/jdk/nashorn/internal/runtime/Source.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/Source.java Wed May 28 16:53:43 2014 +0200 @@ -27,27 +27,40 @@ 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; +import jdk.nashorn.internal.runtime.logging.DebugLogger; +import jdk.nashorn.internal.runtime.logging.Loggable; +import jdk.nashorn.internal.runtime.logging.Logger; /** * Source objects track the origin of JavaScript entities. - * */ -public final class Source { +@Logger(name="source") +public final class Source implements Loggable { + 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 +75,309 @@ */ 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)); + } + } + + // 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 RawData(final char[] array) { + this.array = Objects.requireNonNull(array); + } - private static final int BUFSIZE = 8 * 1024; + 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) { + final DebugLogger logger = getLoggerStatic(); + if (logger != null) { + logger.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; @@ -523,4 +847,19 @@ return null; } } + + private static DebugLogger getLoggerStatic() { + final Context context = Context.getContextTrustedOrNull(); + return context == null ? null : context.getLogger(Source.class); + } + + @Override + public DebugLogger initLogger(Context context) { + return context.getLogger(this.getClass()); + } + + @Override + public DebugLogger getLogger() { + return initLogger(Context.getContextTrusted()); + } }
--- a/src/jdk/nashorn/internal/runtime/SpillProperty.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/SpillProperty.java Wed May 28 16:53:43 2014 +0200 @@ -25,16 +25,18 @@ package jdk.nashorn.internal.runtime; +import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY; +import static jdk.nashorn.internal.lookup.Lookup.MH; + import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; -import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY; -import static jdk.nashorn.internal.lookup.Lookup.MH; - /** * Spill property */ public class SpillProperty extends AccessorProperty { + private static final long serialVersionUID = 3028496245198669460L; + private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); private static final MethodHandle PARRAY_GETTER = MH.asType(MH.getter(LOOKUP, ScriptObject.class, "primitiveSpill", long[].class), MH.type(long[].class, Object.class));
--- a/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java Wed May 28 16:53:43 2014 +0200 @@ -56,6 +56,8 @@ */ public final class UserAccessorProperty extends SpillProperty { + private static final long serialVersionUID = -5928687246526840321L; + static class Accessors { Object getter; Object setter; @@ -257,6 +259,11 @@ } @Override + void initMethodHandles(final Class<?> structure) { + throw new UnsupportedOperationException(); + } + + @Override public ScriptFunction getGetterFunction(final ScriptObject sobj) { final Object value = getAccessors(sobj).getter; return (value instanceof ScriptFunction) ? (ScriptFunction)value : null;
--- a/src/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java Wed May 28 16:53:43 2014 +0200 @@ -141,6 +141,21 @@ return this; } + private static void printTrace(final Throwable t, String msg) { + final java.io.StringWriter sw = new java.io.StringWriter(); + final java.io.PrintWriter pw = new java.io.PrintWriter(sw, false); + pw.println(msg); + final StackTraceElement[] trace = t.getStackTrace(); + for(final StackTraceElement e: trace) { + pw.println(" at " + e); + if(e.getClassName().startsWith("jdk.nashorn.")) { + break; + } + } + pw.flush(); + System.out.println(sw.toString()); + } + @Override public Type getOptimisticType() { return underlying.getOptimisticType();
--- a/src/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java Wed May 28 16:53:43 2014 +0200 @@ -36,17 +36,25 @@ private long lo, hi; DeletedRangeArrayFilter(final ArrayData underlying, final long lo, final long hi) { - super(underlying); + super(maybeSparse(underlying, hi)); this.lo = lo; this.hi = hi; } + private static ArrayData maybeSparse(final ArrayData underlying, final long hi) { + if(hi < SparseArrayData.MAX_DENSE_LENGTH || underlying instanceof SparseArrayData) { + return underlying; + } + return new SparseArrayData(underlying, underlying.length()); + } + private boolean isEmpty() { return lo > hi; } private boolean isDeleted(final int index) { - return lo <= index && index <= hi; + final long longIndex = ArrayIndex.toLongIndex(index); + return lo <= longIndex && longIndex <= hi; } @Override
--- a/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java Wed May 28 16:53:43 2014 +0200 @@ -162,8 +162,9 @@ underlying = underlying.set(index, value, strict); setLength(Math.max(underlying.length(), length())); } else { - sparseMap.put(indexToKey(index), value); - setLength(Math.max(index + 1, length())); + final Long longIndex = indexToKey(index); + sparseMap.put(longIndex, value); + setLength(Math.max(longIndex + 1, length())); } return this; @@ -176,8 +177,9 @@ underlying = underlying.set(index, value, strict); setLength(Math.max(underlying.length(), length())); } else { - sparseMap.put(indexToKey(index), value); - setLength(Math.max(index + 1, length())); + final Long longIndex = indexToKey(index); + sparseMap.put(longIndex, value); + setLength(Math.max(longIndex + 1, length())); } return this; } @@ -189,8 +191,9 @@ underlying = underlying.set(index, value, strict); setLength(Math.max(underlying.length(), length())); } else { - sparseMap.put(indexToKey(index), value); - setLength(Math.max(index + 1, length())); + final Long longIndex = indexToKey(index); + sparseMap.put(longIndex, value); + setLength(Math.max(longIndex + 1, length())); } return this; } @@ -202,8 +205,9 @@ underlying = underlying.set(index, value, strict); setLength(Math.max(underlying.length(), length())); } else { - sparseMap.put(indexToKey(index), value); - setLength(Math.max(index + 1, length())); + final Long longIndex = indexToKey(index); + sparseMap.put(longIndex, value); + setLength(Math.max(longIndex + 1, length())); } return this; } @@ -321,7 +325,7 @@ } private static Long indexToKey(final int index) { - return Long.valueOf(index & JSType.MAX_UINT); + return Long.valueOf(ArrayIndex.toLongIndex(index)); } @Override
--- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java Wed May 28 16:53:43 2014 +0200 @@ -66,7 +66,6 @@ import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Type; import jdk.internal.org.objectweb.asm.commons.InstructionAdapter; -import jdk.nashorn.internal.objects.Global; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.ScriptFunction; @@ -135,24 +134,19 @@ * implemented securely. */ final class JavaAdapterBytecodeGenerator { - private static final Type CONTEXT_TYPE = Type.getType(Context.class); - private static final Type OBJECT_TYPE = Type.getType(Object.class); - private static final Type SCRIPT_OBJECT_TYPE = Type.getType(ScriptObject.class); - private static final Type GLOBAL_TYPE = Type.getType(Global.class); - private static final Type CLASS_TYPE = Type.getType(Class.class); + private static final Type OBJECT_TYPE = Type.getType(Object.class); + private static final Type CLASS_TYPE = Type.getType(Class.class); - static final String CONTEXT_TYPE_NAME = CONTEXT_TYPE.getInternalName(); static final String OBJECT_TYPE_NAME = OBJECT_TYPE.getInternalName(); static final String INIT = "<init>"; static final String GLOBAL_FIELD_NAME = "global"; - static final String SCRIPT_OBJECT_TYPE_DESCRIPTOR = SCRIPT_OBJECT_TYPE.getDescriptor(); - static final String GLOBAL_TYPE_DESCRIPTOR = GLOBAL_TYPE.getDescriptor(); + // "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, GLOBAL_TYPE); + static final String SET_GLOBAL_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE, OBJECT_TYPE); static final String VOID_NOARG_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE); private static final Type SCRIPT_FUNCTION_TYPE = Type.getType(ScriptFunction.class); @@ -163,7 +157,7 @@ OBJECT_TYPE, STRING_TYPE, METHOD_TYPE_TYPE); private static final String GET_HANDLE_FUNCTION_DESCRIPTOR = Type.getMethodDescriptor(METHOD_HANDLE_TYPE, SCRIPT_FUNCTION_TYPE, METHOD_TYPE_TYPE); - private static final String GET_CLASS_INITIALIZER_DESCRIPTOR = Type.getMethodDescriptor(SCRIPT_OBJECT_TYPE); + private static final String GET_CLASS_INITIALIZER_DESCRIPTOR = Type.getMethodDescriptor(OBJECT_TYPE); private static final Type RUNTIME_EXCEPTION_TYPE = Type.getType(RuntimeException.class); private static final Type THROWABLE_TYPE = Type.getType(Throwable.class); private static final Type UNSUPPORTED_OPERATION_TYPE = Type.getType(UnsupportedOperationException.class); @@ -175,7 +169,7 @@ private static final String UNSUPPORTED_OPERATION_TYPE_NAME = UNSUPPORTED_OPERATION_TYPE.getInternalName(); private static final String METHOD_HANDLE_TYPE_DESCRIPTOR = METHOD_HANDLE_TYPE.getDescriptor(); - private static final String GET_GLOBAL_METHOD_DESCRIPTOR = Type.getMethodDescriptor(GLOBAL_TYPE); + private static final String GET_GLOBAL_METHOD_DESCRIPTOR = Type.getMethodDescriptor(OBJECT_TYPE); private static final String GET_CLASS_METHOD_DESCRIPTOR = Type.getMethodDescriptor(CLASS_TYPE); private static final String EXPORT_RETURN_VALUE_METHOD_DESCRIPTOR = Type.getMethodDescriptor(OBJECT_TYPE, OBJECT_TYPE); private static final String GET_CONVERTER_METHOD_DESCRIPTOR = Type.getMethodDescriptor(METHOD_HANDLE_TYPE, CLASS_TYPE); @@ -603,11 +597,11 @@ } private static void invokeGetGlobal(final InstructionAdapter mv) { - mv.invokestatic(CONTEXT_TYPE_NAME, "getGlobal", GET_GLOBAL_METHOD_DESCRIPTOR, false); + mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getGlobal", GET_GLOBAL_METHOD_DESCRIPTOR, false); } private static void invokeSetGlobal(final InstructionAdapter mv) { - mv.invokestatic(CONTEXT_TYPE_NAME, "setGlobal", SET_GLOBAL_METHOD_DESCRIPTOR, false); + mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "setGlobal", SET_GLOBAL_METHOD_DESCRIPTOR, false); } /**
--- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java Wed May 28 16:53:43 2014 +0200 @@ -30,9 +30,15 @@ import java.security.PrivilegedAction; import java.security.ProtectionDomain; import java.security.SecureClassLoader; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; import jdk.internal.dynalink.beans.StaticClass; import jdk.nashorn.internal.codegen.DumpBytecode; import jdk.nashorn.internal.runtime.Context; +import jdk.nashorn.internal.runtime.JSType; +import jdk.nashorn.internal.runtime.ScriptFunction; /** * This class encapsulates the bytecode of the adapter class and can be used to load it into the JVM as an actual Class. @@ -44,6 +50,8 @@ final class JavaAdapterClassLoader { private static final AccessControlContext CREATE_LOADER_ACC_CTXT = ClassAndLoader.createPermAccCtxt("createClassLoader"); private static final AccessControlContext GET_CONTEXT_ACC_CTXT = ClassAndLoader.createPermAccCtxt(Context.NASHORN_GET_CONTEXT); + private static final Collection<String> VISIBLE_INTERNAL_CLASS_NAMES = Collections.unmodifiableCollection(new HashSet<>( + Arrays.asList(JavaAdapterServices.class.getName(), ScriptFunction.class.getName(), JSType.class.getName()))); private final String className; private final byte[] classBytes; @@ -87,13 +95,14 @@ @Override public Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException { try { + Context.checkPackageAccess(name); return super.loadClass(name, resolve); } catch (final SecurityException se) { // we may be implementing an interface or extending a class that was // loaded by a loader that prevents package.access. If so, it'd throw // SecurityException for nashorn's classes!. For adapter's to work, we - // should be able to refer to nashorn classes. - if (name.startsWith("jdk.nashorn.internal.")) { + // should be able to refer to the few classes it needs in its implementation. + if(VISIBLE_INTERNAL_CLASS_NAMES.contains(name)) { return myLoader.loadClass(name); } throw se;
--- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Wed May 28 16:53:43 2014 +0200 @@ -247,7 +247,7 @@ } private static class AdapterInfo { - private static final ClassAndLoader SCRIPT_OBJECT_LOADER = new ClassAndLoader(ScriptObject.class, true); + private static final ClassAndLoader SCRIPT_OBJECT_LOADER = new ClassAndLoader(ScriptFunction.class, true); private final ClassLoader commonLoader; // TODO: soft reference the JavaAdapterClassLoader objects. They can be recreated when needed.
--- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java Wed May 28 16:53:43 2014 +0200 @@ -116,8 +116,8 @@ * static initializers. * @return the thread-local JS object used to define methods for the class being initialized. */ - public static ScriptObject getClassOverrides() { - final ScriptObject overrides = classOverrides.get(); + public static Object getClassOverrides() { + final Object overrides = classOverrides.get(); assert overrides != null; return overrides; } @@ -134,6 +134,22 @@ NO_PERMISSIONS_INVOKER.invokeExact(method, arg); } + /** + * Set the current global scope + * @param global the global scope + */ + public static void setGlobal(final Object global) { + Context.setGlobal((ScriptObject)global); + } + + /** + * Get the current global scope + * @return the current global scope + */ + public static Object getGlobal() { + return Context.getGlobal(); + } + static void setClassOverrides(ScriptObject overrides) { classOverrides.set(overrides); }
--- a/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java Wed May 28 16:53:43 2014 +0200 @@ -39,16 +39,38 @@ * Check java reflection permission for java reflective and java.lang.invoke access from scripts */ final class ReflectionCheckLinker implements TypeBasedGuardingDynamicLinker{ + private static final Class<?> STATEMENT_CLASS = getBeanClass("Statement"); + private static final Class<?> XMLENCODER_CLASS = getBeanClass("XMLEncoder"); + private static final Class<?> XMLDECODER_CLASS = getBeanClass("XMLDecoder"); + + private static Class<?> getBeanClass(final String name) { + try { + return Class.forName("java.beans." + name); + } catch (final ClassNotFoundException cnfe) { + // Possible to miss this class in other profiles. + return null; + } + } + @Override public boolean canLinkType(final Class<?> type) { return isReflectionClass(type); } private static boolean isReflectionClass(final Class<?> type) { + // Class or ClassLoader subclasses if (type == Class.class || ClassLoader.class.isAssignableFrom(type)) { return true; } + // check for bean reflection + if ((STATEMENT_CLASS != null && STATEMENT_CLASS.isAssignableFrom(type)) || + (XMLENCODER_CLASS != null && XMLENCODER_CLASS.isAssignableFrom(type)) || + (XMLDECODER_CLASS != null && XMLDECODER_CLASS.isAssignableFrom(type))) { + return true; + } + + // package name check final String name = type.getName(); return name.startsWith("java.lang.reflect.") || name.startsWith("java.lang.invoke."); }
--- a/src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java Wed May 28 16:53:43 2014 +0200 @@ -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/Regex.java Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java Wed May 28 16:53:43 2014 +0200 @@ -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/resources/Options.properties Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/resources/Options.properties Wed May 28 16:53:43 2014 +0200 @@ -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", \ @@ -187,6 +194,12 @@ desc="Generate local variable table in .class files." \ } +nashorn.option.lazy.compilation = { \ + name="--lazy-compilation", \ + is_undocumented=true, \ + desc="Use lazy code generation strategies - do not compile the entire script at once." \ +} + nashorn.option.loader.per.compile = { \ name="--loader-per-compile", \ is_undocumented=true, \ @@ -224,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 Wed May 28 13:58:46 2014 +0200 +++ b/src/jdk/nashorn/tools/Shell.java Wed May 28 16:53:43 2014 +0200 @@ -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; @@ -244,7 +246,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, env._strict, FunctionNode.FIRST_FUNCTION_ID, 0, context.getLogger(Parser.class)).parse(); + final FunctionNode functionNode = new Parser(env, sourceFor(fileName, new File(fileName)), errors, env._strict, FunctionNode.FIRST_FUNCTION_ID, 0, context.getLogger(Parser.class)).parse(); if (errors.getNumberOfErrors() != 0) { return COMPILATION_ERROR; @@ -309,7 +311,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; } @@ -411,7 +413,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);
--- a/test/script/basic/JDK-8008448.js Wed May 28 13:58:46 2014 +0200 +++ b/test/script/basic/JDK-8008448.js Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 13:58:46 2014 +0200 +++ b/test/script/basic/JDK-8024120.js Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 13:58:46 2014 +0200 +++ b/test/script/basic/JDK-8024174.js Wed May 28 16:53:43 2014 +0200 @@ -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"); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8027933.js Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -0,0 +1,3 @@ +9223372036854778000 +true +9223372036854778000
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8037562.js Wed May 28 16:53:43 2014 +0200 @@ -0,0 +1,41 @@ +/* + * 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-8037562: Nashorn: JSON.parse comes up with nonexistent entries if there are gaps between the keys + * + * @test + * @run + */ + +var strs = [ + '{ "0":0, "2":2 }', + '{ "0":"", "2":"" }', + '{ "0":0, "5":"hello" }', + '{ "0":"", "15":3234 }', +] + +for (var i in strs) { + print(JSON.stringify(JSON.parse(strs[i]))); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8037562.js.EXPECTED Wed May 28 16:53:43 2014 +0200 @@ -0,0 +1,4 @@ +{"0":0,"2":2} +{"0":"","2":""} +{"0":0,"5":"hello"} +{"0":"","15":3234}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8039387.js Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -0,0 +1,5 @@ +Object.prototype has __proto__? true +descriptor +{"configurable":true,"enumerable":false} +getter function getProto() { [native code] } +setter function setProto() { [native code] }
--- a/test/script/basic/NASHORN-173.js.EXPECTED Wed May 28 13:58:46 2014 +0200 +++ b/test/script/basic/NASHORN-173.js.EXPECTED Wed May 28 16:53:43 2014 +0200 @@ -132,7 +132,7 @@ 2.3423446609034533e+21 2.3423446609034533e+21 11111101111101010001111111010101101000101011011001001000000000000000000 -2224143002343343220233144213324 +2224143002343343220233044213324 375752177255053311000000 73b92b9962990aa44400 7efa8fead15b240000
--- a/test/script/basic/list.js Wed May 28 13:58:46 2014 +0200 +++ b/test/script/basic/list.js Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 13:58:46 2014 +0200 +++ b/test/script/basic/list.js.EXPECTED Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 16:53:43 2014 +0200 @@ -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/error/JDK-8039047.js Wed May 28 16:53:43 2014 +0200 @@ -0,0 +1,35 @@ +/* + * 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-8039047: Parser accepts conditional catch clauses even when --no-syntax-extensions / -nse option is passed + * + * @option --no-syntax-extensions + * @test/compile-error + */ + +try { + func() +} catch (e if e instanceof ReferenceError) { + print("Got ReferenceError " + e); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/error/JDK-8039047.js.EXPECTED Wed May 28 16:53:43 2014 +0200 @@ -0,0 +1,6 @@ +test/script/error/JDK-8039047.js:33:11 Expected ) but found if +} catch (e if e instanceof ReferenceError) { + ^ +test/script/error/JDK-8039047.js:35:0 Expected eof but found } +} +^
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/nosecurity/nosecurity.js Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 13:58:46 2014 +0200 +++ b/test/script/trusted/JDK-8006529.js Wed May 28 16:53:43 2014 +0200 @@ -118,7 +118,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(Context.class, ScriptEnvironment.class, CodeInstaller.class, Source.class, String.class, boolean.class); @@ -126,7 +126,7 @@ // source code, returns a jdk.nashorn.internal.ir.FunctionNode object // representing it. function compile(source, phases) { - var source = SourceConstructor.newInstance("<no name>", source); + var source = sourceForMethod.invoke(null, "<no name>", source); var ctxt = getContextMethod.invoke(null); var env = getEnvMethod.invoke(ctxt);
--- a/test/script/trusted/event_queue.js Wed May 28 13:58:46 2014 +0200 +++ b/test/script/trusted/event_queue.js Wed May 28 16:53:43 2014 +0200 @@ -29,6 +29,7 @@ * @fork * @option -Dnashorn.debug=true * @option --log=recompile:quiet + * @option --lazy-compilation */ print(Debug);
--- a/test/script/trusted/optimistic_recompilation.js Wed May 28 13:58:46 2014 +0200 +++ b/test/script/trusted/optimistic_recompilation.js Wed May 28 16:53:43 2014 +0200 @@ -28,6 +28,7 @@ * @fork * @option -Dnashorn.debug=true * @option --log=recompile:quiet + * @option --lazy-compilation */ var forName = java.lang.Class["forName(String)"];
--- a/test/src/jdk/nashorn/internal/codegen/CompilerTest.java Wed May 28 13:58:46 2014 +0200 +++ b/test/src/jdk/nashorn/internal/codegen/CompilerTest.java Wed May 28 16:53:43 2014 +0200 @@ -25,6 +25,9 @@ package jdk.nashorn.internal.codegen; +import static jdk.nashorn.internal.runtime.Source.readFully; +import static jdk.nashorn.internal.runtime.Source.sourceFor; + 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()); @@ -180,9 +183,9 @@ } } catch (final Throwable t) { log("Compile failed: " + file.getAbsolutePath() + " : " + t); - // if (VERBOSE) { + if (VERBOSE) { t.printStackTrace(System.out); - //} + } failed++; } finally { if (globalChanged) {
--- a/test/src/jdk/nashorn/internal/parser/ParserTest.java Wed May 28 13:58:46 2014 +0200 +++ b/test/src/jdk/nashorn/internal/parser/ParserTest.java Wed May 28 16:53:43 2014 +0200 @@ -25,6 +25,9 @@ package jdk.nashorn.internal.parser; +import static jdk.nashorn.internal.runtime.Source.readFully; +import static jdk.nashorn.internal.runtime.Source.sourceFor; + 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); final 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, context.getEnv()._strict, null).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 Wed May 28 16:53:43 2014 +0200 @@ -0,0 +1,166 @@ +/* + * 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 static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; + +import java.io.File; +import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import javax.script.ScriptEngine; +import javax.script.ScriptException; +import jdk.nashorn.api.scripting.NashornScriptEngineFactory; +import org.testng.annotations.Test; + +/** + * @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 { + assertFalse(ScriptEnvironment.globalOptimistic()); + 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 { + assertFalse(ScriptEnvironment.globalOptimistic()); + 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); + try { + // Check that a new compiled script is stored in existing 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 + } finally { + System.setProperty("user.dir", oldUserDir); + } + } + + @Test + public void codeCacheTest() throws ScriptException, IOException { + assertFalse(ScriptEnvironment.globalOptimistic()); + 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 Wed May 28 13:58:46 2014 +0200 +++ b/test/src/jdk/nashorn/internal/runtime/ContextTest.java Wed May 28 16:53:43 2014 +0200 @@ -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/SourceTest.java Wed May 28 16:53:43 2014 +0200 @@ -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 Wed May 28 13:58:46 2014 +0200 +++ b/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java Wed May 28 16:53:43 2014 +0200 @@ -219,4 +219,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 Wed May 28 13:58:46 2014 +0200 +++ b/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java Wed May 28 16:53:43 2014 +0200 @@ -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;
--- a/test/src/jdk/nashorn/test/models/SourceHelper.java Wed May 28 13:58:46 2014 +0200 +++ b/test/src/jdk/nashorn/test/models/SourceHelper.java Wed May 28 16:53:43 2014 +0200 @@ -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 {