Mon, 15 Jul 2013 12:33:48 +0200
8020324: Implement Object.bindProperties(target, source) for beans
Reviewed-by: hannesw, sundar
1.1 --- a/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java Fri Jul 12 20:06:41 2013 +0530 1.2 +++ b/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java Mon Jul 15 12:33:48 2013 +0200 1.3 @@ -92,6 +92,8 @@ 1.4 import java.lang.reflect.Member; 1.5 import java.lang.reflect.Method; 1.6 import java.lang.reflect.Modifier; 1.7 +import java.util.Collection; 1.8 +import java.util.Collections; 1.9 import java.util.HashMap; 1.10 import java.util.List; 1.11 import java.util.Map; 1.12 @@ -194,6 +196,22 @@ 1.13 1.14 abstract FacetIntrospector createFacetIntrospector(); 1.15 1.16 + Collection<String> getReadablePropertyNames() { 1.17 + return getUnmodifiableKeys(propertyGetters); 1.18 + } 1.19 + 1.20 + Collection<String> getWritablePropertyNames() { 1.21 + return getUnmodifiableKeys(propertySetters); 1.22 + } 1.23 + 1.24 + Collection<String> getMethodNames() { 1.25 + return getUnmodifiableKeys(methods); 1.26 + } 1.27 + 1.28 + private static Collection<String> getUnmodifiableKeys(Map<String, ?> m) { 1.29 + return Collections.unmodifiableCollection(m.keySet()); 1.30 + } 1.31 + 1.32 /** 1.33 * Sets the specified dynamic method to be the property getter for the specified property. Note that you can only 1.34 * use this when you're certain that the method handle does not belong to a caller-sensitive method. For properties
2.1 --- a/src/jdk/internal/dynalink/beans/BeansLinker.java Fri Jul 12 20:06:41 2013 +0530 2.2 +++ b/src/jdk/internal/dynalink/beans/BeansLinker.java Mon Jul 15 12:33:48 2013 +0200 2.3 @@ -84,6 +84,8 @@ 2.4 package jdk.internal.dynalink.beans; 2.5 2.6 import java.lang.invoke.MethodHandles; 2.7 +import java.util.Collection; 2.8 +import java.util.Collections; 2.9 import jdk.internal.dynalink.CallSiteDescriptor; 2.10 import jdk.internal.dynalink.DynamicLinkerFactory; 2.11 import jdk.internal.dynalink.linker.GuardedInvocation; 2.12 @@ -166,6 +168,72 @@ 2.13 return obj instanceof DynamicMethod; 2.14 } 2.15 2.16 + /** 2.17 + * Returns a collection of names of all readable instance properties of a class. 2.18 + * @param clazz the class 2.19 + * @return a collection of names of all readable instance properties of a class. 2.20 + */ 2.21 + public static Collection<String> getReadableInstancePropertyNames(Class<?> clazz) { 2.22 + TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz); 2.23 + if(linker instanceof BeanLinker) { 2.24 + return ((BeanLinker)linker).getReadablePropertyNames(); 2.25 + } 2.26 + return Collections.emptySet(); 2.27 + } 2.28 + 2.29 + /** 2.30 + * Returns a collection of names of all writable instance properties of a class. 2.31 + * @param clazz the class 2.32 + * @return a collection of names of all writable instance properties of a class. 2.33 + */ 2.34 + public static Collection<String> getWritableInstancePropertyNames(Class<?> clazz) { 2.35 + TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz); 2.36 + if(linker instanceof BeanLinker) { 2.37 + return ((BeanLinker)linker).getWritablePropertyNames(); 2.38 + } 2.39 + return Collections.emptySet(); 2.40 + } 2.41 + 2.42 + /** 2.43 + * Returns a collection of names of all instance methods of a class. 2.44 + * @param clazz the class 2.45 + * @return a collection of names of all instance methods of a class. 2.46 + */ 2.47 + public static Collection<String> getInstanceMethodNames(Class<?> clazz) { 2.48 + TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz); 2.49 + if(linker instanceof BeanLinker) { 2.50 + return ((BeanLinker)linker).getMethodNames(); 2.51 + } 2.52 + return Collections.emptySet(); 2.53 + } 2.54 + 2.55 + /** 2.56 + * Returns a collection of names of all readable static properties of a class. 2.57 + * @param clazz the class 2.58 + * @return a collection of names of all readable static properties of a class. 2.59 + */ 2.60 + public static Collection<String> getReadableStaticPropertyNames(Class<?> clazz) { 2.61 + return StaticClassLinker.getReadableStaticPropertyNames(clazz); 2.62 + } 2.63 + 2.64 + /** 2.65 + * Returns a collection of names of all writable static properties of a class. 2.66 + * @param clazz the class 2.67 + * @return a collection of names of all writable static properties of a class. 2.68 + */ 2.69 + public static Collection<String> getWritableStaticPropertyNames(Class<?> clazz) { 2.70 + return StaticClassLinker.getWritableStaticPropertyNames(clazz); 2.71 + } 2.72 + 2.73 + /** 2.74 + * Returns a collection of names of all static methods of a class. 2.75 + * @param clazz the class 2.76 + * @return a collection of names of all static methods of a class. 2.77 + */ 2.78 + public static Collection<String> getStaticMethodNames(Class<?> clazz) { 2.79 + return StaticClassLinker.getStaticMethodNames(clazz); 2.80 + } 2.81 + 2.82 @Override 2.83 public GuardedInvocation getGuardedInvocation(LinkRequest request, final LinkerServices linkerServices) 2.84 throws Exception {
3.1 --- a/src/jdk/internal/dynalink/beans/StaticClassLinker.java Fri Jul 12 20:06:41 2013 +0530 3.2 +++ b/src/jdk/internal/dynalink/beans/StaticClassLinker.java Mon Jul 15 12:33:48 2013 +0200 3.3 @@ -88,10 +88,10 @@ 3.4 import java.lang.invoke.MethodType; 3.5 import java.lang.reflect.Array; 3.6 import java.util.Arrays; 3.7 +import java.util.Collection; 3.8 import jdk.internal.dynalink.CallSiteDescriptor; 3.9 import jdk.internal.dynalink.beans.GuardedInvocationComponent.ValidationType; 3.10 import jdk.internal.dynalink.linker.GuardedInvocation; 3.11 -import jdk.internal.dynalink.linker.GuardingDynamicLinker; 3.12 import jdk.internal.dynalink.linker.LinkRequest; 3.13 import jdk.internal.dynalink.linker.LinkerServices; 3.14 import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; 3.15 @@ -102,9 +102,9 @@ 3.16 * @author Attila Szegedi 3.17 */ 3.18 class StaticClassLinker implements TypeBasedGuardingDynamicLinker { 3.19 - private final ClassValue<GuardingDynamicLinker> linkers = new ClassValue<GuardingDynamicLinker>() { 3.20 + private static final ClassValue<SingleClassStaticsLinker> linkers = new ClassValue<SingleClassStaticsLinker>() { 3.21 @Override 3.22 - protected GuardingDynamicLinker computeValue(Class<?> clazz) { 3.23 + protected SingleClassStaticsLinker computeValue(Class<?> clazz) { 3.24 return new SingleClassStaticsLinker(clazz); 3.25 } 3.26 }; 3.27 @@ -160,6 +160,18 @@ 3.28 } 3.29 } 3.30 3.31 + static Collection<String> getReadableStaticPropertyNames(Class<?> clazz) { 3.32 + return linkers.get(clazz).getReadablePropertyNames(); 3.33 + } 3.34 + 3.35 + static Collection<String> getWritableStaticPropertyNames(Class<?> clazz) { 3.36 + return linkers.get(clazz).getWritablePropertyNames(); 3.37 + } 3.38 + 3.39 + static Collection<String> getStaticMethodNames(Class<?> clazz) { 3.40 + return linkers.get(clazz).getMethodNames(); 3.41 + } 3.42 + 3.43 @Override 3.44 public GuardedInvocation getGuardedInvocation(LinkRequest request, LinkerServices linkerServices) throws Exception { 3.45 final Object receiver = request.getReceiver();
4.1 --- a/src/jdk/nashorn/internal/objects/NativeObject.java Fri Jul 12 20:06:41 2013 +0530 4.2 +++ b/src/jdk/nashorn/internal/objects/NativeObject.java Mon Jul 15 12:33:48 2013 +0200 4.3 @@ -29,8 +29,22 @@ 4.4 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 4.5 4.6 import java.lang.invoke.MethodHandle; 4.7 +import java.lang.invoke.MethodHandles; 4.8 +import java.lang.invoke.MethodType; 4.9 import java.util.ArrayList; 4.10 +import java.util.Collection; 4.11 +import java.util.HashSet; 4.12 +import java.util.List; 4.13 +import java.util.Set; 4.14 +import jdk.internal.dynalink.beans.BeansLinker; 4.15 +import jdk.internal.dynalink.beans.StaticClass; 4.16 +import jdk.internal.dynalink.linker.GuardedInvocation; 4.17 +import jdk.internal.dynalink.linker.GuardingDynamicLinker; 4.18 +import jdk.internal.dynalink.linker.LinkRequest; 4.19 +import jdk.internal.dynalink.support.CallSiteDescriptorFactory; 4.20 +import jdk.internal.dynalink.support.LinkRequestImpl; 4.21 import jdk.nashorn.api.scripting.ScriptObjectMirror; 4.22 +import jdk.nashorn.internal.lookup.Lookup; 4.23 import jdk.nashorn.internal.objects.annotations.Attribute; 4.24 import jdk.nashorn.internal.objects.annotations.Constructor; 4.25 import jdk.nashorn.internal.objects.annotations.Function; 4.26 @@ -58,6 +72,8 @@ 4.27 @ScriptClass("Object") 4.28 public final class NativeObject { 4.29 private static final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class); 4.30 + private static final MethodType MIRROR_GETTER_TYPE = MethodType.methodType(Object.class, ScriptObjectMirror.class); 4.31 + private static final MethodType MIRROR_SETTER_TYPE = MethodType.methodType(Object.class, ScriptObjectMirror.class, Object.class); 4.32 4.33 // initialized by nasgen 4.34 @SuppressWarnings("unused") 4.35 @@ -577,14 +593,91 @@ 4.36 final AccessorProperty[] props = new AccessorProperty[keys.length]; 4.37 for (int idx = 0; idx < keys.length; idx++) { 4.38 final String name = keys[idx]; 4.39 - final MethodHandle getter = Bootstrap.createDynamicInvoker("dyn:getMethod|getProp|getElem:" + name, Object.class, ScriptObjectMirror.class); 4.40 - final MethodHandle setter = Bootstrap.createDynamicInvoker("dyn:setProp|setElem:" + name, Object.class, ScriptObjectMirror.class, Object.class); 4.41 + final MethodHandle getter = Bootstrap.createDynamicInvoker("dyn:getMethod|getProp|getElem:" + name, MIRROR_GETTER_TYPE); 4.42 + final MethodHandle setter = Bootstrap.createDynamicInvoker("dyn:setProp|setElem:" + name, MIRROR_SETTER_TYPE); 4.43 props[idx] = (AccessorProperty.create(name, 0, getter, setter)); 4.44 } 4.45 4.46 targetObj.addBoundProperties(source, props); 4.47 + } else if (source instanceof StaticClass) { 4.48 + final Class<?> clazz = ((StaticClass)source).getRepresentedClass(); 4.49 + bindBeanProperties(targetObj, source, BeansLinker.getReadableStaticPropertyNames(clazz), 4.50 + BeansLinker.getWritableStaticPropertyNames(clazz), BeansLinker.getStaticMethodNames(clazz)); 4.51 + } else { 4.52 + final Class<?> clazz = source.getClass(); 4.53 + bindBeanProperties(targetObj, source, BeansLinker.getReadableInstancePropertyNames(clazz), 4.54 + BeansLinker.getWritableInstancePropertyNames(clazz), BeansLinker.getInstanceMethodNames(clazz)); 4.55 } 4.56 4.57 return target; 4.58 } 4.59 + 4.60 + private static void bindBeanProperties(final ScriptObject targetObj, final Object source, 4.61 + final Collection<String> readablePropertyNames, final Collection<String> writablePropertyNames, 4.62 + final Collection<String> methodNames) { 4.63 + final Set<String> propertyNames = new HashSet<>(readablePropertyNames); 4.64 + propertyNames.addAll(writablePropertyNames); 4.65 + 4.66 + final Class<?> clazz = source.getClass(); 4.67 + 4.68 + final MethodType getterType = MethodType.methodType(Object.class, clazz); 4.69 + final MethodType setterType = MethodType.methodType(Object.class, clazz, Object.class); 4.70 + 4.71 + final GuardingDynamicLinker linker = BeansLinker.getLinkerForClass(clazz); 4.72 + 4.73 + final List<AccessorProperty> properties = new ArrayList<>(propertyNames.size() + methodNames.size()); 4.74 + for(final String methodName: methodNames) { 4.75 + properties.add(AccessorProperty.create(methodName, Property.NOT_WRITABLE, 4.76 + getBoundBeanMethodGetter(source, getBeanOperation(linker, "dyn:getMethod:" + methodName, getterType, source)), 4.77 + null)); 4.78 + } 4.79 + for(final String propertyName: propertyNames) { 4.80 + final boolean isWritable = writablePropertyNames.contains(propertyName); 4.81 + properties.add(AccessorProperty.create(propertyName, isWritable ? 0 : Property.NOT_WRITABLE, 4.82 + readablePropertyNames.contains(propertyName) ? getBeanOperation(linker, "dyn:getProp:" + propertyName, getterType, source) : Lookup.EMPTY_GETTER, 4.83 + isWritable ? getBeanOperation(linker, "dyn:setProp:" + propertyName, setterType, source) : Lookup.EMPTY_SETTER)); 4.84 + } 4.85 + 4.86 + targetObj.addBoundProperties(source, properties.toArray(new AccessorProperty[properties.size()])); 4.87 + } 4.88 + 4.89 + private static MethodHandle getBoundBeanMethodGetter(Object source, MethodHandle methodGetter) { 4.90 + try { 4.91 + // NOTE: we're relying on the fact that "dyn:getMethod:..." return value is constant for any given method 4.92 + // name and object linked with BeansLinker. (Actually, an even stronger assumption is true: return value is 4.93 + // constant for any given method name and object's class.) 4.94 + return MethodHandles.dropArguments(MethodHandles.constant(Object.class, 4.95 + Bootstrap.bindDynamicMethod(methodGetter.invoke(source), source)), 0, Object.class); 4.96 + } catch(RuntimeException|Error e) { 4.97 + throw e; 4.98 + } catch(Throwable t) { 4.99 + throw new RuntimeException(t); 4.100 + } 4.101 + } 4.102 + 4.103 + private static MethodHandle getBeanOperation(final GuardingDynamicLinker linker, final String operation, 4.104 + final MethodType methodType, final Object source) { 4.105 + final GuardedInvocation inv; 4.106 + try { 4.107 + inv = linker.getGuardedInvocation(createLinkRequest(operation, methodType, source), 4.108 + Bootstrap.getLinkerServices()); 4.109 + assert passesGuard(source, inv.getGuard()); 4.110 + } catch(RuntimeException|Error e) { 4.111 + throw e; 4.112 + } catch(Throwable t) { 4.113 + throw new RuntimeException(t); 4.114 + } 4.115 + assert inv.getSwitchPoint() == null; // Linkers in Dynalink's beans package don't use switchpoints. 4.116 + // We discard the guard, as all method handles will be bound to a specific object. 4.117 + return inv.getInvocation(); 4.118 + } 4.119 + 4.120 + private static boolean passesGuard(final Object obj, final MethodHandle guard) throws Throwable { 4.121 + return guard == null || (boolean)guard.invoke(obj); 4.122 + } 4.123 + 4.124 + private static LinkRequest createLinkRequest(String operation, MethodType methodType, Object source) { 4.125 + return new LinkRequestImpl(CallSiteDescriptorFactory.create(MethodHandles.publicLookup(), operation, 4.126 + methodType), false, source); 4.127 + } 4.128 }
5.1 --- a/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Fri Jul 12 20:06:41 2013 +0530 5.2 +++ b/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Mon Jul 15 12:33:48 2013 +0200 5.3 @@ -57,7 +57,7 @@ 5.4 static { 5.5 final DynamicLinkerFactory factory = new DynamicLinkerFactory(); 5.6 factory.setPrioritizedLinkers(new NashornLinker(), new NashornPrimitiveLinker(), new NashornStaticClassLinker(), 5.7 - new JSObjectLinker(), new ReflectionCheckLinker()); 5.8 + new BoundDynamicMethodLinker(), new JSObjectLinker(), new ReflectionCheckLinker()); 5.9 factory.setFallbackLinkers(new BeansLinker(), new NashornBottomLinker()); 5.10 factory.setSyncOnRelink(true); 5.11 final int relinkThreshold = Options.getIntProperty("nashorn.unstable.relink.threshold", -1); 5.12 @@ -208,6 +208,16 @@ 5.13 } 5.14 5.15 /** 5.16 + * Binds a bean dynamic method (returned by invoking {@code dyn:getMethod} on an object linked with 5.17 + * {@code BeansLinker} to a receiver. 5.18 + * @param dynamicMethod the dynamic method to bind 5.19 + * @param boundThis the bound "this" value. 5.20 + * @return a bound dynamic method. 5.21 + */ 5.22 + public static Object bindDynamicMethod(Object dynamicMethod, Object boundThis) { 5.23 + return new BoundDynamicMethod(dynamicMethod, boundThis); 5.24 + } 5.25 + /** 5.26 * Returns the Nashorn's internally used dynamic linker's services object. Note that in code that is processing a 5.27 * linking request, you will normally use the {@code LinkerServices} object passed by whatever top-level linker 5.28 * invoked the linking (if the call site is in Nashorn-generated code, you'll get this object anyway). You should
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethod.java Mon Jul 15 12:33:48 2013 +0200 6.3 @@ -0,0 +1,51 @@ 6.4 +/* 6.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.7 + * 6.8 + * This code is free software; you can redistribute it and/or modify it 6.9 + * under the terms of the GNU General Public License version 2 only, as 6.10 + * published by the Free Software Foundation. Oracle designates this 6.11 + * particular file as subject to the "Classpath" exception as provided 6.12 + * by Oracle in the LICENSE file that accompanied this code. 6.13 + * 6.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 6.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 6.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 6.17 + * version 2 for more details (a copy is included in the LICENSE file that 6.18 + * accompanied this code). 6.19 + * 6.20 + * You should have received a copy of the GNU General Public License version 6.21 + * 2 along with this work; if not, write to the Free Software Foundation, 6.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 6.23 + * 6.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 6.25 + * or visit www.oracle.com if you need additional information or have any 6.26 + * questions. 6.27 + */ 6.28 + 6.29 +package jdk.nashorn.internal.runtime.linker; 6.30 + 6.31 +import jdk.internal.dynalink.beans.BeansLinker; 6.32 + 6.33 +/** 6.34 + * Represents a Dynalink dynamic method bound to a receiver. Note that objects of this class are just the tuples of 6.35 + * a method and a bound this, without any behavior. All the behavior is defined in the {@link BoundDynamicMethodLinker}. 6.36 + */ 6.37 +final class BoundDynamicMethod { 6.38 + private final Object dynamicMethod; 6.39 + private final Object boundThis; 6.40 + 6.41 + BoundDynamicMethod(final Object dynamicMethod, final Object boundThis) { 6.42 + assert BeansLinker.isDynamicMethod(dynamicMethod); 6.43 + this.dynamicMethod = dynamicMethod; 6.44 + this.boundThis = boundThis; 6.45 + } 6.46 + 6.47 + Object getDynamicMethod() { 6.48 + return dynamicMethod; 6.49 + } 6.50 + 6.51 + Object getBoundThis() { 6.52 + return boundThis; 6.53 + } 6.54 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethodLinker.java Mon Jul 15 12:33:48 2013 +0200 7.3 @@ -0,0 +1,90 @@ 7.4 +/* 7.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 7.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7.7 + * 7.8 + * This code is free software; you can redistribute it and/or modify it 7.9 + * under the terms of the GNU General Public License version 2 only, as 7.10 + * published by the Free Software Foundation. Oracle designates this 7.11 + * particular file as subject to the "Classpath" exception as provided 7.12 + * by Oracle in the LICENSE file that accompanied this code. 7.13 + * 7.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 7.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 7.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 7.17 + * version 2 for more details (a copy is included in the LICENSE file that 7.18 + * accompanied this code). 7.19 + * 7.20 + * You should have received a copy of the GNU General Public License version 7.21 + * 2 along with this work; if not, write to the Free Software Foundation, 7.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 7.23 + * 7.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 7.25 + * or visit www.oracle.com if you need additional information or have any 7.26 + * questions. 7.27 + */ 7.28 + 7.29 +package jdk.nashorn.internal.runtime.linker; 7.30 + 7.31 +import java.lang.invoke.MethodHandle; 7.32 +import java.lang.invoke.MethodHandles; 7.33 +import java.lang.invoke.MethodType; 7.34 +import jdk.internal.dynalink.CallSiteDescriptor; 7.35 +import jdk.internal.dynalink.beans.BeansLinker; 7.36 +import jdk.internal.dynalink.linker.GuardedInvocation; 7.37 +import jdk.internal.dynalink.linker.LinkRequest; 7.38 +import jdk.internal.dynalink.linker.LinkerServices; 7.39 +import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; 7.40 +import jdk.internal.dynalink.support.Guards; 7.41 + 7.42 +/** 7.43 + * Links {@link BoundDynamicMethod} objects. Passes through to Dynalink's BeansLinker for linking a dynamic method 7.44 + * (they only respond to "dyn:call"), and modifies the returned invocation to deal with the receiver binding. 7.45 + */ 7.46 +final class BoundDynamicMethodLinker implements TypeBasedGuardingDynamicLinker { 7.47 + @Override 7.48 + public boolean canLinkType(Class<?> type) { 7.49 + return type == BoundDynamicMethod.class; 7.50 + } 7.51 + 7.52 + @Override 7.53 + public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, LinkerServices linkerServices) throws Exception { 7.54 + final Object objBoundDynamicMethod = linkRequest.getReceiver(); 7.55 + if(!(objBoundDynamicMethod instanceof BoundDynamicMethod)) { 7.56 + return null; 7.57 + } 7.58 + 7.59 + final BoundDynamicMethod boundDynamicMethod = (BoundDynamicMethod)objBoundDynamicMethod; 7.60 + final Object dynamicMethod = boundDynamicMethod.getDynamicMethod(); 7.61 + final Object boundThis = boundDynamicMethod.getBoundThis(); 7.62 + 7.63 + // Replace arguments (boundDynamicMethod, this, ...) => (dynamicMethod, boundThis, ...) when delegating to 7.64 + // BeansLinker 7.65 + final Object[] args = linkRequest.getArguments(); 7.66 + args[0] = dynamicMethod; 7.67 + args[1] = boundThis; 7.68 + 7.69 + // Use R(T0, T1, ...) => R(dynamicMethod.class, boundThis.class, ...) call site type when delegating to 7.70 + // BeansLinker. 7.71 + final CallSiteDescriptor descriptor = linkRequest.getCallSiteDescriptor(); 7.72 + final MethodType type = descriptor.getMethodType(); 7.73 + final CallSiteDescriptor newDescriptor = descriptor.changeMethodType( 7.74 + type.changeParameterType(0, dynamicMethod.getClass()).changeParameterType(1, boundThis.getClass())); 7.75 + 7.76 + // Delegate to BeansLinker 7.77 + final GuardedInvocation inv = BeansLinker.getLinkerForClass(dynamicMethod.getClass()).getGuardedInvocation( 7.78 + linkRequest.replaceArguments(newDescriptor, args), linkerServices); 7.79 + if(inv == null) { 7.80 + return null; 7.81 + } 7.82 + 7.83 + // Bind (dynamicMethod, boundThis) to the handle 7.84 + final MethodHandle boundHandle = MethodHandles.insertArguments(inv.getInvocation(), 0, dynamicMethod, boundThis); 7.85 + final Class<?> p0Type = type.parameterType(0); 7.86 + // Ignore incoming (boundDynamicMethod, this) 7.87 + final MethodHandle droppingHandle = MethodHandles.dropArguments(boundHandle, 0, p0Type, type.parameterType(1)); 7.88 + // Identity guard on boundDynamicMethod object 7.89 + final MethodHandle newGuard = Guards.getIdentityGuard(boundDynamicMethod); 7.90 + 7.91 + return inv.replaceMethods(droppingHandle, newGuard.asType(newGuard.type().changeParameterType(0, p0Type))); 7.92 + } 7.93 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/test/script/basic/JDK-8020324.js Mon Jul 15 12:33:48 2013 +0200 8.3 @@ -0,0 +1,139 @@ 8.4 +/* 8.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 8.7 + * 8.8 + * This code is free software; you can redistribute it and/or modify it 8.9 + * under the terms of the GNU General Public License version 2 only, as 8.10 + * published by the Free Software Foundation. 8.11 + * 8.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 8.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 8.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 8.15 + * version 2 for more details (a copy is included in the LICENSE file that 8.16 + * accompanied this code). 8.17 + * 8.18 + * You should have received a copy of the GNU General Public License version 8.19 + * 2 along with this work; if not, write to the Free Software Foundation, 8.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 8.21 + * 8.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 8.23 + * or visit www.oracle.com if you need additional information or have any 8.24 + * questions. 8.25 + */ 8.26 + 8.27 +/** 8.28 + * JDK-8020324: Implement Object.bindProperties(target, source) for beans 8.29 + * 8.30 + * @test 8.31 + * @run 8.32 + */ 8.33 + 8.34 +var PropertyBind = Java.type("jdk.nashorn.test.models.PropertyBind") 8.35 +var bean = new PropertyBind 8.36 + 8.37 +var obj1 = {} 8.38 +Object.bindProperties(obj1, bean) 8.39 + 8.40 +printBanner("Two-way read-write instance field") 8.41 +printEval("obj1.publicInt = 13") 8.42 +printEval("bean.publicInt") 8.43 +printEval("bean.publicInt = 15") 8.44 +printEval("obj1.publicInt") 8.45 + 8.46 +printBanner("Read only public instance field") 8.47 +printEval("obj1.publicFinalInt") 8.48 +printEval("obj1.publicFinalInt = 16") 8.49 +printEval("obj1.publicFinalInt") 8.50 +printEval("bean.publicFinalInt") 8.51 + 8.52 +printBanner("Two-way read-write instance property") 8.53 +printEval("obj1.readWrite = 17") 8.54 +printEval("bean.readWrite") 8.55 +printEval("bean.readWrite = 18") 8.56 +printEval("obj1.readWrite") 8.57 +printEval("obj1.getReadWrite()") 8.58 +printEval("obj1.setReadWrite(19)") 8.59 +printEval("obj1.readWrite") 8.60 +printEval("bean.readWrite") 8.61 + 8.62 +printBanner("Read only instance property") 8.63 +printEval("obj1.readOnly") 8.64 +printEval("obj1.readOnly = 20") 8.65 +printEval("obj1.readOnly") 8.66 +printEval("obj1.getReadOnly()") 8.67 +printEval("bean.getReadOnly()") 8.68 + 8.69 +printBanner("Write only instance property") 8.70 +printEval("obj1.writeOnly = 21") 8.71 +printEval("obj1.writeOnly") 8.72 +printEval("bean.writeOnly") 8.73 +printEval("bean.peekWriteOnly()") 8.74 + 8.75 +var obj2 = {} 8.76 +Object.bindProperties(obj2, PropertyBind) 8.77 + 8.78 +printBanner("Two-way read-write public static field") 8.79 +printEval("obj2.publicStaticInt = 22") 8.80 +printEval("PropertyBind.publicStaticInt") 8.81 +printEval("PropertyBind.publicStaticInt = 23") 8.82 +printEval("obj2.publicStaticInt") 8.83 + 8.84 +printBanner("Read only public static field") 8.85 +printEval("obj2.publicStaticFinalInt") 8.86 +printEval("obj2.publicStaticFinalInt = 24") 8.87 +printEval("obj2.publicStaticFinalInt") 8.88 +printEval("PropertyBind.publicStaticFinalInt") 8.89 + 8.90 +printBanner("Two-way read-write static property") 8.91 +printEval("obj2.staticReadWrite = 25") 8.92 +printEval("PropertyBind.staticReadWrite") 8.93 +printEval("PropertyBind.staticReadWrite = 26") 8.94 +printEval("obj2.staticReadWrite") 8.95 +printEval("obj2.getStaticReadWrite()") 8.96 +printEval("obj2.setStaticReadWrite(27)") 8.97 +printEval("obj2.staticReadWrite") 8.98 +printEval("PropertyBind.staticReadWrite") 8.99 + 8.100 +printBanner("Read only static property") 8.101 +printEval("obj2.staticReadOnly") 8.102 +printEval("obj2.staticReadOnly = 28") 8.103 +printEval("obj2.staticReadOnly") 8.104 +printEval("obj2.getStaticReadOnly()") 8.105 +printEval("PropertyBind.getStaticReadOnly()") 8.106 + 8.107 +printBanner("Write only static property") 8.108 +printEval("obj2.staticWriteOnly = 29") 8.109 +printEval("obj2.staticWriteOnly") 8.110 +printEval("PropertyBind.staticWriteOnly") 8.111 +printEval("PropertyBind.peekStaticWriteOnly()") 8.112 + 8.113 +printBanner("Sanity check to ensure property values remained what they were") 8.114 +printEval("obj1.publicInt") 8.115 +printEval("bean.publicInt") 8.116 +printEval("obj1.publicFinalInt") 8.117 +printEval("bean.publicFinalInt") 8.118 +printEval("obj1.readWrite") 8.119 +printEval("bean.readWrite") 8.120 +printEval("obj1.readOnly") 8.121 +printEval("bean.readOnly") 8.122 +printEval("bean.peekWriteOnly()") 8.123 + 8.124 +printEval("obj2.publicStaticInt") 8.125 +printEval("PropertyBind.publicStaticInt") 8.126 +printEval("obj2.publicStaticFinalInt") 8.127 +printEval("PropertyBind.publicStaticFinalInt") 8.128 +printEval("obj2.staticReadWrite") 8.129 +printEval("PropertyBind.staticReadWrite") 8.130 +printEval("obj2.staticReadOnly") 8.131 +printEval("PropertyBind.staticReadOnly") 8.132 +printEval("PropertyBind.peekStaticWriteOnly()") 8.133 + 8.134 + 8.135 +function printEval(s) { 8.136 + print(s + ": " + eval(s)) 8.137 +} 8.138 + 8.139 +function printBanner(s) { 8.140 + print() 8.141 + print("==== " + s + " ====") 8.142 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/test/script/basic/JDK-8020324.js.EXPECTED Mon Jul 15 12:33:48 2013 +0200 9.3 @@ -0,0 +1,90 @@ 9.4 + 9.5 +==== Two-way read-write instance field ==== 9.6 +obj1.publicInt = 13: 13 9.7 +bean.publicInt: 13 9.8 +bean.publicInt = 15: 15 9.9 +obj1.publicInt: 15 9.10 + 9.11 +==== Read only public instance field ==== 9.12 +obj1.publicFinalInt: 42 9.13 +obj1.publicFinalInt = 16: 16 9.14 +obj1.publicFinalInt: 42 9.15 +bean.publicFinalInt: 42 9.16 + 9.17 +==== Two-way read-write instance property ==== 9.18 +obj1.readWrite = 17: 17 9.19 +bean.readWrite: 17 9.20 +bean.readWrite = 18: 18 9.21 +obj1.readWrite: 18 9.22 +obj1.getReadWrite(): 18 9.23 +obj1.setReadWrite(19): null 9.24 +obj1.readWrite: 19 9.25 +bean.readWrite: 19 9.26 + 9.27 +==== Read only instance property ==== 9.28 +obj1.readOnly: 123 9.29 +obj1.readOnly = 20: 20 9.30 +obj1.readOnly: 123 9.31 +obj1.getReadOnly(): 123 9.32 +bean.getReadOnly(): 123 9.33 + 9.34 +==== Write only instance property ==== 9.35 +obj1.writeOnly = 21: 21 9.36 +obj1.writeOnly: undefined 9.37 +bean.writeOnly: undefined 9.38 +bean.peekWriteOnly(): 21 9.39 + 9.40 +==== Two-way read-write public static field ==== 9.41 +obj2.publicStaticInt = 22: 22 9.42 +PropertyBind.publicStaticInt: 22 9.43 +PropertyBind.publicStaticInt = 23: 23 9.44 +obj2.publicStaticInt: 23 9.45 + 9.46 +==== Read only public static field ==== 9.47 +obj2.publicStaticFinalInt: 2112 9.48 +obj2.publicStaticFinalInt = 24: 24 9.49 +obj2.publicStaticFinalInt: 2112 9.50 +PropertyBind.publicStaticFinalInt: 2112 9.51 + 9.52 +==== Two-way read-write static property ==== 9.53 +obj2.staticReadWrite = 25: 25 9.54 +PropertyBind.staticReadWrite: 25 9.55 +PropertyBind.staticReadWrite = 26: 26 9.56 +obj2.staticReadWrite: 26 9.57 +obj2.getStaticReadWrite(): 26 9.58 +obj2.setStaticReadWrite(27): null 9.59 +obj2.staticReadWrite: 27 9.60 +PropertyBind.staticReadWrite: 27 9.61 + 9.62 +==== Read only static property ==== 9.63 +obj2.staticReadOnly: 1230 9.64 +obj2.staticReadOnly = 28: 28 9.65 +obj2.staticReadOnly: 1230 9.66 +obj2.getStaticReadOnly(): 1230 9.67 +PropertyBind.getStaticReadOnly(): 1230 9.68 + 9.69 +==== Write only static property ==== 9.70 +obj2.staticWriteOnly = 29: 29 9.71 +obj2.staticWriteOnly: undefined 9.72 +PropertyBind.staticWriteOnly: undefined 9.73 +PropertyBind.peekStaticWriteOnly(): 29 9.74 + 9.75 +==== Sanity check to ensure property values remained what they were ==== 9.76 +obj1.publicInt: 15 9.77 +bean.publicInt: 15 9.78 +obj1.publicFinalInt: 42 9.79 +bean.publicFinalInt: 42 9.80 +obj1.readWrite: 19 9.81 +bean.readWrite: 19 9.82 +obj1.readOnly: 123 9.83 +bean.readOnly: 123 9.84 +bean.peekWriteOnly(): 21 9.85 +obj2.publicStaticInt: 23 9.86 +PropertyBind.publicStaticInt: 23 9.87 +obj2.publicStaticFinalInt: 2112 9.88 +PropertyBind.publicStaticFinalInt: 2112 9.89 +obj2.staticReadWrite: 27 9.90 +PropertyBind.staticReadWrite: 27 9.91 +obj2.staticReadOnly: 1230 9.92 +PropertyBind.staticReadOnly: 1230 9.93 +PropertyBind.peekStaticWriteOnly(): 29
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/test/src/jdk/nashorn/test/models/PropertyBind.java Mon Jul 15 12:33:48 2013 +0200 10.3 @@ -0,0 +1,82 @@ 10.4 +/* 10.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 10.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 10.7 + * 10.8 + * This code is free software; you can redistribute it and/or modify it 10.9 + * under the terms of the GNU General Public License version 2 only, as 10.10 + * published by the Free Software Foundation. Oracle designates this 10.11 + * particular file as subject to the "Classpath" exception as provided 10.12 + * by Oracle in the LICENSE file that accompanied this code. 10.13 + * 10.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 10.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 10.17 + * version 2 for more details (a copy is included in the LICENSE file that 10.18 + * accompanied this code). 10.19 + * 10.20 + * You should have received a copy of the GNU General Public License version 10.21 + * 2 along with this work; if not, write to the Free Software Foundation, 10.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 10.23 + * 10.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 10.25 + * or visit www.oracle.com if you need additional information or have any 10.26 + * questions. 10.27 + */ 10.28 + 10.29 +package jdk.nashorn.test.models; 10.30 + 10.31 +public class PropertyBind { 10.32 + public static int publicStaticInt; 10.33 + public static final int publicStaticFinalInt = 2112; 10.34 + 10.35 + private static int staticReadWrite; 10.36 + private static int staticReadOnly = 1230; 10.37 + private static int staticWriteOnly; 10.38 + 10.39 + public int publicInt; 10.40 + public final int publicFinalInt = 42; 10.41 + 10.42 + private int readWrite; 10.43 + private int readOnly = 123; 10.44 + private int writeOnly; 10.45 + 10.46 + public int getReadWrite() { 10.47 + return readWrite; 10.48 + } 10.49 + 10.50 + public void setReadWrite(int readWrite) { 10.51 + this.readWrite = readWrite; 10.52 + } 10.53 + 10.54 + public int getReadOnly() { 10.55 + return readOnly; 10.56 + } 10.57 + 10.58 + public void setWriteOnly(int writeOnly) { 10.59 + this.writeOnly = writeOnly; 10.60 + } 10.61 + 10.62 + public int peekWriteOnly() { 10.63 + return writeOnly; 10.64 + } 10.65 + 10.66 + public static int getStaticReadWrite() { 10.67 + return staticReadWrite; 10.68 + } 10.69 + 10.70 + public static void setStaticReadWrite(int staticReadWrite) { 10.71 + PropertyBind.staticReadWrite = staticReadWrite; 10.72 + } 10.73 + 10.74 + public static int getStaticReadOnly() { 10.75 + return staticReadOnly; 10.76 + } 10.77 + 10.78 + public static void setStaticWriteOnly(int staticWriteOnly) { 10.79 + PropertyBind.staticWriteOnly = staticWriteOnly; 10.80 + } 10.81 + 10.82 + public static int peekStaticWriteOnly() { 10.83 + return PropertyBind.staticWriteOnly; 10.84 + } 10.85 +}