# HG changeset patch # User lana # Date 1384528565 28800 # Node ID 1db3d4e4d18913e853d7bebf86816e87fda00a71 # Parent 774c636298702b3325f85002e2ac5bd95933ea96# Parent 2f0f8d1d0753d47954604e2e9b13ce0a9617c577 Merge diff -r 774c63629870 -r 1db3d4e4d189 make/build.xml --- a/make/build.xml Thu Nov 14 09:05:27 2013 -0800 +++ b/make/build.xml Fri Nov 15 07:16:05 2013 -0800 @@ -372,6 +372,12 @@ + + + + + + @@ -380,6 +386,7 @@ + diff -r 774c63629870 -r 1db3d4e4d189 make/project.properties --- a/make/project.properties Thu Nov 14 09:05:27 2013 -0800 +++ b/make/project.properties Fri Nov 15 07:16:05 2013 -0800 @@ -230,7 +230,7 @@ ${file.reference.jemmyawtinput.jar}${path.separator}\ ${file.reference.testng.jar}${path.separator}\ ${nashorn.internal.tests.jar}${path.separator}\ - ${nashorn.api.tests.jar} + ${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} diff -r 774c63629870 -r 1db3d4e4d189 src/jdk/nashorn/api/scripting/ScriptObjectMirror.java --- a/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java Thu Nov 14 09:05:27 2013 -0800 +++ b/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java Fri Nov 15 07:16:05 2013 -0800 @@ -41,6 +41,7 @@ import java.util.Set; import java.util.concurrent.Callable; import javax.script.Bindings; +import jdk.nashorn.internal.runtime.ConsString; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.GlobalObject; import jdk.nashorn.internal.runtime.JSType; @@ -594,14 +595,35 @@ } /** - * Make a script object mirror on given object if needed. + * Utilitity to convert this script object to the given type. * - * @param obj object to be wrapped - * @param homeGlobal global to which this object belongs - * @return wrapped object + * @param type destination type to convert to + * @return converted object */ - public static Object wrap(final Object obj, final ScriptObject homeGlobal) { - return (obj instanceof ScriptObject && homeGlobal != null) ? new ScriptObjectMirror((ScriptObject)obj, homeGlobal) : obj; + public T to(final Class type) { + return inGlobal(new Callable() { + @Override + public T call() { + return type.cast(ScriptUtils.convert(sobj, type)); + } + }); + } + + /** + * Make a script object mirror on given object if needed. Also converts ConsString instances to Strings. + * + * @param obj object to be wrapped/converted + * @param homeGlobal global to which this object belongs. Not used for ConsStrings. + * @return wrapped/converted object + */ + public static Object wrap(final Object obj, final Object homeGlobal) { + if(obj instanceof ScriptObject) { + return homeGlobal instanceof ScriptObject ? new ScriptObjectMirror((ScriptObject)obj, (ScriptObject)homeGlobal) : obj; + } + if(obj instanceof ConsString) { + return obj.toString(); + } + return obj; } /** @@ -611,7 +633,7 @@ * @param homeGlobal global to which this object belongs * @return unwrapped object */ - public static Object unwrap(final Object obj, final ScriptObject homeGlobal) { + public static Object unwrap(final Object obj, final Object homeGlobal) { if (obj instanceof ScriptObjectMirror) { final ScriptObjectMirror mirror = (ScriptObjectMirror)obj; return (mirror.global == homeGlobal)? mirror.sobj : obj; @@ -627,7 +649,7 @@ * @param homeGlobal global to which this object belongs * @return wrapped array */ - public static Object[] wrapArray(final Object[] args, final ScriptObject homeGlobal) { + public static Object[] wrapArray(final Object[] args, final Object homeGlobal) { if (args == null || args.length == 0) { return args; } @@ -648,7 +670,7 @@ * @param homeGlobal global to which this object belongs * @return unwrapped array */ - public static Object[] unwrapArray(final Object[] args, final ScriptObject homeGlobal) { + public static Object[] unwrapArray(final Object[] args, final Object homeGlobal) { if (args == null || args.length == 0) { return args; } diff -r 774c63629870 -r 1db3d4e4d189 src/jdk/nashorn/api/scripting/ScriptUtils.java --- a/src/jdk/nashorn/api/scripting/ScriptUtils.java Thu Nov 14 09:05:27 2013 -0800 +++ b/src/jdk/nashorn/api/scripting/ScriptUtils.java Fri Nov 15 07:16:05 2013 -0800 @@ -25,11 +25,17 @@ package jdk.nashorn.api.scripting; +import java.lang.invoke.MethodHandle; +import jdk.internal.dynalink.beans.StaticClass; +import jdk.internal.dynalink.linker.LinkerServices; +import jdk.nashorn.internal.runtime.linker.Bootstrap; +import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ScriptFunction; +import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; /** - * Utilities that are to be called from script code + * Utilities that are to be called from script code. */ public final class ScriptUtils { private ScriptUtils() {} @@ -71,4 +77,96 @@ return func.makeSynchronizedFunction(sync); } + /** + * Make a script object mirror on given object if needed. + * + * @param obj object to be wrapped + * @return wrapped object + */ + public static Object wrap(final Object obj) { + if (obj instanceof ScriptObject) { + return ScriptObjectMirror.wrap(obj, Context.getGlobal()); + } + + return obj; + } + + /** + * Unwrap a script object mirror if needed. + * + * @param obj object to be unwrapped + * @return unwrapped object + */ + public static Object unwrap(final Object obj) { + if (obj instanceof ScriptObjectMirror) { + return ScriptObjectMirror.unwrap(obj, Context.getGlobal()); + } + + return obj; + } + + /** + * Wrap an array of object to script object mirrors if needed. + * + * @param args array to be unwrapped + * @return wrapped array + */ + public static Object[] wrapArray(final Object[] args) { + if (args == null || args.length == 0) { + return args; + } + + return ScriptObjectMirror.wrapArray(args, Context.getGlobal()); + } + + /** + * Unwrap an array of script object mirrors if needed. + * + * @param args array to be unwrapped + * @return unwrapped array + */ + public static Object[] unwrapArray(final Object[] args) { + if (args == null || args.length == 0) { + return args; + } + + return ScriptObjectMirror.unwrapArray(args, Context.getGlobal()); + } + + /** + * Convert the given object to the given type. + * + * @param obj object to be converted + * @param type destination type to convert to + * @return converted object + */ + public static Object convert(final Object obj, final Object type) { + if (obj == null) { + return null; + } + + final Class clazz; + if (type instanceof Class) { + clazz = (Class)type; + } else if (type instanceof StaticClass) { + clazz = ((StaticClass)type).getRepresentedClass(); + } else { + throw new IllegalArgumentException("type expected"); + } + + final LinkerServices linker = Bootstrap.getLinkerServices(); + final MethodHandle converter = linker.getTypeConverter(obj.getClass(), clazz); + if (converter == null) { + // no supported conversion! + throw new UnsupportedOperationException("conversion not supported"); + } + + try { + return converter.invoke(obj); + } catch (final RuntimeException | Error e) { + throw e; + } catch (final Throwable t) { + throw new RuntimeException(t); + } + } } diff -r 774c63629870 -r 1db3d4e4d189 src/jdk/nashorn/internal/codegen/Attr.java --- a/src/jdk/nashorn/internal/codegen/Attr.java Thu Nov 14 09:05:27 2013 -0800 +++ b/src/jdk/nashorn/internal/codegen/Attr.java Fri Nov 15 07:16:05 2013 -0800 @@ -271,6 +271,7 @@ functionNode.addDeclaredSymbol(symbol); if (varNode.isFunctionDeclaration()) { newType(symbol, FunctionNode.FUNCTION_TYPE); + symbol.setIsFunctionDeclaration(); } return varNode.setName((IdentNode)ident.setSymbol(lc, symbol)); } @@ -1264,12 +1265,17 @@ @Override public Node leaveCOMMARIGHT(final BinaryNode binaryNode) { - return end(ensureSymbol(binaryNode.rhs().getType(), binaryNode)); + return leaveComma(binaryNode, binaryNode.rhs()); } @Override public Node leaveCOMMALEFT(final BinaryNode binaryNode) { - return end(ensureSymbol(binaryNode.lhs().getType(), binaryNode)); + return leaveComma(binaryNode, binaryNode.lhs()); + } + + private Node leaveComma(final BinaryNode commaNode, final Expression effectiveExpr) { + ensureTypeNotUnknown(effectiveExpr); + return end(ensureSymbol(effectiveExpr.getType(), commaNode)); } @Override diff -r 774c63629870 -r 1db3d4e4d189 src/jdk/nashorn/internal/codegen/CodeGenerator.java --- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java Thu Nov 14 09:05:27 2013 -0800 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java Fri Nov 15 07:16:05 2013 -0800 @@ -412,6 +412,8 @@ return method; } + assert !type.isUnknown(); + /* * The load may be of type IdentNode, e.g. "x", AccessNode, e.g. "x.y" * or IndexNode e.g. "x[y]". Both AccessNodes and IndexNodes are diff -r 774c63629870 -r 1db3d4e4d189 src/jdk/nashorn/internal/codegen/MapCreator.java --- a/src/jdk/nashorn/internal/codegen/MapCreator.java Thu Nov 14 09:05:27 2013 -0800 +++ b/src/jdk/nashorn/internal/codegen/MapCreator.java Fri Nov 15 07:16:05 2013 -0800 @@ -134,6 +134,10 @@ flags |= Property.CAN_BE_UNDEFINED; } + if (symbol.isFunctionDeclaration()) { + flags |= Property.IS_FUNCTION_DECLARATION; + } + return flags; } diff -r 774c63629870 -r 1db3d4e4d189 src/jdk/nashorn/internal/ir/Symbol.java --- a/src/jdk/nashorn/internal/ir/Symbol.java Thu Nov 14 09:05:27 2013 -0800 +++ b/src/jdk/nashorn/internal/ir/Symbol.java Fri Nov 15 07:16:05 2013 -0800 @@ -75,6 +75,8 @@ public static final int IS_SPECIALIZED_PARAM = 1 << 13; /** Is this symbol a shared temporary? */ public static final int IS_SHARED = 1 << 14; + /** Is this a function declaration? */ + public static final int IS_FUNCTION_DECLARATION = 1 << 15; /** Null or name identifying symbol. */ private final String name; @@ -360,6 +362,14 @@ } /** + * Check if this symbol is a function declaration + * @return true if a function declaration + */ + public boolean isFunctionDeclaration() { + return (flags & IS_FUNCTION_DECLARATION) == IS_FUNCTION_DECLARATION; + } + + /** * Creates an unshared copy of a symbol. The symbol must be currently shared. * @param newName the name for the new symbol. * @return a new, unshared symbol. @@ -396,6 +406,16 @@ /** + * Mark this symbol as a function declaration. + */ + public void setIsFunctionDeclaration() { + if (!isFunctionDeclaration()) { + trace("SET IS FUNCTION DECLARATION"); + flags |= IS_FUNCTION_DECLARATION; + } + } + + /** * Check if this symbol is a variable * @return true if variable */ diff -r 774c63629870 -r 1db3d4e4d189 src/jdk/nashorn/internal/objects/Global.java --- a/src/jdk/nashorn/internal/objects/Global.java Thu Nov 14 09:05:27 2013 -0800 +++ b/src/jdk/nashorn/internal/objects/Global.java Fri Nov 15 07:16:05 2013 -0800 @@ -53,19 +53,19 @@ import jdk.nashorn.internal.runtime.GlobalObject; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.NativeJavaPackage; +import jdk.nashorn.internal.runtime.PropertyDescriptor; import jdk.nashorn.internal.runtime.PropertyMap; +import jdk.nashorn.internal.runtime.Scope; import jdk.nashorn.internal.runtime.ScriptEnvironment; -import jdk.nashorn.internal.runtime.PropertyDescriptor; -import jdk.nashorn.internal.runtime.arrays.ArrayData; -import jdk.nashorn.internal.runtime.regexp.RegExpResult; -import jdk.nashorn.internal.runtime.Scope; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.ScriptingFunctions; import jdk.nashorn.internal.runtime.Source; +import jdk.nashorn.internal.runtime.arrays.ArrayData; import jdk.nashorn.internal.runtime.linker.Bootstrap; import jdk.nashorn.internal.runtime.linker.InvokeByName; +import jdk.nashorn.internal.runtime.regexp.RegExpResult; import jdk.nashorn.internal.scripts.JO; /** diff -r 774c63629870 -r 1db3d4e4d189 src/jdk/nashorn/internal/objects/NativeObject.java --- a/src/jdk/nashorn/internal/objects/NativeObject.java Thu Nov 14 09:05:27 2013 -0800 +++ b/src/jdk/nashorn/internal/objects/NativeObject.java Fri Nov 15 07:16:05 2013 -0800 @@ -60,6 +60,7 @@ import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.linker.Bootstrap; import jdk.nashorn.internal.runtime.linker.InvokeByName; +import jdk.nashorn.internal.runtime.linker.NashornBeansLinker; /** * ECMA 15.2 Object objects @@ -729,8 +730,7 @@ final MethodType methodType, final Object source) { final GuardedInvocation inv; try { - inv = linker.getGuardedInvocation(createLinkRequest(operation, methodType, source), - Bootstrap.getLinkerServices()); + inv = NashornBeansLinker.getGuardedInvocation(linker, createLinkRequest(operation, methodType, source), Bootstrap.getLinkerServices()); assert passesGuard(source, inv.getGuard()); } catch(RuntimeException|Error e) { throw e; diff -r 774c63629870 -r 1db3d4e4d189 src/jdk/nashorn/internal/runtime/ConsString.java --- a/src/jdk/nashorn/internal/runtime/ConsString.java Thu Nov 14 09:05:27 2013 -0800 +++ b/src/jdk/nashorn/internal/runtime/ConsString.java Fri Nov 15 07:16:05 2013 -0800 @@ -57,10 +57,7 @@ @Override public String toString() { - if (!flat) { - flatten(); - } - return (String) left; + return (String) flattened(); } @Override @@ -70,18 +67,19 @@ @Override public char charAt(final int index) { - if (!flat) { - flatten(); - } - return left.charAt(index); + return flattened().charAt(index); } @Override public CharSequence subSequence(final int start, final int end) { + return flattened().subSequence(start, end); + } + + private CharSequence flattened() { if (!flat) { flatten(); } - return left.subSequence(start, end); + return left; } private void flatten() { diff -r 774c63629870 -r 1db3d4e4d189 src/jdk/nashorn/internal/runtime/JSType.java --- a/src/jdk/nashorn/internal/runtime/JSType.java Thu Nov 14 09:05:27 2013 -0800 +++ b/src/jdk/nashorn/internal/runtime/JSType.java Fri Nov 15 07:16:05 2013 -0800 @@ -88,6 +88,9 @@ /** JavaScript compliant conversion function from Object to number */ public static final Call TO_NUMBER = staticCall(myLookup, JSType.class, "toNumber", double.class, Object.class); + /** JavaScript compliant conversion function from Object to String */ + public static final Call TO_STRING = staticCall(myLookup, JSType.class, "toString", String.class, Object.class); + /** JavaScript compliant conversion function from Object to int32 */ public static final Call TO_INT32 = staticCall(myLookup, JSType.class, "toInt32", int.class, Object.class); @@ -883,7 +886,7 @@ */ public static Object toJavaArray(final Object obj, final Class componentType) { if (obj instanceof ScriptObject) { - return convertArray(((ScriptObject)obj).getArray().asObjectArray(), componentType); + return ((ScriptObject)obj).getArray().asArrayOfType(componentType); } else if (obj instanceof JSObject) { final ArrayLikeIterator itr = ArrayLikeIterator.arrayLikeIterator(obj); final int len = (int) itr.getLength(); @@ -908,6 +911,15 @@ * @return converted Java array */ public static Object convertArray(final Object[] src, final Class componentType) { + if(componentType == Object.class) { + for(int i = 0; i < src.length; ++i) { + final Object e = src[i]; + if(e instanceof ConsString) { + src[i] = e.toString(); + } + } + } + final int l = src.length; final Object dst = Array.newInstance(componentType, l); final MethodHandle converter = Bootstrap.getLinkerServices().getTypeConverter(Object.class, componentType); diff -r 774c63629870 -r 1db3d4e4d189 src/jdk/nashorn/internal/runtime/Property.java --- a/src/jdk/nashorn/internal/runtime/Property.java Thu Nov 14 09:05:27 2013 -0800 +++ b/src/jdk/nashorn/internal/runtime/Property.java Fri Nov 15 07:16:05 2013 -0800 @@ -56,33 +56,36 @@ public static final int WRITABLE_ENUMERABLE_CONFIGURABLE = 0b0000_0000_0000; /** ECMA 8.6.1 - Is this property not writable? */ - public static final int NOT_WRITABLE = 0b0000_0000_0001; + public static final int NOT_WRITABLE = 1 << 0; /** ECMA 8.6.1 - Is this property not enumerable? */ - public static final int NOT_ENUMERABLE = 0b0000_0000_0010; + public static final int NOT_ENUMERABLE = 1 << 1; /** ECMA 8.6.1 - Is this property not configurable? */ - public static final int NOT_CONFIGURABLE = 0b0000_0000_0100; + public static final int NOT_CONFIGURABLE = 1 << 2; - private static final int MODIFY_MASK = 0b0000_0000_1111; + private static final int MODIFY_MASK = (NOT_WRITABLE | NOT_ENUMERABLE | NOT_CONFIGURABLE); /** Is this a spill property? See {@link AccessorProperty} */ - public static final int IS_SPILL = 0b0000_0001_0000; + public static final int IS_SPILL = 1 << 3; /** Is this a function parameter? */ - public static final int IS_PARAMETER = 0b0000_0010_0000; + public static final int IS_PARAMETER = 1 << 4; /** Is parameter accessed thru arguments? */ - public static final int HAS_ARGUMENTS = 0b0000_0100_0000; + public static final int HAS_ARGUMENTS = 1 << 5; /** Is this property always represented as an Object? See {@link ObjectClassGenerator} and dual fields flag. */ - public static final int IS_ALWAYS_OBJECT = 0b0000_1000_0000; + public static final int IS_ALWAYS_OBJECT = 1 << 6; /** Can this property be primitive? */ - public static final int CAN_BE_PRIMITIVE = 0b0001_0000_0000; + public static final int CAN_BE_PRIMITIVE = 1 << 7; /** Can this property be undefined? */ - public static final int CAN_BE_UNDEFINED = 0b0010_0000_0000; + public static final int CAN_BE_UNDEFINED = 1 << 8; + + /* Is this a function declaration property ? */ + public static final int IS_FUNCTION_DECLARATION = 1 << 9; /** Property key. */ private final String key; @@ -522,4 +525,12 @@ public boolean canBeUndefined() { return (flags & CAN_BE_UNDEFINED) == CAN_BE_UNDEFINED; } + + /** + * Check whether this property represents a function declaration. + * @return whether this property is a function declaration or not. + */ + public boolean isFunctionDeclaration() { + return (flags & IS_FUNCTION_DECLARATION) == IS_FUNCTION_DECLARATION; + } } diff -r 774c63629870 -r 1db3d4e4d189 src/jdk/nashorn/internal/runtime/ScriptObject.java --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Thu Nov 14 09:05:27 2013 -0800 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java Fri Nov 15 07:16:05 2013 -0800 @@ -226,14 +226,23 @@ for (final Property property : properties) { final String key = property.getKey(); - - if (newMap.findProperty(key) == null) { + final Property oldProp = newMap.findProperty(key); + if (oldProp == null) { if (property instanceof UserAccessorProperty) { final UserAccessorProperty prop = this.newUserAccessors(key, property.getFlags(), property.getGetterFunction(source), property.getSetterFunction(source)); newMap = newMap.addProperty(prop); } else { newMap = newMap.addPropertyBind((AccessorProperty)property, source); } + } else { + // See ECMA section 10.5 Declaration Binding Instantiation + // step 5 processing each function declaration. + if (property.isFunctionDeclaration() && !oldProp.isConfigurable()) { + if (oldProp instanceof UserAccessorProperty || + !(oldProp.isWritable() && oldProp.isEnumerable())) { + throw typeError("cant.redefine.property", key, ScriptRuntime.safeToString(this)); + } + } } } diff -r 774c63629870 -r 1db3d4e4d189 src/jdk/nashorn/internal/runtime/linker/Bootstrap.java --- a/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Thu Nov 14 09:05:27 2013 -0800 +++ b/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Fri Nov 15 07:16:05 2013 -0800 @@ -63,7 +63,7 @@ final DynamicLinkerFactory factory = new DynamicLinkerFactory(); factory.setPrioritizedLinkers(new NashornLinker(), new NashornPrimitiveLinker(), new NashornStaticClassLinker(), new BoundDynamicMethodLinker(), new JavaSuperAdapterLinker(), new JSObjectLinker(), new ReflectionCheckLinker()); - factory.setFallbackLinkers(new BeansLinker(), new NashornBottomLinker()); + factory.setFallbackLinkers(new NashornBeansLinker(), new NashornBottomLinker()); factory.setSyncOnRelink(true); final int relinkThreshold = Options.getIntProperty("nashorn.unstable.relink.threshold", -1); if (relinkThreshold > -1) { diff -r 774c63629870 -r 1db3d4e4d189 src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethodLinker.java --- a/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethodLinker.java Thu Nov 14 09:05:27 2013 -0800 +++ b/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethodLinker.java Fri Nov 15 07:16:05 2013 -0800 @@ -72,7 +72,7 @@ type.changeParameterType(0, dynamicMethodClass).changeParameterType(1, boundThis.getClass())); // Delegate to BeansLinker - final GuardedInvocation inv = BeansLinker.getLinkerForClass(dynamicMethodClass).getGuardedInvocation( + final GuardedInvocation inv = NashornBeansLinker.getGuardedInvocation(BeansLinker.getLinkerForClass(dynamicMethodClass), linkRequest.replaceArguments(newDescriptor, args), linkerServices); if(inv == null) { return null; diff -r 774c63629870 -r 1db3d4e4d189 src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java --- a/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java Thu Nov 14 09:05:27 2013 -0800 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java Fri Nov 15 07:16:05 2013 -0800 @@ -100,8 +100,9 @@ type.changeParameterType(0, adapterClass), 0); // Delegate to BeansLinker - final GuardedInvocation guardedInv = BeansLinker.getLinkerForClass(adapterClass).getGuardedInvocation( - linkRequest.replaceArguments(newDescriptor, args), linkerServices); + final GuardedInvocation guardedInv = NashornBeansLinker.getGuardedInvocation( + BeansLinker.getLinkerForClass(adapterClass), linkRequest.replaceArguments(newDescriptor, args), + linkerServices); final MethodHandle guard = IS_ADAPTER_OF_CLASS.bindTo(adapterClass); if(guardedInv == null) { diff -r 774c63629870 -r 1db3d4e4d189 src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Fri Nov 15 07:16:05 2013 -0800 @@ -0,0 +1,127 @@ +/* + * 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.linker; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import jdk.internal.dynalink.beans.BeansLinker; +import jdk.internal.dynalink.linker.ConversionComparator.Comparison; +import jdk.internal.dynalink.linker.GuardedInvocation; +import jdk.internal.dynalink.linker.GuardingDynamicLinker; +import jdk.internal.dynalink.linker.LinkRequest; +import jdk.internal.dynalink.linker.LinkerServices; +import jdk.internal.dynalink.support.Lookup; +import jdk.nashorn.internal.runtime.ConsString; + +/** + * This linker delegates to a {@code BeansLinker} but passes it a special linker services object that has a modified + * {@code asType} method that will ensure that we never pass internal engine objects that should not be externally + * observable (currently only ConsString) to Java APIs, but rather that we flatten it into a String. We can't just add + * this functionality as custom converters via {@code GuaardingTypeConverterFactory}, since they are not consulted when + * the target method handle parameter signature is {@code Object}. + */ +public class NashornBeansLinker implements GuardingDynamicLinker { + private static final MethodHandle EXPORT_ARGUMENT = new Lookup(MethodHandles.lookup()).findOwnStatic("exportArgument", Object.class, Object.class); + + private final BeansLinker beansLinker = new BeansLinker(); + + @Override + public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception { + return getGuardedInvocation(beansLinker, linkRequest, linkerServices); + } + + /** + * Delegates to the specified linker but injects its linker services wrapper so that it will apply all special + * conversions that this class does. + * @param delegateLinker the linker to which the actual work is delegated to. + * @param linkRequest the delegated link request + * @param linkerServices the original link services that will be augmented with special conversions + * @return the guarded invocation from the delegate, possibly augmented with special conversions + * @throws Exception if the delegate throws an exception + */ + public static GuardedInvocation getGuardedInvocation(final GuardingDynamicLinker delegateLinker, final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception { + return delegateLinker.getGuardedInvocation(linkRequest, new NashornBeansLinkerServices(linkerServices)); + } + + @SuppressWarnings("unused") + private static Object exportArgument(final Object arg) { + return arg instanceof ConsString ? arg.toString() : arg; + } + + private static class NashornBeansLinkerServices implements LinkerServices { + private final LinkerServices linkerServices; + + NashornBeansLinkerServices(final LinkerServices linkerServices) { + this.linkerServices = linkerServices; + } + + @Override + public MethodHandle asType(final MethodHandle handle, final MethodType fromType) { + final MethodHandle typed = linkerServices.asType(handle, fromType); + + final MethodType handleType = handle.type(); + final int paramCount = handleType.parameterCount(); + assert fromType.parameterCount() == handleType.parameterCount(); + + MethodHandle[] filters = null; + for(int i = 0; i < paramCount; ++i) { + if(shouldConvert(handleType.parameterType(i), fromType.parameterType(i))) { + if(filters == null) { + filters = new MethodHandle[paramCount]; + } + filters[i] = EXPORT_ARGUMENT; + } + } + + return filters != null ? MethodHandles.filterArguments(typed, 0, filters) : typed; + } + + private static boolean shouldConvert(final Class handleType, final Class fromType) { + return handleType == Object.class && fromType == Object.class; + } + + @Override + public MethodHandle getTypeConverter(final Class sourceType, final Class targetType) { + return linkerServices.getTypeConverter(sourceType, targetType); + } + + @Override + public boolean canConvert(final Class from, final Class to) { + return linkerServices.canConvert(from, to); + } + + @Override + public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest) throws Exception { + return linkerServices.getGuardedInvocation(linkRequest); + } + + @Override + public Comparison compareConversion(final Class sourceType, final Class targetType1, final Class targetType2) { + return linkerServices.compareConversion(sourceType, targetType1, targetType2); + } + } +} diff -r 774c63629870 -r 1db3d4e4d189 src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java --- a/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java Thu Nov 14 09:05:27 2013 -0800 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java Fri Nov 15 07:16:05 2013 -0800 @@ -33,14 +33,18 @@ import java.lang.invoke.MethodType; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.util.Map; +import java.util.HashMap; import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.beans.BeansLinker; import jdk.internal.dynalink.linker.GuardedInvocation; import jdk.internal.dynalink.linker.GuardingDynamicLinker; +import jdk.internal.dynalink.linker.GuardingTypeConverterFactory; import jdk.internal.dynalink.linker.LinkRequest; import jdk.internal.dynalink.linker.LinkerServices; import jdk.internal.dynalink.support.Guards; import jdk.nashorn.internal.runtime.Context; +import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.ScriptRuntime; /** @@ -50,7 +54,7 @@ * setters for Java objects that couldn't be linked by any other linker, and throw appropriate ECMAScript errors for * attempts to invoke arbitrary Java objects as functions or constructors. */ -final class NashornBottomLinker implements GuardingDynamicLinker { +final class NashornBottomLinker implements GuardingDynamicLinker, GuardingTypeConverterFactory { @Override public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) @@ -129,6 +133,29 @@ throw new AssertionError("unknown call type " + desc); } + @Override + public GuardedInvocation convertToType(final Class sourceType, final Class targetType) throws Exception { + final GuardedInvocation gi = convertToTypeNoCast(sourceType, targetType); + return gi == null ? null : gi.asType(MH.type(targetType, sourceType)); + } + + /** + * Main part of the implementation of {@link GuardingTypeConverterFactory#convertToType(Class, Class)} that doesn't + * care about adapting the method signature; that's done by the invoking method. Returns conversion from Object to String/number/boolean (JS primitive types). + * @param sourceType the source type + * @param targetType the target type + * @return a guarded invocation that converts from the source type to the target type. + * @throws Exception if something goes wrong + */ + private static GuardedInvocation convertToTypeNoCast(final Class sourceType, final Class targetType) throws Exception { + final MethodHandle mh = CONVERTERS.get(targetType); + if (mh != null) { + return new GuardedInvocation(mh, null); + } + + return null; + } + private static GuardedInvocation getInvocation(final MethodHandle handle, final Object self, final LinkerServices linkerServices, final CallSiteDescriptor desc) { return Bootstrap.asType(new GuardedInvocation(handle, Guards.getClassGuard(self.getClass())), linkerServices, desc); } @@ -161,6 +188,15 @@ throw new AssertionError("unknown call type " + desc); } + private static final Map, MethodHandle> CONVERTERS = new HashMap<>(); + static { + CONVERTERS.put(boolean.class, JSType.TO_BOOLEAN.methodHandle()); + CONVERTERS.put(double.class, JSType.TO_NUMBER.methodHandle()); + CONVERTERS.put(int.class, JSType.TO_INTEGER.methodHandle()); + CONVERTERS.put(long.class, JSType.TO_LONG.methodHandle()); + CONVERTERS.put(String.class, JSType.TO_STRING.methodHandle()); + } + private static String getArgument(final LinkRequest linkRequest) { final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor(); if (desc.getNameTokenCount() > 2) { diff -r 774c63629870 -r 1db3d4e4d189 src/jdk/nashorn/internal/runtime/linker/NashornLinker.java --- a/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java Thu Nov 14 09:05:27 2013 -0800 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java Fri Nov 15 07:16:05 2013 -0800 @@ -32,6 +32,8 @@ import java.lang.reflect.Modifier; import java.util.Deque; import java.util.List; +import java.util.Map; +import javax.script.Bindings; import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.linker.ConversionComparator; import jdk.internal.dynalink.linker.GuardedInvocation; @@ -40,7 +42,11 @@ import jdk.internal.dynalink.linker.LinkerServices; import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; import jdk.internal.dynalink.support.Guards; +import jdk.nashorn.api.scripting.JSObject; +import jdk.nashorn.api.scripting.ScriptObjectMirror; +import jdk.nashorn.api.scripting.ScriptUtils; import jdk.nashorn.internal.objects.NativeArray; +import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; @@ -115,9 +121,14 @@ return new GuardedInvocation(mh, canLinkTypeStatic(sourceType) ? null : IS_NASHORN_OR_UNDEFINED_TYPE); } - GuardedInvocation inv = getArrayConverter(sourceType, targetType); - if(inv != null) { - return inv; + final GuardedInvocation arrayConverter = getArrayConverter(sourceType, targetType); + if(arrayConverter != null) { + return arrayConverter; + } + + final GuardedInvocation mirrorConverter = getMirrorConverter(sourceType, targetType); + if(mirrorConverter != null) { + return mirrorConverter; } return getSamTypeConverter(sourceType, targetType); @@ -181,6 +192,18 @@ return MH.asType(converter, converter.type().changeReturnType(type)); } + private static GuardedInvocation getMirrorConverter(Class sourceType, Class targetType) { + // Could've also used (targetType.isAssignableFrom(ScriptObjectMirror.class) && targetType != Object.class) but + // it's probably better to explicitly spell out the supported target types + if (targetType == Map.class || targetType == Bindings.class || targetType == JSObject.class || targetType == ScriptObjectMirror.class) { + if(ScriptObject.class.isAssignableFrom(sourceType)) { + return new GuardedInvocation(CREATE_MIRROR, null); + } + return new GuardedInvocation(CREATE_MIRROR, IS_SCRIPT_OBJECT); + } + return null; + } + private static boolean isAutoConvertibleFromFunction(final Class clazz) { return isAbstractClass(clazz) && !ScriptObject.class.isAssignableFrom(clazz) && JavaAdapterFactory.isAutoConvertibleFromFunction(clazz); @@ -235,17 +258,23 @@ return clazz == List.class || clazz == Deque.class; } + private static final MethodHandle IS_SCRIPT_OBJECT = Guards.isInstance(ScriptObject.class, MH.type(Boolean.TYPE, Object.class)); private static final MethodHandle IS_SCRIPT_FUNCTION = Guards.isInstance(ScriptFunction.class, MH.type(Boolean.TYPE, Object.class)); private static final MethodHandle IS_NATIVE_ARRAY = Guards.isOfClass(NativeArray.class, MH.type(Boolean.TYPE, Object.class)); - private static final MethodHandle IS_NASHORN_OR_UNDEFINED_TYPE = findOwnMH("isNashornTypeOrUndefined", - Boolean.TYPE, Object.class); + private static final MethodHandle IS_NASHORN_OR_UNDEFINED_TYPE = findOwnMH("isNashornTypeOrUndefined", Boolean.TYPE, Object.class); + private static final MethodHandle CREATE_MIRROR = findOwnMH("createMirror", Object.class, Object.class); @SuppressWarnings("unused") private static boolean isNashornTypeOrUndefined(final Object obj) { return obj instanceof ScriptObject || obj instanceof Undefined; } + @SuppressWarnings("unused") + private static Object createMirror(final Object obj) { + return ScriptUtils.wrap(obj); + } + private static MethodHandle findOwnMH(final String name, final Class rtype, final Class... types) { return MH.findStatic(MethodHandles.lookup(), NashornLinker.class, name, MH.type(rtype, types)); } diff -r 774c63629870 -r 1db3d4e4d189 src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java --- a/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java Thu Nov 14 09:05:27 2013 -0800 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java Fri Nov 15 07:16:05 2013 -0800 @@ -93,7 +93,7 @@ } private static GuardedInvocation delegate(LinkerServices linkerServices, final LinkRequest request) throws Exception { - return staticClassLinker.getGuardedInvocation(request, linkerServices); + return NashornBeansLinker.getGuardedInvocation(staticClassLinker, request, linkerServices); } private static GuardedInvocation checkNullConstructor(final GuardedInvocation ctorInvocation, final Class receiverClass) { diff -r 774c63629870 -r 1db3d4e4d189 test/script/basic/JDK-8015355.js --- a/test/script/basic/JDK-8015355.js Thu Nov 14 09:05:27 2013 -0800 +++ b/test/script/basic/JDK-8015355.js Fri Nov 15 07:16:05 2013 -0800 @@ -28,10 +28,6 @@ * @run */ -function fail(msg) { - print(msg); -} - function check(callback) { try { callback(); diff -r 774c63629870 -r 1db3d4e4d189 test/script/basic/JDK-8027236.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8027236.js Fri Nov 15 07:16:05 2013 -0800 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8027236: Ensure ScriptObject and ConsString aren't visible to Java + * + * @test + * @run + */ + +// Check that ConsString is flattened +var m = new java.util.HashMap() +var x = "f" +x += "oo" +m.put(x, "bar") +print(m.get("foo")) +// Note: many more tests are run by the JavaExportImportTest TestNG class. diff -r 774c63629870 -r 1db3d4e4d189 test/script/basic/JDK-8027236.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8027236.js.EXPECTED Fri Nov 15 07:16:05 2013 -0800 @@ -0,0 +1,1 @@ +bar diff -r 774c63629870 -r 1db3d4e4d189 test/script/basic/JDK-8027700.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8027700.js Fri Nov 15 07:16:05 2013 -0800 @@ -0,0 +1,54 @@ +/* + * 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-8027700: function redeclaration checks missing for declaration binding instantiation + * + * @test + * @run + */ + +Object.defineProperty(this,"x", { + value:0, + writable:true, + enumerable:false +}) + +try { + eval("function x() {}"); + fail("should have thrown TypeError"); +} catch (e) { + if (! (e instanceof TypeError)) { + fail("TypeError expected but got " + e); + } +} + +Object.defineProperty(this, "foo", { value:0 }) +try { + eval("function foo() {}"); + fail("should have thrown TypeError"); +} catch (e) { + if (! (e instanceof TypeError)) { + fail("TypeError expected but got " + e); + } +} diff -r 774c63629870 -r 1db3d4e4d189 test/script/basic/JDK-8027753.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8027753.js Fri Nov 15 07:16:05 2013 -0800 @@ -0,0 +1,50 @@ +/* + * 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-8027753: Support ScriptObject to JSObject, ScriptObjectMirror, Map, Bindings auto-conversion as well as explicit wrap, unwrap + * + * @test + * @run + */ + +var ScriptUtils = Java.type("jdk.nashorn.api.scripting.ScriptUtils"); +var ScriptObjectMirror = Java.type("jdk.nashorn.api.scripting.ScriptObjectMirror"); + +var obj = { foo: 34, bar: 'hello' }; + +var wrapped = ScriptUtils.wrap(obj); +if (! (wrapped instanceof ScriptObjectMirror)) { + fail("ScriptUtils.wrap does not return a ScriptObjectMirror"); +} + +print("wrapped.foo = " + wrapped.foo); +print("wrapped.bar = " + wrapped.bar); + +var unwrapped = ScriptUtils.unwrap(wrapped); +if (! (unwrapped instanceof Object)) { + fail("ScriptUtils.unwrap does not return a ScriptObject"); +} + +// same object unwrapped? +print(unwrapped === obj); diff -r 774c63629870 -r 1db3d4e4d189 test/script/basic/JDK-8027753.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8027753.js.EXPECTED Fri Nov 15 07:16:05 2013 -0800 @@ -0,0 +1,3 @@ +wrapped.foo = 34 +wrapped.bar = hello +true diff -r 774c63629870 -r 1db3d4e4d189 test/script/basic/JDK-8027828.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8027828.js Fri Nov 15 07:16:05 2013 -0800 @@ -0,0 +1,35 @@ +/* + * 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-8027828: ClassCastException when converting return value of a Java method to boolean + * + * @test + * @run + */ + +var x = new java.util.HashMap() +x.put('test', new java.io.File('test')) +if (x.get("test")) { + print('Found!') +} diff -r 774c63629870 -r 1db3d4e4d189 test/script/basic/JDK-8027828.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8027828.js.EXPECTED Fri Nov 15 07:16:05 2013 -0800 @@ -0,0 +1,1 @@ +Found! diff -r 774c63629870 -r 1db3d4e4d189 test/script/basic/JDK-8028020.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8028020.js Fri Nov 15 07:16:05 2013 -0800 @@ -0,0 +1,40 @@ +/* + * 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-8028020: Function parameter as last expression in comma in return value causes bad type calculation + * + * @test + * @run + */ + +function f(x) { + return 1, x +} + +function g(x, y) { + return x, y +} + +print(f("'1, x' works.")) +print(g(42, "'x, y' works too.")) diff -r 774c63629870 -r 1db3d4e4d189 test/script/basic/JDK-8028020.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8028020.js.EXPECTED Fri Nov 15 07:16:05 2013 -0800 @@ -0,0 +1,2 @@ +'1, x' works. +'x, y' works too. diff -r 774c63629870 -r 1db3d4e4d189 test/script/basic/convert.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/convert.js Fri Nov 15 07:16:05 2013 -0800 @@ -0,0 +1,61 @@ +/* + * 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. + */ + +/** + * Tests for convert method of ScriptUtils. + * + * @test + * @run + */ + +var ScriptUtils = Java.type("jdk.nashorn.api.scripting.ScriptUtils"); +obj = { valueOf: function() { print("hello"); return 43.3; } }; + +// object to double +print(ScriptUtils.convert(obj, java.lang.Number.class)); + +// array to List +var arr = [3, 44, 23, 33]; +var list = ScriptUtils.convert(arr, java.util.List.class); +print(list instanceof java.util.List) +print(list); + +// object to Map +obj = { foo: 333, bar: 'hello'}; +var map = ScriptUtils.convert(obj, java.util.Map.class); +print(map instanceof java.util.Map); +for (m in map) { + print(m + " " + map[m]); +} + +// object to String +obj = { toString: function() { print("in toString"); return "foo" } }; +print(ScriptUtils.convert(obj, java.lang.String.class)); + +// array to Java array +var jarr = ScriptUtils.convert(arr, Java.type("int[]")); +print(jarr instanceof Java.type("int[]")); +for (i in jarr) { + print(jarr[i]); +} + diff -r 774c63629870 -r 1db3d4e4d189 test/script/basic/convert.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/convert.js.EXPECTED Fri Nov 15 07:16:05 2013 -0800 @@ -0,0 +1,14 @@ +hello +43.3 +true +[3, 44, 23, 33] +true +foo 333 +bar hello +in toString +foo +true +3 +44 +23 +33 diff -r 774c63629870 -r 1db3d4e4d189 test/script/jfx.js --- a/test/script/jfx.js Thu Nov 14 09:05:27 2013 -0800 +++ b/test/script/jfx.js Fri Nov 15 07:16:05 2013 -0800 @@ -37,13 +37,24 @@ 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 Paint = Java.type("javafx.scene.paint.Paint"); +var Color = Java.type("javafx.scene.paint.Color"); +var Image = Java.type("javafx.scene.image.Image"); +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 Platform = Java.type("javafx.application.Platform"); +var Runnable = Java.type("java.lang.Runnable"); +var RunnableExtend = Java.extend(Runnable); +var AnimationTimer = Java.type("javafx.animation.AnimationTimer"); +var AnimationTimerExtend = Java.extend(AnimationTimer); +var Timer = Java.type("java.util.Timer"); +var TimerTask = Java.type("java.util.TimerTask"); -var WAIT = 2000; var TESTNAME = "test"; var fsep = System.getProperty("file.separator"); @@ -53,14 +64,16 @@ 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"); + var scrShotTmp = tmpdir + fsep + "screenshot" + timenow +".png"; + var goldenImageDir = __DIR__ + "jfx" + fsep + TESTNAME + fsep + "golden"; + makeScreenShot(scrShotTmp); + var dupImg = isDuplicateImages(scrShotTmp, goldenImageDir); + (new File(scrShotTmp)).delete(); + if (!dupImg) System.err.println("ERROR: screenshot does not match the golden image"); exit(0); } }; - raceTimer.schedule(timerTask, WAIT); + raceTimer.schedule(timerTask, 100); } function makeScreenShot(shootToImg) { @@ -70,10 +83,10 @@ imageJemmy.save(shootToImg); } -function isDuplicateImages(file1, file2) { - var f1 = new File(file1); +function isDuplicateImages(screenShot, goldenDir) { + var f1 = new File(screenShot); var f2; - var sb = new StringBuffer(file2); + var sb = new StringBuffer(goldenDir); if (OSInfo.getOSType() == OSType.WINDOWS) { f2 = new File(sb.append(fsep + "windows.png").toString()); } else if (OSInfo.getOSType() == OSType.LINUX) { @@ -81,8 +94,6 @@ } 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())); diff -r 774c63629870 -r 1db3d4e4d189 test/script/jfx/flyingimage.js --- a/test/script/jfx/flyingimage.js Thu Nov 14 09:05:27 2013 -0800 +++ b/test/script/jfx/flyingimage.js Fri Nov 15 07:16:05 2013 -0800 @@ -31,15 +31,6 @@ 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); @@ -48,10 +39,9 @@ } 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 t = frame; var gc = canvas.graphicsContext2D; gc.setFill(Color.web("#cccccc")); gc.fillRect(0, 0, WIDTH, HEIGHT); @@ -61,7 +51,7 @@ var c = 200; var msc= 0.5 * HEIGHT / img.height; var sp0 = 0.003; - for (var h = 0; h < c; h++, t++) { + for (var h = 0; h < c; h++) { 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)); @@ -69,15 +59,26 @@ 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(); +var frame = 0; +var timer = new AnimationTimerExtend() { + handle: function handle(now) { + if (frame < 200) { + renderFrame(); + frame++; + } else { + checkImageAndExit(); + timer.stop(); + } + } +}; +timer.start(); + diff -r 774c63629870 -r 1db3d4e4d189 test/script/jfx/flyingimage/flyingimage.png Binary file test/script/jfx/flyingimage/flyingimage.png has changed diff -r 774c63629870 -r 1db3d4e4d189 test/script/jfx/flyingimage/golden/linux.png Binary file test/script/jfx/flyingimage/golden/linux.png has changed diff -r 774c63629870 -r 1db3d4e4d189 test/script/jfx/flyingimage/golden/macosx.png Binary file test/script/jfx/flyingimage/golden/macosx.png has changed diff -r 774c63629870 -r 1db3d4e4d189 test/script/jfx/flyingimage/golden/windows.png Binary file test/script/jfx/flyingimage/golden/windows.png has changed diff -r 774c63629870 -r 1db3d4e4d189 test/script/jfx/kaleidoscope.js --- a/test/script/jfx/kaleidoscope.js Thu Nov 14 09:05:27 2013 -0800 +++ b/test/script/jfx/kaleidoscope.js Fri Nov 15 07:16:05 2013 -0800 @@ -30,13 +30,6 @@ */ 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; @@ -56,26 +49,28 @@ var r,e; var fade; var prv_x,prv_y,prv_x2,prv_y2; +var isFrameRendered = false; 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(); + if (!isFrameRendered) { + 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]); + isFrameRendered = true; } + anim(); } function anim() { @@ -154,9 +149,19 @@ 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 +var frame = 0; +var timer = new AnimationTimerExtend() { + handle: function handle(now) { + if (frame < 800) { + renderFrame(); + frame++; + } else { + checkImageAndExit(); + timer.stop(); + } + } +}; +timer.start(); diff -r 774c63629870 -r 1db3d4e4d189 test/script/jfx/kaleidoscope/golden/linux.png Binary file test/script/jfx/kaleidoscope/golden/linux.png has changed diff -r 774c63629870 -r 1db3d4e4d189 test/script/jfx/kaleidoscope/golden/macosx.png Binary file test/script/jfx/kaleidoscope/golden/macosx.png has changed diff -r 774c63629870 -r 1db3d4e4d189 test/script/jfx/kaleidoscope/golden/windows.png Binary file test/script/jfx/kaleidoscope/golden/windows.png has changed diff -r 774c63629870 -r 1db3d4e4d189 test/script/jfx/spread.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/jfx/spread.js Fri Nov 15 07:16:05 2013 -0800 @@ -0,0 +1,222 @@ +/* + * 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 = "spread"; + +var WIDTH = 800; +var HEIGHT = 600; +var canvas = new Canvas(WIDTH, HEIGHT); +var context = canvas.graphicsContext2D; + +/* "Spread" tech demo of canvas by Tom Theisen + * + * This will animate a sequence of branch structures in a canvas element. + * Each frame, a new direction is calculated, similar to the last frame. + */ + +var start_width = 20; // starting width of each branch +var frame_time = 30; // milliseconds per frame +var straighten_factor = 0.95; // value from 0 to 1, factor applied to direction_offset every frame +var curviness = 0.2; // amount of random direction change each frame + +var color_speed = 0.03; // speed at which colors change when cycling is enabled +var branch_shrink = 0.95; // factor by which branches shrink every frame +var min_width = 1; // minimum WIDTH for branch, after which they are discontinued +var branch_opacity = 0.4; // opacity of lines drawn +var branch_count = 3; // branch count per tree +var branch_bud_size = 0.5; // ratio of original branch size at which branch will split +var branch_bud_angle = 1; // angle offset for split branch; + +var paper; // reference to graphics context +var branches = Object(); // linked list of active branches +var color_styles = []; // pre-computed list of colors as styles. format: (r,g,b,a) +var direction_offset = 0; // current direction offset in radians. this is applied to all branches. +var frame = 0; // frame counter +var timespent = 0; // total time spent so far, used to calculate average frame render duration +var frameratespan; // html span element for updating performance number + +// preferences object, contains an attribute for each user setting +var prefs = { + wrap: true, // causes branches reaching edge of viewable area to appear on opposite side + fade: false, // fade existing graphics on each frame + cycle: true, // gradually change colors each frame + new_branch_frames: 20 // number of frames elapsed between each auto-generated tree +}; + +// create tree at the specified position with number of branches +function create_tree(branches, start_width, position, branch_count) { + var angle_offset = Math.PI * 2 / branch_count; + for (var i = 0; i < branch_count; ++i) { + branch_add(branches, new Branch(position, angle_offset * i, start_width)); + } +} + +// add branch to collection +function branch_add(branches, branch) { + branch.next = branches.next; + branches.next = branch; +} + +// get the coordinates for the position of a new tree +// use the center of the canvas +function get_new_tree_center(width, height) { + return { + x: 0.5 * width, + y: 0.5 * height + }; +} + +// Branch constructor +// position has x and y properties +// direction is in radians +function Branch(position, direction, width) { + this.x = position.x; + this.y = position.y; + this.width = width; + this.original_width = width; + this.direction = direction; +} + +// update position, direction and width of a particular branch +function branch_update(branches, branch, paper) { + paper.beginPath(); + paper.lineWidth = branch.width; + paper.moveTo(branch.x, branch.y); + + branch.width *= branch_shrink; + branch.direction += direction_offset; + branch.x += Math.cos(branch.direction) * branch.width; + branch.y += Math.sin(branch.direction) * branch.width; + + paper.lineTo(branch.x, branch.y); + paper.stroke(); + + if (prefs.wrap) wrap_branch(branch, WIDTH, HEIGHT); + + if (branch.width < branch.original_width * branch_bud_size) { + branch.original_width *= branch_bud_size; + branch_add(branches, new Branch(branch, branch.direction + 1, branch.original_width)); + } +} + +function draw_frame() { + if (prefs.fade) { + paper.fillRect(0, 0, WIDTH, HEIGHT); + } + + if (prefs.cycle) { + paper.setStroke(Paint.valueOf(color_styles[frame % color_styles.length])); + } + + if (frame++ % prefs.new_branch_frames == 0) { + create_tree(branches, start_width, get_new_tree_center(WIDTH, HEIGHT), branch_count); + } + + direction_offset += (0.35 + (frame % 200) * 0.0015) * curviness - curviness / 2; + direction_offset *= straighten_factor; + + var branch = branches; + var prev_branch = branches; + while (branch = branch.next) { + branch_update(branches, branch, paper); + + if (branch.width < min_width) { + // remove branch from list + prev_branch.next = branch.next; + } + + prev_branch = branch; + } +} + +// constrain branch position to visible area by "wrapping" from edge to edge +function wrap_branch(branch, WIDTH, HEIGHT) { + branch.x = positive_mod(branch.x, WIDTH); + branch.y = positive_mod(branch.y, HEIGHT); +} + +// for a < 0, b > 0, javascript returns a negative number for a % b +// this is a variant of the % operator that adds b to the result in this case +function positive_mod(a, b) { + // ECMA 262 11.5.3: Applying the % Operator + // remainder operator does not convert operands to integers, + // although negative results are possible + + return ((a % b) + b) % b; +} + +// pre-compute color styles that will be used for color cycling +function populate_colors(color_speed, color_styles, branch_opacity) { + // used in calculation of RGB values + var two_thirds_pi = Math.PI * 2 / 3; + var four_thirds_pi = Math.PI * 4 / 3; + var two_pi = Math.PI * 2; + + // hue does represent hue, but not in the conventional HSL scheme + for(var hue = 0; hue < two_pi; hue += color_speed) { + var r = Math.floor(Math.sin(hue) * 128 + 128); + var g = Math.floor(Math.sin(hue + two_thirds_pi) * 128 + 128); + var b = Math.floor(Math.sin(hue + four_thirds_pi) * 128 + 128); + color = "rgba(" + [r, g, b, branch_opacity].join() + ")"; + + color_styles.push(color); + } +} + +// apply initial settings to canvas object +function setup_canvas() { + paper = canvas.graphicsContext2D; + paper.setFill(Paint.valueOf('rgb(0, 0, 0)')); + paper.fillRect(0, 0, WIDTH, HEIGHT); + paper.setFill(Paint.valueOf("rgba(0, 0, 0, 0.005)")); + paper.setStroke(Paint.valueOf("rgba(128, 128, 64, " + String(branch_opacity) + ")")); +} + +populate_colors(color_speed, color_styles, branch_opacity); +setup_canvas(); + +var stack = new StackPane(); +var pane = new BorderPane(); +pane.setCenter(canvas); +stack.getChildren().add(pane); +$STAGE.scene = new Scene(stack); +var timer = new AnimationTimerExtend() { + handle: function handle(now) { + if (frame < 200) { + draw_frame(); + } else { + checkImageAndExit(); + timer.stop(); + } + } +}; +timer.start(); + diff -r 774c63629870 -r 1db3d4e4d189 test/script/jfx/spread/golden/linux.png Binary file test/script/jfx/spread/golden/linux.png has changed diff -r 774c63629870 -r 1db3d4e4d189 test/script/jfx/spread/golden/macosx.png Binary file test/script/jfx/spread/golden/macosx.png has changed diff -r 774c63629870 -r 1db3d4e4d189 test/script/jfx/spread/golden/windows.png Binary file test/script/jfx/spread/golden/windows.png has changed diff -r 774c63629870 -r 1db3d4e4d189 test/src/jdk/nashorn/api/javaaccess/ConsStringTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/src/jdk/nashorn/api/javaaccess/ConsStringTest.java Fri Nov 15 07:16:05 2013 -0800 @@ -0,0 +1,99 @@ +/* + * 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.javaaccess; + +import static org.testng.AssertJUnit.assertEquals; + +import java.util.HashMap; +import java.util.Map; +import javax.script.Bindings; +import javax.script.ScriptContext; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import jdk.nashorn.api.scripting.JSObject; +import org.testng.TestNG; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +public class ConsStringTest { + private static ScriptEngine e = null; + + public static void main(final String[] args) { + TestNG.main(args); + } + + @BeforeClass + public static void setUpClass() throws ScriptException { + e = new ScriptEngineManager().getEngineByName("nashorn"); + } + + @AfterClass + public static void tearDownClass() { + e = null; + } + + @Test + public void testConsStringFlattening() throws ScriptException { + final Bindings b = e.getBindings(ScriptContext.ENGINE_SCOPE); + final Map m = new HashMap<>(); + b.put("m", m); + e.eval("var x = 'f'; x += 'oo'; var y = 'b'; y += 'ar'; m.put(x, y)"); + assertEquals("bar", m.get("foo")); + } + + @Test + public void testConsStringFromMirror() throws ScriptException { + final Bindings b = e.getBindings(ScriptContext.ENGINE_SCOPE); + final Map m = new HashMap<>(); + e.eval("var x = 'f'; x += 'oo'; var obj = {x: x};"); + assertEquals("foo", ((JSObject)b.get("obj")).getMember("x")); + } + + @Test + public void testArrayConsString() throws ScriptException { + final Bindings b = e.getBindings(ScriptContext.ENGINE_SCOPE); + final ArrayHolder h = new ArrayHolder(); + b.put("h", h); + e.eval("var x = 'f'; x += 'oo'; h.array = [x];"); + assertEquals(1, h.array.length); + assertEquals("foo", h.array[0]); + } + + + public static class ArrayHolder { + private Object[] array; + + public void setArray(Object[] array) { + this.array = array; + } + + public Object[] getArray() { + return array; + } + } +} diff -r 774c63629870 -r 1db3d4e4d189 test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java --- a/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java Thu Nov 14 09:05:27 2013 -0800 +++ b/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java Fri Nov 15 07:16:05 2013 -0800 @@ -523,6 +523,18 @@ assertEquals(sw.toString(), println("34 true hello")); } + @Test + public void scriptObjectAutoConversionTest() throws ScriptException { + final ScriptEngineManager m = new ScriptEngineManager(); + final ScriptEngine e = m.getEngineByName("nashorn"); + e.eval("obj = { foo: 'hello' }"); + e.put("Window", e.eval("Packages.jdk.nashorn.api.scripting.Window")); + assertEquals(e.eval("Window.funcJSObject(obj)"), "hello"); + assertEquals(e.eval("Window.funcScriptObjectMirror(obj)"), "hello"); + assertEquals(e.eval("Window.funcMap(obj)"), "hello"); + assertEquals(e.eval("Window.funcJSObject(obj)"), "hello"); + } + private static final String LINE_SEPARATOR = System.getProperty("line.separator"); // Returns String that would be the result of calling PrintWriter.println diff -r 774c63629870 -r 1db3d4e4d189 test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java --- a/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java Thu Nov 14 09:05:27 2013 -0800 +++ b/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java Fri Nov 15 07:16:05 2013 -0800 @@ -26,6 +26,7 @@ package jdk.nashorn.api.scripting; import java.util.HashMap; +import java.util.List; import java.util.Map; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; @@ -227,4 +228,28 @@ final Object newObj = ((ScriptObjectMirror)e2obj.getMember("foo")).newObject(); assertTrue(newObj instanceof ScriptObjectMirror); } + + @Test + public void conversionTest() throws ScriptException { + final ScriptEngineManager m = new ScriptEngineManager(); + final ScriptEngine e = m.getEngineByName("nashorn"); + final ScriptObjectMirror arr = (ScriptObjectMirror)e.eval("[33, 45, 23]"); + final int[] intArr = arr.to(int[].class); + assertEquals(intArr[0], 33); + assertEquals(intArr[1], 45); + assertEquals(intArr[2], 23); + + final List list = arr.to(List.class); + assertEquals(list.get(0), 33); + assertEquals(list.get(1), 45); + assertEquals(list.get(2), 23); + + ScriptObjectMirror obj = (ScriptObjectMirror)e.eval( + "({ valueOf: function() { return 42 } })"); + assertEquals(Double.valueOf(42.0), obj.to(Double.class)); + + obj = (ScriptObjectMirror)e.eval( + "({ toString: function() { return 'foo' } })"); + assertEquals("foo", obj.to(String.class)); + } } diff -r 774c63629870 -r 1db3d4e4d189 test/src/jdk/nashorn/api/scripting/Window.java --- a/test/src/jdk/nashorn/api/scripting/Window.java Thu Nov 14 09:05:27 2013 -0800 +++ b/test/src/jdk/nashorn/api/scripting/Window.java Fri Nov 15 07:16:05 2013 -0800 @@ -25,6 +25,9 @@ package jdk.nashorn.api.scripting; +import java.util.Map; +import javax.script.Bindings; + public class Window { private String location = "http://localhost:8080/window"; @@ -63,4 +66,20 @@ System.out.println("window.setTimeout: " + delay + ", code: " + code); return 0; } + + public static Object funcJSObject(final JSObject jsobj) { + return jsobj.getMember("foo"); + } + + public static Object funcScriptObjectMirror(final ScriptObjectMirror sobj) { + return sobj.get("foo"); + } + + public static Object funcMap(final Map map) { + return map.get("foo"); + } + + public static Object funcBindings(final Bindings bindings) { + return bindings.get("foo"); + } }