8020324: Implement Object.bindProperties(target, source) for beans

Reviewed-by: hannesw, sundar
This commit is contained in:
Attila Szegedi 2013-07-15 12:33:48 +02:00
parent b8081def9f
commit e11a9b1d07
10 changed files with 659 additions and 6 deletions

View File

@ -92,6 +92,8 @@ import java.lang.reflect.Field;
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 class AbstractJavaLinker implements GuardingDynamicLinker {
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

View File

@ -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 @@ public class BeansLinker implements GuardingDynamicLinker {
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 {

View File

@ -88,10 +88,10 @@ import java.lang.invoke.MethodHandles;
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 @@ import jdk.internal.dynalink.support.Lookup;
* @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 @@ class StaticClassLinker implements TypeBasedGuardingDynamicLinker {
}
}
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();

View File

@ -29,8 +29,22 @@ import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
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 @@ import jdk.nashorn.internal.runtime.linker.InvokeByName;
@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,91 @@ public final class NativeObject {
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();
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);
}
}

View File

@ -57,7 +57,7 @@ public final class Bootstrap {
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);
@ -207,6 +207,16 @@ public final class Bootstrap {
return bootstrap(MethodHandles.publicLookup(), opDesc, type, 0).dynamicInvoker();
}
/**
* 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);
}
/**
* 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

View File

@ -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;
}
}

View File

@ -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)));
}
}

View File

@ -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 + " ====")
}

View File

@ -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

View File

@ -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;
}
}