Mercurial > hg > openjdk > aarch64-port > nashorn
changeset 667:f0d3ac2474ee jdk8-b115
Merge
author | lana |
---|---|
date | Thu, 31 Oct 2013 16:47:09 -0700 |
parents | f109bb255b80 (current diff) 5ce78473d6c3 (diff) |
children | 0fb1a427fbf6 |
files | src/jdk/nashorn/internal/runtime/ScriptObjectListAdapter.java |
diffstat | 72 files changed, 2122 insertions(+), 409 deletions(-) [+] |
line wrap: on
line diff
--- a/make/build.xml Thu Oct 31 12:36:38 2013 -0700 +++ b/make/build.xml Thu Oct 31 16:47:09 2013 -0700 @@ -46,6 +46,16 @@ <available property="asm.available" classname="jdk.internal.org.objectweb.asm.Type"/> <!-- check if testng.jar is avaiable --> <available property="testng.available" file="${file.reference.testng.jar}"/> + <!-- check if Jemmy ang testng.jar are avaiable --> + <condition property="jemmy.jfx.testng.available" value="true"> + <and> + <available file="${file.reference.jemmyfx.jar}"/> + <available file="${file.reference.jemmycore.jar}"/> + <available file="${file.reference.jemmyawtinput.jar}"/> + <available file="${file.reference.jfxrt.jar}"/> + <isset property="testng.available"/> + </and> + </condition> <!-- enable/disable make code coverage --> <condition property="cc.enabled"> @@ -351,6 +361,31 @@ </java> </target> + <target name="check-jemmy.jfx.testng" unless="jemmy.jfx.testng.available"> + <echo message="WARNING: Jemmy or JavaFX or TestNG not available, will not run tests. Please copy testng.jar, JemmyCore.jar, JemmyFX.jar, JemmyAWTInput.jar under test${file.separator}lib directory. And make sure you have jfxrt.jar in ${java.home}${file.separator}lib${file.separator}ext dir."/> + </target> + + <target name="testjfx" depends="jar, check-jemmy.jfx.testng, compile-test" if="jemmy.jfx.testng.available"> + <fileset id="test.classes" dir="${build.test.classes.dir}"> + <include name="**/framework/*Test.class"/> + </fileset> + + <copy file="${file.reference.jfxrt.jar}" todir="dist"/> + + <testng outputdir="${build.test.results.dir}" classfilesetref="test.classes" + verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}"> + <jvmarg line="${ext.class.path}"/> + <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx}"/> + <propertyset> + <propertyref prefix="testjfx-test-sys-prop."/> + <mapper from="testjfx-test-sys-prop.*" to="*" type="glob"/> + </propertyset> + <classpath> + <pathelement path="${testjfx.run.test.classpath}"/> + </classpath> + </testng> + </target> + <target name="test262" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available"> <fileset id="test.classes" dir="${build.test.classes.dir}"> <include name="**/framework/*Test.class"/>
--- a/make/project.properties Thu Oct 31 12:36:38 2013 -0700 +++ b/make/project.properties Thu Oct 31 16:47:09 2013 -0700 @@ -118,6 +118,7 @@ test.external.dir=test/script/external test262.dir=${test.external.dir}/test262 test262.suite.dir=${test262.dir}/test/suite +testjfx.dir=${test.script.dir}/jfx test-sys-prop.test.dir=${test.dir} test-sys-prop.test.js.roots=${test.basic.dir} ${test.error.dir} ${test.sandbox.dir} ${test.trusted.dir} @@ -208,6 +209,32 @@ ${test262.dir}/test/harness/framework.js \ ${test262.dir}/test/harness/sta.js +# testjfx test root +testjfx-test-sys-prop.test.js.roots=${testjfx.dir} + +# execute testjfx tests in shared nashorn context or not? +testjfx-test-sys-prop.test.js.shared.context=false + +# framework root for our script tests +testjfx-test-sys-prop.test.js.framework=\ + -fx \ + ${test.script.dir}${file.separator}jfx.js + +file.reference.jemmyfx.jar=test${file.separator}lib${file.separator}JemmyFX.jar +file.reference.jemmycore.jar=test${file.separator}lib${file.separator}JemmyCore.jar +file.reference.jemmyawtinput.jar=test${file.separator}lib${file.separator}JemmyAWTInput.jar +file.reference.jfxrt.jar=${java.home}${file.separator}lib${file.separator}ext${file.separator}jfxrt.jar +testjfx.run.test.classpath=\ + ${file.reference.jemmyfx.jar}${path.separator}\ + ${file.reference.jemmycore.jar}${path.separator}\ + ${file.reference.jemmyawtinput.jar}${path.separator}\ + ${file.reference.testng.jar}${path.separator}\ + ${nashorn.internal.tests.jar}${path.separator}\ + ${nashorn.api.tests.jar} + +# testjfx VM options for script tests with @fork option +testjfx-test-sys-prop.test.fork.jvm.options=${run.test.jvmargs.main} -Xmx${run.test.xmx} -cp ${testjfx.run.test.classpath} + run.test.classpath=\ ${file.reference.testng.jar}:\ ${nashorn.internal.tests.jar}:\
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/nashorn/api/scripting/AbstractJSObject.java Thu Oct 31 16:47:09 2013 -0700 @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.api.scripting; + +import java.util.Collection; +import java.util.Collections; +import java.util.Set; + +/** + * This is the base class for nashorn ScriptObjectMirror class. + * + * This class can also be subclassed by an arbitrary Java class. Nashorn will + * treat objects of such classes just like nashorn script objects. Usual nashorn + * operations like obj[i], obj.foo, obj.func(), delete obj.foo will be glued + * to appropriate method call of this class. + */ +public abstract class AbstractJSObject implements JSObject { + /** + * Call this object as a JavaScript function. This is equivalent to + * 'func.apply(thiz, args)' in JavaScript. + * + * @param thiz 'this' object to be passed to the function + * @param args arguments to method + * @return result of call + */ + @Override + public Object call(final Object thiz, final Object... args) { + throw new UnsupportedOperationException("call"); + } + + /** + * Call this 'constructor' JavaScript function to create a new object. + * This is equivalent to 'new func(arg1, arg2...)' in JavaScript. + * + * @param args arguments to method + * @return result of constructor call + */ + @Override + public Object newObject(final Object... args) { + throw new UnsupportedOperationException("newObject"); + } + + /** + * Evaluate a JavaScript expression. + * + * @param s JavaScript expression to evaluate + * @return evaluation result + */ + @Override + public Object eval(final String s) { + throw new UnsupportedOperationException("eval"); + } + + /** + * Retrieves a named member of this JavaScript object. + * + * @param name of member + * @return member + */ + @Override + public Object getMember(final String name) { + return null; + } + + /** + * Retrieves an indexed member of this JavaScript object. + * + * @param index index slot to retrieve + * @return member + */ + @Override + public Object getSlot(final int index) { + return null; + } + + /** + * Does this object have a named member? + * + * @param name name of member + * @return true if this object has a member of the given name + */ + @Override + public boolean hasMember(final String name) { + return false; + } + + /** + * Does this object have a indexed property? + * + * @param slot index to check + * @return true if this object has a slot + */ + @Override + public boolean hasSlot(final int slot) { + return false; + } + + /** + * Remove a named member from this JavaScript object + * + * @param name name of the member + */ + @Override + public void removeMember(final String name) { + //empty + } + + /** + * Set a named member in this JavaScript object + * + * @param name name of the member + * @param value value of the member + */ + @Override + public void setMember(final String name, final Object value) { + //empty + } + + /** + * Set an indexed member in this JavaScript object + * + * @param index index of the member slot + * @param value value of the member + */ + @Override + public void setSlot(final int index, final Object value) { + //empty + } + + // property and value iteration + + /** + * Returns the set of all property names of this object. + * + * @return set of property names + */ + @Override + @SuppressWarnings("unchecked") + public Set<String> keySet() { + return Collections.EMPTY_SET; + } + + /** + * Returns the set of all property values of this object. + * + * @return set of property values. + */ + @Override + @SuppressWarnings("unchecked") + public Collection<Object> values() { + return Collections.EMPTY_SET; + } + + // JavaScript instanceof check + + /** + * Checking whether the given object is an instance of 'this' object. + * + * @param instance instace to check + * @return true if the given 'instance' is an instance of this 'function' object + */ + @Override + public boolean isInstance(final Object instance) { + return false; + } + + /** + * Checking whether this object is an instance of the given 'clazz' object. + * + * @param clazz clazz to check + * @return true if this object is an instance of the given 'clazz' + */ + @Override + public boolean isInstanceOf(final Object clazz) { + if (clazz instanceof JSObject) { + return ((JSObject)clazz).isInstance(this); + } + + return false; + } + + /** + * ECMA [[Class]] property + * + * @return ECMA [[Class]] property value of this object + */ + @Override + public String getClassName() { + return getClass().getName(); + } + + /** + * Is this a function object? + * + * @return if this mirror wraps a ECMAScript function instance + */ + @Override + public boolean isFunction() { + return false; + } + + /** + * Is this a 'use strict' function object? + * + * @return true if this mirror represents a ECMAScript 'use strict' function + */ + @Override + public boolean isStrictFunction() { + return false; + } + + /** + * Is this an array object? + * + * @return if this mirror wraps a ECMAScript array object + */ + @Override + public boolean isArray() { + return false; + } + + /** + * Returns this object's numeric value. + * + * @return this object's numeric value. + */ + @Override + public double toNumber() { + return Double.NaN; + } +}
--- a/src/jdk/nashorn/api/scripting/JSObject.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/api/scripting/JSObject.java Thu Oct 31 16:47:09 2013 -0700 @@ -30,14 +30,12 @@ import java.util.Set; /** - * This is the base class for nashorn ScriptObjectMirror class. - * - * This class can also be subclassed by an arbitrary Java class. Nashorn will + * This interface can be implemented by an arbitrary Java class. Nashorn will * treat objects of such classes just like nashorn script objects. Usual nashorn * operations like obj[i], obj.foo, obj.func(), delete obj.foo will be glued - * to appropriate method call of this class. + * to appropriate method call of this interface. */ -public abstract class JSObject { +public interface JSObject { /** * Call this object as a JavaScript function. This is equivalent to * 'func.apply(thiz, args)' in JavaScript. @@ -46,9 +44,7 @@ * @param args arguments to method * @return result of call */ - public Object call(final Object thiz, final Object... args) { - throw new UnsupportedOperationException("call"); - } + public Object call(final Object thiz, final Object... args); /** * Call this 'constructor' JavaScript function to create a new object. @@ -57,9 +53,7 @@ * @param args arguments to method * @return result of constructor call */ - public Object newObject(final Object... args) { - throw new UnsupportedOperationException("newObject"); - } + public Object newObject(final Object... args); /** * Evaluate a JavaScript expression. @@ -67,20 +61,7 @@ * @param s JavaScript expression to evaluate * @return evaluation result */ - public Object eval(final String s) { - throw new UnsupportedOperationException("eval"); - } - - /** - * Call a JavaScript function member of this object. - * - * @param name name of the member function to call - * @param args arguments to be passed to the member function - * @return result of call - */ - public Object callMember(final String name, final Object... args) { - throw new UnsupportedOperationException("call"); - } + public Object eval(final String s); /** * Retrieves a named member of this JavaScript object. @@ -88,9 +69,7 @@ * @param name of member * @return member */ - public Object getMember(final String name) { - return null; - } + public Object getMember(final String name); /** * Retrieves an indexed member of this JavaScript object. @@ -98,9 +77,7 @@ * @param index index slot to retrieve * @return member */ - public Object getSlot(final int index) { - return null; - } + public Object getSlot(final int index); /** * Does this object have a named member? @@ -108,9 +85,7 @@ * @param name name of member * @return true if this object has a member of the given name */ - public boolean hasMember(final String name) { - return false; - } + public boolean hasMember(final String name); /** * Does this object have a indexed property? @@ -118,18 +93,14 @@ * @param slot index to check * @return true if this object has a slot */ - public boolean hasSlot(final int slot) { - return false; - } + public boolean hasSlot(final int slot); /** * Remove a named member from this JavaScript object * * @param name name of the member */ - public void removeMember(final String name) { - //empty - } + public void removeMember(final String name); /** * Set a named member in this JavaScript object @@ -137,9 +108,7 @@ * @param name name of the member * @param value value of the member */ - public void setMember(final String name, final Object value) { - //empty - } + public void setMember(final String name, final Object value); /** * Set an indexed member in this JavaScript object @@ -147,9 +116,7 @@ * @param index index of the member slot * @param value value of the member */ - public void setSlot(final int index, final Object value) { - //empty - } + public void setSlot(final int index, final Object value); // property and value iteration @@ -158,20 +125,14 @@ * * @return set of property names */ - @SuppressWarnings("unchecked") - public Set<String> keySet() { - return Collections.EMPTY_SET; - } + public Set<String> keySet(); /** * Returns the set of all property values of this object. * * @return set of property values. */ - @SuppressWarnings("unchecked") - public Collection<Object> values() { - return Collections.EMPTY_SET; - } + public Collection<Object> values(); // JavaScript instanceof check @@ -181,9 +142,7 @@ * @param instance instace to check * @return true if the given 'instance' is an instance of this 'function' object */ - public boolean isInstance(final Object instance) { - return false; - } + public boolean isInstance(final Object instance); /** * Checking whether this object is an instance of the given 'clazz' object. @@ -191,47 +150,40 @@ * @param clazz clazz to check * @return true if this object is an instance of the given 'clazz' */ - public boolean isInstanceOf(final Object clazz) { - if (clazz instanceof JSObject) { - return ((JSObject)clazz).isInstance(this); - } - - return false; - } + public boolean isInstanceOf(final Object clazz); /** * ECMA [[Class]] property * * @return ECMA [[Class]] property value of this object */ - public String getClassName() { - return getClass().getName(); - } + public String getClassName(); /** * Is this a function object? * * @return if this mirror wraps a ECMAScript function instance */ - public boolean isFunction() { - return false; - } + public boolean isFunction(); /** * Is this a 'use strict' function object? * * @return true if this mirror represents a ECMAScript 'use strict' function */ - public boolean isStrictFunction() { - return false; - } + public boolean isStrictFunction(); /** * Is this an array object? * * @return if this mirror wraps a ECMAScript array object */ - public boolean isArray() { - return false; - } + public boolean isArray(); + + /** + * Returns this object's numeric value. + * + * @return this object's numeric value. + */ + public double toNumber(); }
--- a/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java Thu Oct 31 16:47:09 2013 -0700 @@ -43,6 +43,7 @@ import javax.script.Bindings; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.GlobalObject; +import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; @@ -50,7 +51,7 @@ /** * Mirror object that wraps a given Nashorn Script object. */ -public final class ScriptObjectMirror extends JSObject implements Bindings { +public final class ScriptObjectMirror extends AbstractJSObject implements Bindings { private static AccessControlContext getContextAccCtxt() { final Permissions perms = new Permissions(); perms.add(new RuntimePermission(Context.NASHORN_GET_CONTEXT)); @@ -161,7 +162,6 @@ }); } - @Override public Object callMember(final String functionName, final Object... args) { functionName.getClass(); // null check final ScriptObject oldGlobal = Context.getGlobal(); @@ -705,4 +705,13 @@ } } } + + @Override + public double toNumber() { + return inGlobal(new Callable<Double>() { + @Override public Double call() { + return JSType.toNumber(sobj); + } + }); + } }
--- a/src/jdk/nashorn/internal/codegen/BranchOptimizer.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/codegen/BranchOptimizer.java Thu Oct 31 16:47:09 2013 -0700 @@ -72,8 +72,7 @@ } // convert to boolean - codegen.load(unaryNode); - method.convert(Type.BOOLEAN); + codegen.load(unaryNode, Type.BOOLEAN); if (state) { method.ifne(label); } else { @@ -146,8 +145,7 @@ break; } - codegen.load(binaryNode); - method.convert(Type.BOOLEAN); + codegen.load(binaryNode, Type.BOOLEAN); if (state) { method.ifne(label); } else { @@ -169,8 +167,7 @@ } } - codegen.load(node); - method.convert(Type.BOOLEAN); + codegen.load(node, Type.BOOLEAN); if (state) { method.ifne(label); } else {
--- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java Thu Oct 31 16:47:09 2013 -0700 @@ -359,8 +359,11 @@ return load(node, node.hasType() ? node.getType() : null, false); } - private static boolean safeLiteral(final Expression rhs) { - return rhs instanceof LiteralNode && !(rhs instanceof ArrayLiteralNode); + // Test whether conversion from source to target involves a call of ES 9.1 ToPrimitive + // with possible side effects from calling an object's toString or valueOf methods. + private boolean noToPrimitiveConversion(final Type source, final Type target) { + // Object to boolean conversion does not cause ToPrimitive call + return source.isJSPrimitive() || !target.isJSPrimitive() || target.isBoolean(); } MethodEmitter loadBinaryOperands(final Expression lhs, final Expression rhs, final Type type) { @@ -374,25 +377,19 @@ // can combine a LOAD with a CONVERT operation (e.g. use a dynamic getter with the conversion target type as its // return value). What we do here is reorder LOAD RIGHT and CONVERT LEFT when possible; it is possible only when // we can prove that executing CONVERT LEFT can't have a side effect that changes the value of LOAD RIGHT. - // Basically, if we know that either LEFT is not an object, or RIGHT is a constant literal, then we can do the + // Basically, if we know that either LEFT already is a primitive value, or does not have to be converted to + // a primitive value, or RIGHT is an expression that loads without side effects, then we can do the // reordering and collapse LOAD/CONVERT into a single operation; otherwise we need to do the more costly // separate operations to preserve specification semantics. - final Type lhsType = lhs.getType(); - if (lhsType.isObject() && !safeLiteral(rhs)) { - // Can't reorder. Load and convert separately. - load(lhs, lhsType, baseAlreadyOnStack); - load(rhs, rhs.getType(), false); - // Avoid empty SWAP, SWAP bytecode sequence if CONVERT LEFT is a no-op - if (!lhsType.isEquivalentTo(type)) { - method.swap(); - method.convert(type); - method.swap(); - } - method.convert(type); - } else { + if (noToPrimitiveConversion(lhs.getType(), type) || rhs.isLocal()) { // Can reorder. Combine load and convert into single operations. load(lhs, type, baseAlreadyOnStack); load(rhs, type, false); + } else { + // Can't reorder. Load and convert separately. + load(lhs, lhs.getType(), baseAlreadyOnStack); + load(rhs, rhs.getType(), false); + method.swap().convert(type).swap().convert(type); } return method; @@ -402,7 +399,7 @@ return loadBinaryOperands(node.lhs(), node.rhs(), node.getType(), false); } - private MethodEmitter load(final Expression node, final Type type) { + MethodEmitter load(final Expression node, final Type type) { return load(node, type, false); } @@ -432,7 +429,7 @@ @Override public boolean enterAccessNode(final AccessNode accessNode) { if (!baseAlreadyOnStack) { - load(accessNode.getBase()).convert(Type.OBJECT); + load(accessNode.getBase(), Type.OBJECT); } assert method.peekType().isObject(); method.dynamicGet(type, accessNode.getProperty().getName(), getCallSiteFlags(), accessNode.isFunction()); @@ -442,7 +439,7 @@ @Override public boolean enterIndexNode(final IndexNode indexNode) { if (!baseAlreadyOnStack) { - load(indexNode.getBase()).convert(Type.OBJECT); + load(indexNode.getBase(), Type.OBJECT); load(indexNode.getIndex()); } method.dynamicGetIndex(type, getCallSiteFlags(), indexNode.isFunction()); @@ -632,11 +629,13 @@ final Type[] params = signature == null ? null : Type.getMethodArguments(signature); for (final Expression arg : args) { assert arg != null; - load(arg); if (n >= argCount) { + load(arg); method.pop(); // we had to load the arg for its side effects } else if (params != null) { - method.convert(params[n]); + load(arg, params[n]); + } else { + load(arg); } n++; } @@ -707,6 +706,12 @@ final CallNode.EvalArgs evalArgs = callNode.getEvalArgs(); // load evaluated code load(evalArgs.getCode(), Type.OBJECT); + // load second and subsequent args for side-effect + final List<Expression> args = callNode.getArgs(); + final int numArgs = args.size(); + for (int i = 1; i < numArgs; i++) { + load(args.get(i)).pop(); + } // special/extra 'eval' arguments load(evalArgs.getThis()); method.load(evalArgs.getLocation()); @@ -1277,7 +1282,7 @@ for (int i = 0; i < args.size(); i++) { method.dup(); method.load(i); - load(args.get(i)).convert(Type.OBJECT); //has to be upcast to object or we fail + load(args.get(i), Type.OBJECT); //has to be upcast to object or we fail method.arraystore(); } @@ -1719,7 +1724,7 @@ } for (final Expression arg : args) { - load(arg).convert(Type.OBJECT); + load(arg, Type.OBJECT); } method.invokestatic( @@ -2105,7 +2110,7 @@ if (exceptionCondition != null) { next = new Label("next"); - load(exceptionCondition).convert(Type.BOOLEAN).ifeq(next); + load(exceptionCondition, Type.BOOLEAN).ifeq(next); } else { next = null; } @@ -2352,7 +2357,7 @@ final List<Expression> args = callNode.getArgs(); // Load function reference. - load(callNode.getFunction()).convert(Type.OBJECT); // must detect type error + load(callNode.getFunction(), Type.OBJECT); // must detect type error method.dynamicNew(1 + loadArgs(args), getCallSiteFlags()); method.store(unaryNode.getSymbol()); @@ -2383,7 +2388,7 @@ @Override public boolean enterSUB(final UnaryNode unaryNode) { assert unaryNode.getType().isNumeric(); - load(unaryNode.rhs()).convert(unaryNode.getType()).neg().store(unaryNode.getSymbol()); + load(unaryNode.rhs(), unaryNode.getType()).neg().store(unaryNode.getSymbol()); return false; } @@ -2424,7 +2429,7 @@ final Label skip = new Label("skip"); - load(lhs).convert(Type.OBJECT).dup().convert(Type.BOOLEAN); + load(lhs, Type.OBJECT).dup().convert(Type.BOOLEAN); if (binaryNode.tokenType() == TokenType.AND) { method.ifeq(skip); @@ -2433,7 +2438,7 @@ } method.pop(); - load(rhs).convert(Type.OBJECT); + load(rhs, Type.OBJECT); method.label(skip); method.store(binaryNode.getSymbol());
--- a/src/jdk/nashorn/internal/codegen/Lower.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/codegen/Lower.java Thu Oct 31 16:47:09 2013 -0700 @@ -88,12 +88,12 @@ private static final DebugLogger LOG = new DebugLogger("lower"); // needed only to get unique eval id - private final CodeInstaller installer; + private final CodeInstaller<?> installer; /** * Constructor. */ - Lower(final CodeInstaller installer) { + Lower(final CodeInstaller<?> installer) { super(new BlockLexicalContext() { @Override
--- a/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java Thu Oct 31 16:47:09 2013 -0700 @@ -32,7 +32,6 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Set; - import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.Expression; import jdk.nashorn.internal.ir.LiteralNode; @@ -143,7 +142,7 @@ method.dup(); method.getField(Type.getInternalName(ScriptObject.class), "spill", Type.OBJECT_ARRAY.getDescriptor()); method.load(property.getSlot()); - codegen.load(values.get(i)).convert(OBJECT); + codegen.load(values.get(i), OBJECT); method.arraystore(); } }
--- a/src/jdk/nashorn/internal/codegen/types/Type.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/codegen/types/Type.java Thu Oct 31 16:47:09 2013 -0700 @@ -292,6 +292,16 @@ } /** + * Determines whether this type represents an primitive type according to the ECMAScript specification, + * which includes Boolean, Number, and String. + * + * @return true if a JavaScript primitive type, false otherwise. + */ + public boolean isJSPrimitive() { + return !isObject() || isString(); + } + + /** * Determines whether a type is the BOOLEAN type * @return true if BOOLEAN, false otherwise */ @@ -443,7 +453,7 @@ } else if (type0.isArray() != type1.isArray()) { //array and non array is always object, widest(Object[], int) NEVER returns Object[], which has most weight. that does not make sense return Type.OBJECT; - } else if (type0.isObject() && type1.isObject() && ((ObjectType)type0).getTypeClass() != ((ObjectType)type1).getTypeClass()) { + } else if (type0.isObject() && type1.isObject() && type0.getTypeClass() != type1.getTypeClass()) { // Object<type=String> and Object<type=ScriptFunction> will produce Object // TODO: maybe find most specific common superclass? return Type.OBJECT;
--- a/src/jdk/nashorn/internal/ir/BinaryNode.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/ir/BinaryNode.java Thu Oct 31 16:47:09 2013 -0700 @@ -90,6 +90,9 @@ return Type.LONG; case ASSIGN_SAR: case ASSIGN_SHL: + case BIT_AND: + case BIT_OR: + case BIT_XOR: case ASSIGN_BIT_AND: case ASSIGN_BIT_OR: case ASSIGN_BIT_XOR: @@ -170,6 +173,42 @@ } @Override + public boolean isLocal() { + switch (tokenType()) { + case SAR: + case SHL: + case SHR: + case BIT_AND: + case BIT_OR: + case BIT_XOR: + case ADD: + case DIV: + case MOD: + case MUL: + case SUB: + return lhs.isLocal() && lhs.getType().isJSPrimitive() + && rhs.isLocal() && rhs.getType().isJSPrimitive(); + case ASSIGN_ADD: + case ASSIGN_BIT_AND: + case ASSIGN_BIT_OR: + case ASSIGN_BIT_XOR: + case ASSIGN_DIV: + case ASSIGN_MOD: + case ASSIGN_MUL: + case ASSIGN_SAR: + case ASSIGN_SHL: + case ASSIGN_SHR: + case ASSIGN_SUB: + return lhs instanceof IdentNode && lhs.isLocal() && lhs.getType().isJSPrimitive() + && rhs.isLocal() && rhs.getType().isJSPrimitive(); + case ASSIGN: + return lhs instanceof IdentNode && lhs.isLocal() && rhs.isLocal(); + default: + return false; + } + } + + @Override public void toString(final StringBuilder sb) { final TokenType type = tokenType();
--- a/src/jdk/nashorn/internal/ir/Expression.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/ir/Expression.java Thu Oct 31 16:47:09 2013 -0700 @@ -96,4 +96,16 @@ assert hasType() : this + " has no type"; return symbol.getSymbolType(); } + + /** + * Returns {@code true} if this expression depends exclusively on state that is constant + * or local to the currently running function and thus inaccessible to other functions. + * This implies that a local expression must not call any other functions (neither directly + * nor implicitly through a getter, setter, or object-to-primitive type conversion). + * + * @return true if this expression does not depend on state shared with other functions. + */ + public boolean isLocal() { + return false; + } }
--- a/src/jdk/nashorn/internal/ir/IdentNode.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/ir/IdentNode.java Thu Oct 31 16:47:09 2013 -0700 @@ -138,6 +138,11 @@ return getName(); } + @Override + public boolean isLocal() { + return !getSymbol().isScope(); + } + /** * Check if this IdentNode is a property name * @return true if this is a property name
--- a/src/jdk/nashorn/internal/ir/LiteralNode.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/ir/LiteralNode.java Thu Oct 31 16:47:09 2013 -0700 @@ -275,6 +275,11 @@ public boolean isTrue() { return JSType.toBoolean(value); } + + @Override + public boolean isLocal() { + return true; + } } @Immutable
--- a/src/jdk/nashorn/internal/ir/TernaryNode.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/ir/TernaryNode.java Thu Oct 31 16:47:09 2013 -0700 @@ -109,6 +109,13 @@ } } + @Override + public boolean isLocal() { + return getTest().isLocal() + && getTrueExpression().isLocal() + && getFalseExpression().isLocal(); + } + /** * Get the test expression for this ternary expression, i.e. "x" in x ? y : z * @return the test expression
--- a/src/jdk/nashorn/internal/ir/UnaryNode.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/ir/UnaryNode.java Thu Oct 31 16:47:09 2013 -0700 @@ -129,6 +129,26 @@ } @Override + public boolean isLocal() { + switch (tokenType()) { + case NEW: + return false; + case ADD: + case SUB: + case NOT: + case BIT_NOT: + return rhs.isLocal() && rhs.getType().isJSPrimitive(); + case DECPOSTFIX: + case DECPREFIX: + case INCPOSTFIX: + case INCPREFIX: + return rhs instanceof IdentNode && rhs.isLocal() && rhs.getType().isJSPrimitive(); + default: + return rhs.isLocal(); + } + } + + @Override public void toString(final StringBuilder sb) { toString(sb, new Runnable() { @Override
--- a/src/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java Thu Oct 31 16:47:09 2013 -0700 @@ -25,10 +25,10 @@ package jdk.nashorn.internal.ir.debug; -import java.lang.management.ManagementFactory; -import java.lang.management.MemoryPoolMXBean; import java.lang.reflect.Array; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayDeque; import java.util.ArrayList; @@ -51,9 +51,9 @@ * switch, it can not detect * this fact and will report incorrect sizes, as it will presume the default JVM * behavior. - * - * @author Attila Szegedi */ + +@SuppressWarnings("StaticNonFinalUsedInInitialization") public class ObjectSizeCalculator { /** @@ -368,6 +368,29 @@ type.getName()); } + // ALERT: java.lang.management is not available in compact 1. We need + // to use reflection to soft link test memory statistics. + + static Class<?> managementFactory = null; + static Class<?> memoryPoolMXBean = null; + static Class<?> memoryUsage = null; + static Method getMemoryPoolMXBeans = null; + static Method getUsage = null; + static Method getMax = null; + static { + try { + managementFactory = Class.forName("java.lang.management.ManagementFactory"); + memoryPoolMXBean = Class.forName("java.lang.management.MemoryPoolMXBean"); + memoryUsage = Class.forName("java.lang.management.MemoryUsage"); + + getMemoryPoolMXBeans = managementFactory.getMethod("getMemoryPoolMXBeans"); + getUsage = memoryPoolMXBean.getMethod("getUsage"); + getMax = memoryUsage.getMethod("getMax"); + } catch (ClassNotFoundException | NoSuchMethodException | SecurityException ex) { + // Pass thru, asserts when attempting to use. + } + } + /** * Return the current memory usage * @return current memory usage derived from system configuration @@ -409,9 +432,33 @@ strVmVersion.indexOf('.'))); if (vmVersion >= 17) { long maxMemory = 0; - for (MemoryPoolMXBean mp : ManagementFactory.getMemoryPoolMXBeans()) { - maxMemory += mp.getUsage().getMax(); + + /* + See ALERT above. The reflection code below duplicates the following + sequence, and avoids hard coding of java.lang.management. + + for (MemoryPoolMXBean mp : ManagementFactory.getMemoryPoolMXBeans()) { + maxMemory += mp.getUsage().getMax(); + } + */ + + if (getMemoryPoolMXBeans == null) { + throw new AssertionError("java.lang.management not available in compact 1"); } + + try { + final List<?> memoryPoolMXBeans = (List<?>)getMemoryPoolMXBeans.invoke(managementFactory); + for (final Object mp : memoryPoolMXBeans) { + final Object usage = getUsage.invoke(mp); + final Object max = getMax.invoke(usage); + maxMemory += ((Long)max).longValue(); + } + } catch (IllegalAccessException | + IllegalArgumentException | + InvocationTargetException ex) { + throw new AssertionError("java.lang.management not available in compact 1"); + } + if (maxMemory < 30L * 1024 * 1024 * 1024) { // HotSpot 17.0 and above use compressed OOPs below 30GB of RAM total // for all memory pools (yes, including code cache).
--- a/src/jdk/nashorn/internal/objects/Global.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/objects/Global.java Thu Oct 31 16:47:09 2013 -0700 @@ -1665,9 +1665,9 @@ final ScriptObject stringPrototype = getStringPrototype(); stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0); - // add Array.prototype.length + // set isArray flag on Array.prototype final ScriptObject arrayPrototype = getArrayPrototype(); - arrayPrototype.addOwnProperty("length", Attribute.NOT_ENUMERABLE|Attribute.NOT_CONFIGURABLE, 0.0); + arrayPrototype.setIsArray(); this.DEFAULT_DATE = new NativeDate(Double.NaN, this);
--- a/src/jdk/nashorn/internal/objects/NativeArray.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/objects/NativeArray.java Thu Oct 31 16:47:09 2013 -0700 @@ -372,9 +372,7 @@ */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) public static Object isArray(final Object self, final Object arg) { - return isArray(arg) || (arg == Global.instance().getArrayPrototype()) - || (arg instanceof NativeRegExpExecResult) - || (arg instanceof JSObject && ((JSObject)arg).isArray()); + return isArray(arg) || (arg instanceof JSObject && ((JSObject)arg).isArray()); } /** @@ -403,6 +401,26 @@ } } + /** + * Prototype length getter + * @param self self reference + * @return the length of the object + */ + @Getter(name = "length", where = Where.PROTOTYPE, attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE) + public static Object getProtoLength(final Object self) { + return length(self); // Same as instance getter but we can't make nasgen use the same method for prototype + } + + /** + * Prototype length setter + * @param self self reference + * @param length new length property + */ + @Setter(name = "length", where = Where.PROTOTYPE, attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE) + public static void setProtoLength(final Object self, final Object length) { + length(self, length); // Same as instance setter but we can't make nasgen use the same method for prototype + } + static long validLength(final Object length, final boolean reject) { final double doubleLength = JSType.toNumber(length); if (!Double.isNaN(doubleLength) && JSType.isRepresentableAsLong(doubleLength)) { @@ -1007,19 +1025,42 @@ final long actualStart = relativeStart < 0 ? Math.max(len + relativeStart, 0) : Math.min(relativeStart, len); final long actualDeleteCount = Math.min(Math.max(JSType.toLong(deleteCount), 0), len - actualStart); - final NativeArray array = new NativeArray(actualDeleteCount); + NativeArray returnValue; + + if (actualStart <= Integer.MAX_VALUE && actualDeleteCount <= Integer.MAX_VALUE && bulkable(sobj)) { + try { + returnValue = new NativeArray(sobj.getArray().fastSplice((int)actualStart, (int)actualDeleteCount, items.length)); - for (long k = 0; k < actualDeleteCount; k++) { - final long from = actualStart + k; + // Since this is a dense bulkable array we can use faster defineOwnProperty to copy new elements + int k = (int) actualStart; + for (int i = 0; i < items.length; i++, k++) { + sobj.defineOwnProperty(k, items[i]); + } + } catch (UnsupportedOperationException uoe) { + returnValue = slowSplice(sobj, actualStart, actualDeleteCount, items, len); + } + } else { + returnValue = slowSplice(sobj, actualStart, actualDeleteCount, items, len); + } + + return returnValue; + } + + private static NativeArray slowSplice(final ScriptObject sobj, final long start, final long deleteCount, final Object[] items, final long len) { + + final NativeArray array = new NativeArray(deleteCount); + + for (long k = 0; k < deleteCount; k++) { + final long from = start + k; if (sobj.has(from)) { array.defineOwnProperty(ArrayIndex.getArrayIndex(k), sobj.get(from)); } } - if (items.length < actualDeleteCount) { - for (long k = actualStart; k < (len - actualDeleteCount); k++) { - final long from = k + actualDeleteCount; + if (items.length < deleteCount) { + for (long k = start; k < (len - deleteCount); k++) { + final long from = k + deleteCount; final long to = k + items.length; if (sobj.has(from)) { @@ -1029,12 +1070,12 @@ } } - for (long k = len; k > (len - actualDeleteCount + items.length); k--) { + for (long k = len; k > (len - deleteCount + items.length); k--) { sobj.delete(k - 1, true); } - } else if (items.length > actualDeleteCount) { - for (long k = len - actualDeleteCount; k > actualStart; k--) { - final long from = k + actualDeleteCount - 1; + } else if (items.length > deleteCount) { + for (long k = len - deleteCount; k > start; k--) { + final long from = k + deleteCount - 1; final long to = k + items.length - 1; if (sobj.has(from)) { @@ -1046,12 +1087,12 @@ } } - long k = actualStart; + long k = start; for (int i = 0; i < items.length; i++, k++) { sobj.set(k, items[i], true); } - final long newLength = len - actualDeleteCount + items.length; + final long newLength = len - deleteCount + items.length; sobj.set("length", newLength, true); return array; @@ -1122,12 +1163,16 @@ try { final ScriptObject sobj = (ScriptObject)Global.toObject(self); final long len = JSType.toUint32(sobj.getLength()); - final long n = JSType.toLong(fromIndex); - - if (len == 0 || n >= len) { + if (len == 0) { return -1; } + final long n = JSType.toLong(fromIndex); + if (n >= len) { + return -1; + } + + for (long k = Math.max(0, (n < 0) ? (len - Math.abs(n)) : n); k < len; k++) { if (sobj.has(k)) { if (ScriptRuntime.EQ_STRICT(sobj.get(k), searchElement)) {
--- a/src/jdk/nashorn/internal/objects/NativeJSAdapter.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/objects/NativeJSAdapter.java Thu Oct 31 16:47:09 2013 -0700 @@ -629,7 +629,8 @@ // to name. Probably not a big deal, but if we can ever make it leaner, it'd be nice. return new GuardedInvocation(MH.dropArguments(MH.constant(Object.class, func.makeBoundFunction(this, new Object[] { name })), 0, Object.class), - adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), __call__), testJSAdaptor(adaptee, null, null, null)); + adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), __call__), + testJSAdaptor(adaptee, null, null, null)); } } throw typeError("no.such.function", desc.getNameToken(2), ScriptRuntime.safeToString(this));
--- a/src/jdk/nashorn/internal/objects/NativeString.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/objects/NativeString.java Thu Oct 31 16:47:09 2013 -0700 @@ -505,7 +505,7 @@ */ @Function(attributes = Attribute.NOT_ENUMERABLE) public static Object charAt(final Object self, final Object pos) { - return charAt(self, JSType.toInteger(pos)); + return charAtImpl(checkObjectToString(self), JSType.toInteger(pos)); } /** @@ -527,7 +527,10 @@ */ @SpecializedFunction public static String charAt(final Object self, final int pos) { - final String str = checkObjectToString(self); + return charAtImpl(checkObjectToString(self), pos); + } + + private static String charAtImpl(final String str, final int pos) { return (pos < 0 || pos >= str.length()) ? "" : String.valueOf(str.charAt(pos)); } @@ -539,7 +542,7 @@ */ @Function(attributes = Attribute.NOT_ENUMERABLE) public static Object charCodeAt(final Object self, final Object pos) { - return charCodeAt(self, JSType.toInteger(pos)); + return charCodeAtImpl(checkObjectToString(self), JSType.toInteger(pos)); } /** @@ -561,7 +564,10 @@ */ @SpecializedFunction public static double charCodeAt(final Object self, final int pos) { - final String str = checkObjectToString(self); + return charCodeAtImpl(checkObjectToString(self), pos); + } + + private static double charCodeAtImpl(final String str, final int pos) { return (pos < 0 || pos >= str.length()) ? Double.NaN : str.charAt(pos); }
--- a/src/jdk/nashorn/internal/parser/Lexer.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/parser/Lexer.java Thu Oct 31 16:47:09 2013 -0700 @@ -47,7 +47,6 @@ import jdk.nashorn.internal.runtime.ECMAErrors; import jdk.nashorn.internal.runtime.ErrorManager; import jdk.nashorn.internal.runtime.JSErrorType; -import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.ParserException; import jdk.nashorn.internal.runtime.Source; import jdk.nashorn.internal.runtime.options.Options; @@ -1054,16 +1053,6 @@ } /** - * Convert string to number. - * - * @param valueString String to convert. - * @return Converted number. - */ - private static Number valueOf(final String valueString) throws NumberFormatException { - return JSType.narrowestIntegerRepresentation(Double.valueOf(valueString)); - } - - /** * Scan a number. */ protected void scanNumber() { @@ -1623,7 +1612,7 @@ case HEXADECIMAL: return Lexer.valueOf(source.getString(start + 2, len - 2), 16); // number case FLOATING: - return Lexer.valueOf(source.getString(start, len)); // number + return Double.valueOf(source.getString(start, len)); // number case STRING: return source.getString(start, len); // String case ESCSTRING:
--- a/src/jdk/nashorn/internal/runtime/CompiledFunctions.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/runtime/CompiledFunctions.java Thu Oct 31 16:47:09 2013 -0700 @@ -24,6 +24,7 @@ */ package jdk.nashorn.internal.runtime; +import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; import java.util.Iterator; import java.util.TreeSet; @@ -35,6 +36,8 @@ @SuppressWarnings("serial") final class CompiledFunctions extends TreeSet<CompiledFunction> { + private CompiledFunction generic; + CompiledFunction best(final MethodType type) { final Iterator<CompiledFunction> iter = iterator(); while (iter.hasNext()) { @@ -43,13 +46,10 @@ return next; } } - return mostGeneric(); + return generic(); } boolean needsCallee() { - for (final CompiledFunction inv : this) { - assert ScriptFunctionData.needsCallee(inv.getInvoker()) == ScriptFunctionData.needsCallee(mostGeneric().getInvoker()); - } return ScriptFunctionData.needsCallee(mostGeneric().getInvoker()); } @@ -57,6 +57,48 @@ return last(); } + CompiledFunction generic() { + CompiledFunction gen = this.generic; + if (gen == null) { + gen = this.generic = makeGeneric(mostGeneric()); + } + return gen; + } + + private static CompiledFunction makeGeneric(final CompiledFunction func) { + final MethodHandle invoker = composeGenericMethod(func.getInvoker()); + final MethodHandle constructor = func.hasConstructor() ? composeGenericMethod(func.getConstructor()) : null; + return new CompiledFunction(invoker.type(), invoker, constructor); + } + + /** + * Takes a method handle, and returns a potentially different method handle that can be used in + * {@code ScriptFunction#invoke(Object, Object...)} or {code ScriptFunction#construct(Object, Object...)}. + * The returned method handle will be sure to return {@code Object}, and will have all its parameters turned into + * {@code Object} as well, except for the following ones: + * <ul> + * <li>a last parameter of type {@code Object[]} which is used for vararg functions,</li> + * <li>the first argument, which is forced to be {@link ScriptFunction}, in case the function receives itself + * (callee) as an argument.</li> + * </ul> + * + * @param mh the original method handle + * + * @return the new handle, conforming to the rules above. + */ + private static MethodHandle composeGenericMethod(final MethodHandle mh) { + final MethodType type = mh.type(); + final boolean isVarArg = ScriptFunctionData.isVarArg(mh); + final int paramCount = isVarArg ? type.parameterCount() - 1 : type.parameterCount(); + + MethodType newType = MethodType.genericMethodType(paramCount, isVarArg); + + if (ScriptFunctionData.needsCallee(mh)) { + newType = newType.changeParameterType(0, ScriptFunction.class); + } + return type.equals(newType) ? mh : mh.asType(newType); + } + /** * Is the given type even more specific than this entire list? That means * we have an opportunity for more specific versions of the method
--- a/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java Thu Oct 31 16:47:09 2013 -0700 @@ -40,7 +40,7 @@ * * @param name name * @param arity arity - * @param list precompiled code + * @param functions precompiled code * @param isStrict strict * @param isBuiltin builtin * @param isConstructor constructor @@ -73,12 +73,13 @@ } private void addInvoker(final MethodHandle mh) { - boolean needsCallee = needsCallee(mh); if (isConstructor(mh)) { - //only nasgen constructors: (boolean, self, args) are subject to binding a boolean newObj. isConstructor - //is too conservative a check. However, isConstructor(mh) always implies isConstructor param + // only nasgen constructors: (boolean, self, args) are subject to binding a boolean newObj. isConstructor + // is too conservative a check. However, isConstructor(mh) always implies isConstructor param assert isConstructor(); - code.add(new CompiledFunction(mh.type(), MH.insertArguments(mh, 0, false), composeConstructor(MH.insertArguments(mh, 0, true), needsCallee))); //make sure callee state can be determined when we reach constructor + 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)); } else { code.add(new CompiledFunction(mh.type(), mh)); }
--- a/src/jdk/nashorn/internal/runtime/JSType.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/runtime/JSType.java Thu Oct 31 16:47:09 2013 -0700 @@ -210,26 +210,6 @@ } /** - * Get the smallest integer representation of a number. Returns an Integer - * for something that is int representable, and Long for something that - * is long representable. If the number needs to be a double, this is an - * identity function - * - * @param number number to check - * - * @return Number instanceof the narrowest possible integer representation for number - */ - public static Number narrowestIntegerRepresentation(final double number) { - if (isRepresentableAsInt(number)) { - return (int)number; - } else if (isRepresentableAsLong(number)) { - return (long)number; - } else { - return number; - } - } - - /** * Check whether an object is primitive * * @param obj an object @@ -266,12 +246,11 @@ * @return the primitive form of the object */ public static Object toPrimitive(final Object obj, final Class<?> hint) { - if (!(obj instanceof ScriptObject)) { - return obj; - } + return obj instanceof ScriptObject ? toPrimitive((ScriptObject)obj, hint) : obj; + } - final ScriptObject sobj = (ScriptObject)obj; - final Object result = sobj.getDefaultValue(hint); + private static Object toPrimitive(final ScriptObject sobj, final Class<?> hint) { + final Object result = sobj.getDefaultValue(hint); if (!isPrimitive(result)) { throw typeError("bad.default.value", result.toString()); @@ -495,6 +474,19 @@ return toNumberGeneric(obj); } + + /** + * JavaScript compliant conversion of Object to number + * See ECMA 9.3 ToNumber + * + * @param obj an object + * + * @return a number + */ + public static double toNumber(final ScriptObject obj) { + return toNumber(toPrimitive(obj, Number.class)); + } + /** * Digit representation for a character * @@ -1048,7 +1040,11 @@ } if (obj instanceof ScriptObject) { - return toNumber(toPrimitive(obj, Number.class)); + return toNumber((ScriptObject)obj); + } + + if (obj instanceof JSObject) { + return ((JSObject)obj).toNumber(); } return Double.NaN;
--- a/src/jdk/nashorn/internal/runtime/ListAdapter.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/runtime/ListAdapter.java Thu Oct 31 16:47:09 2013 -0700 @@ -33,6 +33,7 @@ import java.util.RandomAccess; import java.util.concurrent.Callable; import jdk.nashorn.api.scripting.JSObject; +import jdk.nashorn.api.scripting.ScriptObjectMirror; import jdk.nashorn.internal.runtime.linker.Bootstrap; import jdk.nashorn.internal.runtime.linker.InvokeByName; @@ -135,7 +136,8 @@ */ public static ListAdapter create(final Object obj) { if (obj instanceof ScriptObject) { - return new ScriptObjectListAdapter((ScriptObject)obj); + final Object mirror = ScriptObjectMirror.wrap(obj, Context.getGlobal()); + return new JSObjectListAdapter((JSObject)mirror); } else if (obj instanceof JSObject) { return new JSObjectListAdapter((JSObject)obj); } else {
--- a/src/jdk/nashorn/internal/runtime/PropertyMap.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/runtime/PropertyMap.java Thu Oct 31 16:47:09 2013 -0700 @@ -26,6 +26,8 @@ package jdk.nashorn.internal.runtime; import static jdk.nashorn.internal.runtime.PropertyHashMap.EMPTY_HASHMAP; +import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex; +import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex; import java.lang.invoke.SwitchPoint; import java.lang.ref.WeakReference; @@ -50,6 +52,8 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener { /** 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? */ + public static final int CONTAINS_ARRAY_KEYS = 0b0000_0010; /** This mask is used to preserve certain flags when cloning the PropertyMap. Others should not be copied */ private static final int CLONEABLE_FLAGS_MASK = 0b0000_1111; /** Has a listener been added to this property map. This flag is not copied when cloning a map. See {@link PropertyListener} */ @@ -91,12 +95,16 @@ * @param fieldCount Number of fields in use. * @param fieldMaximum Number of fields available. * @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) { + private PropertyMap(final PropertyHashMap properties, final int fieldCount, final int fieldMaximum, final int spillLength, final boolean containsArrayKeys) { this.properties = properties; this.fieldCount = fieldCount; this.fieldMaximum = fieldMaximum; this.spillLength = spillLength; + if (containsArrayKeys) { + setContainsArrayKeys(); + } if (Context.DEBUG) { count++; @@ -104,15 +112,6 @@ } /** - * Constructor. - * - * @param properties A {@link PropertyHashMap} with initial contents. - */ - private PropertyMap(final PropertyHashMap properties) { - this(properties, 0, 0, 0); - } - - /** * Cloning constructor. * * @param propertyMap Existing property map. @@ -152,12 +151,15 @@ if (Context.DEBUG) { duplicatedCount++; } - return new PropertyMap(this.properties); + return new PropertyMap(this.properties, 0, 0, 0, containsArrayKeys()); } /** * Public property map allocator. * + * <p>It is the caller's responsibility to make sure that {@code properties} does not contain + * properties with keys that are valid array indices.</p> + * * @param properties Collection of initial properties. * @param fieldCount Number of fields in use. * @param fieldMaximum Number of fields available. @@ -166,11 +168,15 @@ */ public static PropertyMap newMap(final Collection<Property> properties, final int fieldCount, final int fieldMaximum, final int spillLength) { PropertyHashMap newProperties = EMPTY_HASHMAP.immutableAdd(properties); - return new PropertyMap(newProperties, fieldCount, fieldMaximum, spillLength); + return new PropertyMap(newProperties, fieldCount, fieldMaximum, spillLength, false); } /** * Public property map allocator. Used by nasgen generated code. + * + * <p>It is the caller's responsibility to make sure that {@code properties} does not contain + * properties with keys that are valid array indices.</p> + * * @param properties Collection of initial properties. * @return New {@link PropertyMap}. */ @@ -184,7 +190,7 @@ * @return New empty {@link PropertyMap}. */ public static PropertyMap newMap() { - return new PropertyMap(EMPTY_HASHMAP); + return new PropertyMap(EMPTY_HASHMAP, 0, 0, 0, false); } /** @@ -294,6 +300,9 @@ if(!property.isSpill()) { newMap.fieldCount = Math.max(newMap.fieldCount, property.getSlot() + 1); } + if (isValidArrayIndex(getArrayIndex(property.getKey()))) { + newMap.setContainsArrayKeys(); + } newMap.spillLength += property.getSpillCount(); } @@ -408,6 +417,9 @@ final PropertyMap newMap = new PropertyMap(this, newProperties); for (final Property property : otherProperties) { + if (isValidArrayIndex(getArrayIndex(property.getKey()))) { + newMap.setContainsArrayKeys(); + } newMap.spillLength += property.getSpillCount(); } @@ -700,6 +712,22 @@ } /** + * Check if this map contains properties with valid array keys + * + * @return {@code true} if this map contains properties with valid array keys + */ + public final boolean containsArrayKeys() { + return (flags & CONTAINS_ARRAY_KEYS) != 0; + } + + /** + * Flag this object as having array keys in defined properties + */ + private void setContainsArrayKeys() { + flags |= CONTAINS_ARRAY_KEYS; + } + + /** * Check whether a {@link PropertyListener} has been added to this map. * * @return {@code true} if {@link PropertyListener} exists
--- a/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Thu Oct 31 16:47:09 2013 -0700 @@ -213,13 +213,13 @@ */ public final MethodHandle getGenericInvoker() { ensureCodeGenerated(); - return composeGenericMethod(code.mostGeneric().getInvoker()); + return code.generic().getInvoker(); } final MethodHandle getGenericConstructor() { ensureCodeGenerated(); - ensureConstructor(code.mostGeneric()); - return composeGenericMethod(code.mostGeneric().getConstructor()); + ensureConstructor(code.generic()); + return code.generic().getConstructor(); } private CompiledFunction getBest(final MethodType callSiteType) { @@ -267,18 +267,17 @@ } /** - * Compose a constructor given a primordial constructor handle + * Compose a constructor given a primordial constructor handle. * - * @param ctor primordial constructor handle - * @param needsCallee do we need to pass a callee - * + * @param ctor primordial constructor handle * @return the composed constructor */ - protected MethodHandle composeConstructor(final MethodHandle ctor, final boolean needsCallee) { + protected MethodHandle composeConstructor(final MethodHandle ctor) { // If it was (callee, this, args...), permute it to (this, callee, args...). We're doing this because having // "this" in the first argument position is what allows the elegant folded composition of // (newFilter x constructor x allocator) further down below in the code. Also, ensure the composite constructor // always returns Object. + final boolean needsCallee = needsCallee(ctor); MethodHandle composedCtor = needsCallee ? swapCalleeAndThis(ctor) : ctor; composedCtor = changeReturnTypeToObject(composedCtor); @@ -472,33 +471,6 @@ } /** - * Takes a method handle, and returns a potentially different method handle that can be used in - * {@code ScriptFunction#invoke(Object, Object...)} or {code ScriptFunction#construct(Object, Object...)}. - * The returned method handle will be sure to return {@code Object}, and will have all its parameters turned into - * {@code Object} as well, except for the following ones: - * <ul> - * <li>a last parameter of type {@code Object[]} which is used for vararg functions,</li> - * <li>the first argument, which is forced to be {@link ScriptFunction}, in case the function receives itself - * (callee) as an argument.</li> - * </ul> - * - * @param mh the original method handle - * - * @return the new handle, conforming to the rules above. - */ - protected MethodHandle composeGenericMethod(final MethodHandle mh) { - final MethodType type = mh.type(); - MethodType newType = type.generic(); - if (isVarArg(mh)) { - newType = newType.changeParameterType(type.parameterCount() - 1, Object[].class); - } - if (needsCallee(mh)) { - newType = newType.changeParameterType(0, ScriptFunction.class); - } - return type.equals(newType) ? mh : mh.asType(newType); - } - - /** * Execute this script function. * * @param self Target object. @@ -508,10 +480,9 @@ * @throws Throwable if there is an exception/error with the invocation or thrown from it */ Object invoke(final ScriptFunction fn, final Object self, final Object... arguments) throws Throwable { - final MethodHandle mh = getGenericInvoker(); - - final Object selfObj = convertThisObject(self); - final Object[] args = arguments == null ? ScriptRuntime.EMPTY_ARRAY : arguments; + final MethodHandle mh = getGenericInvoker(); + final Object selfObj = convertThisObject(self); + final Object[] args = arguments == null ? ScriptRuntime.EMPTY_ARRAY : arguments; if (isVarArg(mh)) { if (needsCallee(mh)) { @@ -531,6 +502,12 @@ return mh.invokeExact(fn, selfObj, getArg(args, 0), getArg(args, 1)); case 5: return mh.invokeExact(fn, selfObj, getArg(args, 0), getArg(args, 1), getArg(args, 2)); + case 6: + return mh.invokeExact(fn, selfObj, getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3)); + case 7: + return mh.invokeExact(fn, selfObj, getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3), getArg(args, 4)); + case 8: + return mh.invokeExact(fn, selfObj, getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3), getArg(args, 4), getArg(args, 5)); default: return mh.invokeWithArguments(withArguments(fn, selfObj, paramCount, args)); } @@ -545,15 +522,20 @@ return mh.invokeExact(selfObj, getArg(args, 0), getArg(args, 1)); case 4: return mh.invokeExact(selfObj, getArg(args, 0), getArg(args, 1), getArg(args, 2)); + case 5: + return mh.invokeExact(selfObj, getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3)); + case 6: + return mh.invokeExact(selfObj, getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3), getArg(args, 4)); + case 7: + return mh.invokeExact(selfObj, getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3), getArg(args, 4), getArg(args, 5)); default: return mh.invokeWithArguments(withArguments(null, selfObj, paramCount, args)); } } Object construct(final ScriptFunction fn, final Object... arguments) throws Throwable { - final MethodHandle mh = getGenericConstructor(); - - final Object[] args = arguments == null ? ScriptRuntime.EMPTY_ARRAY : arguments; + final MethodHandle mh = getGenericConstructor(); + final Object[] args = arguments == null ? ScriptRuntime.EMPTY_ARRAY : arguments; if (isVarArg(mh)) { if (needsCallee(mh)) { @@ -573,6 +555,12 @@ return mh.invokeExact(fn, getArg(args, 0), getArg(args, 1)); case 4: return mh.invokeExact(fn, getArg(args, 0), getArg(args, 1), getArg(args, 2)); + case 5: + return mh.invokeExact(fn, getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3)); + case 6: + return mh.invokeExact(fn, getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3), getArg(args, 4)); + case 7: + return mh.invokeExact(fn, getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3), getArg(args, 4), getArg(args, 5)); default: return mh.invokeWithArguments(withArguments(fn, paramCount, args)); } @@ -587,6 +575,12 @@ return mh.invokeExact(getArg(args, 0), getArg(args, 1)); case 3: return mh.invokeExact(getArg(args, 0), getArg(args, 1), getArg(args, 2)); + case 4: + return mh.invokeExact(getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3)); + case 5: + return mh.invokeExact(getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3), getArg(args, 4)); + case 6: + return mh.invokeExact(getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3), getArg(args, 4), getArg(args, 5)); default: return mh.invokeWithArguments(withArguments(null, paramCount, args)); } @@ -664,20 +658,21 @@ * @return the adapted handle */ private static MethodHandle changeReturnTypeToObject(final MethodHandle mh) { - return MH.asType(mh, mh.type().changeReturnType(Object.class)); + final MethodType type = mh.type(); + return (type.returnType() == Object.class) ? mh : MH.asType(mh, type.changeReturnType(Object.class)); } private void ensureConstructor(final CompiledFunction inv) { if (!inv.hasConstructor()) { - inv.setConstructor(composeConstructor(inv.getInvoker(), needsCallee(inv.getInvoker()))); + inv.setConstructor(composeConstructor(inv.getInvoker())); } } /** - * Heuristic to figure out if the method handle has a callee argument. If it's type is either - * {@code (boolean, ScriptFunction, ...)} or {@code (ScriptFunction, ...)}, then we'll assume it has - * a callee argument. We need this as the constructor above is not passed this information, and can't just blindly - * assume it's false (notably, it's being invoked for creation of new scripts, and scripts have scopes, therefore + * Heuristic to figure out if the method handle has a callee argument. If it's type is + * {@code (ScriptFunction, ...)}, then we'll assume it has a callee argument. We need this as + * the constructor above is not passed this information, and can't just blindly assume it's false + * (notably, it's being invoked for creation of new scripts, and scripts have scopes, therefore * they also always receive a callee). * * @param mh the examined method handle @@ -685,18 +680,8 @@ * @return true if the method handle expects a callee, false otherwise */ protected static boolean needsCallee(final MethodHandle mh) { - final MethodType type = mh.type(); - final int length = type.parameterCount(); - - if (length == 0) { - return false; - } - - if (type.parameterType(0) == ScriptFunction.class) { - return true; - } - - return length > 1 && type.parameterType(0) == boolean.class && type.parameterType(1) == ScriptFunction.class; + final MethodType type = mh.type(); + return (type.parameterCount() > 0 && type.parameterType(0) == ScriptFunction.class); } /**
--- a/src/jdk/nashorn/internal/runtime/ScriptLoader.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/runtime/ScriptLoader.java Thu Oct 31 16:47:09 2013 -0700 @@ -52,24 +52,10 @@ @Override protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { checkPackageAccess(name); - try { - return super.loadClass(name, resolve); - } catch (final ClassNotFoundException | SecurityException e) { - // We'll get ClassNotFoundException for Nashorn 'struct' classes. - // Also, we'll get SecurityException for jdk.nashorn.internal.* - // classes. So, load these using to context's 'shared' loader. - // All these classes start with "jdk.nashorn.internal." prefix. - try { - if (name.startsWith(NASHORN_PKG_PREFIX)) { - return context.getSharedLoader().loadClass(name); - } - } catch (final ClassNotFoundException ignored) { - //ignored - } - - // throw the original exception from here - throw e; + if (name.startsWith(NASHORN_PKG_PREFIX)) { + return context.getSharedLoader().loadClass(name); } + return super.loadClass(name, resolve); } // package-private and private stuff below this point
--- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java Thu Oct 31 16:47:09 2013 -0700 @@ -508,7 +508,7 @@ if (property == null) { // promoting an arrayData value to actual property addOwnProperty(key, propFlags, value); - removeArraySlot(key); + checkIntegerKey(key); } else { // Now set the new flags modifyOwnProperty(property, propFlags); @@ -594,7 +594,7 @@ * @param index key for property * @param value value to define */ - protected final void defineOwnProperty(final int index, final Object value) { + 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()) { @@ -616,15 +616,6 @@ } } - private void removeArraySlot(final String key) { - final int index = getArrayIndex(key); - final ArrayData array = getArray(); - - if (array.has(index)) { - setArray(array.delete(index)); - } - } - /** * Add a new property to the object. * @@ -1203,21 +1194,10 @@ * Check if this ScriptObject has array entries. This means that someone has * set values with numeric keys in the object. * - * Note: this can be O(n) up to the array length - * * @return true if array entries exists. */ public boolean hasArrayEntries() { - final ArrayData array = getArray(); - final long length = array.length(); - - for (long i = 0; i < length; i++) { - if (array.has((int)i)) { - return true; - } - } - - return false; + return getArray().length() > 0 || getMap().containsArrayKeys(); } /** @@ -2356,8 +2336,29 @@ } if (newLength < arrayLength) { - setArray(getArray().shrink(newLength)); - getArray().setLength(newLength); + long actualLength = newLength; + + // Check for numeric keys in property map and delete them or adjust length, depending on whether + // they're defined as configurable. See ES5 #15.4.5.2 + if (getMap().containsArrayKeys()) { + + for (long l = arrayLength - 1; l >= newLength; l--) { + final FindProperty find = findProperty(JSType.toString(l), false); + + if (find != null) { + + if (find.getProperty().isConfigurable()) { + deleteOwnProperty(find.getProperty()); + } else { + actualLength = l + 1; + break; + } + } + } + } + + setArray(getArray().shrink(actualLength)); + getArray().setLength(actualLength); } } @@ -2680,7 +2681,7 @@ final long oldLength = getArray().length(); final long longIndex = index & JSType.MAX_UINT; - if (!getArray().has(index)) { + if (getMap().containsArrayKeys()) { final String key = JSType.toString(longIndex); final FindProperty find = findProperty(key, true);
--- a/src/jdk/nashorn/internal/runtime/ScriptObjectListAdapter.java Thu Oct 31 12:36:38 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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; - -/** - * A ListAdapter that can wrap a ScriptObject. - */ -public final class ScriptObjectListAdapter extends ListAdapter { - /** - * Creates a new list wrapper for the specified ScriptObject. - * @param obj script the object to wrap - */ - public ScriptObjectListAdapter(final ScriptObject obj) { - super(obj); - } - - @Override - public int size() { - return JSType.toInt32(((ScriptObject)obj).getLength()); - } - - @Override - protected Object getAt(int index) { - return ((ScriptObject)obj).get(index); - } - - @Override - protected void setAt(int index, Object element) { - ((ScriptObject)obj).set(index, element, false); - } -}
--- a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Thu Oct 31 16:47:09 2013 -0700 @@ -47,6 +47,7 @@ import jdk.nashorn.api.scripting.ScriptObjectMirror; import jdk.nashorn.internal.codegen.CompilerConstants.Call; import jdk.nashorn.internal.ir.debug.JSONWriter; +import jdk.nashorn.internal.objects.Global; import jdk.nashorn.internal.parser.Lexer; import jdk.nashorn.internal.runtime.linker.Bootstrap; @@ -258,6 +259,11 @@ return ((Map<?,?>)obj).keySet().iterator(); } + final Object wrapped = Global.instance().wrapAsObject(obj); + if (wrapped instanceof ScriptObject) { + return ((ScriptObject)wrapped).propertyIterator(); + } + return Collections.emptyIterator(); } @@ -336,6 +342,11 @@ return ((Iterable<?>)obj).iterator(); } + final Object wrapped = Global.instance().wrapAsObject(obj); + if (wrapped instanceof ScriptObject) { + return ((ScriptObject)wrapped).valueIterator(); + } + return Collections.emptyIterator(); }
--- a/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java Thu Oct 31 16:47:09 2013 -0700 @@ -190,7 +190,7 @@ char buffer[] = new char[1024]; try (final InputStreamReader inputStream = new InputStreamReader(process.getErrorStream())) { for (int length; (length = inputStream.read(buffer, 0, buffer.length)) != -1; ) { - outBuffer.append(buffer, 0, length); + errBuffer.append(buffer, 0, length); } } catch (IOException ex) { exception[1] = ex;
--- a/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java Thu Oct 31 16:47:09 2013 -0700 @@ -461,7 +461,23 @@ */ public abstract ArrayData slice(long from, long to); - private static Class<?> widestType(final Object... items) { + /** + * Fast splice operation. This just modifies the array according to the number of + * elements added and deleted but does not insert the added elements. Throws + * {@code UnsupportedOperationException} if fast splice operation is not supported + * for this class or arguments. + * + * @param start start index of splice operation + * @param removed number of removed elements + * @param added number of added elements + * @throws UnsupportedOperationException if fast splice is not supported for the class or arguments. + */ + public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + + static Class<?> widestType(final Object... items) { assert items.length > 0; Class<?> widest = Integer.class;
--- a/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Thu Oct 31 16:47:09 2013 -0700 @@ -269,4 +269,32 @@ return new IntArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength); } + + @Override + public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { + final long oldLength = length(); + final long newLength = oldLength - removed + added; + if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) { + throw new UnsupportedOperationException(); + } + final ArrayData returnValue = (removed == 0) ? + EMPTY_ARRAY : new IntArrayData(Arrays.copyOfRange(array, start, start + removed), removed); + + if (newLength != oldLength) { + final int[] newArray; + + if (newLength > array.length) { + newArray = new int[ArrayData.nextSize((int)newLength)]; + System.arraycopy(array, 0, newArray, 0, start); + } else { + newArray = array; + } + + System.arraycopy(array, start + removed, newArray, start + added, (int)(oldLength - start - removed)); + array = newArray; + setLength(newLength); + } + + return returnValue; + } }
--- a/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java Thu Oct 31 16:47:09 2013 -0700 @@ -92,7 +92,7 @@ @Override public ArrayData convert(final Class<?> type) { - if (type == Long.class) { + if (type == Integer.class || type == Long.class) { return this; } final int length = (int) length(); @@ -238,4 +238,32 @@ final long newLength = to - start; return new LongArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength); } + + @Override + public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { + final long oldLength = length(); + final long newLength = oldLength - removed + added; + if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) { + throw new UnsupportedOperationException(); + } + final ArrayData returnValue = (removed == 0) ? + EMPTY_ARRAY : new LongArrayData(Arrays.copyOfRange(array, start, start + removed), removed); + + if (newLength != oldLength) { + final long[] newArray; + + if (newLength > array.length) { + newArray = new long[ArrayData.nextSize((int)newLength)]; + System.arraycopy(array, 0, newArray, 0, start); + } else { + newArray = array; + } + + System.arraycopy(array, start + removed, newArray, start + added, (int)(oldLength - start - removed)); + array = newArray; + setLength(newLength); + } + + return returnValue; + } }
--- a/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Thu Oct 31 16:47:09 2013 -0700 @@ -218,4 +218,32 @@ final long newLength = to - start; return new NumberArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength); } + + @Override + public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { + final long oldLength = length(); + final long newLength = oldLength - removed + added; + if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) { + throw new UnsupportedOperationException(); + } + final ArrayData returnValue = (removed == 0) ? + EMPTY_ARRAY : new NumberArrayData(Arrays.copyOfRange(array, start, start + removed), removed); + + if (newLength != oldLength) { + final double[] newArray; + + if (newLength > array.length) { + newArray = new double[ArrayData.nextSize((int)newLength)]; + System.arraycopy(array, 0, newArray, 0, start); + } else { + newArray = array; + } + + System.arraycopy(array, start + removed, newArray, start + added, (int)(oldLength - start - removed)); + array = newArray; + setLength(newLength); + } + + return returnValue; + } }
--- a/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java Thu Oct 31 16:47:09 2013 -0700 @@ -206,4 +206,32 @@ final long newLength = to - start; return new ObjectArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength); } + + @Override + public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { + final long oldLength = length(); + final long newLength = oldLength - removed + added; + if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) { + throw new UnsupportedOperationException(); + } + final ArrayData returnValue = (removed == 0) ? + EMPTY_ARRAY : new ObjectArrayData(Arrays.copyOfRange(array, start, start + removed), removed); + + if (newLength != oldLength) { + final Object[] newArray; + + if (newLength > array.length) { + newArray = new Object[ArrayData.nextSize((int)newLength)]; + System.arraycopy(array, 0, newArray, 0, start); + } else { + newArray = array; + } + + System.arraycopy(array, start + removed, newArray, start + added, (int)(oldLength - start - removed)); + array = newArray; + setLength(newLength); + } + + return returnValue; + } }
--- a/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java Thu Oct 31 12:36:38 2013 -0700 +++ b/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java Thu Oct 31 16:47:09 2013 -0700 @@ -25,25 +25,28 @@ package jdk.nashorn.internal.runtime.linker; -import jdk.nashorn.internal.lookup.MethodHandleFunctionality; -import jdk.nashorn.internal.lookup.MethodHandleFactory; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import java.util.HashMap; +import java.util.Map; import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.linker.GuardedInvocation; +import jdk.internal.dynalink.linker.GuardingTypeConverterFactory; import jdk.internal.dynalink.linker.LinkRequest; import jdk.internal.dynalink.linker.LinkerServices; import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; import jdk.internal.dynalink.support.CallSiteDescriptorFactory; +import jdk.nashorn.api.scripting.JSObject; +import jdk.nashorn.internal.lookup.MethodHandleFactory; +import jdk.nashorn.internal.lookup.MethodHandleFunctionality; import jdk.nashorn.internal.runtime.JSType; -import jdk.nashorn.api.scripting.JSObject; /** * A Dynalink linker to handle web browser built-in JS (DOM etc.) objects as well * as ScriptObjects from other Nashorn contexts. */ -final class JSObjectLinker implements TypeBasedGuardingDynamicLinker { +final class JSObjectLinker implements TypeBasedGuardingDynamicLinker, GuardingTypeConverterFactory { @Override public boolean canLinkType(final Class<?> type) { return canLinkTypeStatic(type); @@ -75,6 +78,22 @@ return Bootstrap.asType(inv, linkerServices, desc); } + @Override + public GuardedInvocation convertToType(final Class<?> sourceType, final Class<?> targetType) throws Exception { + final boolean sourceIsAlwaysJSObject = JSObject.class.isAssignableFrom(sourceType); + if(!sourceIsAlwaysJSObject && !sourceType.isAssignableFrom(JSObject.class)) { + return null; + } + + final MethodHandle converter = CONVERTERS.get(targetType); + if(converter == null) { + return null; + } + + return new GuardedInvocation(converter, sourceIsAlwaysJSObject ? null : IS_JSOBJECT_GUARD).asType(MethodType.methodType(targetType, sourceType)); + } + + private static GuardedInvocation lookup(final CallSiteDescriptor desc) { final String operator = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0); final int c = desc.getNameTokenCount(); @@ -87,9 +106,7 @@ case "setElem": return c > 2 ? findSetMethod(desc) : findSetIndexMethod(); case "call": - return findCallMethod(desc, operator); - case "callMethod": - return findCallMethodMethod(desc, operator); + return findCallMethod(desc); case "new": return findNewMethod(desc); default: @@ -115,14 +132,7 @@ return new GuardedInvocation(JSOBJECTLINKER_PUT, null, IS_JSOBJECT_GUARD); } - private static GuardedInvocation findCallMethodMethod(final CallSiteDescriptor desc, final String operator) { - final String methodName = desc.getNameToken(2); - MethodHandle func = MH.insertArguments(JSOBJECT_CALLMEMBER, 1, methodName); - func = MH.asCollector(func, Object[].class, desc.getMethodType().parameterCount() - 1); - return new GuardedInvocation(func, null, IS_JSOBJECT_GUARD); - } - - private static GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final String operator) { + private static GuardedInvocation findCallMethod(final CallSiteDescriptor desc) { final MethodHandle func = MH.asCollector(JSOBJECT_CALL, Object[].class, desc.getMethodType().parameterCount() - 2); return new GuardedInvocation(func, null, IS_JSOBJECT_GUARD); } @@ -163,6 +173,25 @@ } } + @SuppressWarnings("unused") + private static int toInt32(final JSObject obj) { + return JSType.toInt32(toNumber(obj)); + } + + @SuppressWarnings("unused") + private static long toInt64(final JSObject obj) { + return JSType.toInt64(toNumber(obj)); + } + + private static double toNumber(final JSObject obj) { + return obj == null ? 0 : obj.toNumber(); + } + + @SuppressWarnings("unused") + private static boolean toBoolean(final JSObject obj) { + return obj != null; + } + private static int getIndex(final Number n) { final double value = n.doubleValue(); return JSType.isRepresentableAsInt(value) ? (int)value : -1; @@ -178,27 +207,31 @@ // method handles of JSObject class private static final MethodHandle JSOBJECT_GETMEMBER = findJSObjectMH("getMember", Object.class, String.class); private static final MethodHandle JSOBJECT_SETMEMBER = findJSObjectMH("setMember", Void.TYPE, String.class, Object.class); - private static final MethodHandle JSOBJECT_CALLMEMBER = findJSObjectMH("callMember", Object.class, String.class, Object[].class); private static final MethodHandle JSOBJECT_CALL = findJSObjectMH("call", Object.class, Object.class, Object[].class); private static final MethodHandle JSOBJECT_NEW = findJSObjectMH("newObject", Object.class, Object[].class); + private static final Map<Class<?>, MethodHandle> CONVERTERS = new HashMap<>(); + static { + CONVERTERS.put(boolean.class, findOwnMH("toBoolean", boolean.class, JSObject.class)); + CONVERTERS.put(int.class, findOwnMH("toInt32", int.class, JSObject.class)); + CONVERTERS.put(long.class, findOwnMH("toInt64", long.class, JSObject.class)); + CONVERTERS.put(double.class, findOwnMH("toNumber", double.class, JSObject.class)); + } + private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) { - final Class<?> own = JSObjectLinker.class; - final MethodType mt = MH.type(rtype, types); - try { - return MH.findStatic(MethodHandles.lookup(), own, name, mt); - } catch (final MethodHandleFactory.LookupException e) { - return MH.findVirtual(MethodHandles.lookup(), own, name, mt); - } + return findMH(name, JSObjectLinker.class, rtype, types); } private static MethodHandle findJSObjectMH(final String name, final Class<?> rtype, final Class<?>... types) { - final Class<?> own = JSObject.class; + return findMH(name, JSObject.class, rtype, types); + } + + private static MethodHandle findMH(final String name, final Class<?> target, final Class<?> rtype, final Class<?>... types) { final MethodType mt = MH.type(rtype, types); try { - return MH.findVirtual(MethodHandles.publicLookup(), own, name, mt); + return MH.findStatic(MethodHandles.lookup(), target, name, mt); } catch (final MethodHandleFactory.LookupException e) { - return MH.findVirtual(MethodHandles.lookup(), own, name, mt); + return MH.findVirtual(MethodHandles.lookup(), target, name, mt); } } }
--- a/src/overview.html Thu Oct 31 12:36:38 2013 -0700 +++ b/src/overview.html Thu Oct 31 16:47:09 2013 -0700 @@ -108,6 +108,6 @@ <h2>Other non-standard built-in objects</h2> In addition to {@code Java}, Nashorn also exposes some other non-standard built-in objects: <a href="jdk/nashorn/internal/objects/NativeJSAdapter.html">{@code JSAdapter}</a>, -<a href="jdk/nashorn/internal/objects/NativeJavaImporter.html">{@code JavaImporter}, +<a href="jdk/nashorn/internal/objects/NativeJavaImporter.html">{@code JavaImporter}</a>, <a href="jdk/nashorn/internal/runtime/NativeJavaPackage.html">{@code Packages}.</a> </body>
--- a/test/examples/array-micro.js Thu Oct 31 12:36:38 2013 -0700 +++ b/test/examples/array-micro.js Thu Oct 31 16:47:09 2013 -0700 @@ -90,6 +90,24 @@ array[6] = 6; }); +bench("push", function() { + var arr = [1, 2, 3]; + arr.push(4); + arr.push(5); + arr.push(6); +}); + +bench("pop", function() { + var arr = [1, 2, 3]; + arr.pop(); + arr.pop(); + arr.pop(); +}); + +bench("splice", function() { + [1, 2, 3].splice(0, 2, 5, 6, 7); +}); + var all = function(e) { return true; }; var none = function(e) { return false; };
--- a/test/script/basic/JDK-8024847.js Thu Oct 31 12:36:38 2013 -0700 +++ b/test/script/basic/JDK-8024847.js Thu Oct 31 16:47:09 2013 -0700 @@ -100,3 +100,9 @@ var jlist = Java.to(obj, java.util.List); print(jlist instanceof java.util.List); print(jlist); + +var obj = new JSObject() { + toNumber: function() { return 42; } +}; + +print(32 + obj);
--- a/test/script/basic/JDK-8024847.js.EXPECTED Thu Oct 31 12:36:38 2013 -0700 +++ b/test/script/basic/JDK-8024847.js.EXPECTED Thu Oct 31 16:47:09 2013 -0700 @@ -10,3 +10,4 @@ [hello, world] true [nashorn, js] +74
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8026161.js Thu Oct 31 16:47:09 2013 -0700 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8026161: Don't narrow floating-point literals in the lexer + * + * @test + * @run + */ + +print(new java.awt.Color(1, 1, 1)) // creates Color[r=1,g=1,b=1] +print(new java.awt.Color(1.0, 1.0, 1.0)) // Color[r=255,g=255,b=255]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8026161.js.EXPECTED Thu Oct 31 16:47:09 2013 -0700 @@ -0,0 +1,2 @@ +java.awt.Color[r=1,g=1,b=1] +java.awt.Color[r=255,g=255,b=255]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8026701.js Thu Oct 31 16:47:09 2013 -0700 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8026701: Array.prototype.splice is slow on dense arrays + * + * @test + * @run + */ + +function testSplice(arr, e1, e2, e3) { + try { + print(arr); + print(arr.splice(3, 0, e1, e2, e3)); + print(arr); + print(arr.splice(2, 3)); + print(arr); + print(arr.splice(2, 3, arr[2], arr[3], arr[4])); + print(arr); + print(arr.splice(20, 10)); + print(arr); + print(arr.splice(arr.length, 0, e1, e2, e3)); + print(arr); + print(arr.splice(0, 2, arr[0], arr[1], arr[2], arr[3])); + print(arr); + } catch (error) { + print(error); + } +} + +function convert(array, type) { + return (typeof Java === "undefined") ? array : Java.from(Java.to(array, type)); +} + +// run some splice tests on all dense array implementations +testSplice([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], -1, -2, -3); +testSplice(convert([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], "long[]"), -1, -2, -3); +testSplice(convert([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], "double[]"), -1, -2, -3); +testSplice(["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], -1, -2, -3); + +// test array conversion during splice +testSplice([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], -1, "-2", "-3"); +testSplice([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], -1, -2.5, -3.5); +testSplice(convert([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], "long[]"), -1, "-2", "-3"); +testSplice(convert([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], "long[]"), -1, -2.5, -3.5); +testSplice(convert([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], "double[]"), -1, "-2", "-3"); + +// test combination with defined elements +testSplice(Object.defineProperty([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 5, {value: 13}), -1, -2, -3); +testSplice(Object.defineProperty([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 5, {value: 13, writable: false}), -1, -2, -3); +testSplice(Object.defineProperty([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 5, {value: 13, configurable: false}), -1, -2, -3); +testSplice(Object.defineProperty([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 5, {value: 13, writable: false, configurable: false}), -1, -2, -3);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8026701.js.EXPECTED Thu Oct 31 16:47:09 2013 -0700 @@ -0,0 +1,147 @@ +1,2,3,4,5,6,7,8,9,10 + +1,2,3,-1,-2,-3,4,5,6,7,8,9,10 +3,-1,-2 +1,2,-3,4,5,6,7,8,9,10 +-3,4,5 +1,2,-3,4,5,6,7,8,9,10 + +1,2,-3,4,5,6,7,8,9,10 + +1,2,-3,4,5,6,7,8,9,10,-1,-2,-3 +1,2 +1,2,-3,4,-3,4,5,6,7,8,9,10,-1,-2,-3 +1,2,3,4,5,6,7,8,9,10 + +1,2,3,-1,-2,-3,4,5,6,7,8,9,10 +3,-1,-2 +1,2,-3,4,5,6,7,8,9,10 +-3,4,5 +1,2,-3,4,5,6,7,8,9,10 + +1,2,-3,4,5,6,7,8,9,10 + +1,2,-3,4,5,6,7,8,9,10,-1,-2,-3 +1,2 +1,2,-3,4,-3,4,5,6,7,8,9,10,-1,-2,-3 +1,2,3,4,5,6,7,8,9,10 + +1,2,3,-1,-2,-3,4,5,6,7,8,9,10 +3,-1,-2 +1,2,-3,4,5,6,7,8,9,10 +-3,4,5 +1,2,-3,4,5,6,7,8,9,10 + +1,2,-3,4,5,6,7,8,9,10 + +1,2,-3,4,5,6,7,8,9,10,-1,-2,-3 +1,2 +1,2,-3,4,-3,4,5,6,7,8,9,10,-1,-2,-3 +1,2,3,4,5,6,7,8,9,10 + +1,2,3,-1,-2,-3,4,5,6,7,8,9,10 +3,-1,-2 +1,2,-3,4,5,6,7,8,9,10 +-3,4,5 +1,2,-3,4,5,6,7,8,9,10 + +1,2,-3,4,5,6,7,8,9,10 + +1,2,-3,4,5,6,7,8,9,10,-1,-2,-3 +1,2 +1,2,-3,4,-3,4,5,6,7,8,9,10,-1,-2,-3 +1,2,3,4,5,6,7,8,9,10 + +1,2,3,-1,-2,-3,4,5,6,7,8,9,10 +3,-1,-2 +1,2,-3,4,5,6,7,8,9,10 +-3,4,5 +1,2,-3,4,5,6,7,8,9,10 + +1,2,-3,4,5,6,7,8,9,10 + +1,2,-3,4,5,6,7,8,9,10,-1,-2,-3 +1,2 +1,2,-3,4,-3,4,5,6,7,8,9,10,-1,-2,-3 +1,2,3,4,5,6,7,8,9,10 + +1,2,3,-1,-2.5,-3.5,4,5,6,7,8,9,10 +3,-1,-2.5 +1,2,-3.5,4,5,6,7,8,9,10 +-3.5,4,5 +1,2,-3.5,4,5,6,7,8,9,10 + +1,2,-3.5,4,5,6,7,8,9,10 + +1,2,-3.5,4,5,6,7,8,9,10,-1,-2.5,-3.5 +1,2 +1,2,-3.5,4,-3.5,4,5,6,7,8,9,10,-1,-2.5,-3.5 +1,2,3,4,5,6,7,8,9,10 + +1,2,3,-1,-2,-3,4,5,6,7,8,9,10 +3,-1,-2 +1,2,-3,4,5,6,7,8,9,10 +-3,4,5 +1,2,-3,4,5,6,7,8,9,10 + +1,2,-3,4,5,6,7,8,9,10 + +1,2,-3,4,5,6,7,8,9,10,-1,-2,-3 +1,2 +1,2,-3,4,-3,4,5,6,7,8,9,10,-1,-2,-3 +1,2,3,4,5,6,7,8,9,10 + +1,2,3,-1,-2.5,-3.5,4,5,6,7,8,9,10 +3,-1,-2.5 +1,2,-3.5,4,5,6,7,8,9,10 +-3.5,4,5 +1,2,-3.5,4,5,6,7,8,9,10 + +1,2,-3.5,4,5,6,7,8,9,10 + +1,2,-3.5,4,5,6,7,8,9,10,-1,-2.5,-3.5 +1,2 +1,2,-3.5,4,-3.5,4,5,6,7,8,9,10,-1,-2.5,-3.5 +1,2,3,4,5,6,7,8,9,10 + +1,2,3,-1,-2,-3,4,5,6,7,8,9,10 +3,-1,-2 +1,2,-3,4,5,6,7,8,9,10 +-3,4,5 +1,2,-3,4,5,6,7,8,9,10 + +1,2,-3,4,5,6,7,8,9,10 + +1,2,-3,4,5,6,7,8,9,10,-1,-2,-3 +1,2 +1,2,-3,4,-3,4,5,6,7,8,9,10,-1,-2,-3 +1,2,3,4,5,13,7,8,9,10 + +1,2,3,-1,-2,-3,4,5,13,7,8,9,10 +3,-1,-2 +1,2,-3,4,5,13,7,8,9,10 +-3,4,5 +1,2,-3,4,5,13,7,8,9,10 + +1,2,-3,4,5,13,7,8,9,10 + +1,2,-3,4,5,13,7,8,9,10,-1,-2,-3 +1,2 +1,2,-3,4,-3,4,5,13,7,8,9,10,-1,-2,-3 +1,2,3,4,5,13,7,8,9,10 +TypeError: "5" is not a writable property of [object Array] +1,2,3,4,5,13,7,8,9,10 + +1,2,3,-1,-2,-3,4,5,13,7,8,9,10 +3,-1,-2 +1,2,-3,4,5,13,7,8,9,10 +-3,4,5 +1,2,-3,4,5,13,7,8,9,10 + +1,2,-3,4,5,13,7,8,9,10 + +1,2,-3,4,5,13,7,8,9,10,-1,-2,-3 +1,2 +1,2,-3,4,-3,4,5,13,7,8,9,10,-1,-2,-3 +1,2,3,4,5,13,7,8,9,10 +TypeError: "5" is not a writable property of [object Array]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8026805.js Thu Oct 31 16:47:09 2013 -0700 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8026805: Array.prototype.length doesn't work as expected + * + * @test + * @run + */ + +if (Array.prototype.length !== 0) { + throw new Error("Initial length not 0"); +} + +Array.prototype[3] = 1; + +if (Array.prototype.length !== 4) { + throw new Error("length not updated to 4"); +} + +Array.prototype.length = 0; + +if (Array.prototype.length !== 0) { + throw new Error("length not reset to 0"); +} + +if (3 in Array.prototype) { + throw new Error("array element not deleted"); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8026858.js Thu Oct 31 16:47:09 2013 -0700 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8026858: Array length does not handle defined properties correctly + * + * @test + * @run + */ + +var arr = []; + +Object.defineProperty(arr, "3", {value: 1 /* configurable: false */}); + +if (arr[3] != 1) { + throw new Error("arr[3] not defined"); +} + +if (arr.length !== 4) { + throw new Error("Array length not updated to 4"); +} + +Object.defineProperty(arr, "5", {value: 1, configurable: true}); + +if (arr[5] != 1) { + throw new Error("arr[5] not defined"); +} + +if (arr.length !== 6) { + throw new Error("Array length not updated to 4"); +} + +arr.length = 0; + +if (5 in arr) { + throw new Error("configurable element was not deleted"); +} + +if (arr[3] != 1) { + throw new Error("non-configurable element was deleted"); +} + +if (arr.length !== 4) { + throw new Error("Array length not set"); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8026955.js Thu Oct 31 16:47:09 2013 -0700 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8026955: for-in should convert primitive values to object + * + * @test + * @run + */ + +Object.prototype[4] = "world"; +String.prototype[3] = "hello"; +Number.prototype[3] = "hello"; +Boolean.prototype[3] = "hello"; + +function testForIn(x) { + for (var i in x) { + print(i, x[i]); + } + for each (var i in x) { + print(i); + } +} + +testForIn("abc"); +testForIn(false); +testForIn(3); +testForIn(null); +testForIn(); +testForIn(String.prototype); +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8026955.js.EXPECTED Thu Oct 31 16:47:09 2013 -0700 @@ -0,0 +1,22 @@ +0 a +1 b +2 c +3 hello +4 world +a +b +c +hello +world +3 hello +4 world +hello +world +3 hello +4 world +hello +world +3 hello +4 world +hello +world
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8027016.js Thu Oct 31 16:47:09 2013 -0700 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8027016: Array.prototype.indexOf should return -1 when array is of length zero + * + * @test + * @run + */ + +var res = [].indexOf(null, {valueOf:function(){throw "not reached"}}); +if (res != -1) { + fail("expected -1 on indexOf on empty array"); +} + +// add index beyond length check as well + +res = [].indexOf(null, 1); +if (res != -1) { + fail("expected -1 on indexOf on empty array"); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8027024.js Thu Oct 31 16:47:09 2013 -0700 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8027024: String.prototype.charAt and charCodeAt do not evaluate 'self' and 'pos' arguments in right order + * + * @test + * @run + */ + + +String.prototype.charAt.call( + { + toString: function() { + print("charAt.self.toString"); + } + }, + + { + valueOf: function() { + print("charAt.pos.valueOf"); + } + } +); + +String.prototype.charCodeAt.call( + { + toString: function() { + print("charCodeAt.self.toString"); + } + }, + + { + valueOf: function() { + print("charCodeAt.pos.valueOf"); + } + } +);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8027024.js.EXPECTED Thu Oct 31 16:47:09 2013 -0700 @@ -0,0 +1,4 @@ +charAt.self.toString +charAt.pos.valueOf +charCodeAt.self.toString +charCodeAt.pos.valueOf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8027042.js Thu Oct 31 16:47:09 2013 -0700 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8027042: Evaluation order for binary operators can be improved + * + * @test + * @run + */ + +// var with getter side effect +Object.defineProperty(this, "a", { get: function() {print("get a"); return 1; }}); + +// var with both getter and conversion side effect +Object.defineProperty(this, "b", { get: function() {print("get b"); return {valueOf: function() { print("conv b"); return 10; }}; }}); + +(function() { + // var with toPrimitive conversion side effect + var c = {valueOf: function() { print("conv c"); return 100; }}; + + print(b + (c + a)); + print(b + (c + b)); + print(b + (a + b)); + print(b + (b + c)); + print(b + (b + c)); + print(b + (c + (a - b))); + print(b + (c + (c - b))); + print(b + (c + (b - c))); + print(b + (b + (a ? 2 : 3))); + print(b + (b + (b ? 2 : 3))); + print(b + (b + (c ? 2 : 3))); + print(b + ((-c) + (-a))); + print(b + ((-c) + (-b))); + print(b + ((-c) + (-c))); + try { print(b + new a); } catch (e) {} + try { print(b + new b); } catch (e) {} + try { print(b + new c); } catch (e) {} +})();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8027042.js.EXPECTED Thu Oct 31 16:47:09 2013 -0700 @@ -0,0 +1,88 @@ +get b +get a +conv c +conv b +111 +get b +get b +conv c +conv b +conv b +120 +get b +get a +get b +conv b +conv b +21 +get b +get b +conv b +conv c +conv b +120 +get b +get b +conv b +conv c +conv b +120 +get b +get a +get b +conv b +conv c +conv b +101 +get b +get b +conv c +conv b +conv c +conv b +200 +get b +get b +conv b +conv c +conv c +conv b +20 +get b +get b +get a +conv b +conv b +22 +get b +get b +get b +conv b +conv b +22 +get b +get b +conv b +conv b +22 +get b +conv c +get a +conv b +-91 +get b +conv c +get b +conv b +conv b +-100 +get b +conv c +conv c +conv b +-190 +get b +get a +get b +get b +get b
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8027562.js Thu Oct 31 16:47:09 2013 -0700 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8027562: eval should load second and subsequent arguments for side effect + * + * @test + * @run + */ + +try { + eval("", x); + fail("should have thrown ReferenceError for 'x'"); +} catch (e) { + if (! (e instanceof ReferenceError)) { + fail("Expected ReferenceError, got " + e); + } + print(e); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8027562.js.EXPECTED Thu Oct 31 16:47:09 2013 -0700 @@ -0,0 +1,1 @@ +ReferenceError: "x" is not defined
--- a/test/script/basic/NASHORN-397.js Thu Oct 31 12:36:38 2013 -0700 +++ b/test/script/basic/NASHORN-397.js Thu Oct 31 16:47:09 2013 -0700 @@ -35,11 +35,8 @@ fail("typeof(5).x is not 'number'"); } -// It is function because PrintStream implements Closeable, which is -// marked with @FunctionalInterface. Yes, this means calling a stream -// like "stream()" closes it. -if (typeof (java.lang.System.out) != 'function') { - fail("typeof java.lang.System.out is not 'object'"); +if (typeof (java.net.Proxy.NO_PROXY) != 'object') { + fail("typeof java.net.Proxy.NO_PROXY is not 'object'"); } if (typeof (java.lang.Math.PI) != 'number') {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/jfx.js Thu Oct 31 16:47:09 2013 -0700 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * Base library for JavaFX canvas run by Nashorn testing. + * @subtest + * + * + */ + +var System = Java.type("java.lang.System"); +var AWTImage = Java.type("org.jemmy.image.AWTImage"); +var PNGDecoder = Java.type("org.jemmy.image.PNGDecoder"); +var JemmyFxRoot = Java.type("org.jemmy.fx.Root"); +var AWTRobotCapturer = Java.type("org.jemmy.image.AWTRobotCapturer"); +var ByWindowType = Java.type("org.jemmy.fx.ByWindowType"); +var Scene = Java.type("javafx.scene.Scene"); +var Stage = Java.type("javafx.stage.Stage"); +var File = Java.type("java.io.File"); +var Timer = Java.type("java.util.Timer"); +var TimerTask = Java.type("java.util.TimerTask"); +var OSInfo = Java.type("sun.awt.OSInfo"); +var OSType = Java.type("sun.awt.OSInfo.OSType"); +var StringBuffer = Java.type("java.lang.StringBuffer"); + +var WAIT = 2000; +var TESTNAME = "test"; +var fsep = System.getProperty("file.separator"); + +function checkImageAndExit() { + var raceTimer = new Timer(true); + var timerTask = new TimerTask() { + run: function run() { + var tmpdir = System.getProperty("java.io.tmpdir"); + var timenow = (new Date()).getTime(); + makeScreenShot(tmpdir + fsep + "screenshot" + timenow +".png"); + var dupImg = isDuplicateImages(tmpdir + fsep + "screenshot" + timenow +".png", __DIR__ + "jfx" + fsep + TESTNAME + fsep + "golden"); + (new File(mpdir + fsep + "screenshot" + timenow +".png")).delete(); + if (!dupImg) System.err.println("ERROR: screenshot does not match golden image"); + exit(0); + } + }; + raceTimer.schedule(timerTask, WAIT); +} + +function makeScreenShot(shootToImg) { + JemmyFxRoot.ROOT.getEnvironment().setImageCapturer(new AWTRobotCapturer()); + var wrap = JemmyFxRoot.ROOT.lookup(new ByWindowType($STAGE.class)).lookup(Scene.class).wrap(0); + var imageJemmy = wrap.getScreenImage(); + imageJemmy.save(shootToImg); +} + +function isDuplicateImages(file1, file2) { + var f1 = new File(file1); + var f2; + var sb = new StringBuffer(file2); + if (OSInfo.getOSType() == OSType.WINDOWS) { + f2 = new File(sb.append(fsep + "windows.png").toString()); + } else if (OSInfo.getOSType() == OSType.LINUX) { + f2 = new File(sb.append(fsep + "linux.png").toString()); + } else if (OSInfo.getOSType() == OSType.MACOSX) { + f2 = new File(sb.append(fsep + "macosx.png").toString()); + } + print(f1.getAbsolutePath()); + print(f2.getAbsolutePath()); + if (f1.exists() && f2.exists()) { + var image1 = new AWTImage(PNGDecoder.decode(f1.getAbsolutePath())); + var image2 = new AWTImage(PNGDecoder.decode(f2.getAbsolutePath())); + return image1.compareTo(image2) == null ? true : false; + } + return false; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/jfx/flyingimage.js Thu Oct 31 16:47:09 2013 -0700 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * Testing JavaFX canvas run by Nashorn. + * + * @test/nocompare + * @run + * @fork + */ + +TESTNAME = "flyingimage"; + +var Image = Java.type("javafx.scene.image.Image"); +var Color = Java.type("javafx.scene.paint.Color"); +var Canvas = Java.type("javafx.scene.canvas.Canvas"); +var BorderPane = Java.type("javafx.scene.layout.BorderPane"); +var StackPane = Java.type("javafx.scene.layout.StackPane"); +var Font = Java.type("javafx.scene.text.Font"); +var FontSmoothingType = Java.type("javafx.scene.text.FontSmoothingType"); +var Text = Java.type("javafx.scene.text.Text"); + +var WIDTH = 800; +var HEIGHT = 600; +var canvas = new Canvas(WIDTH, HEIGHT); +function fileToURL(file) { + return new File(file).toURI().toURL().toExternalForm(); +} +var imageUrl = fileToURL(__DIR__ + "flyingimage/flyingimage.png"); +var img = new Image(imageUrl); +var font = new Font("Arial", 16); +var t = 0; +var isFrameRendered = false; +function renderFrame() { + var gc = canvas.graphicsContext2D; + gc.setFill(Color.web("#cccccc")); + gc.fillRect(0, 0, WIDTH, HEIGHT); + gc.setStroke(Color.web("#000000")); + gc.setLineWidth(1); + gc.strokeRect(5, 5, WIDTH - 10, HEIGHT - 10); + var c = 200; + var msc= 0.5 * HEIGHT / img.height; + var sp0 = 0.003; + for (var h = 0; h < c; h++, t++) { + gc.setTransform(1, 0, 0, 1, 0, 0); + var yh = h / (c - 1); + gc.translate((0.5 + Math.sin(t * sp0 + h * 0.1) / 3) * WIDTH, 25 + (HEIGHT * 3 / 4 - 40) * (yh * yh)); + var sc = 30 / img.height + msc * yh * yh; + gc.rotate(90 * Math.sin(t * sp0 + h * 0.1 + Math.PI)); + gc.scale(sc, sc); + gc.drawImage(img, -img.width / 2, -img.height / 2); + } + gc.setTransform(1, 0, 0, 1, 0, 0); + isFrameRendered = true; +} +var stack = new StackPane(); +var pane = new BorderPane(); + +pane.setCenter(canvas); +stack.getChildren().add(pane); +$STAGE.scene = new Scene(stack); +renderFrame(); +checkImageAndExit();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/jfx/kaleidoscope.js Thu Oct 31 16:47:09 2013 -0700 @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * Testing JavaFX canvas run by Nashorn. + * + * @test/nocompare + * @run + * @fork + */ + +TESTNAME = "kaleidoscope"; +WAIT = 4000; + +var Paint = Java.type("javafx.scene.paint.Paint"); +var Canvas = Java.type("javafx.scene.canvas.Canvas"); +var BorderPane = Java.type("javafx.scene.layout.BorderPane"); +var StackPane = Java.type("javafx.scene.layout.StackPane"); +var StrokeLineCap = Java.type("javafx.scene.shape.StrokeLineCap"); + +var WIDTH = 800; +var HEIGHT = 600; +var canvas = new Canvas(WIDTH, HEIGHT); +var context = canvas.graphicsContext2D; + +var x,y; +var p_x,p_y; +var a=0; +var b=0; +var angle=Math.PI/180*8; +var color=0; +var limit1=Math.PI*1.5; +var limit2=Math.PI*1.79; +var c=new Array(6); +var d=new Array(6); +var r,e; +var fade; +var prv_x,prv_y,prv_x2,prv_y2; + +function renderFrame() { + a=0.2*angle; + b=0.7*angle; + r=0; + fade=32; + for(var i=0;i<6;i++) + { + c[i]=1.0/(i+1)/2; + d[i]=1.0/(i+1)/2; + } + radius=Math.round((WIDTH+HEIGHT)/8); + e=radius*0.2; + p_x=Math.round(WIDTH/2); + p_y=Math.round(HEIGHT/2); + x=(radius*c[0])*Math.cos(a*d[1])+(radius*c[2])*Math.sin(a*d[3])+(radius*c[4])*Math.sin(a*d[5]); + y=(radius*c[5])*Math.sin(a*d[4])+(radius*c[3])*Math.cos(a*d[2])+(radius*c[1])*Math.cos(a*d[0]); + for (i = 0; i < 800; i++) { + anim(); + } +} + +function anim() { + var a1=Math.cos(a*2); + var a2=Math.cos(a*4); + var a3=Math.cos(a); + var a4=Math.sin(a); + if(b>limit1&&b<limit2) { + r+=radius*0.02*a1; + prv_x=x; + prv_y=y; + x=prv_x2+r*a3; + y=prv_y2+r*a4; + } else { + prv_x=x; + prv_y=y; + prv_x2=x; + prv_y2=y; + x=(radius*c[0])*Math.cos(a*d[1])+(radius*c[2])*Math.sin(a*d[3])+(radius*c[4])*Math.sin(a*d[5]); + y=(radius*c[5])*Math.sin(a*d[4])+(radius*c[3])*Math.cos(a*d[2])+(radius*c[1])*Math.cos(a*d[0]); + } + var c3=16*Math.cos(a*10); + var c1=Math.floor(56*Math.cos(a*angle*4)+c3); + var c2=Math.floor(56*Math.sin(a*angle*4)-c3); + context.lineCap=StrokeLineCap.ROUND; + context.setStroke(Paint.valueOf('rgba('+(192+c1)+','+(192+c2)+','+(192-c1)+','+(0.01-0.005*-a1)+')')); + context.lineWidth=e*1.4+e*0.8*a3; + draw_line(p_x,p_y,prv_x,prv_y,x,y); + context.lineWidth=e+e*0.8*a3; + draw_line(p_x,p_y,prv_x,prv_y,x,y); + context.setStroke(Paint.valueOf('rgba('+(192+c1)+','+(192+c2)+','+(192-c1)+','+(0.06-0.03*-a1)+')')); + context.lineWidth=e*0.6+e*0.35*a3; + draw_line(p_x,p_y,prv_x,prv_y,x,y); + context.setStroke(Paint.valueOf('rgba(0,0,0,0.06)')); + context.lineWidth=e*0.4+e*0.225*a3; + draw_line(p_x,p_y,prv_x,prv_y,x,y); + context.setStroke(Paint.valueOf('rgba('+(192+c1)+','+(192+c2)+','+(192-c1)+','+(0.1-0.075*-a1)+')')); + context.lineWidth=e*0.2+e*0.1*a3; + draw_line(p_x,p_y,prv_x,prv_y,x,y); + context.setStroke(Paint.valueOf('rgba(255,255,255,0.4)')); + context.lineWidth=e*(0.1-0.05*-a2); + draw_line(p_x,p_y,prv_x,prv_y,x,y); + a+=angle*Math.cos(b); + b+=angle*0.1; +} + +function draw_line(x,y,x1,y1,x2,y2) { + context.beginPath(); + context.moveTo(x+x1,y+y1); + context.lineTo(x+x2,y+y2); + context.moveTo(x-x1,y+y1); + context.lineTo(x-x2,y+y2); + context.moveTo(x-x1,y-y1); + context.lineTo(x-x2,y-y2); + context.moveTo(x+x1,y-y1); + context.lineTo(x+x2,y-y2); + context.moveTo(x+y1,y+x1); + context.lineTo(x+y2,y+x2); + context.moveTo(x-y1,y+x1); + context.lineTo(x-y2,y+x2); + context.moveTo(x-y1,y-x1); + context.lineTo(x-y2,y-x2); + context.moveTo(x+y1,y-x1); + context.lineTo(x+y2,y-x2); + context.moveTo(x,y+x2); + context.lineTo(x,y+x1); + context.moveTo(x,y-x2); + context.lineTo(x,y-x1); + context.moveTo(x+x2,y); + context.lineTo(x+x1,y); + context.moveTo(x-x2,y); + context.lineTo(x-x1,y); + context.stroke(); + context.closePath(); +} + +var stack = new StackPane(); +var pane = new BorderPane(); + +pane.setCenter(canvas); +stack.getChildren().add(pane); +$STAGE.scene = new Scene(stack); +renderFrame(); +checkImageAndExit(); \ No newline at end of file
--- a/test/src/jdk/nashorn/api/javaaccess/MethodAccessTest.java Thu Oct 31 12:36:38 2013 -0700 +++ b/test/src/jdk/nashorn/api/javaaccess/MethodAccessTest.java Thu Oct 31 16:47:09 2013 -0700 @@ -412,7 +412,7 @@ @Test public void accessMethodMixedWithEllipsis() throws ScriptException { - assertArrayEquals(new Object[] { "Hello", 10, true, -100500, 80 }, (Object[])e.eval("o.methodMixedWithEllipsis('Hello', 10, true, -100500,80.0);")); + assertArrayEquals(new Object[] { "Hello", 10, true, -100500, 80d }, (Object[])e.eval("o.methodMixedWithEllipsis('Hello', 10, true, -100500,80.0);")); assertArrayEquals(new Object[] { "Nashorn", 15 }, (Object[])e.eval("o.methodMixedWithEllipsis('Nashorn',15);")); } @@ -431,8 +431,8 @@ @Test public void accessMethodDoubleVSintOverloaded() throws ScriptException { - assertEquals("int", e.eval("o.overloadedMethodDoubleVSint(0.0);")); - assertEquals("int", e.eval("o.overloadedMethodDoubleVSint(1000.0);")); + assertEquals("double", e.eval("o.overloadedMethodDoubleVSint(0.0);")); + assertEquals("double", e.eval("o.overloadedMethodDoubleVSint(1000.0);")); assertEquals("double", e.eval("o.overloadedMethodDoubleVSint(0.01);")); assertEquals("double", e.eval("o.overloadedMethodDoubleVSint(100.02);")); assertEquals("int", e.eval("o.overloadedMethodDoubleVSint(0);"));
--- a/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java Thu Oct 31 12:36:38 2013 -0700 +++ b/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java Thu Oct 31 16:47:09 2013 -0700 @@ -46,7 +46,7 @@ * JSObject implementations. */ public class PluggableJSObjectTest { - public static class MapWrapperObject extends JSObject { + public static class MapWrapperObject extends AbstractJSObject { private final HashMap<String, Object> map = new LinkedHashMap<>(); public HashMap<String, Object> getMap() { @@ -109,7 +109,7 @@ } } - public static class BufferObject extends JSObject { + public static class BufferObject extends AbstractJSObject { private final IntBuffer buf; public BufferObject(int size) { @@ -170,7 +170,7 @@ } } - public static class Adder extends JSObject { + public static class Adder extends AbstractJSObject { @Override public Object call(Object thiz, Object... args) { double res = 0.0; @@ -202,7 +202,7 @@ } } - public static class Factory extends JSObject { + public static class Factory extends AbstractJSObject { @Override public Object newObject(Object... args) { return new HashMap<Object, Object>();
--- a/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java Thu Oct 31 12:36:38 2013 -0700 +++ b/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java Thu Oct 31 16:47:09 2013 -0700 @@ -129,7 +129,7 @@ final ScriptEngine e = m.getEngineByName("nashorn"); try { e.eval("var obj = { '1': 'world', func: function() { return this.bar; }, bar: 'hello' }"); - JSObject obj = (JSObject) e.get("obj"); + ScriptObjectMirror obj = (ScriptObjectMirror) e.get("obj"); // try basic get on existing properties if (!obj.getMember("bar").equals("hello")) {