Mercurial > people > rkennke > jdk9-shenandoah-final > nashorn
changeset 444:d685fec24d13
Merge
author | sundar |
---|---|
date | Tue, 16 Jul 2013 09:54:04 +0530 |
parents | cbfeffbcd3f2 (current diff) 28f1f2374004 (diff) |
children | 965d876853ec |
files | |
diffstat | 24 files changed, 963 insertions(+), 130 deletions(-) [+] |
line wrap: on
line diff
--- a/src/jdk/internal/dynalink/DynamicLinker.java Fri Jul 12 20:13:43 2013 +0530 +++ b/src/jdk/internal/dynalink/DynamicLinker.java Tue Jul 16 09:54:04 2013 +0530 @@ -144,6 +144,9 @@ private static final String CLASS_NAME = DynamicLinker.class.getName(); private static final String RELINK_METHOD_NAME = "relink"; + private static final String INITIAL_LINK_CLASS_NAME = "java.lang.invoke.MethodHandleNatives"; + private static final String INITIAL_LINK_METHOD_NAME = "linkCallSite"; + private final LinkerServices linkerServices; private final int runtimeContextArgCount; private final boolean syncOnRelink; @@ -262,20 +265,54 @@ } /** - * Returns a stack trace element describing the location of the call site currently being relinked on the current + * Returns a stack trace element describing the location of the call site currently being linked on the current * thread. The operation internally creates a Throwable object and inspects its stack trace, so it's potentially * expensive. The recommended usage for it is in writing diagnostics code. - * @return a stack trace element describing the location of the call site currently being relinked, or null if it is - * not invoked while a call site is being relinked. + * @return a stack trace element describing the location of the call site currently being linked, or null if it is + * not invoked while a call site is being linked. */ - public static StackTraceElement getRelinkedCallSiteLocation() { + public static StackTraceElement getLinkedCallSiteLocation() { final StackTraceElement[] trace = new Throwable().getStackTrace(); for(int i = 0; i < trace.length - 1; ++i) { final StackTraceElement frame = trace[i]; - if(RELINK_METHOD_NAME.equals(frame.getMethodName()) && CLASS_NAME.equals(frame.getClassName())) { + if(isRelinkFrame(frame) || isInitialLinkFrame(frame)) { return trace[i + 1]; } } return null; } + + /** + * Deprecated because of not precise name. + * @deprecated Use {@link #getLinkedCallSiteLocation()} instead. + * @return see non-deprecated method + */ + @Deprecated + public static StackTraceElement getRelinkedCallSiteLocation() { + return getLinkedCallSiteLocation(); + } + + /** + * Returns true if the frame represents {@code MethodHandleNatives.linkCallSite()}, the frame immediately on top of + * the call site frame when the call site is being linked for the first time. + * @param frame the frame + * @return true if this frame represents {@code MethodHandleNatives.linkCallSite()} + */ + private static boolean isInitialLinkFrame(final StackTraceElement frame) { + return testFrame(frame, INITIAL_LINK_METHOD_NAME, INITIAL_LINK_CLASS_NAME); + } + + /** + * Returns true if the frame represents {@code DynamicLinker.relink()}, the frame immediately on top of the call + * site frame when the call site is being relinked (linked for second and subsequent times). + * @param frame the frame + * @return true if this frame represents {@code DynamicLinker.relink()} + */ + private static boolean isRelinkFrame(final StackTraceElement frame) { + return testFrame(frame, RELINK_METHOD_NAME, CLASS_NAME); + } + + private static boolean testFrame(final StackTraceElement frame, final String methodName, final String className) { + return methodName.equals(frame.getMethodName()) && className.equals(frame.getClassName()); + } }
--- a/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java Fri Jul 12 20:13:43 2013 +0530 +++ b/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java Tue Jul 16 09:54:04 2013 +0530 @@ -92,6 +92,8 @@ import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -194,6 +196,22 @@ abstract FacetIntrospector createFacetIntrospector(); + Collection<String> getReadablePropertyNames() { + return getUnmodifiableKeys(propertyGetters); + } + + Collection<String> getWritablePropertyNames() { + return getUnmodifiableKeys(propertySetters); + } + + Collection<String> getMethodNames() { + return getUnmodifiableKeys(methods); + } + + private static Collection<String> getUnmodifiableKeys(Map<String, ?> m) { + return Collections.unmodifiableCollection(m.keySet()); + } + /** * Sets the specified dynamic method to be the property getter for the specified property. Note that you can only * use this when you're certain that the method handle does not belong to a caller-sensitive method. For properties
--- a/src/jdk/internal/dynalink/beans/BeansLinker.java Fri Jul 12 20:13:43 2013 +0530 +++ b/src/jdk/internal/dynalink/beans/BeansLinker.java Tue Jul 16 09:54:04 2013 +0530 @@ -84,6 +84,8 @@ package jdk.internal.dynalink.beans; import java.lang.invoke.MethodHandles; +import java.util.Collection; +import java.util.Collections; import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.DynamicLinkerFactory; import jdk.internal.dynalink.linker.GuardedInvocation; @@ -166,6 +168,72 @@ return obj instanceof DynamicMethod; } + /** + * Returns a collection of names of all readable instance properties of a class. + * @param clazz the class + * @return a collection of names of all readable instance properties of a class. + */ + public static Collection<String> getReadableInstancePropertyNames(Class<?> clazz) { + TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz); + if(linker instanceof BeanLinker) { + return ((BeanLinker)linker).getReadablePropertyNames(); + } + return Collections.emptySet(); + } + + /** + * Returns a collection of names of all writable instance properties of a class. + * @param clazz the class + * @return a collection of names of all writable instance properties of a class. + */ + public static Collection<String> getWritableInstancePropertyNames(Class<?> clazz) { + TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz); + if(linker instanceof BeanLinker) { + return ((BeanLinker)linker).getWritablePropertyNames(); + } + return Collections.emptySet(); + } + + /** + * Returns a collection of names of all instance methods of a class. + * @param clazz the class + * @return a collection of names of all instance methods of a class. + */ + public static Collection<String> getInstanceMethodNames(Class<?> clazz) { + TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz); + if(linker instanceof BeanLinker) { + return ((BeanLinker)linker).getMethodNames(); + } + return Collections.emptySet(); + } + + /** + * Returns a collection of names of all readable static properties of a class. + * @param clazz the class + * @return a collection of names of all readable static properties of a class. + */ + public static Collection<String> getReadableStaticPropertyNames(Class<?> clazz) { + return StaticClassLinker.getReadableStaticPropertyNames(clazz); + } + + /** + * Returns a collection of names of all writable static properties of a class. + * @param clazz the class + * @return a collection of names of all writable static properties of a class. + */ + public static Collection<String> getWritableStaticPropertyNames(Class<?> clazz) { + return StaticClassLinker.getWritableStaticPropertyNames(clazz); + } + + /** + * Returns a collection of names of all static methods of a class. + * @param clazz the class + * @return a collection of names of all static methods of a class. + */ + public static Collection<String> getStaticMethodNames(Class<?> clazz) { + return StaticClassLinker.getStaticMethodNames(clazz); + } + @Override public GuardedInvocation getGuardedInvocation(LinkRequest request, final LinkerServices linkerServices) throws Exception {
--- a/src/jdk/internal/dynalink/beans/StaticClassLinker.java Fri Jul 12 20:13:43 2013 +0530 +++ b/src/jdk/internal/dynalink/beans/StaticClassLinker.java Tue Jul 16 09:54:04 2013 +0530 @@ -88,10 +88,10 @@ import java.lang.invoke.MethodType; import java.lang.reflect.Array; import java.util.Arrays; +import java.util.Collection; import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.beans.GuardedInvocationComponent.ValidationType; 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.linker.TypeBasedGuardingDynamicLinker; @@ -102,9 +102,9 @@ * @author Attila Szegedi */ class StaticClassLinker implements TypeBasedGuardingDynamicLinker { - private final ClassValue<GuardingDynamicLinker> linkers = new ClassValue<GuardingDynamicLinker>() { + private static final ClassValue<SingleClassStaticsLinker> linkers = new ClassValue<SingleClassStaticsLinker>() { @Override - protected GuardingDynamicLinker computeValue(Class<?> clazz) { + protected SingleClassStaticsLinker computeValue(Class<?> clazz) { return new SingleClassStaticsLinker(clazz); } }; @@ -160,6 +160,18 @@ } } + static Collection<String> getReadableStaticPropertyNames(Class<?> clazz) { + return linkers.get(clazz).getReadablePropertyNames(); + } + + static Collection<String> getWritableStaticPropertyNames(Class<?> clazz) { + return linkers.get(clazz).getWritablePropertyNames(); + } + + static Collection<String> getStaticMethodNames(Class<?> clazz) { + return linkers.get(clazz).getMethodNames(); + } + @Override public GuardedInvocation getGuardedInvocation(LinkRequest request, LinkerServices linkerServices) throws Exception { final Object receiver = request.getReceiver();
--- a/src/jdk/nashorn/internal/objects/NativeObject.java Fri Jul 12 20:13:43 2013 +0530 +++ b/src/jdk/nashorn/internal/objects/NativeObject.java Tue Jul 16 09:54:04 2013 +0530 @@ -29,8 +29,22 @@ import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import jdk.internal.dynalink.beans.BeansLinker; +import jdk.internal.dynalink.beans.StaticClass; +import jdk.internal.dynalink.linker.GuardedInvocation; +import jdk.internal.dynalink.linker.GuardingDynamicLinker; +import jdk.internal.dynalink.linker.LinkRequest; +import jdk.internal.dynalink.support.CallSiteDescriptorFactory; +import jdk.internal.dynalink.support.LinkRequestImpl; import jdk.nashorn.api.scripting.ScriptObjectMirror; +import jdk.nashorn.internal.lookup.Lookup; import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; import jdk.nashorn.internal.objects.annotations.Function; @@ -58,6 +72,8 @@ @ScriptClass("Object") public final class NativeObject { private static final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class); + private static final MethodType MIRROR_GETTER_TYPE = MethodType.methodType(Object.class, ScriptObjectMirror.class); + private static final MethodType MIRROR_SETTER_TYPE = MethodType.methodType(Object.class, ScriptObjectMirror.class, Object.class); // initialized by nasgen @SuppressWarnings("unused") @@ -577,14 +593,92 @@ final AccessorProperty[] props = new AccessorProperty[keys.length]; for (int idx = 0; idx < keys.length; idx++) { final String name = keys[idx]; - final MethodHandle getter = Bootstrap.createDynamicInvoker("dyn:getMethod|getProp|getElem:" + name, Object.class, ScriptObjectMirror.class); - final MethodHandle setter = Bootstrap.createDynamicInvoker("dyn:setProp|setElem:" + name, Object.class, ScriptObjectMirror.class, Object.class); + final MethodHandle getter = Bootstrap.createDynamicInvoker("dyn:getMethod|getProp|getElem:" + name, MIRROR_GETTER_TYPE); + final MethodHandle setter = Bootstrap.createDynamicInvoker("dyn:setProp|setElem:" + name, MIRROR_SETTER_TYPE); props[idx] = (AccessorProperty.create(name, 0, getter, setter)); } targetObj.addBoundProperties(source, props); + } else if (source instanceof StaticClass) { + final Class<?> clazz = ((StaticClass)source).getRepresentedClass(); + bindBeanProperties(targetObj, source, BeansLinker.getReadableStaticPropertyNames(clazz), + BeansLinker.getWritableStaticPropertyNames(clazz), BeansLinker.getStaticMethodNames(clazz)); + } else { + final Class<?> clazz = source.getClass(); + bindBeanProperties(targetObj, source, BeansLinker.getReadableInstancePropertyNames(clazz), + BeansLinker.getWritableInstancePropertyNames(clazz), BeansLinker.getInstanceMethodNames(clazz)); } return target; } + + private static void bindBeanProperties(final ScriptObject targetObj, final Object source, + final Collection<String> readablePropertyNames, final Collection<String> writablePropertyNames, + final Collection<String> methodNames) { + final Set<String> propertyNames = new HashSet<>(readablePropertyNames); + propertyNames.addAll(writablePropertyNames); + + final Class<?> clazz = source.getClass(); + Bootstrap.checkReflectionAccess(clazz); + + final MethodType getterType = MethodType.methodType(Object.class, clazz); + final MethodType setterType = MethodType.methodType(Object.class, clazz, Object.class); + + final GuardingDynamicLinker linker = BeansLinker.getLinkerForClass(clazz); + + final List<AccessorProperty> properties = new ArrayList<>(propertyNames.size() + methodNames.size()); + for(final String methodName: methodNames) { + properties.add(AccessorProperty.create(methodName, Property.NOT_WRITABLE, + getBoundBeanMethodGetter(source, getBeanOperation(linker, "dyn:getMethod:" + methodName, getterType, source)), + null)); + } + for(final String propertyName: propertyNames) { + final boolean isWritable = writablePropertyNames.contains(propertyName); + properties.add(AccessorProperty.create(propertyName, isWritable ? 0 : Property.NOT_WRITABLE, + readablePropertyNames.contains(propertyName) ? getBeanOperation(linker, "dyn:getProp:" + propertyName, getterType, source) : Lookup.EMPTY_GETTER, + isWritable ? getBeanOperation(linker, "dyn:setProp:" + propertyName, setterType, source) : Lookup.EMPTY_SETTER)); + } + + targetObj.addBoundProperties(source, properties.toArray(new AccessorProperty[properties.size()])); + } + + private static MethodHandle getBoundBeanMethodGetter(Object source, MethodHandle methodGetter) { + try { + // NOTE: we're relying on the fact that "dyn:getMethod:..." return value is constant for any given method + // name and object linked with BeansLinker. (Actually, an even stronger assumption is true: return value is + // constant for any given method name and object's class.) + return MethodHandles.dropArguments(MethodHandles.constant(Object.class, + Bootstrap.bindDynamicMethod(methodGetter.invoke(source), source)), 0, Object.class); + } catch(RuntimeException|Error e) { + throw e; + } catch(Throwable t) { + throw new RuntimeException(t); + } + } + + private static MethodHandle getBeanOperation(final GuardingDynamicLinker linker, final String operation, + final MethodType methodType, final Object source) { + final GuardedInvocation inv; + try { + inv = linker.getGuardedInvocation(createLinkRequest(operation, methodType, source), + Bootstrap.getLinkerServices()); + assert passesGuard(source, inv.getGuard()); + } catch(RuntimeException|Error e) { + throw e; + } catch(Throwable t) { + throw new RuntimeException(t); + } + assert inv.getSwitchPoint() == null; // Linkers in Dynalink's beans package don't use switchpoints. + // We discard the guard, as all method handles will be bound to a specific object. + return inv.getInvocation(); + } + + private static boolean passesGuard(final Object obj, final MethodHandle guard) throws Throwable { + return guard == null || (boolean)guard.invoke(obj); + } + + private static LinkRequest createLinkRequest(String operation, MethodType methodType, Object source) { + return new LinkRequestImpl(CallSiteDescriptorFactory.create(MethodHandles.publicLookup(), operation, + methodType), false, source); + } }
--- a/src/jdk/nashorn/internal/parser/Parser.java Fri Jul 12 20:13:43 2013 +0530 +++ b/src/jdk/nashorn/internal/parser/Parser.java Tue Jul 16 09:54:04 2013 +0530 @@ -55,9 +55,9 @@ import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import jdk.nashorn.internal.codegen.CompilerConstants; @@ -1946,14 +1946,14 @@ // Object context. // Prepare to accumulate elements. - // final List<Node> elements = new ArrayList<>(); - final Map<String, PropertyNode> map = new LinkedHashMap<>(); + final List<PropertyNode> elements = new ArrayList<>(); + final Map<String, Integer> map = new HashMap<>(); // Create a block for the object literal. - boolean commaSeen = true; + boolean commaSeen = true; loop: - while (true) { - switch (type) { + while (true) { + switch (type) { case RBRACE: next(); break loop; @@ -1975,14 +1975,16 @@ // Get and add the next property. final PropertyNode property = propertyAssignment(); final String key = property.getKeyName(); - final PropertyNode existingProperty = map.get(key); - - if (existingProperty == null) { - map.put(key, property); - // elements.add(property); + final Integer existing = map.get(key); + + if (existing == null) { + map.put(key, elements.size()); + elements.add(property); break; } + final PropertyNode existingProperty = elements.get(existing); + // ECMA section 11.1.5 Object Initialiser // point # 4 on property assignment production final Expression value = property.getValue(); @@ -1993,12 +1995,9 @@ final FunctionNode prevGetter = existingProperty.getGetter(); final FunctionNode prevSetter = existingProperty.getSetter(); - boolean redefinitionOk = true; // ECMA 11.1.5 strict mode restrictions - if (isStrictMode) { - if (value != null && prevValue != null) { - redefinitionOk = false; - } + if (isStrictMode && value != null && prevValue != null) { + throw error(AbstractParser.message("property.redefinition", key), property.getToken()); } final boolean isPrevAccessor = prevGetter != null || prevSetter != null; @@ -2006,49 +2005,33 @@ // data property redefined as accessor property if (prevValue != null && isAccessor) { - redefinitionOk = false; + throw error(AbstractParser.message("property.redefinition", key), property.getToken()); } // accessor property redefined as data if (isPrevAccessor && value != null) { - redefinitionOk = false; + throw error(AbstractParser.message("property.redefinition", key), property.getToken()); } if (isAccessor && isPrevAccessor) { if (getter != null && prevGetter != null || - setter != null && prevSetter != null) { - redefinitionOk = false; + setter != null && prevSetter != null) { + throw error(AbstractParser.message("property.redefinition", key), property.getToken()); } } - if (!redefinitionOk) { - throw error(AbstractParser.message("property.redefinition", key), property.getToken()); - } - - PropertyNode newProperty = existingProperty; if (value != null) { - if (prevValue == null) { - map.put(key, newProperty = newProperty.setValue(value)); - } else { - final long propertyToken = Token.recast(newProperty.getToken(), COMMARIGHT); - map.put(key, newProperty = newProperty.setValue(new BinaryNode(propertyToken, prevValue, value))); - } - - map.put(key, newProperty = newProperty.setGetter(null).setSetter(null)); - } - - if (getter != null) { - map.put(key, newProperty = newProperty.setGetter(getter)); - } - - if (setter != null) { - map.put(key, newProperty = newProperty.setSetter(setter)); + elements.add(property); + } else if (getter != null) { + elements.set(existing, existingProperty.setGetter(getter)); + } else if (setter != null) { + elements.set(existing, existingProperty.setSetter(setter)); } break; } } - return new ObjectNode(objectToken, finish, new ArrayList<>(map.values())); + return new ObjectNode(objectToken, finish, elements); } /**
--- a/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java Fri Jul 12 20:13:43 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java Tue Jul 16 09:54:04 2013 +0530 @@ -75,8 +75,13 @@ * @return ArrayData */ public static ArrayData allocate(final int length) { - final ArrayData arrayData = new IntArrayData(length); - return length == 0 ? arrayData : new DeletedRangeArrayFilter(arrayData, 0, length - 1); + if (length == 0) { + return new IntArrayData(); + } else if (length >= SparseArrayData.MAX_DENSE_LENGTH) { + return new SparseArrayData(EMPTY_ARRAY, length); + } else { + return new DeletedRangeArrayFilter(new IntArrayData(length), 0, length - 1); + } } /**
--- a/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Fri Jul 12 20:13:43 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Tue Jul 16 09:54:04 2013 +0530 @@ -75,7 +75,9 @@ } private static Object[] toObjectArray(final int[] array, final int length) { - final Object[] oarray = new Object[length]; + assert length <= array.length : "length exceeds internal array size"; + final Object[] oarray = new Object[array.length]; + for (int index = 0; index < length; index++) { oarray[index] = Integer.valueOf(array[index]); } @@ -83,18 +85,22 @@ return oarray; } - private static double[] toDoubleArray(final int[] array) { + private static double[] toDoubleArray(final int[] array, final int length) { + assert length <= array.length : "length exceeds internal array size"; final double[] darray = new double[array.length]; - for (int index = 0; index < array.length; index++) { + + for (int index = 0; index < length; index++) { darray[index] = array[index]; } return darray; } - private static long[] toLongArray(final int[] array) { + private static long[] toLongArray(final int[] array, final int length) { + assert length <= array.length : "length exceeds internal array size"; final long[] larray = new long[array.length]; - for (int index = 0; index < array.length; index++) { + + for (int index = 0; index < length; index++) { larray[index] = array[index]; } @@ -105,12 +111,14 @@ public ArrayData convert(final Class<?> type) { if (type == Integer.class) { return this; - } else if (type == Long.class) { - return new LongArrayData(IntArrayData.toLongArray(array), (int) length()); + } + final int length = (int) length(); + if (type == Long.class) { + return new LongArrayData(IntArrayData.toLongArray(array, length), length); } else if (type == Double.class) { - return new NumberArrayData(IntArrayData.toDoubleArray(array), (int) length()); + return new NumberArrayData(IntArrayData.toDoubleArray(array, length), length); } else { - return new ObjectArrayData(IntArrayData.toObjectArray(array, array.length), (int) length()); + return new ObjectArrayData(IntArrayData.toObjectArray(array, length), length); } } @@ -161,26 +169,13 @@ @Override public ArrayData set(final int index, final Object value, final boolean strict) { - try { - final int intValue = ((Integer)value).intValue(); - array[index] = intValue; - setLength(Math.max(index + 1, length())); - return this; - } catch (final NullPointerException | ClassCastException e) { - if (value instanceof Short || value instanceof Byte) { - final int intValue = ((Number)value).intValue(); - array[index] = intValue; - setLength(Math.max(index + 1, length())); - return this; - } - - if (value == ScriptRuntime.UNDEFINED) { - return new UndefinedArrayFilter(this).set(index, value, strict); - } + if (value instanceof Integer) { + return set(index, ((Number)value).intValue(), strict); + } else if (value == ScriptRuntime.UNDEFINED) { + return new UndefinedArrayFilter(this).set(index, value, strict); } final ArrayData newData = convert(value == null ? Object.class : value.getClass()); - return newData.set(index, value, strict); }
--- a/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java Fri Jul 12 20:13:43 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java Tue Jul 16 09:54:04 2013 +0530 @@ -55,7 +55,9 @@ } private static Object[] toObjectArray(final long[] array, final int length) { - final Object[] oarray = new Object[length]; + assert length <= array.length : "length exceeds internal array size"; + final Object[] oarray = new Object[array.length]; + for (int index = 0; index < length; index++) { oarray[index] = Long.valueOf(array[index]); } @@ -71,9 +73,11 @@ return super.asArrayOfType(componentType); } - private static double[] toDoubleArray(final long[] array) { + private static double[] toDoubleArray(final long[] array, final int length) { + assert length <= array.length : "length exceeds internal array size"; final double[] darray = new double[array.length]; - for (int index = 0; index < array.length; index++) { + + for (int index = 0; index < length; index++) { darray[index] = array[index]; } @@ -84,10 +88,12 @@ public ArrayData convert(final Class<?> type) { if (type == Long.class) { return this; - } else if (type == Double.class) { - return new NumberArrayData(LongArrayData.toDoubleArray(array), (int) length()); + } + final int length = (int) length(); + if (type == Double.class) { + return new NumberArrayData(LongArrayData.toDoubleArray(array, length), length); } else { - return new ObjectArrayData(LongArrayData.toObjectArray(array, array.length), (int) length()); + return new ObjectArrayData(LongArrayData.toObjectArray(array, length), length); } } @@ -138,19 +144,13 @@ @Override public ArrayData set(final int index, final Object value, final boolean strict) { - try { - final long longValue = ((Long)value).longValue(); - array[index] = longValue; - setLength(Math.max(index + 1, length())); - return this; - } catch (final NullPointerException | ClassCastException e) { - if (value == ScriptRuntime.UNDEFINED) { - return new UndefinedArrayFilter(this).set(index, value, strict); - } + if (value instanceof Long || value instanceof Integer) { + return set(index, ((Number)value).longValue(), strict); + } else if (value == ScriptRuntime.UNDEFINED) { + return new UndefinedArrayFilter(this).set(index, value, strict); } final ArrayData newData = convert(value == null ? Object.class : value.getClass()); - return newData.set(index, value, strict); }
--- a/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Fri Jul 12 20:13:43 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Tue Jul 16 09:54:04 2013 +0530 @@ -58,7 +58,9 @@ } private static Object[] toObjectArray(final double[] array, final int length) { - final Object[] oarray = new Object[length]; + assert length <= array.length : "length exceeds internal array size"; + final Object[] oarray = new Object[array.length]; + for (int index = 0; index < length; index++) { oarray[index] = Double.valueOf(array[index]); } @@ -76,7 +78,8 @@ @Override public ArrayData convert(final Class<?> type) { if (type != Double.class && type != Integer.class && type != Long.class) { - return new ObjectArrayData(NumberArrayData.toObjectArray(array, array.length), (int) length()); + final int length = (int) length(); + return new ObjectArrayData(NumberArrayData.toObjectArray(array, length), length); } return this; } @@ -127,16 +130,12 @@ @Override public ArrayData set(final int index, final Object value, final boolean strict) { - try { - final double doubleValue = ((Number)value).doubleValue(); - array[index] = doubleValue; - setLength(Math.max(index + 1, length())); - return this; - } catch (final NullPointerException | ClassCastException e) { - if (value == UNDEFINED) { - return new UndefinedArrayFilter(this).set(index, value, strict); - } + if (value instanceof Double || value instanceof Integer || value instanceof Long) { + return set(index, ((Number)value).doubleValue(), strict); + } else if (value == UNDEFINED) { + return new UndefinedArrayFilter(this).set(index, value, strict); } + final ArrayData newData = convert(value == null ? Object.class : value.getClass()); return newData.set(index, value, strict); }
--- a/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Fri Jul 12 20:13:43 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Tue Jul 16 09:54:04 2013 +0530 @@ -57,7 +57,7 @@ static { final DynamicLinkerFactory factory = new DynamicLinkerFactory(); factory.setPrioritizedLinkers(new NashornLinker(), new NashornPrimitiveLinker(), new NashornStaticClassLinker(), - new JSObjectLinker(), new ReflectionCheckLinker()); + new BoundDynamicMethodLinker(), new JSObjectLinker(), new ReflectionCheckLinker()); factory.setFallbackLinkers(new BeansLinker(), new NashornBottomLinker()); factory.setSyncOnRelink(true); final int relinkThreshold = Options.getIntProperty("nashorn.unstable.relink.threshold", -1); @@ -208,6 +208,27 @@ } /** + * Binds a bean dynamic method (returned by invoking {@code dyn:getMethod} on an object linked with + * {@code BeansLinker} to a receiver. + * @param dynamicMethod the dynamic method to bind + * @param boundThis the bound "this" value. + * @return a bound dynamic method. + */ + public static Object bindDynamicMethod(Object dynamicMethod, Object boundThis) { + return new BoundDynamicMethod(dynamicMethod, boundThis); + } + + /** + * If the given class is a reflection-specific class (anything in {@code java.lang.reflect} and + * {@code java.lang.invoke} package, as well a {@link Class} and any subclass of {@link ClassLoader}) and there is + * a security manager in the system, then it checks the {@code nashorn.JavaReflection} {@code RuntimePermission}. + * @param clazz the class being tested + */ + public static void checkReflectionAccess(Class<?> clazz) { + ReflectionCheckLinker.checkReflectionAccess(clazz); + } + + /** * Returns the Nashorn's internally used dynamic linker's services object. Note that in code that is processing a * linking request, you will normally use the {@code LinkerServices} object passed by whatever top-level linker * invoked the linking (if the call site is in Nashorn-generated code, you'll get this object anyway). You should
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethod.java Tue Jul 16 09:54:04 2013 +0530 @@ -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. 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 jdk.internal.dynalink.beans.BeansLinker; + +/** + * Represents a Dynalink dynamic method bound to a receiver. Note that objects of this class are just the tuples of + * a method and a bound this, without any behavior. All the behavior is defined in the {@link BoundDynamicMethodLinker}. + */ +final class BoundDynamicMethod { + private final Object dynamicMethod; + private final Object boundThis; + + BoundDynamicMethod(final Object dynamicMethod, final Object boundThis) { + assert BeansLinker.isDynamicMethod(dynamicMethod); + this.dynamicMethod = dynamicMethod; + this.boundThis = boundThis; + } + + Object getDynamicMethod() { + return dynamicMethod; + } + + Object getBoundThis() { + return boundThis; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethodLinker.java Tue Jul 16 09:54:04 2013 +0530 @@ -0,0 +1,90 @@ +/* + * 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.CallSiteDescriptor; +import jdk.internal.dynalink.beans.BeansLinker; +import jdk.internal.dynalink.linker.GuardedInvocation; +import jdk.internal.dynalink.linker.LinkRequest; +import jdk.internal.dynalink.linker.LinkerServices; +import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; +import jdk.internal.dynalink.support.Guards; + +/** + * Links {@link BoundDynamicMethod} objects. Passes through to Dynalink's BeansLinker for linking a dynamic method + * (they only respond to "dyn:call"), and modifies the returned invocation to deal with the receiver binding. + */ +final class BoundDynamicMethodLinker implements TypeBasedGuardingDynamicLinker { + @Override + public boolean canLinkType(Class<?> type) { + return type == BoundDynamicMethod.class; + } + + @Override + public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, LinkerServices linkerServices) throws Exception { + final Object objBoundDynamicMethod = linkRequest.getReceiver(); + if(!(objBoundDynamicMethod instanceof BoundDynamicMethod)) { + return null; + } + + final BoundDynamicMethod boundDynamicMethod = (BoundDynamicMethod)objBoundDynamicMethod; + final Object dynamicMethod = boundDynamicMethod.getDynamicMethod(); + final Object boundThis = boundDynamicMethod.getBoundThis(); + + // Replace arguments (boundDynamicMethod, this, ...) => (dynamicMethod, boundThis, ...) when delegating to + // BeansLinker + final Object[] args = linkRequest.getArguments(); + args[0] = dynamicMethod; + args[1] = boundThis; + + // Use R(T0, T1, ...) => R(dynamicMethod.class, boundThis.class, ...) call site type when delegating to + // BeansLinker. + final CallSiteDescriptor descriptor = linkRequest.getCallSiteDescriptor(); + final MethodType type = descriptor.getMethodType(); + final CallSiteDescriptor newDescriptor = descriptor.changeMethodType( + type.changeParameterType(0, dynamicMethod.getClass()).changeParameterType(1, boundThis.getClass())); + + // Delegate to BeansLinker + final GuardedInvocation inv = BeansLinker.getLinkerForClass(dynamicMethod.getClass()).getGuardedInvocation( + linkRequest.replaceArguments(newDescriptor, args), linkerServices); + if(inv == null) { + return null; + } + + // Bind (dynamicMethod, boundThis) to the handle + final MethodHandle boundHandle = MethodHandles.insertArguments(inv.getInvocation(), 0, dynamicMethod, boundThis); + final Class<?> p0Type = type.parameterType(0); + // Ignore incoming (boundDynamicMethod, this) + final MethodHandle droppingHandle = MethodHandles.dropArguments(boundHandle, 0, p0Type, type.parameterType(1)); + // Identity guard on boundDynamicMethod object + final MethodHandle newGuard = Guards.getIdentityGuard(boundDynamicMethod); + + return inv.replaceMethods(droppingHandle, newGuard.asType(newGuard.type().changeParameterType(0, p0Type))); + } +}
--- a/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java Fri Jul 12 20:13:43 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java Tue Jul 16 09:54:04 2013 +0530 @@ -133,7 +133,7 @@ } private static String getScriptLocation() { - final StackTraceElement caller = DynamicLinker.getRelinkedCallSiteLocation(); + final StackTraceElement caller = DynamicLinker.getLinkedCallSiteLocation(); return caller == null ? "unknown location" : (caller.getFileName() + ":" + caller.getLineNumber()); } @@ -317,7 +317,7 @@ private static final MethodHandle TRACEOBJECT = findOwnMH("traceObject", Object.class, MethodHandle.class, Object[].class); private static final MethodHandle TRACEVOID = findOwnMH("traceVoid", void.class, MethodHandle.class, Object[].class); - private static final MethodHandle TRACEMISS = findOwnMH("traceMiss", void.class, Object[].class); + private static final MethodHandle TRACEMISS = findOwnMH("traceMiss", void.class, String.class, Object[].class); TracingLinkerCallSite(final NashornCallSiteDescriptor desc) { super(desc); @@ -363,7 +363,7 @@ return relink; } final MethodType type = relink.type(); - return MH.foldArguments(relink, MH.asType(MH.asCollector(MH.bindTo(TRACEMISS, this), Object[].class, type.parameterCount()), type.changeReturnType(void.class))); + return MH.foldArguments(relink, MH.asType(MH.asCollector(MH.insertArguments(TRACEMISS, 0, this, "MISS " + getScriptLocation() + " "), Object[].class, type.parameterCount()), type.changeReturnType(void.class))); } private void printObject(final PrintWriter out, final Object arg) { @@ -482,8 +482,8 @@ * @throws Throwable if invocation failes or throws exception/error */ @SuppressWarnings("unused") - public void traceMiss(final Object... args) throws Throwable { - tracePrint(Context.getCurrentErr(), "MISS ", args, null); + public void traceMiss(final String desc, final Object... args) throws Throwable { + tracePrint(Context.getCurrentErr(), desc, args, null); } private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
--- a/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java Fri Jul 12 20:13:43 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java Tue Jul 16 09:54:04 2013 +0530 @@ -40,10 +40,10 @@ final class ReflectionCheckLinker implements TypeBasedGuardingDynamicLinker{ @Override public boolean canLinkType(final Class<?> type) { - return canLinkTypeStatic(type); + return isReflectionClass(type); } - private static boolean canLinkTypeStatic(final Class<?> type) { + private static boolean isReflectionClass(final Class<?> type) { if (type == Class.class || ClassLoader.class.isAssignableFrom(type)) { return true; } @@ -54,6 +54,19 @@ @Override public GuardedInvocation getGuardedInvocation(final LinkRequest origRequest, final LinkerServices linkerServices) throws Exception { + checkLinkRequest(origRequest); + // let the next linker deal with actual linking + return null; + } + + static void checkReflectionAccess(Class<?> clazz) { + final SecurityManager sm = System.getSecurityManager(); + if (sm != null && isReflectionClass(clazz)) { + checkReflectionPermission(sm); + } + } + + private static void checkLinkRequest(final LinkRequest origRequest) { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { final LinkRequest requestWithoutContext = origRequest.withoutRuntimeContext(); // Nashorn has no runtime context @@ -61,23 +74,19 @@ // allow 'static' access on Class objects representing public classes of non-restricted packages if ((self instanceof Class) && Modifier.isPublic(((Class<?>)self).getModifiers())) { final CallSiteDescriptor desc = requestWithoutContext.getCallSiteDescriptor(); - final String operator = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0); - // check for 'get' on 'static' property - switch (operator) { - case "getProp": - case "getMethod": { - if ("static".equals(desc.getNameToken(CallSiteDescriptor.NAME_OPERAND))) { - Context.checkPackageAccess(((Class)self).getName()); - // let bean linker do the actual linking part - return null; - } + if(CallSiteDescriptorFactory.tokenizeOperators(desc).contains("getProp")) { + if ("static".equals(desc.getNameToken(CallSiteDescriptor.NAME_OPERAND))) { + Context.checkPackageAccess(((Class)self).getName()); + // If "getProp:static" passes package access, allow access. + return; } - break; - } // fall through for all other stuff + } } - sm.checkPermission(new RuntimePermission("nashorn.JavaReflection")); + checkReflectionPermission(sm); } - // let the next linker deal with actual linking - return null; + } + + private static void checkReflectionPermission(final SecurityManager sm) { + sm.checkPermission(new RuntimePermission("nashorn.JavaReflection")); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8020324.js Tue Jul 16 09:54:04 2013 +0530 @@ -0,0 +1,139 @@ +/* + * 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-8020324: Implement Object.bindProperties(target, source) for beans + * + * @test + * @run + */ + +var PropertyBind = Java.type("jdk.nashorn.test.models.PropertyBind") +var bean = new PropertyBind + +var obj1 = {} +Object.bindProperties(obj1, bean) + +printBanner("Two-way read-write instance field") +printEval("obj1.publicInt = 13") +printEval("bean.publicInt") +printEval("bean.publicInt = 15") +printEval("obj1.publicInt") + +printBanner("Read only public instance field") +printEval("obj1.publicFinalInt") +printEval("obj1.publicFinalInt = 16") +printEval("obj1.publicFinalInt") +printEval("bean.publicFinalInt") + +printBanner("Two-way read-write instance property") +printEval("obj1.readWrite = 17") +printEval("bean.readWrite") +printEval("bean.readWrite = 18") +printEval("obj1.readWrite") +printEval("obj1.getReadWrite()") +printEval("obj1.setReadWrite(19)") +printEval("obj1.readWrite") +printEval("bean.readWrite") + +printBanner("Read only instance property") +printEval("obj1.readOnly") +printEval("obj1.readOnly = 20") +printEval("obj1.readOnly") +printEval("obj1.getReadOnly()") +printEval("bean.getReadOnly()") + +printBanner("Write only instance property") +printEval("obj1.writeOnly = 21") +printEval("obj1.writeOnly") +printEval("bean.writeOnly") +printEval("bean.peekWriteOnly()") + +var obj2 = {} +Object.bindProperties(obj2, PropertyBind) + +printBanner("Two-way read-write public static field") +printEval("obj2.publicStaticInt = 22") +printEval("PropertyBind.publicStaticInt") +printEval("PropertyBind.publicStaticInt = 23") +printEval("obj2.publicStaticInt") + +printBanner("Read only public static field") +printEval("obj2.publicStaticFinalInt") +printEval("obj2.publicStaticFinalInt = 24") +printEval("obj2.publicStaticFinalInt") +printEval("PropertyBind.publicStaticFinalInt") + +printBanner("Two-way read-write static property") +printEval("obj2.staticReadWrite = 25") +printEval("PropertyBind.staticReadWrite") +printEval("PropertyBind.staticReadWrite = 26") +printEval("obj2.staticReadWrite") +printEval("obj2.getStaticReadWrite()") +printEval("obj2.setStaticReadWrite(27)") +printEval("obj2.staticReadWrite") +printEval("PropertyBind.staticReadWrite") + +printBanner("Read only static property") +printEval("obj2.staticReadOnly") +printEval("obj2.staticReadOnly = 28") +printEval("obj2.staticReadOnly") +printEval("obj2.getStaticReadOnly()") +printEval("PropertyBind.getStaticReadOnly()") + +printBanner("Write only static property") +printEval("obj2.staticWriteOnly = 29") +printEval("obj2.staticWriteOnly") +printEval("PropertyBind.staticWriteOnly") +printEval("PropertyBind.peekStaticWriteOnly()") + +printBanner("Sanity check to ensure property values remained what they were") +printEval("obj1.publicInt") +printEval("bean.publicInt") +printEval("obj1.publicFinalInt") +printEval("bean.publicFinalInt") +printEval("obj1.readWrite") +printEval("bean.readWrite") +printEval("obj1.readOnly") +printEval("bean.readOnly") +printEval("bean.peekWriteOnly()") + +printEval("obj2.publicStaticInt") +printEval("PropertyBind.publicStaticInt") +printEval("obj2.publicStaticFinalInt") +printEval("PropertyBind.publicStaticFinalInt") +printEval("obj2.staticReadWrite") +printEval("PropertyBind.staticReadWrite") +printEval("obj2.staticReadOnly") +printEval("PropertyBind.staticReadOnly") +printEval("PropertyBind.peekStaticWriteOnly()") + + +function printEval(s) { + print(s + ": " + eval(s)) +} + +function printBanner(s) { + print() + print("==== " + s + " ====") +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8020324.js.EXPECTED Tue Jul 16 09:54:04 2013 +0530 @@ -0,0 +1,90 @@ + +==== Two-way read-write instance field ==== +obj1.publicInt = 13: 13 +bean.publicInt: 13 +bean.publicInt = 15: 15 +obj1.publicInt: 15 + +==== Read only public instance field ==== +obj1.publicFinalInt: 42 +obj1.publicFinalInt = 16: 16 +obj1.publicFinalInt: 42 +bean.publicFinalInt: 42 + +==== Two-way read-write instance property ==== +obj1.readWrite = 17: 17 +bean.readWrite: 17 +bean.readWrite = 18: 18 +obj1.readWrite: 18 +obj1.getReadWrite(): 18 +obj1.setReadWrite(19): null +obj1.readWrite: 19 +bean.readWrite: 19 + +==== Read only instance property ==== +obj1.readOnly: 123 +obj1.readOnly = 20: 20 +obj1.readOnly: 123 +obj1.getReadOnly(): 123 +bean.getReadOnly(): 123 + +==== Write only instance property ==== +obj1.writeOnly = 21: 21 +obj1.writeOnly: undefined +bean.writeOnly: undefined +bean.peekWriteOnly(): 21 + +==== Two-way read-write public static field ==== +obj2.publicStaticInt = 22: 22 +PropertyBind.publicStaticInt: 22 +PropertyBind.publicStaticInt = 23: 23 +obj2.publicStaticInt: 23 + +==== Read only public static field ==== +obj2.publicStaticFinalInt: 2112 +obj2.publicStaticFinalInt = 24: 24 +obj2.publicStaticFinalInt: 2112 +PropertyBind.publicStaticFinalInt: 2112 + +==== Two-way read-write static property ==== +obj2.staticReadWrite = 25: 25 +PropertyBind.staticReadWrite: 25 +PropertyBind.staticReadWrite = 26: 26 +obj2.staticReadWrite: 26 +obj2.getStaticReadWrite(): 26 +obj2.setStaticReadWrite(27): null +obj2.staticReadWrite: 27 +PropertyBind.staticReadWrite: 27 + +==== Read only static property ==== +obj2.staticReadOnly: 1230 +obj2.staticReadOnly = 28: 28 +obj2.staticReadOnly: 1230 +obj2.getStaticReadOnly(): 1230 +PropertyBind.getStaticReadOnly(): 1230 + +==== Write only static property ==== +obj2.staticWriteOnly = 29: 29 +obj2.staticWriteOnly: undefined +PropertyBind.staticWriteOnly: undefined +PropertyBind.peekStaticWriteOnly(): 29 + +==== Sanity check to ensure property values remained what they were ==== +obj1.publicInt: 15 +bean.publicInt: 15 +obj1.publicFinalInt: 42 +bean.publicFinalInt: 42 +obj1.readWrite: 19 +bean.readWrite: 19 +obj1.readOnly: 123 +bean.readOnly: 123 +bean.peekWriteOnly(): 21 +obj2.publicStaticInt: 23 +PropertyBind.publicStaticInt: 23 +obj2.publicStaticFinalInt: 2112 +PropertyBind.publicStaticFinalInt: 2112 +obj2.staticReadWrite: 27 +PropertyBind.staticReadWrite: 27 +obj2.staticReadOnly: 1230 +PropertyBind.staticReadOnly: 1230 +PropertyBind.peekStaticWriteOnly(): 29
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8020354.js Tue Jul 16 09:54:04 2013 +0530 @@ -0,0 +1,43 @@ +/* + * 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-8020354: Object literal property initialization is not done in source order + * + * @test + * @run + */ + + +var obj = ({a: print(1), b: print(2), a: print(3)}); + +var obj = ({ + a: print(1), + get x() { print("getting x"); return "x" }, + set x(v) { print("setting x"); }, + b: print(2), + a: print(3) +}); + +print(obj.x); +obj.x = 4;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8020354.js.EXPECTED Tue Jul 16 09:54:04 2013 +0530 @@ -0,0 +1,9 @@ +1 +2 +3 +1 +2 +3 +getting x +x +setting x
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8020358.js Tue Jul 16 09:54:04 2013 +0530 @@ -0,0 +1,43 @@ +/* + * 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-8020358: Array(0xfffffff) throws OutOfMemoryError + * + * @test + * @run + */ + +var x = new Array(0xfffffff); +print(x.length); +x[0xffffffe] = 1; +print(x.length); +x[0xfffffff] = 1; +print(x.length); + +x = new Array(0x8ffff); +print(x.length); +print(Function("return 'ok'").apply(null, x)); +x[0] = "pass"; +print(Function("p", "return p").apply(null, x)); +print(Function("return arguments[0]").apply(null, x));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8020358.js.EXPECTED Tue Jul 16 09:54:04 2013 +0530 @@ -0,0 +1,7 @@ +268435455 +268435455 +268435456 +589823 +ok +pass +pass
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8020508.js Tue Jul 16 09:54:04 2013 +0530 @@ -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-8020508: Enforce reflection check on + * Object.bindProperties(target, source) for beans + * + * @test + * @run + */ + +var x = {} +try { + Object.bindProperties(x, java.util.Vector.class) +} catch(e) { + print(e) +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8020508.js.EXPECTED Tue Jul 16 09:54:04 2013 +0530 @@ -0,0 +1,1 @@ +java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "nashorn.JavaReflection")
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/src/jdk/nashorn/test/models/PropertyBind.java Tue Jul 16 09:54:04 2013 +0530 @@ -0,0 +1,82 @@ +/* + * 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.test.models; + +public class PropertyBind { + public static int publicStaticInt; + public static final int publicStaticFinalInt = 2112; + + private static int staticReadWrite; + private static int staticReadOnly = 1230; + private static int staticWriteOnly; + + public int publicInt; + public final int publicFinalInt = 42; + + private int readWrite; + private int readOnly = 123; + private int writeOnly; + + public int getReadWrite() { + return readWrite; + } + + public void setReadWrite(int readWrite) { + this.readWrite = readWrite; + } + + public int getReadOnly() { + return readOnly; + } + + public void setWriteOnly(int writeOnly) { + this.writeOnly = writeOnly; + } + + public int peekWriteOnly() { + return writeOnly; + } + + public static int getStaticReadWrite() { + return staticReadWrite; + } + + public static void setStaticReadWrite(int staticReadWrite) { + PropertyBind.staticReadWrite = staticReadWrite; + } + + public static int getStaticReadOnly() { + return staticReadOnly; + } + + public static void setStaticWriteOnly(int staticWriteOnly) { + PropertyBind.staticWriteOnly = staticWriteOnly; + } + + public static int peekStaticWriteOnly() { + return PropertyBind.staticWriteOnly; + } +}