author | lana |
Thu, 14 Jan 2016 12:03:53 -0800 | |
changeset 34980 | 722ab3267903 |
parent 34972 | f207de5b9da6 (current diff) |
parent 34979 | 03b189baa361 (diff) |
child 34981 | 7bddba9de860 |
nashorn/test/src/jdk/internal/dynalink/beans/test/CallerSensitiveTest.java | file | annotate | diff | comparison | revisions |
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AbstractJavaLinker.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AbstractJavaLinker.java Thu Jan 14 12:03:53 2016 -0800 @@ -349,55 +349,121 @@ throws Exception { final CallSiteDescriptor callSiteDescriptor = request.getCallSiteDescriptor(); + final MissingMemberHandlerFactory missingMemberHandlerFactory; + final LinkerServices directLinkerServices; + if (linkerServices instanceof LinkerServicesWithMissingMemberHandlerFactory) { + final LinkerServicesWithMissingMemberHandlerFactory lswmmhf = ((LinkerServicesWithMissingMemberHandlerFactory)linkerServices); + missingMemberHandlerFactory = lswmmhf.missingMemberHandlerFactory; + directLinkerServices = lswmmhf.linkerServices; + } else { + missingMemberHandlerFactory = null; + directLinkerServices = linkerServices; + } + // Handle NamedOperation(CALL_METHOD, name) separately final Operation operation = callSiteDescriptor.getOperation(); if (operation instanceof NamedOperation) { final NamedOperation namedOperation = (NamedOperation)operation; if (namedOperation.getBaseOperation() == StandardOperation.CALL_METHOD) { - return createGuardedDynamicMethodInvocation(callSiteDescriptor, - linkerServices, namedOperation.getName().toString(), methods); + final GuardedInvocation inv = + createGuardedDynamicMethodInvocation(callSiteDescriptor, + directLinkerServices, namedOperation.getName().toString(), methods); + if (inv == null) { + return createNoSuchMemberHandler(missingMemberHandlerFactory, + request, directLinkerServices).getGuardedInvocation(); + } + return inv; } } - List<Operation> operations = Arrays.asList( - CompositeOperation.getOperations( - NamedOperation.getBaseOperation(operation))); - final Object name = NamedOperation.getName(operation); + final GuardedInvocationComponent gic = getGuardedInvocationComponent( + new ComponentLinkRequest(request, directLinkerServices, + missingMemberHandlerFactory)); + return gic != null ? gic.getGuardedInvocation() : null; + } + + static final class ComponentLinkRequest { + final LinkRequest linkRequest; + final LinkerServices linkerServices; + final MissingMemberHandlerFactory missingMemberHandlerFactory; + final List<Operation> operations; + final Object name; + + ComponentLinkRequest(final LinkRequest linkRequest, + final LinkerServices linkerServices, + final MissingMemberHandlerFactory missingMemberHandlerFactory) { + this.linkRequest = linkRequest; + this.linkerServices = linkerServices; + this.missingMemberHandlerFactory = missingMemberHandlerFactory; + final Operation operation = linkRequest.getCallSiteDescriptor().getOperation(); + this.operations = Arrays.asList( + CompositeOperation.getOperations( + NamedOperation.getBaseOperation(operation))); + this.name = NamedOperation.getName(operation); + } - while(!operations.isEmpty()) { - final GuardedInvocationComponent gic = - getGuardedInvocationComponent(callSiteDescriptor, - linkerServices, operations, name); - if(gic != null) { - return gic.getGuardedInvocation(); + private ComponentLinkRequest(final LinkRequest linkRequest, + final LinkerServices linkerServices, + final MissingMemberHandlerFactory missingMemberHandlerFactory, + final List<Operation> operations, final Object name) { + this.linkRequest = linkRequest; + this.linkerServices = linkerServices; + this.missingMemberHandlerFactory = missingMemberHandlerFactory; + this.operations = operations; + this.name = name; + } + + CallSiteDescriptor getDescriptor() { + return linkRequest.getCallSiteDescriptor(); + } + + ComponentLinkRequest popOperations() { + return new ComponentLinkRequest(linkRequest, linkerServices, + missingMemberHandlerFactory, + operations.subList(1, operations.size()), name); + } + } + + protected GuardedInvocationComponent getGuardedInvocationComponent(final ComponentLinkRequest req) + throws Exception { + final Operation op = req.operations.get(0); + if (op instanceof StandardOperation) { + switch((StandardOperation)op) { + case GET_PROPERTY: return getPropertyGetter(req.popOperations()); + case SET_PROPERTY: return getPropertySetter(req.popOperations()); + case GET_METHOD: return getMethodGetter(req.popOperations()); + default: } - operations = pop(operations); } return null; } - protected GuardedInvocationComponent getGuardedInvocationComponent( - final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, - final List<Operation> operations, final Object name) - throws Exception { - if(operations.isEmpty()) { + GuardedInvocationComponent getNextComponent(final ComponentLinkRequest req) throws Exception { + if (req.operations.isEmpty()) { + return createNoSuchMemberHandler(req.missingMemberHandlerFactory, + req.linkRequest, req.linkerServices); + } + final GuardedInvocationComponent gic = getGuardedInvocationComponent(req); + if (gic != null) { + return gic; + } + return getNextComponent(req.popOperations()); + } + + private GuardedInvocationComponent createNoSuchMemberHandler( + final MissingMemberHandlerFactory missingMemberHandlerFactory, + final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception { + if (missingMemberHandlerFactory == null) { return null; } - final Operation op = operations.get(0); - // Either GET_PROPERTY:name(this) or GET_PROPERTY(this, name) - if(op == StandardOperation.GET_PROPERTY) { - return getPropertyGetter(callSiteDescriptor, linkerServices, pop(operations), name); + final MethodHandle handler = missingMemberHandlerFactory.createMissingMemberHandler(linkRequest, linkerServices); + if (handler == null) { + return null; } - // Either SET_PROPERTY:name(this, value) or SET_PROPERTY(this, name, value) - if(op == StandardOperation.SET_PROPERTY) { - return getPropertySetter(callSiteDescriptor, linkerServices, pop(operations), name); - } - // Either GET_METHOD:name(this), or GET_METHOD(this, name) - if(op == StandardOperation.GET_METHOD) { - return getMethodGetter(callSiteDescriptor, linkerServices, pop(operations), name); - } - return null; + final MethodType type = linkRequest.getCallSiteDescriptor().getMethodType(); + // The returned handler is allowed to differ in return type. + assert handler.type().changeReturnType(type.returnType()).equals(type); + return getClassGuardedInvocationComponent(handler, type); } static final <T> List<T> pop(final List<T> l) { @@ -483,16 +549,15 @@ private static final MethodHandle CONSTANT_NULL_DROP_METHOD_HANDLE = MethodHandles.dropArguments( MethodHandles.constant(Object.class, null), 0, MethodHandle.class); - private GuardedInvocationComponent getPropertySetter(final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, final List<Operation> operations, final Object name) throws Exception { - if (name == null) { - return getUnnamedPropertySetter(callSiteDescriptor, linkerServices, operations); + private GuardedInvocationComponent getPropertySetter(final ComponentLinkRequest req) throws Exception { + if (req.name == null) { + return getUnnamedPropertySetter(req); } - return getNamedPropertySetter(callSiteDescriptor, linkerServices, operations, name); + return getNamedPropertySetter(req); } - private GuardedInvocationComponent getUnnamedPropertySetter(final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, final List<Operation> operations) throws Exception { + private GuardedInvocationComponent getUnnamedPropertySetter(final ComponentLinkRequest req) throws Exception { + final CallSiteDescriptor callSiteDescriptor = req.getDescriptor(); // Must have three arguments: target object, property name, and property value. assertParameterCount(callSiteDescriptor, 3); @@ -501,6 +566,7 @@ // invoked, we'll conservatively presume Object return type. The one exception is void return. final MethodType origType = callSiteDescriptor.getMethodType(); final MethodType type = origType.returnType() == void.class ? origType : origType.changeReturnType(Object.class); + final LinkerServices linkerServices = req.linkerServices; // What's below is basically: // foldArguments(guardWithTest(isNotNull, invoke, null|nextComponent.invocation), @@ -527,11 +593,10 @@ // Handle to invoke the setter, dropping unnecessary fold arguments R(MethodHandle, O, N, V) final MethodHandle invokeHandleFolded = MethodHandles.dropArguments(invokeHandle, 2, type.parameterType( 1)); - final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor, - linkerServices, operations, null); + final GuardedInvocationComponent nextComponent = getNextComponent(req); final MethodHandle fallbackFolded; - if(nextComponent == null) { + if (nextComponent == null) { // Object(MethodHandle)->Object(MethodHandle, O, N, V); returns constant null fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_METHOD_HANDLE, 1, type.parameterList()).asType(type.insertParameterTypes(0, MethodHandle.class)); @@ -551,19 +616,19 @@ return nextComponent.compose(compositeSetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS); } - private GuardedInvocationComponent getNamedPropertySetter(final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, final List<Operation> operations, final Object name) throws Exception { + private GuardedInvocationComponent getNamedPropertySetter(final ComponentLinkRequest req) throws Exception { + final CallSiteDescriptor callSiteDescriptor = req.getDescriptor(); // Must have two arguments: target object and property value assertParameterCount(callSiteDescriptor, 2); - final GuardedInvocation gi = createGuardedDynamicMethodInvocation(callSiteDescriptor, linkerServices, - name.toString(), propertySetters); + final GuardedInvocation gi = createGuardedDynamicMethodInvocation(callSiteDescriptor, req.linkerServices, + req.name.toString(), propertySetters); // If we have a property setter with this name, this composite operation will always stop here if(gi != null) { return new GuardedInvocationComponent(gi, clazz, ValidationType.EXACT_CLASS); } // If we don't have a property setter with this name, always fall back to the next operation in the // composite (if any) - return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, operations, name); + return getNextComponent(req); } private static final Lookup privateLookup = new Lookup(MethodHandles.lookup()); @@ -576,20 +641,18 @@ "getTarget", MethodType.methodType(MethodHandle.class, CallSiteDescriptor.class, LinkerServices.class)); private static final MethodHandle GETTER_INVOKER = MethodHandles.invoker(MethodType.methodType(Object.class, Object.class)); - private GuardedInvocationComponent getPropertyGetter(final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, final List<Operation> ops, final Object name) throws Exception { - if (name == null) { - return getUnnamedPropertyGetter(callSiteDescriptor, linkerServices, ops); + private GuardedInvocationComponent getPropertyGetter(final ComponentLinkRequest req) throws Exception { + if (req.name == null) { + return getUnnamedPropertyGetter(req); } - - return getNamedPropertyGetter(callSiteDescriptor, linkerServices, ops, name); + return getNamedPropertyGetter(req); } - private GuardedInvocationComponent getUnnamedPropertyGetter(final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, final List<Operation> ops) throws Exception { + private GuardedInvocationComponent getUnnamedPropertyGetter(final ComponentLinkRequest req) throws Exception { // Since we can't know what kind of a getter we'll get back on different invocations, we'll just // conservatively presume Object. Note we can't just coerce to a narrower call site type as the linking // runtime might not allow coercing at that call site. + final CallSiteDescriptor callSiteDescriptor = req.getDescriptor(); final MethodType type = callSiteDescriptor.getMethodType().changeReturnType(Object.class); // Must have exactly two arguments: receiver and name assertParameterCount(callSiteDescriptor, 2); @@ -600,6 +663,7 @@ // AnnotatedDynamicMethod; if it is non-null, invoke its "handle" field, otherwise either return null, // or delegate to next component's invocation. + final LinkerServices linkerServices = req.linkerServices; final MethodHandle typedGetter = linkerServices.asType(getPropertyGetterHandle, type.changeReturnType( AnnotatedDynamicMethod.class)); final MethodHandle callSiteBoundMethodGetter = MethodHandles.insertArguments( @@ -613,8 +677,7 @@ // Object(AnnotatedDynamicMethod, T0)->Object(AnnotatedDynamicMethod, T0, T1) final MethodHandle invokeHandleFolded = MethodHandles.dropArguments(invokeHandleTyped, 2, type.parameterType(1)); - final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor, - linkerServices, ops, null); + final GuardedInvocationComponent nextComponent = getNextComponent(req); final MethodHandle fallbackFolded; if(nextComponent == null) { @@ -639,17 +702,17 @@ return nextComponent.compose(compositeGetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS); } - private GuardedInvocationComponent getNamedPropertyGetter(final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, final List<Operation> ops, final Object name) throws Exception { + private GuardedInvocationComponent getNamedPropertyGetter(final ComponentLinkRequest req) throws Exception { + final CallSiteDescriptor callSiteDescriptor = req.getDescriptor(); // Must have exactly one argument: receiver assertParameterCount(callSiteDescriptor, 1); // Fixed name - final AnnotatedDynamicMethod annGetter = propertyGetters.get(name.toString()); + final AnnotatedDynamicMethod annGetter = propertyGetters.get(req.name.toString()); if(annGetter == null) { // We have no such property, always delegate to the next component operation - return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, ops, name); + return getNextComponent(req); } - final MethodHandle getter = annGetter.getInvocation(callSiteDescriptor, linkerServices); + final MethodHandle getter = annGetter.getInvocation(req); // NOTE: since property getters (not field getters!) are no-arg, we don't have to worry about them being // overloaded in a subclass. Therefore, we can discover the most abstract superclass that has the // method, and use that as the guard with Guards.isInstance() for a more stably linked call site. If @@ -686,28 +749,27 @@ MethodType.methodType(boolean.class, Object.class)); private static final MethodHandle OBJECT_IDENTITY = MethodHandles.identity(Object.class); - private GuardedInvocationComponent getMethodGetter(final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, final List<Operation> ops, final Object name) throws Exception { + private GuardedInvocationComponent getMethodGetter(final ComponentLinkRequest req) throws Exception { + if (req.name == null) { + return getUnnamedMethodGetter(req); + } + return getNamedMethodGetter(req); + } + + private static MethodType getMethodGetterType(final ComponentLinkRequest req) { // The created method handle will always return a DynamicMethod (or null), but since we don't want that type to // be visible outside of this linker, declare it to return Object. - final MethodType type = callSiteDescriptor.getMethodType().changeReturnType(Object.class); - if (name == null) { - return getUnnamedMethodGetter(callSiteDescriptor, linkerServices, ops, type); - } - - return getNamedMethodGetter(callSiteDescriptor, linkerServices, ops, name, type); + return req.getDescriptor().getMethodType().changeReturnType(Object.class); } - private GuardedInvocationComponent getUnnamedMethodGetter(final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, final List<Operation> ops, final MethodType type) throws Exception { + private GuardedInvocationComponent getUnnamedMethodGetter(final ComponentLinkRequest req) throws Exception { // Must have exactly two arguments: receiver and name - assertParameterCount(callSiteDescriptor, 2); - final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor, - linkerServices, ops, null); - if(nextComponent == null || !InternalTypeUtilities.areAssignable(DynamicMethod.class, - nextComponent.getGuardedInvocation().getInvocation().type().returnType())) { - // No next component operation, or it can never produce a dynamic method; just return a component - // for this operation. + assertParameterCount(req.getDescriptor(), 2); + final GuardedInvocationComponent nextComponent = getNextComponent(req); + final LinkerServices linkerServices = req.linkerServices; + final MethodType type = getMethodGetterType(req); + if(nextComponent == null) { + // No next component operation; just return a component for this operation. return getClassGuardedInvocationComponent(linkerServices.asType(getDynamicMethod, type), type); } @@ -728,25 +790,28 @@ final MethodHandle nextCombinedInvocation = MethodHandles.dropArguments(nextComponentInvocation, 0, Object.class); // Assemble it all into a fold(guard(isNotNull, identity, nextInvocation), get) + // Note that nextCombinedInvocation needs to have its return type changed to Object final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest( - IS_DYNAMIC_METHOD, returnMethodHandle, nextCombinedInvocation), typedGetter); + IS_DYNAMIC_METHOD, returnMethodHandle, + nextCombinedInvocation.asType(nextCombinedInvocation.type().changeReturnType(Object.class))), + typedGetter); return nextComponent.compose(compositeGetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS); } - private GuardedInvocationComponent getNamedMethodGetter(final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, final List<Operation> ops, final Object name, final MethodType type) + private GuardedInvocationComponent getNamedMethodGetter(final ComponentLinkRequest req) throws Exception { // Must have exactly one argument: receiver - assertParameterCount(callSiteDescriptor, 1); - final DynamicMethod method = getDynamicMethod(name.toString()); + assertParameterCount(req.getDescriptor(), 1); + final DynamicMethod method = getDynamicMethod(req.name.toString()); if(method == null) { // We have no such method, always delegate to the next component - return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, ops, name); + return getNextComponent(req); } // No delegation to the next component of the composite operation; if we have a method with that name, // we'll always return it at this point. - return getClassGuardedInvocationComponent(linkerServices.asType(MethodHandles.dropArguments( + final MethodType type = getMethodGetterType(req); + return getClassGuardedInvocationComponent(req.linkerServices.asType(MethodHandles.dropArguments( MethodHandles.constant(Object.class, method), 0, type.parameterType(0)), type), type); } @@ -876,8 +941,8 @@ this.validationType = validationType; } - MethodHandle getInvocation(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) { - return method.getInvocation(callSiteDescriptor, linkerServices); + MethodHandle getInvocation(final ComponentLinkRequest req) { + return method.getInvocation(req.getDescriptor(), req.linkerServices); } @SuppressWarnings("unused")
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeanLinker.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeanLinker.java Thu Jan 14 12:03:53 2016 -0800 @@ -88,6 +88,7 @@ import java.lang.invoke.MethodType; import java.lang.reflect.Array; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; import jdk.dynalink.CallSiteDescriptor; @@ -129,25 +130,21 @@ } @Override - protected GuardedInvocationComponent getGuardedInvocationComponent(final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, final List<Operation> operations, final Object name) throws Exception { - final GuardedInvocationComponent superGic = super.getGuardedInvocationComponent(callSiteDescriptor, - linkerServices, operations, name); + protected GuardedInvocationComponent getGuardedInvocationComponent(final ComponentLinkRequest req) throws Exception { + final GuardedInvocationComponent superGic = super.getGuardedInvocationComponent(req); if(superGic != null) { return superGic; } - if(operations.isEmpty()) { - return null; - } - final Operation op = operations.get(0); - if(op == StandardOperation.GET_ELEMENT) { - return getElementGetter(callSiteDescriptor, linkerServices, pop(operations), name); - } - if(op == StandardOperation.SET_ELEMENT) { - return getElementSetter(callSiteDescriptor, linkerServices, pop(operations), name); - } - if(op == StandardOperation.GET_LENGTH) { - return getLengthGetter(callSiteDescriptor); + if (!req.operations.isEmpty()) { + final Operation op = req.operations.get(0); + if (op instanceof StandardOperation) { + switch ((StandardOperation)op) { + case GET_ELEMENT: return getElementGetter(req.popOperations()); + case SET_ELEMENT: return getElementSetter(req.popOperations()); + case GET_LENGTH: return getLengthGetter(req.getDescriptor()); + default: + } + } } return null; } @@ -166,16 +163,31 @@ private static final MethodHandle LIST_GUARD = Guards.getInstanceOfGuard(List.class); private static final MethodHandle MAP_GUARD = Guards.getInstanceOfGuard(Map.class); + private static final MethodHandle NULL_GETTER_1; + private static final MethodHandle NULL_GETTER_2; + static { + final MethodHandle constantNull = MethodHandles.constant(Object.class, null); + NULL_GETTER_1 = dropObjectArguments(constantNull, 1); + NULL_GETTER_2 = dropObjectArguments(constantNull, 2); + } + + private static MethodHandle dropObjectArguments(final MethodHandle m, final int n) { + return MethodHandles.dropArguments(m, 0, Collections.nCopies(n, Object.class)); + } + private enum CollectionType { ARRAY, LIST, MAP }; - private GuardedInvocationComponent getElementGetter(final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, final List<Operation> operations, final Object name) throws Exception { + private GuardedInvocationComponent getElementGetter(final ComponentLinkRequest req) throws Exception { + final CallSiteDescriptor callSiteDescriptor = req.getDescriptor(); + final Object name = req.name; + final boolean isFixedKey = name != null; + assertParameterCount(callSiteDescriptor, isFixedKey ? 1 : 2); + final LinkerServices linkerServices = req.linkerServices; final MethodType callSiteType = callSiteDescriptor.getMethodType(); final Class<?> declaredType = callSiteType.parameterType(0); - final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor, - linkerServices, operations, name); + final GuardedInvocationComponent nextComponent = getNextComponent(req); // If declared type of receiver at the call site is already an array, a list or map, bind without guard. Thing // is, it'd be quite stupid of a call site creator to go though invokedynamic when it knows in advance they're @@ -211,12 +223,14 @@ // Convert the key to a number if we're working with a list or array final Object typedName; - if(collectionType != CollectionType.MAP && name != null) { - typedName = convertKeyToInteger(name, linkerServices); - if(typedName == null) { - // key is not numeric, it can never succeed + if (collectionType != CollectionType.MAP && isFixedKey) { + final Integer integer = convertKeyToInteger(name, linkerServices); + if (integer == null || integer.intValue() < 0) { + // key is not a non-negative integer, it can never address an + // array or list element return nextComponent; } + typedName = integer; } else { typedName = name; } @@ -225,30 +239,33 @@ final Binder binder = new Binder(linkerServices, callSiteType, typedName); final MethodHandle invocation = gi.getInvocation(); - if(nextComponent == null) { - return gic.replaceInvocation(binder.bind(invocation)); - } - final MethodHandle checkGuard; switch(collectionType) { case LIST: - checkGuard = convertArgToInt(RANGE_CHECK_LIST, linkerServices, callSiteDescriptor); + checkGuard = convertArgToNumber(RANGE_CHECK_LIST, linkerServices, callSiteDescriptor); break; case MAP: - // TODO: A more complex solution could be devised for maps, one where we do a get() first, and fold it - // into a GWT that tests if it returned null, and if it did, do another GWT with containsKey() - // that returns constant null (on true), or falls back to next component (on false) checkGuard = linkerServices.filterInternalObjects(CONTAINS_MAP); break; case ARRAY: - checkGuard = convertArgToInt(RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor); + checkGuard = convertArgToNumber(RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor); break; default: throw new AssertionError(); } + + // If there's no next component, produce a fixed null-returning one + final GuardedInvocationComponent finalNextComponent; + if (nextComponent != null) { + finalNextComponent = nextComponent; + } else { + final MethodHandle nullGetterHandle = isFixedKey ? NULL_GETTER_1 : NULL_GETTER_2; + finalNextComponent = createGuardedInvocationComponentAsType(nullGetterHandle, callSiteType, linkerServices); + } + final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation), - nextComponent.getGuardedInvocation().getInvocation()); - return nextComponent.compose(matchedInvocations.guardWithTest(binder.bindTest(checkGuard)), gi.getGuard(), + finalNextComponent.getGuardedInvocation().getInvocation()); + return finalNextComponent.compose(matchedInvocations.guardWithTest(binder.bindTest(checkGuard)), gi.getGuard(), gic.getValidatorClass(), gic.getValidationType()); } @@ -257,6 +274,11 @@ return new GuardedInvocationComponent(linkerServices.filterInternalObjects(invocation)); } + private static GuardedInvocationComponent createGuardedInvocationComponentAsType( + final MethodHandle invocation, final MethodType fromType, final LinkerServices linkerServices) { + return new GuardedInvocationComponent(linkerServices.asType(invocation, fromType)); + } + private static GuardedInvocationComponent createInternalFilteredGuardedInvocationComponent( final MethodHandle invocation, final MethodHandle guard, final Class<?> validatorClass, final ValidationType validationType, final LinkerServices linkerServices) { @@ -310,7 +332,7 @@ return intIndex; } - private static MethodHandle convertArgToInt(final MethodHandle mh, final LinkerServices ls, final CallSiteDescriptor desc) { + private static MethodHandle convertArgToNumber(final MethodHandle mh, final LinkerServices ls, final CallSiteDescriptor desc) { final Class<?> sourceType = desc.getMethodType().parameterType(1); if(TypeUtilities.isMethodInvocationConvertible(sourceType, Number.class)) { return mh; @@ -366,14 +388,10 @@ } final Number n = (Number)index; final int intIndex = n.intValue(); - final double doubleValue = n.doubleValue(); - if(intIndex != doubleValue && !Double.isInfinite(doubleValue)) { // let infinite trigger IOOBE + if (intIndex != n.doubleValue()) { return false; } - if(0 <= intIndex && intIndex < Array.getLength(array)) { - return true; - } - throw new ArrayIndexOutOfBoundsException("Array index out of range: " + n); + return 0 <= intIndex && intIndex < Array.getLength(array); } @SuppressWarnings("unused") @@ -383,14 +401,14 @@ } final Number n = (Number)index; final int intIndex = n.intValue(); - final double doubleValue = n.doubleValue(); - if(intIndex != doubleValue && !Double.isInfinite(doubleValue)) { // let infinite trigger IOOBE + if (intIndex != n.doubleValue()) { return false; } - if(0 <= intIndex && intIndex < list.size()) { - return true; - } - throw new IndexOutOfBoundsException("Index: " + n + ", Size: " + list.size()); + return 0 <= intIndex && intIndex < list.size(); + } + + @SuppressWarnings("unused") + private static void noOpSetter() { } private static final MethodHandle SET_LIST_ELEMENT = Lookup.PUBLIC.findVirtual(List.class, "set", @@ -399,8 +417,20 @@ private static final MethodHandle PUT_MAP_ELEMENT = Lookup.PUBLIC.findVirtual(Map.class, "put", MethodType.methodType(Object.class, Object.class, Object.class)); - private GuardedInvocationComponent getElementSetter(final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, final List<Operation> operations, final Object name) throws Exception { + private static final MethodHandle NO_OP_SETTER_2; + private static final MethodHandle NO_OP_SETTER_3; + static { + final MethodHandle noOpSetter = Lookup.findOwnStatic(MethodHandles.lookup(), "noOpSetter", void.class); + NO_OP_SETTER_2 = dropObjectArguments(noOpSetter, 2); + NO_OP_SETTER_3 = dropObjectArguments(noOpSetter, 3); + } + + private GuardedInvocationComponent getElementSetter(final ComponentLinkRequest req) throws Exception { + final CallSiteDescriptor callSiteDescriptor = req.getDescriptor(); + final Object name = req.name; + final boolean isFixedKey = name != null; + assertParameterCount(callSiteDescriptor, isFixedKey ? 2 : 3); + final LinkerServices linkerServices = req.linkerServices; final MethodType callSiteType = callSiteDescriptor.getMethodType(); final Class<?> declaredType = callSiteType.parameterType(0); @@ -441,20 +471,21 @@ // In contrast to, say, getElementGetter, we only compute the nextComponent if the target object is not a map, // as maps will always succeed in setting the element and will never need to fall back to the next component // operation. - final GuardedInvocationComponent nextComponent = collectionType == CollectionType.MAP ? null : getGuardedInvocationComponent( - callSiteDescriptor, linkerServices, operations, name); + final GuardedInvocationComponent nextComponent = collectionType == CollectionType.MAP ? null : getNextComponent(req); if(gic == null) { return nextComponent; } // Convert the key to a number if we're working with a list or array final Object typedName; - if(collectionType != CollectionType.MAP && name != null) { - typedName = convertKeyToInteger(name, linkerServices); - if(typedName == null) { - // key is not numeric, it can never succeed + if (collectionType != CollectionType.MAP && isFixedKey) { + final Integer integer = convertKeyToInteger(name, linkerServices); + if (integer == null || integer.intValue() < 0) { + // key is not a non-negative integer, it can never address an + // array or list element return nextComponent; } + typedName = integer; } else { typedName = name; } @@ -463,16 +494,27 @@ final Binder binder = new Binder(linkerServices, callSiteType, typedName); final MethodHandle invocation = gi.getInvocation(); - if(nextComponent == null) { + if (collectionType == CollectionType.MAP) { + assert nextComponent == null; return gic.replaceInvocation(binder.bind(invocation)); } assert collectionType == CollectionType.LIST || collectionType == CollectionType.ARRAY; - final MethodHandle checkGuard = convertArgToInt(collectionType == CollectionType.LIST ? RANGE_CHECK_LIST : + final MethodHandle checkGuard = convertArgToNumber(collectionType == CollectionType.LIST ? RANGE_CHECK_LIST : RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor); + + // If there's no next component, produce a no-op one. + final GuardedInvocationComponent finalNextComponent; + if (nextComponent != null) { + finalNextComponent = nextComponent; + } else { + final MethodHandle noOpSetterHandle = isFixedKey ? NO_OP_SETTER_2 : NO_OP_SETTER_3; + finalNextComponent = createGuardedInvocationComponentAsType(noOpSetterHandle, callSiteType, linkerServices); + } + final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation), - nextComponent.getGuardedInvocation().getInvocation()); - return nextComponent.compose(matchedInvocations.guardWithTest(binder.bindTest(checkGuard)), gi.getGuard(), + finalNextComponent.getGuardedInvocation().getInvocation()); + return finalNextComponent.compose(matchedInvocations.guardWithTest(binder.bindTest(checkGuard)), gi.getGuard(), gic.getValidatorClass(), gic.getValidationType()); }
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeansLinker.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeansLinker.java Thu Jan 14 12:03:53 2016 -0800 @@ -146,7 +146,11 @@ * are otherwise public and link requests have call site descriptors carrying * full-strength {@link Lookup} objects and not weakened lookups or the public * lookup.</p> - * <p>The class also exposes various static methods for discovery of available + * <p><strong>The behavior for handling missing members</strong> can be + * customized by passing a {@link MissingMemberHandlerFactory} to the + * {@link BeansLinker#BeansLinker(MissingMemberHandlerFactory) constructor}. + * </p> + * <p>The class also exposes various methods for discovery of available * property and method names on classes and class instances, as well as access * to per-class linkers using the {@link #getLinkerForClass(Class)} * method.</p> @@ -164,10 +168,27 @@ } }; + private final MissingMemberHandlerFactory missingMemberHandlerFactory; + /** - * Creates a new beans linker. + * Creates a new beans linker. Equivalent to + * {@link BeansLinker#BeansLinker(MissingMemberHandlerFactory)} with + * {@code null} passed as the missing member handler factory, resulting in + * the default behavior for linking and evaluating missing members. */ public BeansLinker() { + this(null); + } + + /** + * Creates a new beans linker with the specified factory for creating + * missing member handlers. The passed factory can be null if the default + * behavior is adequate. See {@link MissingMemberHandlerFactory} for details. + * @param missingMemberHandlerFactory a factory for creating handlers for + * operations on missing members. + */ + public BeansLinker(final MissingMemberHandlerFactory missingMemberHandlerFactory) { + this.missingMemberHandlerFactory = missingMemberHandlerFactory; } /** @@ -178,7 +199,37 @@ * @param clazz the class * @return a bean linker for that class */ - public static TypeBasedGuardingDynamicLinker getLinkerForClass(final Class<?> clazz) { + public TypeBasedGuardingDynamicLinker getLinkerForClass(final Class<?> clazz) { + final TypeBasedGuardingDynamicLinker staticLinker = getStaticLinkerForClass(clazz); + if (missingMemberHandlerFactory == null) { + return staticLinker; + } + return new NoSuchMemberHandlerBindingLinker(staticLinker, missingMemberHandlerFactory); + } + + private static class NoSuchMemberHandlerBindingLinker implements TypeBasedGuardingDynamicLinker { + private final TypeBasedGuardingDynamicLinker linker; + private final MissingMemberHandlerFactory missingMemberHandlerFactory; + + NoSuchMemberHandlerBindingLinker(final TypeBasedGuardingDynamicLinker linker, final MissingMemberHandlerFactory missingMemberHandlerFactory) { + this.linker = linker; + this.missingMemberHandlerFactory = missingMemberHandlerFactory; + } + + @Override + public boolean canLinkType(final Class<?> type) { + return linker.canLinkType(type); + } + + @Override + public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception { + return linker.getGuardedInvocation(linkRequest, + LinkerServicesWithMissingMemberHandlerFactory.get( + linkerServices, missingMemberHandlerFactory)); + } + } + + static TypeBasedGuardingDynamicLinker getStaticLinkerForClass(final Class<?> clazz) { return linkers.get(clazz); } @@ -234,7 +285,7 @@ * @return a set of names of all readable instance properties of a class. */ public static Set<String> getReadableInstancePropertyNames(final Class<?> clazz) { - final TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz); + final TypeBasedGuardingDynamicLinker linker = getStaticLinkerForClass(clazz); if(linker instanceof BeanLinker) { return ((BeanLinker)linker).getReadablePropertyNames(); } @@ -247,7 +298,7 @@ * @return a set of names of all writable instance properties of a class. */ public static Set<String> getWritableInstancePropertyNames(final Class<?> clazz) { - final TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz); + final TypeBasedGuardingDynamicLinker linker = getStaticLinkerForClass(clazz); if(linker instanceof BeanLinker) { return ((BeanLinker)linker).getWritablePropertyNames(); } @@ -260,7 +311,7 @@ * @return a set of names of all instance methods of a class. */ public static Set<String> getInstanceMethodNames(final Class<?> clazz) { - final TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz); + final TypeBasedGuardingDynamicLinker linker = getStaticLinkerForClass(clazz); if(linker instanceof BeanLinker) { return ((BeanLinker)linker).getMethodNames(); } @@ -302,6 +353,8 @@ // Can't operate on null return null; } - return getLinkerForClass(receiver.getClass()).getGuardedInvocation(request, linkerServices); + return getLinkerForClass(receiver.getClass()).getGuardedInvocation(request, + LinkerServicesWithMissingMemberHandlerFactory.get(linkerServices, + missingMemberHandlerFactory)); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/LinkerServicesWithMissingMemberHandlerFactory.java Thu Jan 14 12:03:53 2016 -0800 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2015, 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.dynalink.beans; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; +import jdk.dynalink.linker.ConversionComparator.Comparison; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; + +final class LinkerServicesWithMissingMemberHandlerFactory implements LinkerServices { + final LinkerServices linkerServices; + final MissingMemberHandlerFactory missingMemberHandlerFactory; + + static LinkerServices get(final LinkerServices linkerServices, final MissingMemberHandlerFactory missingMemberHandlerFactory) { + if (missingMemberHandlerFactory == null) { + return linkerServices; + } + return new LinkerServicesWithMissingMemberHandlerFactory(linkerServices, missingMemberHandlerFactory); + } + + private LinkerServicesWithMissingMemberHandlerFactory(final LinkerServices linkerServices, final MissingMemberHandlerFactory missingMemberHandlerFactory) { + this.linkerServices = linkerServices; + this.missingMemberHandlerFactory = missingMemberHandlerFactory; + } + + @Override + public MethodHandle asType(final MethodHandle handle, final MethodType fromType) { + return linkerServices.asType(handle, fromType); + } + + @Override + public MethodHandle getTypeConverter(final Class<?> sourceType, final Class<?> targetType) { + return linkerServices.getTypeConverter(sourceType, targetType); + } + + @Override + public boolean canConvert(final Class<?> from, final Class<?> to) { + return linkerServices.canConvert(from, to); + } + + @Override + public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest) throws Exception { + return linkerServices.getGuardedInvocation(linkRequest); + } + + @Override + public Comparison compareConversion(final Class<?> sourceType, final Class<?> targetType1, final Class<?> targetType2) { + return linkerServices.compareConversion(sourceType, targetType1, targetType2); + } + + @Override + public MethodHandle filterInternalObjects(final MethodHandle target) { + return linkerServices.filterInternalObjects(target); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/MissingMemberHandlerFactory.java Thu Jan 14 12:03:53 2016 -0800 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2015, 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.dynalink.beans; + +import java.lang.invoke.MethodHandle; +import jdk.dynalink.DynamicLinkerFactory; +import jdk.dynalink.NamedOperation; +import jdk.dynalink.NoSuchDynamicMethodException; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; + +/** + * A factory for creating method handles for linking missing member behavior + * in {@link BeansLinker}. BeansLinker links these method handles into guarded + * invocations for link requests specifying {@code GET_*} and {@code SET_*} + * {@link StandardOperation}s when it is either certain or possible that the + * requested member (property, method, or element) is missing. They will be + * linked both for {@link NamedOperation named} and unnamed operations. The + * implementer must ensure that the parameter types of the returned method + * handle match the parameter types of the call site described in the link + * request. The return types can differ, though, to allow + * {@link DynamicLinkerFactory#setPrelinkTransformer(jdk.dynalink.linker.GuardedInvocationTransformer)} + * late return type transformations}. It is allowed to return {@code null} for a + * method handle if the default behavior is sufficient. + * <h2>Default missing member behavior</h2> + * When a {@link BeansLinker} is configured without a missing member handler + * factory, or the factory returns {@code null} for a particular handler + * creation invocation, the default behavior is used. The default behavior is to + * return {@code null} from + * {@link BeansLinker#getGuardedInvocation(LinkRequest, LinkerServices)} when it + * can be determined at link time that the linked operation will never address + * an existing member. This lets the {@code DynamicLinker} attempt the next + * linker if there is one, or ultimately fail the link request with + * {@link NoSuchDynamicMethodException}. For other cases (typically all unnamed + * member operations as well as most named operations on collection elements) + * {@code BeansLinker} will produce a conditional linkage that will return + * {@code null} when invoked at runtime with a name that does not match any + * member for getters and silently ignore the passed values for setters. + * <h2>Implementing exception-throwing behavior</h2> + * Note that if the language-specific behavior for an operation on a missing + * member is to throw an exception then the factory should produce a method + * handle that throws the exception when invoked, and must not throw an + * exception itself, as the linkage for the missing member is often conditional. + * + * @see BeansLinker#BeansLinker(MissingMemberHandlerFactory) + */ +@FunctionalInterface +public interface MissingMemberHandlerFactory { + /** + * Returns a method handle suitable for implementing missing member behavior + * for a particular link request. See the class description for details. + * @param linkRequest the current link request + * @param linkerServices the current link services + * @return a method handle that can be invoked if the property, element, or + * method being addressed by an operation is missing. The return value can + * be null. + * @throws Exception if the operation fails for any reason. Please observe + * the class documentation notes for implementing exception-throwing + * missing member behavior. + */ + public MethodHandle createMissingMemberHandler(LinkRequest linkRequest, LinkerServices linkerServices) throws Exception; +}
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClassLinker.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClassLinker.java Thu Jan 14 12:03:53 2016 -0800 @@ -91,6 +91,7 @@ import java.util.Set; import jdk.dynalink.CallSiteDescriptor; import jdk.dynalink.NamedOperation; +import jdk.dynalink.Operation; import jdk.dynalink.StandardOperation; import jdk.dynalink.beans.GuardedInvocationComponent.ValidationType; import jdk.dynalink.linker.GuardedInvocation; @@ -162,6 +163,27 @@ } @Override + protected GuardedInvocationComponent getGuardedInvocationComponent(final ComponentLinkRequest req) throws Exception { + final GuardedInvocationComponent superGic = super.getGuardedInvocationComponent(req); + if (superGic != null) { + return superGic; + } + if (!req.operations.isEmpty()) { + final Operation op = req.operations.get(0); + if (op instanceof StandardOperation) { + switch ((StandardOperation)op) { + case GET_ELEMENT: + case SET_ELEMENT: + // StaticClass doesn't behave as a collection + return getNextComponent(req.popOperations()); + default: + } + } + } + return null; + } + + @Override SingleDynamicMethod getConstructorMethod(final String signature) { return constructor != null? constructor.getMethodForExactParamTypes(signature) : null; }
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocation.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocation.java Thu Jan 14 12:03:53 2016 -0800 @@ -202,6 +202,9 @@ this.invocation = Objects.requireNonNull(invocation); this.guard = guard; this.switchPoints = switchPoint == null ? null : new SwitchPoint[] { switchPoint }; + if (exception != null && !Throwable.class.isAssignableFrom(exception)) { + throw new IllegalArgumentException(exception.getName() + " is not assignable from Throwable"); + } this.exception = exception; } @@ -228,6 +231,9 @@ this.invocation = Objects.requireNonNull(invocation); this.guard = guard; this.switchPoints = switchPoints == null ? null : switchPoints.clone(); + if (exception != null && !Throwable.class.isAssignableFrom(exception)) { + throw new IllegalArgumentException(exception.getName() + " is not assignable from Throwable"); + } this.exception = exception; }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Thu Jan 14 12:03:53 2016 -0800 @@ -1133,6 +1133,8 @@ return NativeNumber.lookupPrimitive(request, self); } else if (self instanceof Boolean) { return NativeBoolean.lookupPrimitive(request, self); + } else if (self instanceof Symbol) { + return NativeSymbol.lookupPrimitive(request, self); } throw new IllegalArgumentException("Unsupported primitive: " + self); }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java Thu Jan 14 12:03:53 2016 -0800 @@ -284,8 +284,8 @@ // Step 3c and 3d - get new length and convert to long final long newLen = NativeArray.validLength(newLenDesc.getValue()); - // Step 3e - newLenDesc.setValue(newLen); + // Step 3e - note that we need to convert to int or double as long is not considered a JS number type anymore + newLenDesc.setValue(JSType.isRepresentableAsInt(newLen) ? Integer.valueOf((int) newLen) : Double.valueOf((double) newLen)); // Step 3f // increasing array length - just need to set new length value (and attributes if any) and return @@ -918,21 +918,6 @@ * @throws ClassCastException if array is empty, facilitating Undefined return value */ @SpecializedFunction(name="pop", linkLogic=PopLinkLogic.class) - public static long popLong(final Object self) { - //must be non empty Int or LongArrayData - return getContinuousNonEmptyArrayDataCCE(self, IntOrLongElements.class).fastPopLong(); - } - - /** - * Specialization of pop for ContinuousArrayData - * - * Primitive specialization, {@link LinkLogic} - * - * @param self self reference - * @return element popped - * @throws ClassCastException if array is empty, facilitating Undefined return value - */ - @SpecializedFunction(name="pop", linkLogic=PopLinkLogic.class) public static double popDouble(final Object self) { //must be non empty int long or double array data return getContinuousNonEmptyArrayDataCCE(self, NumericElements.class).fastPopDouble(); @@ -997,7 +982,7 @@ * @return array length after push */ @SpecializedFunction(linkLogic=PushLinkLogic.class) - public static long push(final Object self, final int arg) { + public static double push(final Object self, final int arg) { return getContinuousArrayDataCCE(self, Integer.class).fastPush(arg); } @@ -1011,7 +996,7 @@ * @return array length after push */ @SpecializedFunction(linkLogic=PushLinkLogic.class) - public static long push(final Object self, final long arg) { + public static double push(final Object self, final long arg) { return getContinuousArrayDataCCE(self, Long.class).fastPush(arg); } @@ -1025,7 +1010,7 @@ * @return array length after push */ @SpecializedFunction(linkLogic=PushLinkLogic.class) - public static long push(final Object self, final double arg) { + public static double push(final Object self, final double arg) { return getContinuousArrayDataCCE(self, Double.class).fastPush(arg); } @@ -1039,7 +1024,7 @@ * @return array length after push */ @SpecializedFunction(name="push", linkLogic=PushLinkLogic.class) - public static long pushObject(final Object self, final Object arg) { + public static double pushObject(final Object self, final Object arg) { return getContinuousArrayDataCCE(self, Object.class).fastPush(arg); } @@ -1081,7 +1066,7 @@ * @return array after pushes */ @SpecializedFunction - public static long push(final Object self, final Object arg) { + public static double push(final Object self, final Object arg) { try { final ScriptObject sobj = (ScriptObject)self; final ArrayData arrayData = sobj.getArray(); @@ -1498,7 +1483,7 @@ * @return index of element, or -1 if not found */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) - public static long indexOf(final Object self, final Object searchElement, final Object fromIndex) { + public static double indexOf(final Object self, final Object searchElement, final Object fromIndex) { try { final ScriptObject sobj = (ScriptObject)Global.toObject(self); final long len = JSType.toUint32(sobj.getLength()); @@ -1534,7 +1519,7 @@ * @return index of element, or -1 if not found */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) - public static long lastIndexOf(final Object self, final Object... args) { + public static double lastIndexOf(final Object self, final Object... args) { try { final ScriptObject sobj = (ScriptObject)Global.toObject(self); final long len = JSType.toUint32(sobj.getLength());
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeBoolean.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeBoolean.java Thu Jan 14 12:03:53 2016 -0800 @@ -168,9 +168,9 @@ } /** - * Wrap a native string in a NativeString object. + * Wrap a native boolean in a NativeBoolean object. * - * @param receiver Native string. + * @param receiver Native boolean. * @return Wrapped object. */ @SuppressWarnings("unused")
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeDate.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeDate.java Thu Jan 14 12:03:53 2016 -0800 @@ -256,8 +256,9 @@ * @return a Date that points to the current moment in time */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) - public static long now(final Object self) { - return System.currentTimeMillis(); + public static double now(final Object self) { + // convert to double as long does not represent the primitive JS number type + return (double) System.currentTimeMillis(); } /**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeNumber.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeNumber.java Thu Jan 14 12:03:53 2016 -0800 @@ -48,6 +48,7 @@ import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.doubleconv.DoubleConversion; +import jdk.nashorn.internal.runtime.linker.NashornGuards; import jdk.nashorn.internal.runtime.linker.PrimitiveLookup; /** @@ -315,7 +316,7 @@ * @return Link to be invoked at call site. */ public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Object receiver) { - return PrimitiveLookup.lookupPrimitive(request, Number.class, new NativeNumber(((Number)receiver).doubleValue()), WRAPFILTER, PROTOFILTER); + return PrimitiveLookup.lookupPrimitive(request, NashornGuards.getNumberGuard(), new NativeNumber(((Number)receiver).doubleValue()), WRAPFILTER, PROTOFILTER); } @SuppressWarnings("unused")
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeObject.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeObject.java Thu Jan 14 12:03:53 2016 -0800 @@ -776,7 +776,7 @@ 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 GuardingDynamicLinker linker = Bootstrap.getBeanLinkerForClass(clazz); final List<AccessorProperty> properties = new ArrayList<>(propertyNames.size() + methodNames.size()); for(final String methodName: methodNames) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExpExecResult.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExpExecResult.java Thu Jan 14 12:03:53 2016 -0800 @@ -74,7 +74,7 @@ @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE) public static Object length(final Object self) { if (self instanceof ScriptObject) { - return JSType.toUint32(((ScriptObject)self).getArray().length()); + return (double) JSType.toUint32(((ScriptObject)self).getArray().length()); } return 0;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java Thu Jan 14 12:03:53 2016 -0800 @@ -146,7 +146,7 @@ if (returnType == Object.class && JSType.isString(self)) { try { - return new GuardedInvocation(MH.findStatic(MethodHandles.lookup(), NativeString.class, "get", desc.getMethodType()), NashornGuards.getInstanceOf2Guard(String.class, ConsString.class)); + return new GuardedInvocation(MH.findStatic(MethodHandles.lookup(), NativeString.class, "get", desc.getMethodType()), NashornGuards.getStringGuard()); } catch (final LookupException e) { //empty. Shouldn't happen. Fall back to super } @@ -1235,8 +1235,8 @@ * @return Link to be invoked at call site. */ public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Object receiver) { - final MethodHandle guard = NashornGuards.getInstanceOf2Guard(String.class, ConsString.class); - return PrimitiveLookup.lookupPrimitive(request, guard, new NativeString((CharSequence)receiver), WRAPFILTER, PROTOFILTER); + return PrimitiveLookup.lookupPrimitive(request, NashornGuards.getStringGuard(), + new NativeString((CharSequence)receiver), WRAPFILTER, PROTOFILTER); } @SuppressWarnings("unused")
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeSymbol.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeSymbol.java Thu Jan 14 12:03:53 2016 -0800 @@ -25,8 +25,14 @@ package jdk.nashorn.internal.objects; +import static jdk.nashorn.internal.lookup.Lookup.MH; import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; import jdk.nashorn.internal.WeakValueCache; import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; @@ -39,6 +45,7 @@ import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.Symbol; import jdk.nashorn.internal.runtime.Undefined; +import jdk.nashorn.internal.runtime.linker.PrimitiveLookup; /** * ECMAScript 6 - 19.4 Symbol Objects @@ -48,12 +55,21 @@ private final Symbol symbol; + /** Method handle to create an object wrapper for a primitive symbol. */ + static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeSymbol.class, Object.class)); + /** Method handle to retrieve the Symbol prototype object. */ + private static final MethodHandle PROTOFILTER = findOwnMH("protoFilter", MH.type(Object.class, Object.class)); + // initialized by nasgen private static PropertyMap $nasgenmap$; /** See ES6 19.4.2.1 */ private static WeakValueCache<String, Symbol> globalSymbolRegistry = new WeakValueCache<>(); + NativeSymbol(final Symbol symbol) { + this(symbol, Global.instance()); + } + NativeSymbol(final Symbol symbol, final Global global) { this(symbol, global.getSymbolPrototype(), $nasgenmap$); } @@ -73,6 +89,17 @@ } } + /** + * Lookup the appropriate method for an invoke dynamic call. + * + * @param request The link request + * @param receiver The receiver for the call + * @return Link to be invoked at call site. + */ + public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Object receiver) { + return PrimitiveLookup.lookupPrimitive(request, Symbol.class, new NativeSymbol((Symbol)receiver), WRAPFILTER, PROTOFILTER); + } + // ECMA 6 19.4.3.4 Symbol.prototype [ @@toPrimitive ] ( hint ) @Override public Object getDefaultValue(final Class<?> typeHint) { @@ -149,4 +176,19 @@ final String name = ((Symbol) arg).getName(); return globalSymbolRegistry.get(name) == arg ? name : Undefined.getUndefined(); } + + @SuppressWarnings("unused") + private static NativeSymbol wrapFilter(final Object receiver) { + return new NativeSymbol((Symbol)receiver); + } + + @SuppressWarnings("unused") + private static Object protoFilter(final Object object) { + return Global.instance().getSymbolPrototype(); + } + + private static MethodHandle findOwnMH(final String name, final MethodType type) { + return MH.findStatic(MethodHandles.lookup(), NativeSymbol.class, name, type); + } + }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java Thu Jan 14 12:03:53 2016 -0800 @@ -178,6 +178,12 @@ /** Method handle for void returns. */ public static final Call VOID_RETURN = staticCall(JSTYPE_LOOKUP, JSType.class, "voidReturn", void.class); + /** Method handle for isString method */ + public static final Call IS_STRING = staticCall(JSTYPE_LOOKUP, JSType.class, "isString", boolean.class, Object.class); + + /** Method handle for isNumber method */ + public static final Call IS_NUMBER = staticCall(JSTYPE_LOOKUP, JSType.class, "isNumber", boolean.class, Object.class); + /** * The list of available accessor types in width order. This order is used for type guesses narrow{@literal ->} wide * in the dual--fields world @@ -280,7 +286,7 @@ return JSType.STRING; } - if (obj instanceof Number) { + if (isNumber(obj)) { return JSType.NUMBER; } @@ -322,7 +328,7 @@ return JSType.STRING; } - if (obj instanceof Number) { + if (isNumber(obj)) { return JSType.NUMBER; } @@ -434,7 +440,7 @@ return obj == null || obj == ScriptRuntime.UNDEFINED || isString(obj) || - obj instanceof Number || + isNumber(obj) || obj instanceof Boolean || obj instanceof Symbol; } @@ -610,6 +616,24 @@ } /** + * Returns true if object represents a primitive JavaScript number value. Note that we only + * treat wrapper objects of Java primitive number types as objects that can be fully represented + * as JavaScript numbers (doubles). This means we exclude {@code long} and special purpose Number + * instances such as {@link java.util.concurrent.atomic.AtomicInteger}, as well as arbitrary precision + * numbers such as {@link java.math.BigInteger}. + * + * @param obj the object + * @return true if the object represents a primitive JavaScript number value. + */ + public static boolean isNumber(final Object obj) { + if (obj != null) { + final Class<?> c = obj.getClass(); + return c == Integer.class || c == Double.class || c == Float.class || c == Short.class || c == Byte.class; + } + return false; + } + + /** * JavaScript compliant conversion of integer to String * * @param num an integer @@ -761,7 +785,7 @@ if (obj instanceof Double) { return (Double)obj; } - if (obj instanceof Number) { + if (isNumber(obj)) { return ((Number)obj).doubleValue(); } return Double.NaN; @@ -1337,7 +1361,7 @@ return obj.toString(); } - if (obj instanceof Number) { + if (isNumber(obj)) { return toString(((Number)obj).doubleValue()); }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Undefined.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Undefined.java Thu Jan 14 12:03:53 2016 -0800 @@ -94,6 +94,9 @@ */ public static GuardedInvocation lookup(final CallSiteDescriptor desc) { final StandardOperation op = NashornCallSiteDescriptor.getFirstStandardOperation(desc); + if (op == null) { + return null; + } switch (op) { case CALL: case NEW:
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java Thu Jan 14 12:03:53 2016 -0800 @@ -287,7 +287,7 @@ * @param arg argument * @return new array length */ - public long fastPush(final int arg) { + public double fastPush(final int arg) { throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink } @@ -296,7 +296,7 @@ * @param arg argument * @return new array length */ - public long fastPush(final long arg) { + public double fastPush(final long arg) { throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink } @@ -305,7 +305,7 @@ * @param arg argument * @return new array length */ - public long fastPush(final double arg) { + public double fastPush(final double arg) { throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink } @@ -314,7 +314,7 @@ * @param arg argument * @return new array length */ - public long fastPush(final Object arg) { + public double fastPush(final Object arg) { throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink } @@ -330,14 +330,6 @@ * Specialization - fast pop implementation * @return element value */ - public long fastPopLong() { - throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink - } - - /** - * Specialization - fast pop implementation - * @return element value - */ public double fastPopDouble() { throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Thu Jan 14 12:03:53 2016 -0800 @@ -340,7 +340,7 @@ } @Override - public long fastPush(final int arg) { + public double fastPush(final int arg) { final int len = (int)length(); if (len == array.length) { array = Arrays.copyOf(array, nextSize(len)); @@ -362,11 +362,6 @@ } @Override - public long fastPopLong() { - return fastPopInt(); - } - - @Override public double fastPopDouble() { return fastPopInt(); }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Thu Jan 14 12:03:53 2016 -0800 @@ -303,17 +303,17 @@ } @Override - public long fastPush(final int arg) { + public double fastPush(final int arg) { return fastPush((double)arg); } @Override - public long fastPush(final long arg) { + public double fastPush(final long arg) { return fastPush((double)arg); } @Override - public long fastPush(final double arg) { + public double fastPush(final double arg) { final int len = (int)length(); if (len == array.length) { //note that fastpush never creates spares arrays, there is nothing to gain by that - it will just use even more memory
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java Thu Jan 14 12:03:53 2016 -0800 @@ -236,22 +236,22 @@ } @Override - public long fastPush(final int arg) { + public double fastPush(final int arg) { return fastPush((Object)arg); } @Override - public long fastPush(final long arg) { + public double fastPush(final long arg) { return fastPush((Object)arg); } @Override - public long fastPush(final double arg) { + public double fastPush(final double arg) { return fastPush((Object)arg); } @Override - public long fastPush(final Object arg) { + public double fastPush(final Object arg) { final int len = (int)length(); if (len == array.length) { array = Arrays.copyOf(array, nextSize(len));
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java Thu Jan 14 12:03:53 2016 -0800 @@ -40,10 +40,11 @@ import jdk.dynalink.beans.BeansLinker; import jdk.dynalink.beans.StaticClass; import jdk.dynalink.linker.GuardedInvocation; -import jdk.dynalink.linker.GuardedInvocationTransformer; +import jdk.dynalink.linker.GuardingDynamicLinker; import jdk.dynalink.linker.LinkRequest; import jdk.dynalink.linker.LinkerServices; import jdk.dynalink.linker.MethodTypeConversionStrategy; +import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker; import jdk.dynalink.linker.support.TypeUtilities; import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.internal.codegen.CompilerConstants.Call; @@ -67,6 +68,24 @@ private static final MethodHandle VOID_TO_OBJECT = MH.constant(Object.class, ScriptRuntime.UNDEFINED); + private static final BeansLinker beansLinker = new BeansLinker(Bootstrap::createMissingMemberHandler); + private static final GuardingDynamicLinker[] prioritizedLinkers; + private static final GuardingDynamicLinker[] fallbackLinkers; + static { + final NashornBeansLinker nashornBeansLinker = new NashornBeansLinker(beansLinker); + prioritizedLinkers = new GuardingDynamicLinker[] { + new NashornLinker(), + new NashornPrimitiveLinker(), + new NashornStaticClassLinker(beansLinker), + new BoundCallableLinker(), + new JavaSuperAdapterLinker(beansLinker), + new JSObjectLinker(nashornBeansLinker), + new BrowserJSObjectLinker(nashornBeansLinker), + new ReflectionCheckLinker() + }; + fallbackLinkers = new GuardingDynamicLinker[] {nashornBeansLinker, new NashornBottomLinker() }; + } + // do not create me!! private Bootstrap() { } @@ -81,31 +100,14 @@ public static DynamicLinker createDynamicLinker(final ClassLoader appLoader, final int unstableRelinkThreshold) { final DynamicLinkerFactory factory = new DynamicLinkerFactory(); - final NashornBeansLinker nashornBeansLinker = new NashornBeansLinker(); - factory.setPrioritizedLinkers( - new NashornLinker(), - new NashornPrimitiveLinker(), - new NashornStaticClassLinker(), - new BoundCallableLinker(), - new JavaSuperAdapterLinker(), - new JSObjectLinker(nashornBeansLinker), - new BrowserJSObjectLinker(nashornBeansLinker), - new ReflectionCheckLinker()); - factory.setFallbackLinkers(nashornBeansLinker, new NashornBottomLinker()); + factory.setPrioritizedLinkers(prioritizedLinkers); + factory.setFallbackLinkers(fallbackLinkers); factory.setSyncOnRelink(true); - factory.setPrelinkTransformer(new GuardedInvocationTransformer() { - @Override - public GuardedInvocation filter(final GuardedInvocation inv, final LinkRequest request, final LinkerServices linkerServices) { - final CallSiteDescriptor desc = request.getCallSiteDescriptor(); - return OptimisticReturnFilters.filterOptimisticReturnValue(inv, desc).asType(linkerServices, desc.getMethodType()); - } + factory.setPrelinkTransformer((inv, request, linkerServices) -> { + final CallSiteDescriptor desc = request.getCallSiteDescriptor(); + return OptimisticReturnFilters.filterOptimisticReturnValue(inv, desc).asType(linkerServices, desc.getMethodType()); }); - factory.setAutoConversionStrategy(new MethodTypeConversionStrategy() { - @Override - public MethodHandle asType(final MethodHandle target, final MethodType newType) { - return unboxReturnType(target, newType); - } - }); + factory.setAutoConversionStrategy(Bootstrap::unboxReturnType); factory.setInternalObjectsFilter(NashornBeansLinker.createHiddenObjectFilter()); factory.setUnstableRelinkThreshold(unstableRelinkThreshold); @@ -115,6 +117,15 @@ } /** + * Returns a dynamic linker for the specific Java class using beans semantics. + * @param clazz the Java class + * @return a dynamic linker for the specific Java class using beans semantics. + */ + public static TypeBasedGuardingDynamicLinker getBeanLinkerForClass(final Class<?> clazz) { + return beansLinker.getLinkerForClass(clazz); + } + + /** * Returns if the given object is a "callable" * @param obj object to be checked for callability * @return true if the obj is callable @@ -475,4 +486,14 @@ } return target; } + + private static MethodHandle createMissingMemberHandler( + final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception { + if (BrowserJSObjectLinker.canLinkTypeStatic(linkRequest.getReceiver().getClass())) { + // Don't create missing member handlers for the browser JS objects as they + // have their own logic. + return null; + } + return NashornBottomLinker.linkMissingBeanMember(linkRequest, linkerServices); + } }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java Thu Jan 14 12:03:53 2016 -0800 @@ -25,7 +25,6 @@ package jdk.nashorn.internal.runtime.linker; -import static jdk.nashorn.internal.lookup.Lookup.EMPTY_GETTER; import static jdk.nashorn.internal.runtime.linker.JavaAdapterBytecodeGenerator.SUPER_PREFIX; import java.lang.invoke.MethodHandle; @@ -62,6 +61,12 @@ IS_ADAPTER_OF_CLASS = lookup.findOwnStatic("isAdapterOfClass", boolean.class, Class.class, Object.class); } + private final BeansLinker beansLinker; + + JavaSuperAdapterLinker(final BeansLinker beansLinker) { + this.beansLinker = beansLinker; + } + @Override public boolean canLinkType(final Class<?> type) { return type == JavaSuperAdapter.class; @@ -101,17 +106,13 @@ // Delegate to BeansLinker final GuardedInvocation guardedInv = NashornBeansLinker.getGuardedInvocation( - BeansLinker.getLinkerForClass(adapterClass), linkRequest.replaceArguments(newDescriptor, args), + beansLinker, linkRequest.replaceArguments(newDescriptor, args), linkerServices); + // Even for non-existent methods, Bootstrap's BeansLinker will link a + // noSuchMember handler. + assert guardedInv != null; final MethodHandle guard = IS_ADAPTER_OF_CLASS.bindTo(adapterClass); - if(guardedInv == null) { - // Short circuit the lookup here for non-existent methods by linking an empty getter. If we just returned - // null instead, BeansLinker would find final methods on the JavaSuperAdapter instead: getClass() and - // wait(). - return new GuardedInvocation(MethodHandles.dropArguments(EMPTY_GETTER, 1,type.parameterList().subList(1, - type.parameterCount())), guard).asType(descriptor); - } final MethodHandle invocation = guardedInv.getInvocation(); final MethodType invType = invocation.type(); @@ -165,7 +166,7 @@ */ @SuppressWarnings("unused") private static Object bindDynamicMethod(final Object dynamicMethod, final Object boundThis) { - return dynamicMethod == null ? ScriptRuntime.UNDEFINED : Bootstrap.bindCallable(dynamicMethod, boundThis, null); + return dynamicMethod == ScriptRuntime.UNDEFINED ? ScriptRuntime.UNDEFINED : Bootstrap.bindCallable(dynamicMethod, boundThis, null); } /**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Thu Jan 14 12:03:53 2016 -0800 @@ -85,7 +85,11 @@ } }; - private final BeansLinker beansLinker = new BeansLinker(); + private final BeansLinker beansLinker; + + NashornBeansLinker(final BeansLinker beansLinker) { + this.beansLinker = beansLinker; + } @Override public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java Thu Jan 14 12:03:53 2016 -0800 @@ -27,26 +27,27 @@ import static jdk.nashorn.internal.lookup.Lookup.MH; import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; -import static jdk.nashorn.internal.runtime.JSType.GET_UNDEFINED; -import static jdk.nashorn.internal.runtime.JSType.TYPE_OBJECT_INDEX; 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.HashMap; import java.util.Map; import java.util.function.Supplier; import jdk.dynalink.CallSiteDescriptor; import jdk.dynalink.NamedOperation; import jdk.dynalink.Operation; +import jdk.dynalink.StandardOperation; import jdk.dynalink.beans.BeansLinker; import jdk.dynalink.linker.GuardedInvocation; import jdk.dynalink.linker.GuardingDynamicLinker; import jdk.dynalink.linker.GuardingTypeConverterFactory; import jdk.dynalink.linker.LinkRequest; import jdk.dynalink.linker.LinkerServices; -import jdk.dynalink.linker.support.Guards; +import jdk.dynalink.linker.support.Lookup; import jdk.nashorn.internal.codegen.types.Type; +import jdk.nashorn.internal.runtime.ECMAException; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.UnwarrantedOptimismException; @@ -73,7 +74,7 @@ // this point is a generic Java bean. Therefore, reaching here with a ScriptObject is a Nashorn bug. assert isExpectedObject(self) : "Couldn't link " + linkRequest.getCallSiteDescriptor() + " for " + self.getClass().getName(); - return linkBean(linkRequest, linkerServices); + return linkBean(linkRequest); } private static final MethodHandle EMPTY_PROP_GETTER = @@ -85,7 +86,18 @@ private static final MethodHandle EMPTY_ELEM_SETTER = MH.dropArguments(EMPTY_PROP_SETTER, 0, Object.class); - private static GuardedInvocation linkBean(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception { + private static final MethodHandle THROW_NO_SUCH_FUNCTION; + private static final MethodHandle THROW_STRICT_PROPERTY_SETTER; + private static final MethodHandle THROW_OPTIMISTIC_UNDEFINED; + + static { + final Lookup lookup = new Lookup(MethodHandles.lookup()); + THROW_NO_SUCH_FUNCTION = lookup.findOwnStatic("throwNoSuchFunction", Object.class, Object.class, Object.class); + THROW_STRICT_PROPERTY_SETTER = lookup.findOwnStatic("throwStrictPropertySetter", void.class, Object.class, Object.class); + THROW_OPTIMISTIC_UNDEFINED = lookup.findOwnStatic("throwOptimisticUndefined", Object.class, int.class); + } + + private static GuardedInvocation linkBean(final LinkRequest linkRequest) throws Exception { final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor(); final Object self = linkRequest.getReceiver(); switch (NashornCallSiteDescriptor.getFirstStandardOperation(desc)) { @@ -105,35 +117,79 @@ throw typeError("no.method.matches.args", ScriptRuntime.safeToString(self)); } throw typeError("not.a.function", NashornCallSiteDescriptor.getFunctionErrorMessage(desc, self)); - case CALL_METHOD: - throw typeError("no.such.function", getArgument(linkRequest), ScriptRuntime.safeToString(self)); - case GET_METHOD: - // evaluate to undefined, later on Undefined will take care of throwing TypeError - return getInvocation(MH.dropArguments(GET_UNDEFINED.get(TYPE_OBJECT_INDEX), 0, Object.class), self, linkerServices, desc); - case GET_PROPERTY: - case GET_ELEMENT: - if(NashornCallSiteDescriptor.isOptimistic(desc)) { - throw new UnwarrantedOptimismException(UNDEFINED, NashornCallSiteDescriptor.getProgramPoint(desc), Type.OBJECT); - } - if (NashornCallSiteDescriptor.getOperand(desc) != null) { - return getInvocation(EMPTY_PROP_GETTER, self, linkerServices, desc); - } - return getInvocation(EMPTY_ELEM_GETTER, self, linkerServices, desc); - case SET_PROPERTY: - case SET_ELEMENT: - final boolean strict = NashornCallSiteDescriptor.isStrict(desc); - if (strict) { - throw typeError("cant.set.property", getArgument(linkRequest), ScriptRuntime.safeToString(self)); - } - if (NashornCallSiteDescriptor.getOperand(desc) != null) { - return getInvocation(EMPTY_PROP_SETTER, self, linkerServices, desc); - } - return getInvocation(EMPTY_ELEM_SETTER, self, linkerServices, desc); default: + // Everything else is supposed to have been already handled by Bootstrap.beansLinker + // delegating to linkNoSuchBeanMember throw new AssertionError("unknown call type " + desc); } } + static MethodHandle linkMissingBeanMember(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception { + final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor(); + final StandardOperation op = NashornCallSiteDescriptor.getFirstStandardOperation(desc); + if (op != null) { + final String operand = NashornCallSiteDescriptor.getOperand(desc); + switch (op) { + case CALL_METHOD: + return adaptThrower(bindOperand(THROW_NO_SUCH_FUNCTION, operand), desc); + case GET_METHOD: + case GET_PROPERTY: + case GET_ELEMENT: { + if (NashornCallSiteDescriptor.isOptimistic(desc)) { + return adaptThrower(MethodHandles.insertArguments(THROW_OPTIMISTIC_UNDEFINED, 0, NashornCallSiteDescriptor.getProgramPoint(desc)), desc); + } + if (NashornCallSiteDescriptor.getOperand(desc) != null) { + return getInvocation(EMPTY_PROP_GETTER, linkerServices, desc); + } + return getInvocation(EMPTY_ELEM_GETTER, linkerServices, desc); + } + case SET_PROPERTY: + case SET_ELEMENT: + final boolean strict = NashornCallSiteDescriptor.isStrict(desc); + if (strict) { + return adaptThrower(bindOperand(THROW_STRICT_PROPERTY_SETTER, operand), desc); + } + if (NashornCallSiteDescriptor.getOperand(desc) != null) { + return getInvocation(EMPTY_PROP_SETTER, linkerServices, desc); + } + return getInvocation(EMPTY_ELEM_SETTER, linkerServices, desc); + default: + } + } + throw new AssertionError("unknown call type " + desc); + } + + private static MethodHandle bindOperand(final MethodHandle handle, final String operand) { + return operand == null ? handle : MethodHandles.insertArguments(handle, 1, operand); + } + + private static MethodHandle adaptThrower(final MethodHandle handle, final CallSiteDescriptor desc) { + final MethodType targetType = desc.getMethodType(); + final int paramCount = handle.type().parameterCount(); + return MethodHandles + .dropArguments(handle, paramCount, targetType.parameterList().subList(paramCount, targetType.parameterCount())) + .asType(targetType); + } + + @SuppressWarnings("unused") + private static Object throwNoSuchFunction(final Object self, final Object name) { + throw createTypeError(self, name, "no.such.function"); + } + + @SuppressWarnings("unused") + private static void throwStrictPropertySetter(final Object self, final Object name) { + throw createTypeError(self, name, "cant.set.property"); + } + + private static ECMAException createTypeError(final Object self, final Object name, final String msg) { + return typeError(msg, String.valueOf(name), ScriptRuntime.safeToString(self)); + } + + @SuppressWarnings("unused") + private static Object throwOptimisticUndefined(final int programPoint) { + throw new UnwarrantedOptimismException(UNDEFINED, programPoint, Type.OBJECT); + } + @Override public GuardedInvocation convertToType(final Class<?> sourceType, final Class<?> targetType, final Supplier<MethodHandles.Lookup> lookupSupplier) throws Exception { final GuardedInvocation gi = convertToTypeNoCast(sourceType, targetType); @@ -158,8 +214,8 @@ return null; } - private static GuardedInvocation getInvocation(final MethodHandle handle, final Object self, final LinkerServices linkerServices, final CallSiteDescriptor desc) { - return Bootstrap.asTypeSafeReturn(new GuardedInvocation(handle, Guards.getClassGuard(self.getClass())), linkerServices, desc); + private static MethodHandle getInvocation(final MethodHandle handle, final LinkerServices linkerServices, final CallSiteDescriptor desc) { + return linkerServices.asTypeLosslessReturn(handle, desc.getMethodType()); } // Used solely in an assertion to figure out if the object we get here is something we in fact expect. Objects
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornGuards.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornGuards.java Thu Jan 14 12:03:53 2016 -0800 @@ -34,6 +34,7 @@ import jdk.dynalink.linker.LinkRequest; import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.internal.objects.Global; +import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.Property; import jdk.nashorn.internal.runtime.PropertyMap; import jdk.nashorn.internal.runtime.ScriptFunction; @@ -46,10 +47,9 @@ public final class NashornGuards { private static final MethodHandle IS_MAP = findOwnMH("isMap", boolean.class, ScriptObject.class, PropertyMap.class); private static final MethodHandle IS_MAP_SCRIPTOBJECT = findOwnMH("isMap", boolean.class, Object.class, PropertyMap.class); - private static final MethodHandle IS_INSTANCEOF_2 = findOwnMH("isInstanceOf2", boolean.class, Object.class, Class.class, Class.class); private static final MethodHandle IS_SCRIPTOBJECT = findOwnMH("isScriptObject", boolean.class, Object.class); private static final MethodHandle IS_NOT_JSOBJECT = findOwnMH("isNotJSObject", boolean.class, Object.class); - private static final MethodHandle SAME_OBJECT = findOwnMH("sameObject", boolean.class, Object.class, WeakReference.class); + private static final MethodHandle SAME_OBJECT = findOwnMH("sameObject", boolean.class, Object.class, WeakReference.class); //TODO - maybe put this back in ScriptFunction instead of the ClassCastException.class relinkage //private static final MethodHandle IS_SCRIPTFUNCTION = findOwnMH("isScriptFunction", boolean.class, Object.class); @@ -165,14 +165,21 @@ } /** - * Get a guard that checks if in item is an instance of either of two classes. + * Get a guard that checks if in item is a JS string. * - * @param class1 the first class - * @param class2 the second class * @return method handle for guard */ - public static MethodHandle getInstanceOf2Guard(final Class<?> class1, final Class<?> class2) { - return MH.insertArguments(IS_INSTANCEOF_2, 1, class1, class2); + public static MethodHandle getStringGuard() { + return JSType.IS_STRING.methodHandle(); + } + + /** + * Get a guard that checks if in item is a JS number. + * + * @return method handle for guard + */ + public static MethodHandle getNumberGuard() { + return JSType.IS_NUMBER.methodHandle(); } /** @@ -224,11 +231,6 @@ } @SuppressWarnings("unused") - private static boolean isInstanceOf2(final Object self, final Class<?> class1, final Class<?> class2) { - return class1.isInstance(self) || class2.isInstance(self); - } - - @SuppressWarnings("unused") private static boolean isScriptFunction(final Object self) { return self instanceof ScriptFunction; }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java Thu Jan 14 12:03:53 2016 -0800 @@ -41,6 +41,7 @@ import jdk.nashorn.internal.runtime.ConsString; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.ScriptRuntime; +import jdk.nashorn.internal.runtime.Symbol; /** * Internal linker for String, Boolean, and Number objects, only ever used by Nashorn engine and not exposed to other @@ -57,7 +58,9 @@ } private static boolean canLinkTypeStatic(final Class<?> type) { - return type == String.class || type == Boolean.class || type == ConsString.class || Number.class.isAssignableFrom(type); + return type == String.class || type == Boolean.class || type == ConsString.class || type == Integer.class + || type == Double.class || type == Float.class || type == Short.class || type == Byte.class + || type == Symbol.class; } @Override @@ -167,7 +170,7 @@ @SuppressWarnings("unused") private static boolean isJavaScriptPrimitive(final Object o) { - return JSType.isString(o) || o instanceof Boolean || o instanceof Number || o == null; + return JSType.isString(o) || o instanceof Boolean || JSType.isNumber(o) || o == null || o instanceof Symbol; } private static final MethodHandle GUARD_PRIMITIVE = findOwnMH("isJavaScriptPrimitive", boolean.class, Object.class);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java Thu Jan 14 12:03:53 2016 -0800 @@ -53,7 +53,11 @@ * </pre> */ final class NashornStaticClassLinker implements TypeBasedGuardingDynamicLinker { - private static final GuardingDynamicLinker staticClassLinker = BeansLinker.getLinkerForClass(StaticClass.class); + private final GuardingDynamicLinker staticClassLinker; + + NashornStaticClassLinker(final BeansLinker beansLinker) { + this.staticClassLinker = beansLinker.getLinkerForClass(StaticClass.class); + } @Override public boolean canLinkType(final Class<?> type) { @@ -100,7 +104,7 @@ return delegate(linkerServices, request); } - private static GuardedInvocation delegate(final LinkerServices linkerServices, final LinkRequest request) throws Exception { + private GuardedInvocation delegate(final LinkerServices linkerServices, final LinkRequest request) throws Exception { return NashornBeansLinker.getGuardedInvocation(staticClassLinker, request, linkerServices); }
--- a/nashorn/test/script/basic/JDK-8030200.js Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/test/script/basic/JDK-8030200.js Thu Jan 14 12:03:53 2016 -0800 @@ -33,4 +33,4 @@ var s = n.toString(5); var m = parseInt(s, 5); print(m === n); -print(n); +print(m);
--- a/nashorn/test/script/basic/JDK-8049242.js.EXPECTED Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/test/script/basic/JDK-8049242.js.EXPECTED Thu Jan 14 12:03:53 2016 -0800 @@ -1,10 +1,10 @@ abc [jdk.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)] ava -TypeError: null is not a function -TypeError: null is not a function -TypeError: null is not a function +TypeError: Java.type("java.lang.Object")["()xxxxx"] is not a function +TypeError: Java.type("java.lang.Object")["("] is not a function +TypeError: Java.type("java.lang.Object")[")"] is not a function TypeError: Constructor [jdk.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)] requires "new". -TypeError: null is not a function -TypeError: null is not a function +TypeError: Java.type("java.lang.Runnable")["()"] is not a function +TypeError: Java.type("java.lang.Runnable")["(int)"] is not a function java.lang.InstantiationException: java.io.InputStream
--- a/nashorn/test/script/basic/JDK-8066669.js Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/test/script/basic/JDK-8066669.js Thu Jan 14 12:03:53 2016 -0800 @@ -29,12 +29,13 @@ */ // Make sure index access on Java objects is working as expected. -var map = new java.util.HashMap(); +var map = new java.util.LinkedHashMap(); map["foo"] = "bar"; map[1] = 2; map[false] = true; map[null] = 0; +map["a"] = null; print(map); @@ -49,10 +50,12 @@ print(typeof map[1], map[1]); print(typeof map[false], map[false]); print(typeof map[null], map[null]); +print(typeof map["a"], map["a"]); -print(map.foo); -print(map.false); -print(map.null); +print("map.foo=" + map.foo); +print("map.false=" + map.false); +print("map.null=" + map.null); +print("map.a=" + map.a); map.foo = "baz"; print(map);
--- a/nashorn/test/script/basic/JDK-8066669.js.EXPECTED Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/test/script/basic/JDK-8066669.js.EXPECTED Thu Jan 14 12:03:53 2016 -0800 @@ -1,13 +1,16 @@ -{null=0, 1=2, false=true, foo=bar} -object null +{foo=bar, 1=2, false=true, null=0, a=null} +string foo number 1 boolean false -string foo +object null +string a string bar number 2 boolean true number 0 -bar -null -null -{null=0, 1=2, false=true, foo=baz} +object null +map.foo=bar +map.false=undefined +map.null=undefined +map.a=null +{foo=baz, 1=2, false=true, null=0, a=null}
--- a/nashorn/test/script/basic/JDK-8079145.js.EXPECTED Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/test/script/basic/JDK-8079145.js.EXPECTED Thu Jan 14 12:03:53 2016 -0800 @@ -5,8 +5,8 @@ int array: check widen for true [class java.lang.Boolean] int array: check widen for 34 [class java.lang.Byte] int array: check widen for 344454 [class java.lang.Integer] -int array: check widen for 454545 [class java.lang.Long] -int array: check widen for 2147483648 [class java.lang.Long] +int array: check widen for 454545 +int array: check widen for 2147483648 int array: check widen for 34.29999923706055 [class java.lang.Float] int array: check widen for 3.141592653589793 [class java.lang.Double] int array: check widen for s @@ -17,8 +17,8 @@ long array: check widen for true [class java.lang.Boolean] long array: check widen for 34 [class java.lang.Byte] long array: check widen for 344454 [class java.lang.Integer] -long array: check widen for 454545 [class java.lang.Long] -long array: check widen for 2147483648 [class java.lang.Long] +long array: check widen for 454545 +long array: check widen for 2147483648 long array: check widen for 34.29999923706055 [class java.lang.Float] long array: check widen for 3.141592653589793 [class java.lang.Double] long array: check widen for s @@ -29,8 +29,8 @@ number array: check widen for true [class java.lang.Boolean] number array: check widen for 34 [class java.lang.Byte] number array: check widen for 344454 [class java.lang.Integer] -number array: check widen for 454545 [class java.lang.Long] -number array: check widen for 2147483648 [class java.lang.Long] +number array: check widen for 454545 +number array: check widen for 2147483648 number array: check widen for 34.29999923706055 [class java.lang.Float] number array: check widen for 3.141592653589793 [class java.lang.Double] number array: check widen for s @@ -41,8 +41,8 @@ object array: check widen for true [class java.lang.Boolean] object array: check widen for 34 [class java.lang.Byte] object array: check widen for 344454 [class java.lang.Integer] -object array: check widen for 454545 [class java.lang.Long] -object array: check widen for 2147483648 [class java.lang.Long] +object array: check widen for 454545 +object array: check widen for 2147483648 object array: check widen for 34.29999923706055 [class java.lang.Float] object array: check widen for 3.141592653589793 [class java.lang.Double] object array: check widen for s
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8143896.js Thu Jan 14 12:03:53 2016 -0800 @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2016, 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-8143896: java.lang.Long is implicitly converted to double + * + * @test + * @run + */ + +Assert.assertTrue(java.lang.Long.valueOf("301077366599181567").toString() === "301077366599181567"); +Assert.assertTrue(java.lang.Long.valueOf("-301077366599181567").toString() === "-301077366599181567"); +Assert.assertTrue(java.lang.Long.valueOf("301077366599181567") == 301077366599181567); +Assert.assertFalse(java.lang.Long.valueOf("301077366599181567") === 301077366599181567); + +Assert.assertTrue(new java.math.BigInteger("301077366599181567").toString() === "301077366599181567"); +Assert.assertTrue(new java.math.BigInteger("-301077366599181567").toString() === "-301077366599181567"); +Assert.assertTrue(new java.math.BigInteger("301077366599181567") == 301077366599181567); +Assert.assertFalse(new java.math.BigInteger("301077366599181567") === 301077366599181567); + + +var n = new java.lang.Byte("123"); +Assert.assertTrue(typeof n === "number"); +Assert.assertTrue(n + 1 === 124); +Assert.assertTrue(n == 123); +Assert.assertTrue(n === 123); + +n = new java.lang.Short("123"); +Assert.assertTrue(typeof n === "number"); +Assert.assertTrue(n + 1 === 124); +Assert.assertTrue(n == 123); +Assert.assertTrue(n === 123); + +n = new java.lang.Integer("123"); +Assert.assertTrue(typeof n === "number"); +Assert.assertTrue(n + 1 === 124); +Assert.assertTrue(n == 123); +Assert.assertTrue(n === 123); + +n = new java.lang.Float("123"); +Assert.assertTrue(typeof n === "number"); +Assert.assertTrue(n + 1 === 124); +Assert.assertTrue(n == 123); +Assert.assertTrue(n === 123); + +n = new java.lang.Double("123"); +Assert.assertTrue(typeof n === "number"); +Assert.assertTrue(n + 1 === 124); +Assert.assertTrue(n == 123); +Assert.assertTrue(n === 123); + +n = new java.lang.Long("123"); +Assert.assertTrue(typeof n === "object"); +Assert.assertTrue(n + 1 === 124); +Assert.assertTrue(n == 123); +Assert.assertFalse(n === 123); + +n = new java.util.concurrent.atomic.DoubleAdder(); +n.add("123"); +Assert.assertTrue(typeof n === "object"); +Assert.assertTrue(n + 1 === 124); +Assert.assertTrue(n == 123); +Assert.assertFalse(n === 123); + +n = new java.util.concurrent.atomic.AtomicInteger(123); +Assert.assertTrue(typeof n === "object"); +Assert.assertTrue(n + 1 === 124); +Assert.assertTrue(n == 123); +Assert.assertFalse(n === 123); + +n = new java.util.concurrent.atomic.AtomicLong(123); +Assert.assertTrue(typeof n === "object"); +Assert.assertTrue(n + 1 === 124); +Assert.assertTrue(n == 123); +Assert.assertFalse(n === 123); + +n = new java.math.BigInteger("123"); +Assert.assertTrue(typeof n === "object"); +Assert.assertTrue(n + 1 === 124); +Assert.assertTrue(n == 123); +Assert.assertFalse(n === 123); + +n = new java.math.BigDecimal("123"); +Assert.assertTrue(typeof n === "object"); +Assert.assertTrue(n + 1 === 124); +Assert.assertTrue(n == 123); +Assert.assertFalse(n === 123);
--- a/nashorn/test/script/basic/es6/symbols.js Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/test/script/basic/es6/symbols.js Thu Jan 14 12:03:53 2016 -0800 @@ -40,11 +40,11 @@ Assert.assertTrue(Symbol(null).toString() === 'Symbol(null)'); Assert.assertTrue(Symbol(undefined).toString() === 'Symbol()'); -var s1 = Symbol(); -var s2 = Symbol("s2"); +const s1 = Symbol(); +const s2 = Symbol("s2"); Assert.assertFalse(s1 instanceof Symbol); // not an object -var obj = {}; +let obj = {}; obj['foo'] = 'foo'; obj[s1] = s1; obj['bar'] = 'bar'; @@ -57,17 +57,17 @@ Assert.assertTrue(obj[1] === 1); Assert.assertTrue(obj[s2] === s2); -var expectedNames = ['1', 'foo', 'bar']; -var expectedSymbols = [s1, s2]; -var actualNames = Object.getOwnPropertyNames(obj); -var actualSymbols = Object.getOwnPropertySymbols(obj); +const expectedNames = ['1', 'foo', 'bar']; +const expectedSymbols = [s1, s2]; +const actualNames = Object.getOwnPropertyNames(obj); +let actualSymbols = Object.getOwnPropertySymbols(obj); Assert.assertTrue(expectedNames.length == actualNames.length); Assert.assertTrue(expectedSymbols.length == actualSymbols.length); -for (var key in expectedNames) { +for (let key in expectedNames) { Assert.assertTrue(expectedNames[key] === actualNames[key]); } -for (var key in expectedSymbols) { +for (let key in expectedSymbols) { Assert.assertTrue(expectedSymbols[key] === actualSymbols[key]); } @@ -114,8 +114,8 @@ // Symbol.for and Symbol.keyFor -var uncached = Symbol('foo'); -var cached = Symbol.for('foo'); +const uncached = Symbol('foo'); +const cached = Symbol.for('foo'); Assert.assertTrue(uncached !== cached); Assert.assertTrue(Symbol.keyFor(uncached) === undefined); @@ -123,9 +123,15 @@ Assert.assertTrue(cached === Symbol.for('foo')); Assert.assertTrue(cached === Symbol.for('f' + 'oo')); +// JDK-8147008: Make sure symbols are handled by primitive linker +Symbol.prototype.foo = 123; +Symbol.prototype[s2] = s2; +Assert.assertEquals(s1.foo, 123); +Assert.assertEquals(s2[s2], s2); + // Object wrapper -var o = Object(s1); +const o = Object(s1); obj = {}; obj[s1] = "s1"; Assert.assertTrue(o == s1); @@ -134,6 +140,8 @@ Assert.assertTrue(o instanceof Symbol); Assert.assertTrue(obj[o] == 's1'); Assert.assertTrue(o in obj); +Assert.assertEquals(o.foo, 123); +Assert.assertEquals(o[s2], s2); // various non-strict comparisons that should fail
--- a/nashorn/test/script/basic/list.js Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/test/script/basic/list.js Thu Jan 14 12:03:53 2016 -0800 @@ -54,15 +54,14 @@ var size_name = "size" print("l[size_name]()=" + l[size_name]()) // ... but existing methods can be accessed with [] -expectException(2) // Java lists don't auto-expand to accommodate new indices -expectException(java.lang.Double.POSITIVE_INFINITY) // Dynalink will throw IOOBE -expectException(java.lang.Double.NEGATIVE_INFINITY) // Dynalink will throw IOOBE +// All illegal indices, even those out of bounds, return undefined +print("l[2]=" + l[2]); +print("l[-1]=" + l[-1]); +print("l[2.1]=" + l[2.1]); +print("l[-1.1]=" + l[-1.1]); +print("l[Infinity]=" + l[Infinity]); +print("l[-Infinity]=" + l[-Infinity]); +print("l[NaN]=" + l[NaN]); -function expectException(index) { - try { - l[index] = "x" - print("Not caught out-of-bounds assignment for " + index) - } catch(e) { - print(e) - } -} +l[1.1]="b"; // should be no-op +print("l[0]=" + l[0]);
--- a/nashorn/test/script/basic/list.js.EXPECTED Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/test/script/basic/list.js.EXPECTED Thu Jan 14 12:03:53 2016 -0800 @@ -9,9 +9,14 @@ --for each end-- l[0]=foo l[1]=a -l[0.9]=null +l[0.9]=undefined l['blah']=undefined l[size_name]()=2 -java.lang.IndexOutOfBoundsException: Index: 2, Size: 2 -java.lang.IndexOutOfBoundsException: Index: Infinity, Size: 2 -java.lang.IndexOutOfBoundsException: Index: -Infinity, Size: 2 +l[2]=undefined +l[-1]=undefined +l[2.1]=undefined +l[-1.1]=undefined +l[Infinity]=undefined +l[-Infinity]=undefined +l[NaN]=undefined +l[0]=foo
--- a/nashorn/test/script/basic/map.js Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/test/script/basic/map.js Thu Jan 14 12:03:53 2016 -0800 @@ -44,8 +44,8 @@ print("m['empty'] = " + m['empty']) print("m[empty_key] = " + m[empty_key]) // prints "foo" -print("m.bwah = " + m.bwah) // prints "null" -print("m['bwah'] = " + m['bwah']) // prints "null" +print("m.bwah = " + m.bwah) // prints "undefined" +print("m['bwah'] = " + m['bwah']) // prints "undefined" m.put("twonk", "ding") print("m.twonk = " + m.twonk) // prints "ding"
--- a/nashorn/test/script/basic/map.js.EXPECTED Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/test/script/basic/map.js.EXPECTED Thu Jan 14 12:03:53 2016 -0800 @@ -7,8 +7,8 @@ m.empty = false m['empty'] = foo m[empty_key] = foo -m.bwah = null -m['bwah'] = null +m.bwah = undefined +m['bwah'] = undefined m.twonk = ding m['twonk'] = ding m.size()=2
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/nosecurity/context-dependent-logging.js Thu Jan 14 12:03:53 2016 -0800 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016, 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. + */ + +/** + * Test that logging configuration is per engine, rather than per process. + * + * @test + * @bug 8036977 + * @run/ignore-std-error + * @fork + * @option -scripting + */ + +// To test, start another engine (testEngine) with a time logger and ensure the +// logger exists. + +var NashornFactory = new (Java.type('jdk.nashorn.api.scripting.NashornScriptEngineFactory'))(), + testEngine = NashornFactory.getScriptEngine("-scripting", "--log=time") + +if (!testEngine.eval('$OPTIONS._loggers.time')) { + throw 'fresh testEngine does not have time logger' +} + +// To test further, have the testEngine start yet another engine (e) without +// time logging, but with compiler logging. Check the logging is as configured, +// and verify the testEngine still has time logging, but no compiler logging. + +var script = <<EOS + var F = new (Java.type('jdk.nashorn.api.scripting.NashornScriptEngineFactory'))(), + e = F.getScriptEngine('-scripting', '--log=compiler') + if (!e.eval('$OPTIONS._loggers.compiler')) { + throw 'e does not have compiler logger' + } + if (e.eval('$OPTIONS._loggers.time')) { + throw 'e has time logger' + } +EOS + +testEngine.eval(script) + +if (!testEngine.eval('$OPTIONS._loggers.time')) { + throw 'after-test testEngine does not have time logger' +} +if (testEngine.eval('$OPTIONS._loggers.compiler')) { + throw 'after-test testEngine has compiler logger' +}
--- a/nashorn/test/script/nosecurity/parserapi.js Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/test/script/nosecurity/parserapi.js Thu Jan 14 12:03:53 2016 -0800 @@ -30,8 +30,8 @@ */ function Parser() { - // create nashorn parser - this._parser = Parser.create(); + // create nashorn parser + this._parser = Parser.create(); } // Java types used @@ -54,59 +54,60 @@ // convert Nashorn parser Tree, Diagnostic as a script friendly object Parser.prototype.convert = function(tree) { - if (!tree || typeof tree != 'object') { + if (!tree || typeof tree != 'object' || tree instanceof java.lang.Long) { return tree; } var obj = Object.bindProperties({}, tree); var result = {}; for (var i in obj) { - var val = obj[i]; - if (val instanceof Parser.Tree) { - result[i] = this.convert(val); - } else if (val instanceof Parser.List) { - var arr = new Array(val.size()); - for (var j in val) { - arr[j] = this.convert(val[j]); - } - - result[i] = arr; - } else { - switch (typeof val) { - case 'number': - case 'string': - case 'boolean': - result[i] = String(val); - default: - if (val instanceof Parser.Enum) { - result[i] = String(val); - } - } - } - } - return result; + var val = obj[i]; + if (val instanceof Parser.Tree) { + result[i] = this.convert(val); + } else if (val instanceof Parser.List) { + var arr = new Array(val.size()); + for (var j in val) { + arr[j] = this.convert(val[j]); + } + + result[i] = arr; + } else { + switch (typeof val) { + case 'number': + case 'string': + case 'boolean': + result[i] = String(val); + break; + default: + if (val instanceof java.lang.Long || val instanceof Parser.Enum) { + result[i] = String(val); + } + } + } + } + return result; } function processFiles(subdir) { - var File = Java.type("java.io.File"); - var files = new File(__DIR__ + subdir).listFiles(); - java.util.Arrays.sort(files); - for each (var file in files) { - if (file.name.endsWith(".js")) { - var script = readFully(file); - var parser = new Parser(); - var tree = parser.parse(subdir + "/" + file.name, script, - function(diagnostic) { - print(JSON.stringify(parser.convert(diagnostic), null, 2).replace(/\\r/g, '')); - print(","); - }); + var File = Java.type("java.io.File"); + var files = new File(__DIR__ + subdir).listFiles(); + java.util.Arrays.sort(files); + for each (var file in files) { + if (file.name.endsWith(".js")) { + var script = readFully(file); + var parser = new Parser(); + var tree = parser.parse(subdir + "/" + file.name, script, + function(diagnostic) { + print(JSON.stringify(parser.convert(diagnostic), null, 2).replace(/\\r/g, '')); + print(","); + }); - if (tree != null) { - print(JSON.stringify(tree, null, 2)); - print(","); - } - } - } + if (tree != null) { + print(JSON.stringify(tree, null, 2)); + print(","); + } + } + } } // parse files in parsertests directory
--- a/nashorn/test/script/nosecurity/parserapi.js.EXPECTED Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/test/script/nosecurity/parserapi.js.EXPECTED Thu Jan 14 12:03:53 2016 -0800 @@ -1,4 +1,4 @@ -[ +[ { "endPosition": "1113", "kind": "COMPILATION_UNIT", @@ -132,8 +132,8 @@ "sourceName": "parsertests/array_literal.js", "strict": "false", "startPosition": "1113" -} -, +} +, { "endPosition": "1126", "kind": "COMPILATION_UNIT", @@ -406,8 +406,8 @@ "sourceName": "parsertests/assignmentExpr.js", "strict": "false", "startPosition": "1126" -} -, +} +, { "endPosition": "1116", "kind": "COMPILATION_UNIT", @@ -912,8 +912,8 @@ "sourceName": "parsertests/binaryExpr.js", "strict": "false", "startPosition": "1116" -} -, +} +, { "endPosition": "1117", "kind": "COMPILATION_UNIT", @@ -959,8 +959,8 @@ "sourceName": "parsertests/block.js", "strict": "false", "startPosition": "1117" -} -, +} +, { "endPosition": "1117", "kind": "COMPILATION_UNIT", @@ -1060,8 +1060,8 @@ "sourceName": "parsertests/breakStat.js", "strict": "false", "startPosition": "1117" -} -, +} +, { "endPosition": "1117", "kind": "COMPILATION_UNIT", @@ -1098,8 +1098,8 @@ "sourceName": "parsertests/condExpr.js", "strict": "false", "startPosition": "1117" -} -, +} +, { "endPosition": "1120", "kind": "COMPILATION_UNIT", @@ -1199,8 +1199,8 @@ "sourceName": "parsertests/continueStat.js", "strict": "false", "startPosition": "1120" -} -, +} +, { "endPosition": "1118", "kind": "COMPILATION_UNIT", @@ -1214,8 +1214,8 @@ "sourceName": "parsertests/debuggerStat.js", "strict": "false", "startPosition": "1118" -} -, +} +, { "endPosition": "1137", "kind": "COMPILATION_UNIT", @@ -1500,8 +1500,8 @@ "sourceName": "parsertests/functions.js", "strict": "false", "startPosition": "1137" -} -, +} +, { "endPosition": "1114", "kind": "COMPILATION_UNIT", @@ -1604,8 +1604,8 @@ "sourceName": "parsertests/ifStat.js", "strict": "false", "startPosition": "1114" -} -, +} +, { "endPosition": "1113", "kind": "COMPILATION_UNIT", @@ -1668,8 +1668,8 @@ "sourceName": "parsertests/labelledStat.js", "strict": "false", "startPosition": "1113" -} -, +} +, { "endPosition": "1125", "kind": "COMPILATION_UNIT", @@ -2066,8 +2066,8 @@ "sourceName": "parsertests/lhsExpr.js", "strict": "false", "startPosition": "1125" -} -, +} +, { "endPosition": "1110", "kind": "COMPILATION_UNIT", @@ -2350,8 +2350,8 @@ "sourceName": "parsertests/loopStat.js", "strict": "false", "startPosition": "1110" -} -, +} +, { "endPosition": "1125", "kind": "COMPILATION_UNIT", @@ -2705,8 +2705,8 @@ "sourceName": "parsertests/objectLitExpr.js", "strict": "false", "startPosition": "1125" -} -, +} +, { "endPosition": "1118", "kind": "COMPILATION_UNIT", @@ -2781,8 +2781,8 @@ "sourceName": "parsertests/parenExpr.js", "strict": "false", "startPosition": "1118" -} -, +} +, { "endPosition": "1119", "kind": "COMPILATION_UNIT", @@ -2995,8 +2995,8 @@ "sourceName": "parsertests/primaryExpr.js", "strict": "false", "startPosition": "1119" -} -, +} +, { "endPosition": "1114", "kind": "COMPILATION_UNIT", @@ -3044,8 +3044,8 @@ "sourceName": "parsertests/regexp_literal.js", "strict": "false", "startPosition": "1114" -} -, +} +, { "endPosition": "1118", "kind": "COMPILATION_UNIT", @@ -3144,8 +3144,8 @@ "sourceName": "parsertests/returnStat.js", "strict": "false", "startPosition": "1118" -} -, +} +, { "endPosition": "1111", "kind": "COMPILATION_UNIT", @@ -3309,8 +3309,8 @@ "sourceName": "parsertests/switchStat.js", "strict": "false", "startPosition": "1111" -} -, +} +, { "endPosition": "1110", "kind": "COMPILATION_UNIT", @@ -3421,8 +3421,8 @@ "sourceName": "parsertests/throwStat.js", "strict": "false", "startPosition": "1110" -} -, +} +, { "endPosition": "1121", "kind": "COMPILATION_UNIT", @@ -3783,8 +3783,8 @@ "sourceName": "parsertests/tryCatchStat.js", "strict": "false", "startPosition": "1121" -} -, +} +, { "endPosition": "1115", "kind": "COMPILATION_UNIT", @@ -3969,8 +3969,8 @@ "sourceName": "parsertests/unaryExpr.js", "strict": "false", "startPosition": "1115" -} -, +} +, { "endPosition": "1122", "kind": "COMPILATION_UNIT", @@ -4016,8 +4016,8 @@ "sourceName": "parsertests/useStrict.js", "strict": "true", "startPosition": "1122" -} -, +} +, { "endPosition": "1143", "kind": "COMPILATION_UNIT", @@ -4092,8 +4092,8 @@ "sourceName": "parsertests/varDecl.js", "strict": "false", "startPosition": "1143" -} -, +} +, { "endPosition": "1111", "kind": "COMPILATION_UNIT", @@ -4142,8 +4142,8 @@ "sourceName": "parsertests/withStat.js", "strict": "false", "startPosition": "1111" -} -, +} +, { "fileName": "parsernegativetests/caseoutofswitch.js", "code": "case (1090, 4)", @@ -4152,8 +4152,8 @@ "position": "1090", "message": "parsernegativetests/caseoutofswitch.js:29:0 Expected an operand but found case\ncase 23:\n^", "lineNumber": "29" -} -, +} +, { "fileName": "parsernegativetests/caseoutofswitch.js", "code": "default (1112, 7)", @@ -4162,8 +4162,8 @@ "position": "1112", "message": "parsernegativetests/caseoutofswitch.js:31:0 Expected an operand but found default\ndefault:\n^", "lineNumber": "31" -} -, +} +, { "endPosition": "1090", "kind": "COMPILATION_UNIT", @@ -4240,8 +4240,8 @@ "sourceName": "parsernegativetests/caseoutofswitch.js", "strict": "false", "startPosition": "1090" -} -, +} +, { "fileName": "parsernegativetests/illegalbreak.js", "code": "break (1090, 5)", @@ -4250,8 +4250,8 @@ "position": "1090", "message": "parsernegativetests/illegalbreak.js:29:0 Illegal break statement\nbreak;\n^", "lineNumber": "29" -} -, +} +, { "fileName": "parsernegativetests/illegalbreak.js", "code": "ident (1103, 3)", @@ -4260,8 +4260,8 @@ "position": "1103", "message": "parsernegativetests/illegalbreak.js:30:6 Undefined Label \"foo\"\nbreak foo;\n ^", "lineNumber": "30" -} -, +} +, { "endPosition": "1090", "kind": "COMPILATION_UNIT", @@ -4290,8 +4290,8 @@ "sourceName": "parsernegativetests/illegalbreak.js", "strict": "false", "startPosition": "1090" -} -, +} +, { "fileName": "parsernegativetests/illegalcontinue.js", "code": "continue (1090, 8)", @@ -4300,8 +4300,8 @@ "position": "1090", "message": "parsernegativetests/illegalcontinue.js:29:0 Illegal continue statement\ncontinue;\n^", "lineNumber": "29" -} -, +} +, { "fileName": "parsernegativetests/illegalcontinue.js", "code": "ident (1109, 3)", @@ -4310,8 +4310,8 @@ "position": "1109", "message": "parsernegativetests/illegalcontinue.js:30:9 Undefined Label \"foo\"\ncontinue foo;\n ^", "lineNumber": "30" -} -, +} +, { "endPosition": "1090", "kind": "COMPILATION_UNIT", @@ -4340,8 +4340,8 @@ "sourceName": "parsernegativetests/illegalcontinue.js", "strict": "false", "startPosition": "1090" -} -, +} +, { "fileName": "parsernegativetests/illegallvalue.js", "code": "decimal (1090, 2)", @@ -4350,8 +4350,8 @@ "position": "1090", "message": "parsernegativetests/illegallvalue.js:29:0 Invalid left hand side for assignment\n44 = 54;\n^", "lineNumber": "29" -} -, +} +, { "fileName": "parsernegativetests/illegallvalue.js", "code": "decimal (1099, 3)", @@ -4360,8 +4360,8 @@ "position": "1099", "message": "parsernegativetests/illegallvalue.js:30:0 Invalid left hand side for assignment\n233 += 33;\n^", "lineNumber": "30" -} -, +} +, { "fileName": "parsernegativetests/illegallvalue.js", "code": "decimal (1110, 4)", @@ -4370,8 +4370,8 @@ "position": "1110", "message": "parsernegativetests/illegallvalue.js:31:0 Invalid left hand side for assignment\n3423 -= 234;\n^", "lineNumber": "31" -} -, +} +, { "endPosition": "1090", "kind": "COMPILATION_UNIT", @@ -4410,8 +4410,8 @@ "sourceName": "parsernegativetests/illegallvalue.js", "strict": "false", "startPosition": "1090" -} -, +} +, { "fileName": "parsernegativetests/illegaloperator.js", "code": "* (1093, 1)", @@ -4420,8 +4420,8 @@ "position": "1093", "message": "parsernegativetests/illegaloperator.js:29:3 Expected an operand but found *\nx ** y\n ^", "lineNumber": "29" -} -, +} +, { "endPosition": "1090", "kind": "COMPILATION_UNIT", @@ -4440,8 +4440,8 @@ "sourceName": "parsernegativetests/illegaloperator.js", "strict": "false", "startPosition": "1090" -} -, +} +, { "fileName": "parsernegativetests/keywordident.js", "code": "var (1094, 3)", @@ -4450,8 +4450,8 @@ "position": "1094", "message": "parsernegativetests/keywordident.js:29:4 Expected ident but found var\nvar var = 23;\n ^", "lineNumber": "29" -} -, +} +, { "endPosition": "1090", "kind": "COMPILATION_UNIT", @@ -4482,8 +4482,8 @@ "sourceName": "parsernegativetests/keywordident.js", "strict": "false", "startPosition": "1090" -} -, +} +, { "fileName": "parsernegativetests/parenmissing.js", "code": "; (1096, 1)", @@ -4492,8 +4492,8 @@ "position": "1096", "message": "parsernegativetests/parenmissing.js:29:6 Expected ) but found ;\n(1 + 2;\n ^", "lineNumber": "29" -} -, +} +, { "fileName": "parsernegativetests/parenmissing.js", "code": ") (1103, 1)", @@ -4502,8 +4502,8 @@ "position": "1103", "message": "parsernegativetests/parenmissing.js:30:5 Expected ; but found )\nx * y);\n ^", "lineNumber": "30" -} -, +} +, { "endPosition": "1090", "kind": "COMPILATION_UNIT", @@ -4554,8 +4554,8 @@ "sourceName": "parsernegativetests/parenmissing.js", "strict": "false", "startPosition": "1090" -} -, +} +, { "fileName": "parsernegativetests/repeatedproperty.js", "code": "ident (1111, 3)", @@ -4564,8 +4564,8 @@ "position": "1111", "message": "parsernegativetests/repeatedproperty.js:29:21 Property \"foo\" already defined\nvar obj = { foo: 34, get foo() { return 'hello' } };\n ^", "lineNumber": "29" -} -, +} +, { "fileName": "parsernegativetests/repeatedproperty.js", "code": "ident (1165, 3)", @@ -4574,8 +4574,8 @@ "position": "1165", "message": "parsernegativetests/repeatedproperty.js:30:22 Property \"foo\" already defined\nvar obj1 = { foo: 34, set foo(x) { } };\n ^", "lineNumber": "30" -} -, +} +, { "fileName": "parsernegativetests/repeatedproperty.js", "code": "ident (1205, 3)", @@ -4584,8 +4584,8 @@ "position": "1205", "message": "parsernegativetests/repeatedproperty.js:31:22 Property \"foo\" already defined\nvar obj2 = { foo: 34, set foo(x) { } };\n ^", "lineNumber": "31" -} -, +} +, { "fileName": "parsernegativetests/repeatedproperty.js", "code": "ident (1251, 3)", @@ -4594,8 +4594,8 @@ "position": "1251", "message": "parsernegativetests/repeatedproperty.js:32:28 Property \"bar\" already defined\nvar obj3 = { get bar() { }, get bar() {} };\n ^", "lineNumber": "32" -} -, +} +, { "fileName": "parsernegativetests/repeatedproperty.js", "code": "ident (1296, 3)", @@ -4604,8 +4604,8 @@ "position": "1296", "message": "parsernegativetests/repeatedproperty.js:33:29 Property \"bar\" already defined\nvar obj4 = { set bar(x) { }, set bar(x) {} };\n ^", "lineNumber": "33" -} -, +} +, { "endPosition": "1090", "kind": "COMPILATION_UNIT", @@ -4664,8 +4664,8 @@ "sourceName": "parsernegativetests/repeatedproperty.js", "strict": "false", "startPosition": "1090" -} -, +} +, { "fileName": "parsernegativetests/strict_repeatedproperty.js", "code": "ident (1126, 3)", @@ -4674,8 +4674,8 @@ "position": "1126", "message": "parsernegativetests/strict_repeatedproperty.js:31:21 Property \"foo\" already defined\nvar obj = { foo: 34, foo: 'hello' };\n ^", "lineNumber": "31" -} -, +} +, { "endPosition": "1090", "kind": "COMPILATION_UNIT", @@ -4705,8 +4705,8 @@ "sourceName": "parsernegativetests/strict_repeatedproperty.js", "strict": "true", "startPosition": "1090" -} -, +} +, { "fileName": "parsernegativetests/strict_repeatparam.js", "code": "ident (1119, 1)", @@ -4715,8 +4715,8 @@ "position": "1119", "message": "parsernegativetests/strict_repeatparam.js:31:14 strict mode function cannot have duplicate parameter name \"x\"\nfunction func(x, x) {}\n ^", "lineNumber": "31" -} -, +} +, { "endPosition": "1090", "kind": "COMPILATION_UNIT", @@ -4746,8 +4746,8 @@ "sourceName": "parsernegativetests/strict_repeatparam.js", "strict": "true", "startPosition": "1090" -} -, +} +, { "fileName": "parsernegativetests/strict_with.js", "code": "with (1105, 4)", @@ -4756,8 +4756,8 @@ "position": "1105", "message": "parsernegativetests/strict_with.js:31:0 \"with\" statement cannot be used in strict mode\nwith({}) {}\n^", "lineNumber": "31" -} -, +} +, { "fileName": "parsernegativetests/strict_with.js", "code": ") (1112, 1)", @@ -4766,8 +4766,8 @@ "position": "1112", "message": "parsernegativetests/strict_with.js:31:7 Expected ; but found )\nwith({}) {}\n ^", "lineNumber": "31" -} -, +} +, { "endPosition": "1090", "kind": "COMPILATION_UNIT", @@ -4807,8 +4807,8 @@ "sourceName": "parsernegativetests/strict_with.js", "strict": "true", "startPosition": "1090" -} -, +} +, { "fileName": "parsernegativetests/toplevelreturn.js", "code": "return (1090, 6)", @@ -4817,8 +4817,8 @@ "position": "1090", "message": "parsernegativetests/toplevelreturn.js:29:0 Invalid return statement\nreturn;\n^", "lineNumber": "29" -} -, +} +, { "fileName": "parsernegativetests/toplevelreturn.js", "code": "return (1098, 6)", @@ -4827,8 +4827,8 @@ "position": "1098", "message": "parsernegativetests/toplevelreturn.js:30:0 Invalid return statement\nreturn 23;\n^", "lineNumber": "30" -} -, +} +, { "endPosition": "1090", "kind": "COMPILATION_UNIT", @@ -4857,59 +4857,59 @@ "sourceName": "parsernegativetests/toplevelreturn.js", "strict": "false", "startPosition": "1090" -} -, +} +, { "endPosition": "1136", "kind": "COMPILATION_UNIT", "sourceElements": [ { - "endPosition": "1240", + "endPosition": "1242", "kind": "FUNCTION", "name": "Parser", "body": { - "endPosition": "1218", + "endPosition": "1220", "kind": "BLOCK", "statements": [ { "expression": { "expression": { - "endPosition": "1217", + "endPosition": "1219", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "create", "expression": { - "endPosition": "1208", + "endPosition": "1210", "kind": "IDENTIFIER", "name": "Parser", - "startPosition": "1202" + "startPosition": "1204" }, - "endPosition": "1215", + "endPosition": "1217", "kind": "MEMBER_SELECT", - "startPosition": "1202" + "startPosition": "1204" }, "arguments": [], - "startPosition": "1202" + "startPosition": "1204" }, - "endPosition": "1217", + "endPosition": "1219", "kind": "ASSIGNMENT", "variable": { "identifier": "_parser", "expression": { - "endPosition": "1191", + "endPosition": "1193", "kind": "IDENTIFIER", "name": "this", - "startPosition": "1187" + "startPosition": "1189" }, - "endPosition": "1199", + "endPosition": "1201", "kind": "MEMBER_SELECT", - "startPosition": "1187" + "startPosition": "1189" }, - "startPosition": "1187" + "startPosition": "1189" }, - "endPosition": "1217", + "endPosition": "1219", "kind": "EXPRESSION_STATEMENT", - "startPosition": "1187" + "startPosition": "1189" } ], "startPosition": "1154" @@ -4921,1368 +4921,1489 @@ { "expression": { "expression": { - "endPosition": "1305", + "endPosition": "1307", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "type", "expression": { - "endPosition": "1265", + "endPosition": "1267", "kind": "IDENTIFIER", "name": "Java", - "startPosition": "1261" + "startPosition": "1263" }, - "endPosition": "1270", + "endPosition": "1272", "kind": "MEMBER_SELECT", - "startPosition": "1261" + "startPosition": "1263" }, "arguments": [ { - "endPosition": "1303", + "endPosition": "1305", "kind": "STRING_LITERAL", "value": "jdk.nashorn.api.tree.Diagnostic", - "startPosition": "1272" + "startPosition": "1274" } ], - "startPosition": "1261" - }, - "endPosition": "1305", + "startPosition": "1263" + }, + "endPosition": "1307", "kind": "ASSIGNMENT", "variable": { "identifier": "Diagnostic", "expression": { - "endPosition": "1247", + "endPosition": "1249", "kind": "IDENTIFIER", "name": "Parser", - "startPosition": "1241" + "startPosition": "1243" }, - "endPosition": "1258", + "endPosition": "1260", "kind": "MEMBER_SELECT", - "startPosition": "1241" - }, - "startPosition": "1241" - }, - "endPosition": "1305", + "startPosition": "1243" + }, + "startPosition": "1243" + }, + "endPosition": "1307", "kind": "EXPRESSION_STATEMENT", - "startPosition": "1241" + "startPosition": "1243" }, { "expression": { "expression": { - "endPosition": "1390", + "endPosition": "1392", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "type", "expression": { - "endPosition": "1338", + "endPosition": "1340", "kind": "IDENTIFIER", "name": "Java", - "startPosition": "1334" + "startPosition": "1336" }, - "endPosition": "1343", + "endPosition": "1345", "kind": "MEMBER_SELECT", - "startPosition": "1334" + "startPosition": "1336" }, "arguments": [ { - "endPosition": "1388", + "endPosition": "1390", "kind": "STRING_LITERAL", "value": "jdk.nashorn.api.tree.SimpleTreeVisitorES5_1", - "startPosition": "1345" + "startPosition": "1347" } ], - "startPosition": "1334" - }, - "endPosition": "1390", + "startPosition": "1336" + }, + "endPosition": "1392", "kind": "ASSIGNMENT", "variable": { "identifier": "SimpleTreeVisitor", "expression": { - "endPosition": "1313", + "endPosition": "1315", "kind": "IDENTIFIER", "name": "Parser", - "startPosition": "1307" + "startPosition": "1309" }, - "endPosition": "1331", + "endPosition": "1333", "kind": "MEMBER_SELECT", - "startPosition": "1307" - }, - "startPosition": "1307" - }, - "endPosition": "1390", + "startPosition": "1309" + }, + "startPosition": "1309" + }, + "endPosition": "1392", "kind": "EXPRESSION_STATEMENT", - "startPosition": "1307" + "startPosition": "1309" }, { "expression": { "expression": { - "endPosition": "1444", + "endPosition": "1446", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "type", "expression": { - "endPosition": "1410", + "endPosition": "1412", "kind": "IDENTIFIER", "name": "Java", - "startPosition": "1406" + "startPosition": "1408" }, - "endPosition": "1415", + "endPosition": "1417", "kind": "MEMBER_SELECT", - "startPosition": "1406" + "startPosition": "1408" }, "arguments": [ { - "endPosition": "1442", + "endPosition": "1444", "kind": "STRING_LITERAL", "value": "jdk.nashorn.api.tree.Tree", - "startPosition": "1417" + "startPosition": "1419" } ], - "startPosition": "1406" - }, - "endPosition": "1444", + "startPosition": "1408" + }, + "endPosition": "1446", "kind": "ASSIGNMENT", "variable": { "identifier": "Tree", "expression": { - "endPosition": "1398", + "endPosition": "1400", "kind": "IDENTIFIER", "name": "Parser", - "startPosition": "1392" + "startPosition": "1394" }, - "endPosition": "1403", + "endPosition": "1405", "kind": "MEMBER_SELECT", - "startPosition": "1392" - }, - "startPosition": "1392" - }, - "endPosition": "1444", + "startPosition": "1394" + }, + "startPosition": "1394" + }, + "endPosition": "1446", "kind": "EXPRESSION_STATEMENT", - "startPosition": "1392" + "startPosition": "1394" }, { "expression": { "expression": { - "endPosition": "1487", + "endPosition": "1489", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "type", "expression": { - "endPosition": "1464", + "endPosition": "1466", "kind": "IDENTIFIER", "name": "Java", - "startPosition": "1460" + "startPosition": "1462" }, - "endPosition": "1469", + "endPosition": "1471", "kind": "MEMBER_SELECT", - "startPosition": "1460" + "startPosition": "1462" }, "arguments": [ { - "endPosition": "1485", + "endPosition": "1487", "kind": "STRING_LITERAL", "value": "java.util.List", - "startPosition": "1471" + "startPosition": "1473" } ], - "startPosition": "1460" - }, - "endPosition": "1487", + "startPosition": "1462" + }, + "endPosition": "1489", "kind": "ASSIGNMENT", "variable": { "identifier": "List", "expression": { - "endPosition": "1452", + "endPosition": "1454", "kind": "IDENTIFIER", "name": "Parser", - "startPosition": "1446" + "startPosition": "1448" }, - "endPosition": "1457", + "endPosition": "1459", "kind": "MEMBER_SELECT", - "startPosition": "1446" - }, - "startPosition": "1446" - }, - "endPosition": "1487", + "startPosition": "1448" + }, + "startPosition": "1448" + }, + "endPosition": "1489", "kind": "EXPRESSION_STATEMENT", - "startPosition": "1446" + "startPosition": "1448" }, { "expression": { "expression": { - "endPosition": "1530", + "endPosition": "1532", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "type", "expression": { - "endPosition": "1507", + "endPosition": "1509", "kind": "IDENTIFIER", "name": "Java", - "startPosition": "1503" + "startPosition": "1505" }, - "endPosition": "1512", + "endPosition": "1514", "kind": "MEMBER_SELECT", - "startPosition": "1503" + "startPosition": "1505" }, "arguments": [ { - "endPosition": "1528", + "endPosition": "1530", "kind": "STRING_LITERAL", "value": "java.lang.Enum", - "startPosition": "1514" + "startPosition": "1516" } ], - "startPosition": "1503" - }, - "endPosition": "1530", + "startPosition": "1505" + }, + "endPosition": "1532", "kind": "ASSIGNMENT", "variable": { "identifier": "Enum", "expression": { - "endPosition": "1495", + "endPosition": "1497", "kind": "IDENTIFIER", "name": "Parser", - "startPosition": "1489" + "startPosition": "1491" }, - "endPosition": "1500", + "endPosition": "1502", "kind": "MEMBER_SELECT", - "startPosition": "1489" - }, - "startPosition": "1489" - }, - "endPosition": "1530", + "startPosition": "1491" + }, + "startPosition": "1491" + }, + "endPosition": "1532", "kind": "EXPRESSION_STATEMENT", - "startPosition": "1489" + "startPosition": "1491" }, { "expression": { "expression": { - "endPosition": "1657", + "endPosition": "1659", "kind": "FUNCTION_EXPRESSION", "body": { - "endPosition": "1803", + "endPosition": "1805", "kind": "BLOCK", "statements": [ { - "endPosition": "1716", + "endPosition": "1718", "kind": "VARIABLE", "name": "tree", - "startPosition": "1667", + "startPosition": "1669", "initializer": { - "endPosition": "1716", + "endPosition": "1718", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "parse", "expression": { "identifier": "_parser", "expression": { - "endPosition": "1678", + "endPosition": "1680", "kind": "IDENTIFIER", "name": "this", - "startPosition": "1674" + "startPosition": "1676" }, - "endPosition": "1686", + "endPosition": "1688", "kind": "MEMBER_SELECT", - "startPosition": "1674" + "startPosition": "1676" }, - "endPosition": "1692", + "endPosition": "1694", "kind": "MEMBER_SELECT", - "startPosition": "1674" + "startPosition": "1676" }, "arguments": [ { - "endPosition": "1697", + "endPosition": "1699", "kind": "IDENTIFIER", "name": "name", - "startPosition": "1693" + "startPosition": "1695" }, { - "endPosition": "1705", + "endPosition": "1707", "kind": "IDENTIFIER", "name": "script", - "startPosition": "1699" + "startPosition": "1701" }, { - "endPosition": "1715", + "endPosition": "1717", "kind": "IDENTIFIER", "name": "listener", - "startPosition": "1707" + "startPosition": "1709" } ], - "startPosition": "1674" + "startPosition": "1676" } }, { "expression": { - "endPosition": "1771", + "endPosition": "1773", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "accept", "expression": { - "endPosition": "1726", + "endPosition": "1728", "kind": "IDENTIFIER", "name": "tree", - "startPosition": "1722" + "startPosition": "1724" }, - "endPosition": "1733", + "endPosition": "1735", "kind": "MEMBER_SELECT", - "startPosition": "1722" + "startPosition": "1724" }, "arguments": [ { "constructorExpression": { - "endPosition": "1764", + "endPosition": "1766", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "SimpleTreeVisitor", "expression": { - "endPosition": "1744", + "endPosition": "1746", "kind": "IDENTIFIER", "name": "Parser", - "startPosition": "1738" + "startPosition": "1740" }, - "endPosition": "1762", + "endPosition": "1764", "kind": "MEMBER_SELECT", - "startPosition": "1738" + "startPosition": "1740" }, "arguments": [], - "startPosition": "1744" + "startPosition": "1746" }, - "endPosition": "1764", + "endPosition": "1766", "kind": "NEW", - "startPosition": "1734" + "startPosition": "1736" }, { - "endPosition": "1770", + "endPosition": "1772", "kind": "NULL_LITERAL", - "startPosition": "1766" + "startPosition": "1768" } ], - "startPosition": "1722" + "startPosition": "1724" }, - "endPosition": "1771", + "endPosition": "1773", "kind": "EXPRESSION_STATEMENT", - "startPosition": "1722" + "startPosition": "1724" }, { "expression": { - "endPosition": "1802", + "endPosition": "1804", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "convert", "expression": { - "endPosition": "1788", + "endPosition": "1790", "kind": "IDENTIFIER", "name": "this", - "startPosition": "1784" + "startPosition": "1786" }, - "endPosition": "1796", + "endPosition": "1798", "kind": "MEMBER_SELECT", - "startPosition": "1784" + "startPosition": "1786" }, "arguments": [ { - "endPosition": "1801", + "endPosition": "1803", "kind": "IDENTIFIER", "name": "tree", - "startPosition": "1797" + "startPosition": "1799" } ], - "startPosition": "1784" + "startPosition": "1786" }, - "endPosition": "1803", + "endPosition": "1805", "kind": "RETURN", - "startPosition": "1777" + "startPosition": "1779" } ], - "startPosition": "1657" + "startPosition": "1659" }, "strict": "false", - "startPosition": "1657", + "startPosition": "1659", "parameters": [ { - "endPosition": "1637", + "endPosition": "1639", "kind": "IDENTIFIER", "name": "name", - "startPosition": "1633" + "startPosition": "1635" }, { - "endPosition": "1645", + "endPosition": "1647", "kind": "IDENTIFIER", "name": "script", - "startPosition": "1639" + "startPosition": "1641" }, { - "endPosition": "1655", + "endPosition": "1657", "kind": "IDENTIFIER", "name": "listener", - "startPosition": "1647" + "startPosition": "1649" } ] }, - "endPosition": "1657", + "endPosition": "1659", "kind": "ASSIGNMENT", "variable": { "identifier": "parse", "expression": { "identifier": "prototype", "expression": { - "endPosition": "1605", + "endPosition": "1607", "kind": "IDENTIFIER", "name": "Parser", - "startPosition": "1599" + "startPosition": "1601" }, - "endPosition": "1615", + "endPosition": "1617", "kind": "MEMBER_SELECT", - "startPosition": "1599" + "startPosition": "1601" }, - "endPosition": "1621", + "endPosition": "1623", "kind": "MEMBER_SELECT", - "startPosition": "1599" - }, - "startPosition": "1599" - }, - "endPosition": "1805", + "startPosition": "1601" + }, + "startPosition": "1601" + }, + "endPosition": "1807", "kind": "EXPRESSION_STATEMENT", - "startPosition": "1599" + "startPosition": "1601" }, { "expression": { "expression": { - "endPosition": "1834", + "endPosition": "1836", "kind": "FUNCTION_EXPRESSION", "body": { - "endPosition": "1897", + "endPosition": "1899", "kind": "BLOCK", "statements": [ { "expression": { - "endPosition": "1896", + "endPosition": "1898", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "create", "expression": { - "endPosition": "1887", + "endPosition": "1889", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "type", "expression": { - "endPosition": "1851", + "endPosition": "1853", "kind": "IDENTIFIER", "name": "Java", - "startPosition": "1847" + "startPosition": "1849" }, - "endPosition": "1856", + "endPosition": "1858", "kind": "MEMBER_SELECT", - "startPosition": "1847" + "startPosition": "1849" }, "arguments": [ { - "endPosition": "1885", + "endPosition": "1887", "kind": "STRING_LITERAL", "value": "jdk.nashorn.api.tree.Parser", - "startPosition": "1858" + "startPosition": "1860" } ], - "startPosition": "1847" + "startPosition": "1849" }, - "endPosition": "1894", + "endPosition": "1896", "kind": "MEMBER_SELECT", - "startPosition": "1847" + "startPosition": "1849" }, "arguments": [], - "startPosition": "1894" + "startPosition": "1896" }, - "endPosition": "1897", + "endPosition": "1899", "kind": "RETURN", - "startPosition": "1840" + "startPosition": "1842" } ], - "startPosition": "1834" + "startPosition": "1836" }, "strict": "false", - "startPosition": "1834", + "startPosition": "1836", "parameters": [] }, - "endPosition": "1834", + "endPosition": "1836", "kind": "ASSIGNMENT", "variable": { "identifier": "create", "expression": { - "endPosition": "1813", + "endPosition": "1815", "kind": "IDENTIFIER", "name": "Parser", - "startPosition": "1807" + "startPosition": "1809" }, - "endPosition": "1820", + "endPosition": "1822", "kind": "MEMBER_SELECT", - "startPosition": "1807" - }, - "startPosition": "1807" - }, - "endPosition": "1971", + "startPosition": "1809" + }, + "startPosition": "1809" + }, + "endPosition": "1973", "kind": "EXPRESSION_STATEMENT", - "startPosition": "1807" + "startPosition": "1809" }, { "expression": { "expression": { - "endPosition": "2014", + "endPosition": "2016", "kind": "FUNCTION_EXPRESSION", "body": { - "endPosition": "2863", + "endPosition": "2994", "kind": "BLOCK", "statements": [ { "condition": { "leftOperand": { - "expression": { - "endPosition": "2029", - "kind": "IDENTIFIER", - "name": "tree", - "startPosition": "2025" + "leftOperand": { + "expression": { + "endPosition": "2031", + "kind": "IDENTIFIER", + "name": "tree", + "startPosition": "2027" + }, + "endPosition": "2031", + "kind": "LOGICAL_COMPLEMENT", + "startPosition": "2026" }, - "endPosition": "2029", - "kind": "LOGICAL_COMPLEMENT", - "startPosition": "2024" + "endPosition": "2057", + "kind": "CONDITIONAL_OR", + "rightOperand": { + "leftOperand": { + "expression": { + "endPosition": "2046", + "kind": "IDENTIFIER", + "name": "tree", + "startPosition": "2042" + }, + "endPosition": "2046", + "kind": "TYPEOF", + "startPosition": "2035" + }, + "endPosition": "2057", + "kind": "NOT_EQUAL_TO", + "rightOperand": { + "endPosition": "2057", + "kind": "STRING_LITERAL", + "value": "object", + "startPosition": "2051" + }, + "startPosition": "2035" + }, + "startPosition": "2026" }, - "endPosition": "2055", + "endPosition": "2092", "kind": "CONDITIONAL_OR", "rightOperand": { "leftOperand": { - "expression": { - "endPosition": "2044", - "kind": "IDENTIFIER", - "name": "tree", - "startPosition": "2040" - }, - "endPosition": "2044", - "kind": "TYPEOF", - "startPosition": "2033" + "endPosition": "2066", + "kind": "IDENTIFIER", + "name": "tree", + "startPosition": "2062" }, - "endPosition": "2055", - "kind": "NOT_EQUAL_TO", + "expression": { + "endPosition": "2066", + "kind": "IDENTIFIER", + "name": "tree", + "startPosition": "2062" + }, + "endPosition": "2092", + "kind": "INSTANCE_OF", "rightOperand": { - "endPosition": "2055", - "kind": "STRING_LITERAL", - "value": "object", - "startPosition": "2049" + "identifier": "Long", + "expression": { + "identifier": "lang", + "expression": { + "endPosition": "2082", + "kind": "IDENTIFIER", + "name": "java", + "startPosition": "2078" + }, + "endPosition": "2087", + "kind": "MEMBER_SELECT", + "startPosition": "2078" + }, + "endPosition": "2092", + "kind": "MEMBER_SELECT", + "startPosition": "2078" }, - "startPosition": "2033" + "type": { + "identifier": "Long", + "expression": { + "identifier": "lang", + "expression": { + "endPosition": "2082", + "kind": "IDENTIFIER", + "name": "java", + "startPosition": "2078" + }, + "endPosition": "2087", + "kind": "MEMBER_SELECT", + "startPosition": "2078" + }, + "endPosition": "2092", + "kind": "MEMBER_SELECT", + "startPosition": "2078" + }, + "startPosition": "2062" }, - "startPosition": "2024" + "startPosition": "2026" }, - "endPosition": "2086", + "endPosition": "2122", "kind": "IF", - "startPosition": "2020", + "startPosition": "2022", "thenStatement": { - "endPosition": "2086", + "endPosition": "2122", "kind": "BLOCK", "statements": [ { "expression": { - "endPosition": "2079", + "endPosition": "2115", "kind": "IDENTIFIER", "name": "tree", - "startPosition": "2075" + "startPosition": "2111" }, - "endPosition": "2080", + "endPosition": "2116", "kind": "RETURN", - "startPosition": "2068" + "startPosition": "2104" } ], - "startPosition": "2058" + "startPosition": "2094" } }, { - "endPosition": "2133", + "endPosition": "2169", "kind": "VARIABLE", "name": "obj", - "startPosition": "2096", + "startPosition": "2132", "initializer": { - "endPosition": "2133", + "endPosition": "2169", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "bindProperties", "expression": { - "endPosition": "2108", + "endPosition": "2144", "kind": "IDENTIFIER", "name": "Object", - "startPosition": "2102" + "startPosition": "2138" }, - "endPosition": "2123", + "endPosition": "2159", "kind": "MEMBER_SELECT", - "startPosition": "2102" + "startPosition": "2138" }, "arguments": [ { - "endPosition": "2126", + "endPosition": "2162", "kind": "OBJECT_LITERAL", - "startPosition": "2124", + "startPosition": "2160", "properties": [] }, { - "endPosition": "2132", + "endPosition": "2168", "kind": "IDENTIFIER", "name": "tree", - "startPosition": "2128" + "startPosition": "2164" } ], - "startPosition": "2102" + "startPosition": "2138" } }, { - "endPosition": "2154", + "endPosition": "2190", "kind": "VARIABLE", "name": "result", - "startPosition": "2143", + "startPosition": "2179", "initializer": { - "endPosition": "2154", + "endPosition": "2190", "kind": "OBJECT_LITERAL", - "startPosition": "2152", + "startPosition": "2188", "properties": [] } }, { - "endPosition": "2170", + "endPosition": "2206", "kind": "VARIABLE", "name": "i", - "startPosition": "2169" + "startPosition": "2205" }, { "expression": { - "endPosition": "2177", + "endPosition": "2213", "kind": "IDENTIFIER", "name": "obj", - "startPosition": "2174" + "startPosition": "2210" }, - "endPosition": "2845", + "endPosition": "2975", "kind": "FOR_IN_LOOP", "forEach": "false", "variable": { - "endPosition": "2170", + "endPosition": "2206", "kind": "IDENTIFIER", "name": "i", - "startPosition": "2169" + "startPosition": "2205" }, "statement": { - "endPosition": "2845", + "endPosition": "2975", "kind": "BLOCK", "statements": [ { - "endPosition": "2204", + "endPosition": "2241", "kind": "VARIABLE", "name": "val", - "startPosition": "2192", + "startPosition": "2229", "initializer": { "expression": { - "endPosition": "2201", + "endPosition": "2238", "kind": "IDENTIFIER", "name": "obj", - "startPosition": "2198" + "startPosition": "2235" }, - "endPosition": "2204", + "endPosition": "2241", "kind": "ARRAY_ACCESS", "index": { - "endPosition": "2203", + "endPosition": "2240", "kind": "IDENTIFIER", "name": "i", - "startPosition": "2202" + "startPosition": "2239" }, - "startPosition": "2198" + "startPosition": "2235" } }, { "condition": { "leftOperand": { - "endPosition": "2220", + "endPosition": "2258", "kind": "IDENTIFIER", "name": "val", - "startPosition": "2217" + "startPosition": "2255" }, "expression": { - "endPosition": "2220", + "endPosition": "2258", "kind": "IDENTIFIER", "name": "val", - "startPosition": "2217" + "startPosition": "2255" }, - "endPosition": "2243", + "endPosition": "2281", "kind": "INSTANCE_OF", "rightOperand": { "identifier": "Tree", "expression": { - "endPosition": "2238", + "endPosition": "2276", "kind": "IDENTIFIER", "name": "Parser", - "startPosition": "2232" + "startPosition": "2270" }, - "endPosition": "2243", + "endPosition": "2281", "kind": "MEMBER_SELECT", - "startPosition": "2232" + "startPosition": "2270" }, "type": { "identifier": "Tree", "expression": { - "endPosition": "2238", + "endPosition": "2276", "kind": "IDENTIFIER", "name": "Parser", - "startPosition": "2232" + "startPosition": "2270" }, - "endPosition": "2243", + "endPosition": "2281", "kind": "MEMBER_SELECT", - "startPosition": "2232" + "startPosition": "2270" }, - "startPosition": "2217" + "startPosition": "2255" }, "elseStatement": { "condition": { "leftOperand": { - "endPosition": "2309", + "endPosition": "2350", "kind": "IDENTIFIER", "name": "val", - "startPosition": "2306" + "startPosition": "2347" }, "expression": { - "endPosition": "2309", + "endPosition": "2350", "kind": "IDENTIFIER", "name": "val", - "startPosition": "2306" + "startPosition": "2347" }, - "endPosition": "2332", + "endPosition": "2373", "kind": "INSTANCE_OF", "rightOperand": { "identifier": "List", "expression": { - "endPosition": "2327", + "endPosition": "2368", "kind": "IDENTIFIER", "name": "Parser", - "startPosition": "2321" + "startPosition": "2362" }, - "endPosition": "2332", + "endPosition": "2373", "kind": "MEMBER_SELECT", - "startPosition": "2321" + "startPosition": "2362" }, "type": { "identifier": "List", "expression": { - "endPosition": "2327", + "endPosition": "2368", "kind": "IDENTIFIER", "name": "Parser", - "startPosition": "2321" + "startPosition": "2362" }, - "endPosition": "2332", + "endPosition": "2373", "kind": "MEMBER_SELECT", - "startPosition": "2321" + "startPosition": "2362" }, - "startPosition": "2306" + "startPosition": "2347" }, "elseStatement": { - "endPosition": "2840", + "endPosition": "2969", "kind": "BLOCK", "statements": [ { "cases": [ { "expression": { - "endPosition": "2574", + "endPosition": "2625", "kind": "STRING_LITERAL", "value": "number", - "startPosition": "2568" + "startPosition": "2619" }, - "endPosition": "2576", + "endPosition": "2627", "kind": "CASE", "statements": [], - "startPosition": "2562" + "startPosition": "2613" }, { "expression": { - "endPosition": "2603", + "endPosition": "2656", "kind": "STRING_LITERAL", "value": "string", - "startPosition": "2597" + "startPosition": "2650" }, - "endPosition": "2605", + "endPosition": "2658", "kind": "CASE", "statements": [], - "startPosition": "2591" + "startPosition": "2644" }, { "expression": { - "endPosition": "2633", + "endPosition": "2688", "kind": "STRING_LITERAL", "value": "boolean", - "startPosition": "2626" + "startPosition": "2681" }, - "endPosition": "2678", + "endPosition": "2762", "kind": "CASE", "statements": [ { "expression": { "expression": { - "endPosition": "2677", + "endPosition": "2734", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "2672", + "endPosition": "2729", "kind": "IDENTIFIER", "name": "String", - "startPosition": "2666" + "startPosition": "2723" }, "arguments": [ { - "endPosition": "2676", + "endPosition": "2733", "kind": "IDENTIFIER", "name": "val", - "startPosition": "2673" + "startPosition": "2730" } ], - "startPosition": "2666" + "startPosition": "2723" }, - "endPosition": "2677", + "endPosition": "2734", "kind": "ASSIGNMENT", "variable": { "expression": { - "endPosition": "2660", + "endPosition": "2717", "kind": "IDENTIFIER", "name": "result", - "startPosition": "2654" + "startPosition": "2711" }, - "endPosition": "2663", + "endPosition": "2720", "kind": "ARRAY_ACCESS", "index": { - "endPosition": "2662", + "endPosition": "2719", "kind": "IDENTIFIER", "name": "i", - "startPosition": "2661" + "startPosition": "2718" }, - "startPosition": "2654" + "startPosition": "2711" }, - "startPosition": "2654" + "startPosition": "2711" }, - "endPosition": "2677", + "endPosition": "2734", "kind": "EXPRESSION_STATEMENT", - "startPosition": "2654" + "startPosition": "2711" + }, + { + "endPosition": "2762", + "kind": "BREAK", + "startPosition": "2756" } ], - "startPosition": "2620" + "startPosition": "2675" }, { - "endPosition": "2820", + "endPosition": "2945", "kind": "CASE", "statements": [ { "condition": { "leftOperand": { - "endPosition": "2727", - "kind": "IDENTIFIER", - "name": "val", - "startPosition": "2724" - }, - "expression": { - "endPosition": "2727", - "kind": "IDENTIFIER", - "name": "val", - "startPosition": "2724" - }, - "endPosition": "2750", - "kind": "INSTANCE_OF", - "rightOperand": { - "identifier": "Enum", + "leftOperand": { + "endPosition": "2815", + "kind": "IDENTIFIER", + "name": "val", + "startPosition": "2812" + }, "expression": { - "endPosition": "2745", + "endPosition": "2815", "kind": "IDENTIFIER", - "name": "Parser", - "startPosition": "2739" + "name": "val", + "startPosition": "2812" + }, + "endPosition": "2841", + "kind": "INSTANCE_OF", + "rightOperand": { + "identifier": "Long", + "expression": { + "identifier": "lang", + "expression": { + "endPosition": "2831", + "kind": "IDENTIFIER", + "name": "java", + "startPosition": "2827" + }, + "endPosition": "2836", + "kind": "MEMBER_SELECT", + "startPosition": "2827" + }, + "endPosition": "2841", + "kind": "MEMBER_SELECT", + "startPosition": "2827" + }, + "type": { + "identifier": "Long", + "expression": { + "identifier": "lang", + "expression": { + "endPosition": "2831", + "kind": "IDENTIFIER", + "name": "java", + "startPosition": "2827" + }, + "endPosition": "2836", + "kind": "MEMBER_SELECT", + "startPosition": "2827" + }, + "endPosition": "2841", + "kind": "MEMBER_SELECT", + "startPosition": "2827" }, - "endPosition": "2750", - "kind": "MEMBER_SELECT", - "startPosition": "2739" + "startPosition": "2812" }, - "type": { - "identifier": "Enum", + "endPosition": "2871", + "kind": "CONDITIONAL_OR", + "rightOperand": { + "leftOperand": { + "endPosition": "2848", + "kind": "IDENTIFIER", + "name": "val", + "startPosition": "2845" + }, "expression": { - "endPosition": "2745", + "endPosition": "2848", "kind": "IDENTIFIER", - "name": "Parser", - "startPosition": "2739" + "name": "val", + "startPosition": "2845" }, - "endPosition": "2750", - "kind": "MEMBER_SELECT", - "startPosition": "2739" + "endPosition": "2871", + "kind": "INSTANCE_OF", + "rightOperand": { + "identifier": "Enum", + "expression": { + "endPosition": "2866", + "kind": "IDENTIFIER", + "name": "Parser", + "startPosition": "2860" + }, + "endPosition": "2871", + "kind": "MEMBER_SELECT", + "startPosition": "2860" + }, + "type": { + "identifier": "Enum", + "expression": { + "endPosition": "2866", + "kind": "IDENTIFIER", + "name": "Parser", + "startPosition": "2860" + }, + "endPosition": "2871", + "kind": "MEMBER_SELECT", + "startPosition": "2860" + }, + "startPosition": "2845" }, - "startPosition": "2724" + "startPosition": "2812" }, - "endPosition": "2820", + "endPosition": "2945", "kind": "IF", - "startPosition": "2720", + "startPosition": "2808", "thenStatement": { - "endPosition": "2820", + "endPosition": "2945", "kind": "BLOCK", "statements": [ { "expression": { "expression": { - "endPosition": "2799", + "endPosition": "2922", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "2794", + "endPosition": "2917", "kind": "IDENTIFIER", "name": "String", - "startPosition": "2788" + "startPosition": "2911" }, "arguments": [ { - "endPosition": "2798", + "endPosition": "2921", "kind": "IDENTIFIER", "name": "val", - "startPosition": "2795" + "startPosition": "2918" } ], - "startPosition": "2788" + "startPosition": "2911" }, - "endPosition": "2799", + "endPosition": "2922", "kind": "ASSIGNMENT", "variable": { "expression": { - "endPosition": "2782", + "endPosition": "2905", "kind": "IDENTIFIER", "name": "result", - "startPosition": "2776" + "startPosition": "2899" }, - "endPosition": "2785", + "endPosition": "2908", "kind": "ARRAY_ACCESS", "index": { - "endPosition": "2784", + "endPosition": "2907", "kind": "IDENTIFIER", "name": "i", - "startPosition": "2783" + "startPosition": "2906" }, - "startPosition": "2776" + "startPosition": "2899" }, - "startPosition": "2776" + "startPosition": "2899" }, - "endPosition": "2799", + "endPosition": "2922", "kind": "EXPRESSION_STATEMENT", - "startPosition": "2776" + "startPosition": "2899" } ], - "startPosition": "2752" + "startPosition": "2873" } } ], - "startPosition": "2693" + "startPosition": "2779" } ], "expression": { "expression": { - "endPosition": "2544", + "endPosition": "2593", "kind": "IDENTIFIER", "name": "val", - "startPosition": "2541" + "startPosition": "2590" }, - "endPosition": "2544", + "endPosition": "2593", "kind": "TYPEOF", - "startPosition": "2534" + "startPosition": "2583" }, - "endPosition": "2832", + "endPosition": "2959", "kind": "SWITCH", - "startPosition": "2526" + "startPosition": "2575" } ], - "startPosition": "2514" + "startPosition": "2561" }, - "endPosition": "2840", + "endPosition": "2969", "kind": "IF", - "startPosition": "2302", + "startPosition": "2343", "thenStatement": { - "endPosition": "2508", + "endPosition": "2555", "kind": "BLOCK", "statements": [ { - "endPosition": "2377", + "endPosition": "2420", "kind": "VARIABLE", "name": "arr", - "startPosition": "2350", + "startPosition": "2393", "initializer": { "constructorExpression": { - "endPosition": "2377", + "endPosition": "2420", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "2365", + "endPosition": "2408", "kind": "IDENTIFIER", "name": "Array", - "startPosition": "2360" + "startPosition": "2403" }, "arguments": [ { - "endPosition": "2376", + "endPosition": "2419", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "size", "expression": { - "endPosition": "2369", + "endPosition": "2412", "kind": "IDENTIFIER", "name": "val", - "startPosition": "2366" + "startPosition": "2409" }, - "endPosition": "2374", + "endPosition": "2417", "kind": "MEMBER_SELECT", - "startPosition": "2366" + "startPosition": "2409" }, "arguments": [], - "startPosition": "2366" + "startPosition": "2409" } ], - "startPosition": "2360" + "startPosition": "2403" }, - "endPosition": "2377", + "endPosition": "2420", "kind": "NEW", - "startPosition": "2356" + "startPosition": "2399" } }, { - "endPosition": "2399", + "endPosition": "2444", "kind": "VARIABLE", "name": "j", - "startPosition": "2398" + "startPosition": "2443" }, { "expression": { - "endPosition": "2406", + "endPosition": "2451", "kind": "IDENTIFIER", "name": "val", - "startPosition": "2403" + "startPosition": "2448" }, - "endPosition": "2466", + "endPosition": "2515", "kind": "FOR_IN_LOOP", "forEach": "false", "variable": { - "endPosition": "2399", + "endPosition": "2444", "kind": "IDENTIFIER", "name": "j", - "startPosition": "2398" + "startPosition": "2443" }, "statement": { - "endPosition": "2466", + "endPosition": "2515", "kind": "BLOCK", "statements": [ { "expression": { "expression": { - "endPosition": "2453", + "endPosition": "2500", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "convert", "expression": { - "endPosition": "2437", + "endPosition": "2484", "kind": "IDENTIFIER", "name": "this", - "startPosition": "2433" + "startPosition": "2480" }, - "endPosition": "2445", + "endPosition": "2492", "kind": "MEMBER_SELECT", - "startPosition": "2433" + "startPosition": "2480" }, "arguments": [ { "expression": { - "endPosition": "2449", + "endPosition": "2496", "kind": "IDENTIFIER", "name": "val", - "startPosition": "2446" + "startPosition": "2493" }, - "endPosition": "2452", + "endPosition": "2499", "kind": "ARRAY_ACCESS", "index": { - "endPosition": "2451", + "endPosition": "2498", "kind": "IDENTIFIER", "name": "j", - "startPosition": "2450" + "startPosition": "2497" }, - "startPosition": "2446" + "startPosition": "2493" } ], - "startPosition": "2433" + "startPosition": "2480" }, - "endPosition": "2453", + "endPosition": "2500", "kind": "ASSIGNMENT", "variable": { "expression": { - "endPosition": "2427", + "endPosition": "2474", "kind": "IDENTIFIER", "name": "arr", - "startPosition": "2424" + "startPosition": "2471" }, - "endPosition": "2430", + "endPosition": "2477", "kind": "ARRAY_ACCESS", "index": { - "endPosition": "2429", + "endPosition": "2476", "kind": "IDENTIFIER", "name": "j", - "startPosition": "2428" + "startPosition": "2475" }, - "startPosition": "2424" + "startPosition": "2471" }, - "startPosition": "2424" + "startPosition": "2471" }, - "endPosition": "2453", + "endPosition": "2500", "kind": "EXPRESSION_STATEMENT", - "startPosition": "2424" + "startPosition": "2471" } ], - "startPosition": "2408" + "startPosition": "2453" }, - "startPosition": "2389" + "startPosition": "2434" }, { "expression": { "expression": { - "endPosition": "2499", + "endPosition": "2544", "kind": "IDENTIFIER", "name": "arr", - "startPosition": "2496" + "startPosition": "2541" }, - "endPosition": "2499", + "endPosition": "2544", "kind": "ASSIGNMENT", "variable": { "expression": { - "endPosition": "2490", + "endPosition": "2535", "kind": "IDENTIFIER", "name": "result", - "startPosition": "2484" + "startPosition": "2529" }, - "endPosition": "2493", + "endPosition": "2538", "kind": "ARRAY_ACCESS", "index": { - "endPosition": "2492", + "endPosition": "2537", "kind": "IDENTIFIER", "name": "i", - "startPosition": "2491" + "startPosition": "2536" }, - "startPosition": "2484" + "startPosition": "2529" }, - "startPosition": "2484" + "startPosition": "2529" }, - "endPosition": "2499", + "endPosition": "2544", "kind": "EXPRESSION_STATEMENT", - "startPosition": "2484" + "startPosition": "2529" } ], - "startPosition": "2334" + "startPosition": "2375" } }, - "endPosition": "2840", + "endPosition": "2969", "kind": "IF", - "startPosition": "2213", + "startPosition": "2251", "thenStatement": { - "endPosition": "2296", + "endPosition": "2337", "kind": "BLOCK", "statements": [ { "expression": { "expression": { - "endPosition": "2286", + "endPosition": "2326", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "convert", "expression": { - "endPosition": "2273", + "endPosition": "2313", "kind": "IDENTIFIER", "name": "this", - "startPosition": "2269" + "startPosition": "2309" }, - "endPosition": "2281", + "endPosition": "2321", "kind": "MEMBER_SELECT", - "startPosition": "2269" + "startPosition": "2309" }, "arguments": [ { - "endPosition": "2285", + "endPosition": "2325", "kind": "IDENTIFIER", "name": "val", - "startPosition": "2282" + "startPosition": "2322" } ], - "startPosition": "2269" + "startPosition": "2309" }, - "endPosition": "2286", + "endPosition": "2326", "kind": "ASSIGNMENT", "variable": { "expression": { - "endPosition": "2263", + "endPosition": "2303", "kind": "IDENTIFIER", "name": "result", - "startPosition": "2257" + "startPosition": "2297" }, - "endPosition": "2266", + "endPosition": "2306", "kind": "ARRAY_ACCESS", "index": { - "endPosition": "2265", + "endPosition": "2305", "kind": "IDENTIFIER", "name": "i", - "startPosition": "2264" + "startPosition": "2304" }, - "startPosition": "2257" + "startPosition": "2297" }, - "startPosition": "2257" + "startPosition": "2297" }, - "endPosition": "2286", + "endPosition": "2326", "kind": "EXPRESSION_STATEMENT", - "startPosition": "2257" + "startPosition": "2297" } ], - "startPosition": "2245" + "startPosition": "2283" } } ], - "startPosition": "2179" + "startPosition": "2215" }, - "startPosition": "2160" + "startPosition": "2196" }, { "expression": { - "endPosition": "2862", + "endPosition": "2993", "kind": "IDENTIFIER", "name": "result", - "startPosition": "2856" + "startPosition": "2987" }, - "endPosition": "2863", + "endPosition": "2994", "kind": "RETURN", - "startPosition": "2849" + "startPosition": "2980" } ], - "startPosition": "2014" + "startPosition": "2016" }, "strict": "false", - "startPosition": "2014", + "startPosition": "2016", "parameters": [ { - "endPosition": "2012", + "endPosition": "2014", "kind": "IDENTIFIER", "name": "tree", - "startPosition": "2008" + "startPosition": "2010" } ] }, - "endPosition": "2014", + "endPosition": "2016", "kind": "ASSIGNMENT", "variable": { "identifier": "convert", "expression": { "identifier": "prototype", "expression": { - "endPosition": "1978", + "endPosition": "1980", "kind": "IDENTIFIER", "name": "Parser", - "startPosition": "1972" + "startPosition": "1974" }, - "endPosition": "1988", + "endPosition": "1990", "kind": "MEMBER_SELECT", - "startPosition": "1972" + "startPosition": "1974" }, - "endPosition": "1996", + "endPosition": "1998", "kind": "MEMBER_SELECT", - "startPosition": "1972" - }, - "startPosition": "1972" - }, - "endPosition": "2865", + "startPosition": "1974" + }, + "startPosition": "1974" + }, + "endPosition": "2996", "kind": "EXPRESSION_STATEMENT", - "startPosition": "1972" - }, - { - "endPosition": "3618", + "startPosition": "1974" + }, + { + "endPosition": "3767", "kind": "FUNCTION", "name": "processFiles", "body": { - "endPosition": "3575", + "endPosition": "3724", "kind": "BLOCK", "statements": [ { - "endPosition": "2938", + "endPosition": "3070", "kind": "VARIABLE", "name": "File", - "startPosition": "2906", + "startPosition": "3038", "initializer": { - "endPosition": "2938", + "endPosition": "3070", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "type", "expression": { - "endPosition": "2917", + "endPosition": "3049", "kind": "IDENTIFIER", "name": "Java", - "startPosition": "2913" + "startPosition": "3045" }, - "endPosition": "2922", + "endPosition": "3054", "kind": "MEMBER_SELECT", - "startPosition": "2913" + "startPosition": "3045" }, "arguments": [ { - "endPosition": "2936", + "endPosition": "3068", "kind": "STRING_LITERAL", "value": "java.io.File", - "startPosition": "2924" + "startPosition": "3056" } ], - "startPosition": "2913" + "startPosition": "3045" } }, { - "endPosition": "2993", + "endPosition": "3126", "kind": "VARIABLE", "name": "files", - "startPosition": "2947", + "startPosition": "3080", "initializer": { - "endPosition": "2993", + "endPosition": "3126", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "listFiles", "expression": { "constructorExpression": { - "endPosition": "2981", + "endPosition": "3114", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "2963", + "endPosition": "3096", "kind": "IDENTIFIER", "name": "File", - "startPosition": "2959" + "startPosition": "3092" }, "arguments": [ { "leftOperand": { - "endPosition": "2971", + "endPosition": "3104", "kind": "IDENTIFIER", "name": "__DIR__", - "startPosition": "2964" + "startPosition": "3097" }, - "endPosition": "2980", + "endPosition": "3113", "kind": "PLUS", "rightOperand": { - "endPosition": "2980", + "endPosition": "3113", "kind": "IDENTIFIER", "name": "subdir", - "startPosition": "2974" + "startPosition": "3107" }, - "startPosition": "2964" + "startPosition": "3097" } ], - "startPosition": "2959" + "startPosition": "3092" }, - "endPosition": "2981", + "endPosition": "3114", "kind": "NEW", - "startPosition": "2955" + "startPosition": "3088" }, - "endPosition": "2991", + "endPosition": "3124", "kind": "MEMBER_SELECT", - "startPosition": "2955" + "startPosition": "3088" }, "arguments": [], - "startPosition": "2955" + "startPosition": "3088" } }, { "expression": { - "endPosition": "3026", + "endPosition": "3160", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "sort", @@ -6291,751 +6412,751 @@ "expression": { "identifier": "util", "expression": { - "endPosition": "3002", + "endPosition": "3136", "kind": "IDENTIFIER", "name": "java", - "startPosition": "2998" + "startPosition": "3132" }, - "endPosition": "3007", + "endPosition": "3141", "kind": "MEMBER_SELECT", - "startPosition": "2998" + "startPosition": "3132" }, - "endPosition": "3014", + "endPosition": "3148", "kind": "MEMBER_SELECT", - "startPosition": "2998" + "startPosition": "3132" }, - "endPosition": "3019", + "endPosition": "3153", "kind": "MEMBER_SELECT", - "startPosition": "2998" + "startPosition": "3132" }, "arguments": [ { - "endPosition": "3025", + "endPosition": "3159", "kind": "IDENTIFIER", "name": "files", - "startPosition": "3020" + "startPosition": "3154" } ], - "startPosition": "2998" + "startPosition": "3132" }, - "endPosition": "3026", + "endPosition": "3160", "kind": "EXPRESSION_STATEMENT", - "startPosition": "2998" + "startPosition": "3132" }, { - "endPosition": "3049", + "endPosition": "3184", "kind": "VARIABLE", "name": "file", - "startPosition": "3045" + "startPosition": "3180" }, { "expression": { - "endPosition": "3058", + "endPosition": "3193", "kind": "IDENTIFIER", "name": "files", - "startPosition": "3053" + "startPosition": "3188" }, - "endPosition": "3575", + "endPosition": "3724", "kind": "FOR_IN_LOOP", "forEach": "true", "variable": { - "endPosition": "3049", + "endPosition": "3184", "kind": "IDENTIFIER", "name": "file", - "startPosition": "3045" + "startPosition": "3180" }, "statement": { - "endPosition": "3575", + "endPosition": "3724", "kind": "BLOCK", "statements": [ { "condition": { - "endPosition": "3098", + "endPosition": "3234", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "endsWith", "expression": { "identifier": "name", "expression": { - "endPosition": "3077", + "endPosition": "3213", "kind": "IDENTIFIER", "name": "file", - "startPosition": "3073" + "startPosition": "3209" }, - "endPosition": "3082", + "endPosition": "3218", "kind": "MEMBER_SELECT", - "startPosition": "3073" + "startPosition": "3209" }, - "endPosition": "3091", + "endPosition": "3227", "kind": "MEMBER_SELECT", - "startPosition": "3073" + "startPosition": "3209" }, "arguments": [ { - "endPosition": "3096", + "endPosition": "3232", "kind": "STRING_LITERAL", "value": ".js", - "startPosition": "3093" + "startPosition": "3229" } ], - "startPosition": "3073" + "startPosition": "3209" }, - "endPosition": "3570", + "endPosition": "3718", "kind": "IF", - "startPosition": "3069", + "startPosition": "3205", "thenStatement": { - "endPosition": "3570", + "endPosition": "3718", "kind": "BLOCK", "statements": [ { - "endPosition": "3141", + "endPosition": "3278", "kind": "VARIABLE", "name": "script", - "startPosition": "3117", + "startPosition": "3254", "initializer": { - "endPosition": "3141", + "endPosition": "3278", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "3135", + "endPosition": "3272", "kind": "IDENTIFIER", "name": "readFully", - "startPosition": "3126" + "startPosition": "3263" }, "arguments": [ { - "endPosition": "3140", + "endPosition": "3277", "kind": "IDENTIFIER", "name": "file", - "startPosition": "3136" + "startPosition": "3273" } ], - "startPosition": "3126" + "startPosition": "3263" } }, { - "endPosition": "3179", + "endPosition": "3317", "kind": "VARIABLE", "name": "parser", - "startPosition": "3158", + "startPosition": "3296", "initializer": { "constructorExpression": { - "endPosition": "3179", + "endPosition": "3317", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "3177", + "endPosition": "3315", "kind": "IDENTIFIER", "name": "Parser", - "startPosition": "3171" + "startPosition": "3309" }, "arguments": [], - "startPosition": "3171" + "startPosition": "3309" }, - "endPosition": "3179", + "endPosition": "3317", "kind": "NEW", - "startPosition": "3167" + "startPosition": "3305" } }, { - "endPosition": "3435", + "endPosition": "3578", "kind": "VARIABLE", "name": "tree", - "startPosition": "3196", + "startPosition": "3335", "initializer": { - "endPosition": "3435", + "endPosition": "3578", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "parse", "expression": { - "endPosition": "3209", + "endPosition": "3348", "kind": "IDENTIFIER", "name": "parser", - "startPosition": "3203" + "startPosition": "3342" }, - "endPosition": "3215", + "endPosition": "3354", "kind": "MEMBER_SELECT", - "startPosition": "3203" + "startPosition": "3342" }, "arguments": [ { "leftOperand": { "leftOperand": { - "endPosition": "3222", + "endPosition": "3361", "kind": "IDENTIFIER", "name": "subdir", - "startPosition": "3216" + "startPosition": "3355" }, - "endPosition": "3227", + "endPosition": "3366", "kind": "PLUS", "rightOperand": { - "endPosition": "3227", + "endPosition": "3366", "kind": "STRING_LITERAL", "value": "/", - "startPosition": "3226" + "startPosition": "3365" }, - "startPosition": "3216" + "startPosition": "3355" }, - "endPosition": "3240", + "endPosition": "3379", "kind": "PLUS", "rightOperand": { "identifier": "name", "expression": { - "endPosition": "3235", + "endPosition": "3374", "kind": "IDENTIFIER", "name": "file", - "startPosition": "3231" + "startPosition": "3370" }, - "endPosition": "3240", + "endPosition": "3379", "kind": "MEMBER_SELECT", - "startPosition": "3231" + "startPosition": "3370" }, - "startPosition": "3216" + "startPosition": "3355" }, { - "endPosition": "3248", + "endPosition": "3387", "kind": "IDENTIFIER", "name": "script", - "startPosition": "3242" + "startPosition": "3381" }, { - "endPosition": "3286", + "endPosition": "3426", "kind": "FUNCTION_EXPRESSION", "body": { - "endPosition": "3417", + "endPosition": "3559", "kind": "BLOCK", "statements": [ { "expression": { - "endPosition": "3385", + "endPosition": "3526", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "3312", + "endPosition": "3453", "kind": "IDENTIFIER", "name": "print", - "startPosition": "3307" + "startPosition": "3448" }, "arguments": [ { - "endPosition": "3384", + "endPosition": "3525", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "replace", "expression": { - "endPosition": "3364", + "endPosition": "3505", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "stringify", "expression": { - "endPosition": "3317", + "endPosition": "3458", "kind": "IDENTIFIER", "name": "JSON", - "startPosition": "3313" + "startPosition": "3454" }, - "endPosition": "3327", + "endPosition": "3468", "kind": "MEMBER_SELECT", - "startPosition": "3313" + "startPosition": "3454" }, "arguments": [ { - "endPosition": "3354", + "endPosition": "3495", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "convert", "expression": { - "endPosition": "3334", + "endPosition": "3475", "kind": "IDENTIFIER", "name": "parser", - "startPosition": "3328" + "startPosition": "3469" }, - "endPosition": "3342", + "endPosition": "3483", "kind": "MEMBER_SELECT", - "startPosition": "3328" + "startPosition": "3469" }, "arguments": [ { - "endPosition": "3353", + "endPosition": "3494", "kind": "IDENTIFIER", "name": "diagnostic", - "startPosition": "3343" + "startPosition": "3484" } ], - "startPosition": "3328" + "startPosition": "3469" }, { - "endPosition": "3360", + "endPosition": "3501", "kind": "NULL_LITERAL", - "startPosition": "3356" + "startPosition": "3497" }, { - "endPosition": "3363", + "endPosition": "3504", "kind": "NUMBER_LITERAL", "value": "2", - "startPosition": "3362" + "startPosition": "3503" } ], - "startPosition": "3313" + "startPosition": "3454" }, - "endPosition": "3372", + "endPosition": "3513", "kind": "MEMBER_SELECT", - "startPosition": "3313" + "startPosition": "3454" }, "arguments": [ { - "endPosition": "3379", + "endPosition": "3520", "kind": "REGEXP_LITERAL", "options": "g", "pattern": "\\\\r", - "startPosition": "3373" + "startPosition": "3514" }, { - "endPosition": "3382", + "endPosition": "3523", "kind": "STRING_LITERAL", "value": "", - "startPosition": "3382" + "startPosition": "3523" } ], - "startPosition": "3372" + "startPosition": "3513" } ], - "startPosition": "3307" + "startPosition": "3448" }, - "endPosition": "3385", + "endPosition": "3526", "kind": "EXPRESSION_STATEMENT", - "startPosition": "3307" + "startPosition": "3448" }, { "expression": { - "endPosition": "3416", + "endPosition": "3558", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "3411", + "endPosition": "3553", "kind": "IDENTIFIER", "name": "print", - "startPosition": "3406" + "startPosition": "3548" }, "arguments": [ { - "endPosition": "3414", + "endPosition": "3556", "kind": "STRING_LITERAL", "value": ",", - "startPosition": "3413" + "startPosition": "3555" } ], - "startPosition": "3406" + "startPosition": "3548" }, - "endPosition": "3416", + "endPosition": "3558", "kind": "EXPRESSION_STATEMENT", - "startPosition": "3406" + "startPosition": "3548" } ], - "startPosition": "3286" + "startPosition": "3426" }, "strict": "false", - "startPosition": "3286", + "startPosition": "3426", "parameters": [ { - "endPosition": "3284", + "endPosition": "3424", "kind": "IDENTIFIER", "name": "diagnostic", - "startPosition": "3274" + "startPosition": "3414" } ] } ], - "startPosition": "3203" + "startPosition": "3342" } }, { "condition": { "leftOperand": { - "endPosition": "3457", + "endPosition": "3601", "kind": "IDENTIFIER", "name": "tree", - "startPosition": "3453" + "startPosition": "3597" }, - "endPosition": "3465", + "endPosition": "3609", "kind": "NOT_EQUAL_TO", "rightOperand": { - "endPosition": "3465", + "endPosition": "3609", "kind": "NULL_LITERAL", - "startPosition": "3461" + "startPosition": "3605" }, - "startPosition": "3453" + "startPosition": "3597" }, - "endPosition": "3561", + "endPosition": "3708", "kind": "IF", - "startPosition": "3449", + "startPosition": "3593", "thenStatement": { - "endPosition": "3561", + "endPosition": "3708", "kind": "BLOCK", "statements": [ { "expression": { - "endPosition": "3520", + "endPosition": "3665", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "3489", + "endPosition": "3634", "kind": "IDENTIFIER", "name": "print", - "startPosition": "3484" + "startPosition": "3629" }, "arguments": [ { - "endPosition": "3519", + "endPosition": "3664", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "stringify", "expression": { - "endPosition": "3494", + "endPosition": "3639", "kind": "IDENTIFIER", "name": "JSON", - "startPosition": "3490" + "startPosition": "3635" }, - "endPosition": "3504", + "endPosition": "3649", "kind": "MEMBER_SELECT", - "startPosition": "3490" + "startPosition": "3635" }, "arguments": [ { - "endPosition": "3509", + "endPosition": "3654", "kind": "IDENTIFIER", "name": "tree", - "startPosition": "3505" + "startPosition": "3650" }, { - "endPosition": "3515", + "endPosition": "3660", "kind": "NULL_LITERAL", - "startPosition": "3511" + "startPosition": "3656" }, { - "endPosition": "3518", + "endPosition": "3663", "kind": "NUMBER_LITERAL", "value": "2", - "startPosition": "3517" + "startPosition": "3662" } ], - "startPosition": "3490" + "startPosition": "3635" } ], - "startPosition": "3484" + "startPosition": "3629" }, - "endPosition": "3520", + "endPosition": "3665", "kind": "EXPRESSION_STATEMENT", - "startPosition": "3484" + "startPosition": "3629" }, { "expression": { - "endPosition": "3547", + "endPosition": "3693", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "3542", + "endPosition": "3688", "kind": "IDENTIFIER", "name": "print", - "startPosition": "3537" + "startPosition": "3683" }, "arguments": [ { - "endPosition": "3545", + "endPosition": "3691", "kind": "STRING_LITERAL", "value": ",", - "startPosition": "3544" + "startPosition": "3690" } ], - "startPosition": "3537" + "startPosition": "3683" }, - "endPosition": "3547", + "endPosition": "3693", "kind": "EXPRESSION_STATEMENT", - "startPosition": "3537" + "startPosition": "3683" } ], - "startPosition": "3467" + "startPosition": "3611" } } ], - "startPosition": "3100" + "startPosition": "3236" } } ], - "startPosition": "3060" + "startPosition": "3195" }, - "startPosition": "3031" + "startPosition": "3166" } ], - "startPosition": "2897" + "startPosition": "3028" }, "strict": "false", - "startPosition": "2867", + "startPosition": "2998", "parameters": [ { - "endPosition": "2895", + "endPosition": "3026", "kind": "IDENTIFIER", "name": "subdir", - "startPosition": "2889" + "startPosition": "3020" } ] }, { - "endPosition": "3921", + "endPosition": "4070", "kind": "FUNCTION", "name": "main", "body": { - "endPosition": "3919", + "endPosition": "4068", "kind": "BLOCK", "statements": [ { "expression": { - "endPosition": "3651", + "endPosition": "3800", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "3646", + "endPosition": "3795", "kind": "IDENTIFIER", "name": "print", - "startPosition": "3641" + "startPosition": "3790" }, "arguments": [ { - "endPosition": "3649", + "endPosition": "3798", "kind": "STRING_LITERAL", "value": "[", - "startPosition": "3648" + "startPosition": "3797" } ], - "startPosition": "3641" + "startPosition": "3790" }, - "endPosition": "3651", + "endPosition": "3800", "kind": "EXPRESSION_STATEMENT", - "startPosition": "3641" + "startPosition": "3790" }, { "expression": { - "endPosition": "3685", + "endPosition": "3834", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "3670", + "endPosition": "3819", "kind": "IDENTIFIER", "name": "processFiles", - "startPosition": "3658" + "startPosition": "3807" }, "arguments": [ { - "endPosition": "3683", + "endPosition": "3832", "kind": "STRING_LITERAL", "value": "parsertests", - "startPosition": "3672" + "startPosition": "3821" } ], - "startPosition": "3658" + "startPosition": "3807" }, - "endPosition": "3685", + "endPosition": "3834", "kind": "EXPRESSION_STATEMENT", - "startPosition": "3658" + "startPosition": "3807" }, { "expression": { - "endPosition": "3726", + "endPosition": "3875", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "3703", + "endPosition": "3852", "kind": "IDENTIFIER", "name": "processFiles", - "startPosition": "3691" + "startPosition": "3840" }, "arguments": [ { - "endPosition": "3724", + "endPosition": "3873", "kind": "STRING_LITERAL", "value": "parsernegativetests", - "startPosition": "3705" + "startPosition": "3854" } ], - "startPosition": "3691" + "startPosition": "3840" }, - "endPosition": "3726", + "endPosition": "3875", "kind": "EXPRESSION_STATEMENT", - "startPosition": "3691" + "startPosition": "3840" }, { - "endPosition": "3795", + "endPosition": "3944", "kind": "VARIABLE", "name": "script", - "startPosition": "3767", + "startPosition": "3916", "initializer": { - "endPosition": "3795", + "endPosition": "3944", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "3785", + "endPosition": "3934", "kind": "IDENTIFIER", "name": "readFully", - "startPosition": "3776" + "startPosition": "3925" }, "arguments": [ { - "endPosition": "3794", + "endPosition": "3943", "kind": "IDENTIFIER", "name": "__FILE__", - "startPosition": "3786" + "startPosition": "3935" } ], - "startPosition": "3776" + "startPosition": "3925" } }, { - "endPosition": "3860", + "endPosition": "4009", "kind": "VARIABLE", "name": "tree", - "startPosition": "3805", + "startPosition": "3954", "initializer": { - "endPosition": "3860", + "endPosition": "4009", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "parse", "expression": { "constructorExpression": { - "endPosition": "3824", + "endPosition": "3973", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "3822", + "endPosition": "3971", "kind": "IDENTIFIER", "name": "Parser", - "startPosition": "3816" + "startPosition": "3965" }, "arguments": [], - "startPosition": "3816" + "startPosition": "3965" }, - "endPosition": "3824", + "endPosition": "3973", "kind": "NEW", - "startPosition": "3812" + "startPosition": "3961" }, - "endPosition": "3830", + "endPosition": "3979", "kind": "MEMBER_SELECT", - "startPosition": "3812" + "startPosition": "3961" }, "arguments": [ { - "endPosition": "3844", + "endPosition": "3993", "kind": "STRING_LITERAL", "value": "parserapi.js", - "startPosition": "3832" + "startPosition": "3981" }, { - "endPosition": "3853", + "endPosition": "4002", "kind": "IDENTIFIER", "name": "script", - "startPosition": "3847" + "startPosition": "3996" }, { - "endPosition": "3859", + "endPosition": "4008", "kind": "NULL_LITERAL", - "startPosition": "3855" + "startPosition": "4004" } ], - "startPosition": "3812" + "startPosition": "3961" } }, { "expression": { - "endPosition": "3902", + "endPosition": "4051", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "3871", + "endPosition": "4020", "kind": "IDENTIFIER", "name": "print", - "startPosition": "3866" + "startPosition": "4015" }, "arguments": [ { - "endPosition": "3901", + "endPosition": "4050", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "stringify", "expression": { - "endPosition": "3876", + "endPosition": "4025", "kind": "IDENTIFIER", "name": "JSON", - "startPosition": "3872" + "startPosition": "4021" }, - "endPosition": "3886", + "endPosition": "4035", "kind": "MEMBER_SELECT", - "startPosition": "3872" + "startPosition": "4021" }, "arguments": [ { - "endPosition": "3891", + "endPosition": "4040", "kind": "IDENTIFIER", "name": "tree", - "startPosition": "3887" + "startPosition": "4036" }, { - "endPosition": "3897", + "endPosition": "4046", "kind": "NULL_LITERAL", - "startPosition": "3893" + "startPosition": "4042" }, { - "endPosition": "3900", + "endPosition": "4049", "kind": "NUMBER_LITERAL", "value": "2", - "startPosition": "3899" + "startPosition": "4048" } ], - "startPosition": "3872" + "startPosition": "4021" } ], - "startPosition": "3866" + "startPosition": "4015" }, - "endPosition": "3902", + "endPosition": "4051", "kind": "EXPRESSION_STATEMENT", - "startPosition": "3866" + "startPosition": "4015" }, { "expression": { - "endPosition": "3918", + "endPosition": "4067", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "3913", + "endPosition": "4062", "kind": "IDENTIFIER", "name": "print", - "startPosition": "3908" + "startPosition": "4057" }, "arguments": [ { - "endPosition": "3916", + "endPosition": "4065", "kind": "STRING_LITERAL", "value": "]", - "startPosition": "3915" + "startPosition": "4064" } ], - "startPosition": "3908" + "startPosition": "4057" }, - "endPosition": "3918", + "endPosition": "4067", "kind": "EXPRESSION_STATEMENT", - "startPosition": "3908" + "startPosition": "4057" } ], - "startPosition": "3635" + "startPosition": "3784" }, "strict": "false", - "startPosition": "3619", + "startPosition": "3768", "parameters": [] }, { "expression": { - "endPosition": "3929", + "endPosition": "4078", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "3927", + "endPosition": "4076", "kind": "IDENTIFIER", "name": "main", - "startPosition": "3923" + "startPosition": "4072" }, "arguments": [], - "startPosition": "3923" - }, - "endPosition": "3929", + "startPosition": "4072" + }, + "endPosition": "4078", "kind": "EXPRESSION_STATEMENT", - "startPosition": "3923" + "startPosition": "4072" } ], "sourceName": "parserapi.js", "strict": "false", "startPosition": "1136" -} -] +} +]
--- a/nashorn/test/script/nosecurity/treeapi/for.js Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/test/script/nosecurity/treeapi/for.js Thu Jan 14 12:03:53 2016 -0800 @@ -1,23 +1,23 @@ /* - * Copyright (c) 2014, Or1cle 1nd/or its 1ffili1tes. 1ll rights reserved. - * DO NOT 1LTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HE1DER. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * This code is free softw1re; you c1n redistri2ute it 1nd/or modify it - * under the terms of the GNU Gener1l Pu2lic License version 2 only, 1s - * pu2lished 2y the Free Softw1re Found1tion. + * 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 distri2uted in the hope th1t it will 2e useful, 2ut WITHOUT - * 1NY W1RR1NTY; without even the implied w1rr1nty of MERCH1NT12ILITY or - * FITNESS FOR 1 P1RTICUL1R PURPOSE. See the GNU Gener1l Pu2lic License - * version 2 for more det1ils (1 copy is included in the LICENSE file th1t - * 1ccomp1nied 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 h1ve received 1 copy of the GNU Gener1l Pu2lic License version - * 2 1long with this work; if not, write to the Free Softw1re Found1tion, - * Inc., 51 Fr1nklin St, Fifth Floor, 2oston, M1 02110-1301 US1. + * 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. * - * Ple1se cont1ct Or1cle, 500 Or1cle P1rkw1y, Redwood Shores, C1 94065 US1 - * or visit www.or1cle.com if you need 1ddition1l inform1tion or h1ve 1ny + * 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. */ @@ -47,4 +47,4 @@ visitForLoop : function (node, obj) { obj.push(convert(node)) } -}))) \ No newline at end of file +})))
--- a/nashorn/test/script/nosecurity/treeapi/forin.js Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/test/script/nosecurity/treeapi/forin.js Thu Jan 14 12:03:53 2016 -0800 @@ -1,23 +1,23 @@ /* - * Copyright (c) 2014, Or1cle 1nd/or its 1ffili1tes. 1ll rights reserved. - * DO NOT 1LTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HE1DER. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * This code is free softw1re; you c1n redistri2ute it 1nd/or modify it - * under the terms of the GNU Gener1l Pu2lic License version 2 only, 1s - * pu2lished 2y the Free Softw1re Found1tion. + * 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 distri2uted in the hope th1t it will 2e useful, 2ut WITHOUT - * 1NY W1RR1NTY; without even the implied w1rr1nty of MERCH1NT12ILITY or - * FITNESS FOR 1 P1RTICUL1R PURPOSE. See the GNU Gener1l Pu2lic License - * version 2 for more det1ils (1 copy is included in the LICENSE file th1t - * 1ccomp1nied 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 h1ve received 1 copy of the GNU Gener1l Pu2lic License version - * 2 1long with this work; if not, write to the Free Softw1re Found1tion, - * Inc., 51 Fr1nklin St, Fifth Floor, 2oston, M1 02110-1301 US1. + * 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. * - * Ple1se cont1ct Or1cle, 500 Or1cle P1rkw1y, Redwood Shores, C1 94065 US1 - * or visit www.or1cle.com if you need 1ddition1l inform1tion or h1ve 1ny + * 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. */ @@ -45,4 +45,4 @@ visitForInLoop : function (node, obj) { obj.push(convert(node)) } -}))) \ No newline at end of file +})))
--- a/nashorn/test/script/nosecurity/treeapi/functionCall.js Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/test/script/nosecurity/treeapi/functionCall.js Thu Jan 14 12:03:53 2016 -0800 @@ -1,23 +1,23 @@ /* - * Copyright (c) 2014, Or1cle 1nd/or its 1ffili1tes. 1ll rights reserved. - * DO NOT 1LTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HE1DER. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * This code is free softw1re; you c1n redistri2ute it 1nd/or modify it - * under the terms of the GNU Gener1l Pu2lic License version 2 only, 1s - * pu2lished 2y the Free Softw1re Found1tion. + * 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 distri2uted in the hope th1t it will 2e useful, 2ut WITHOUT - * 1NY W1RR1NTY; without even the implied w1rr1nty of MERCH1NT12ILITY or - * FITNESS FOR 1 P1RTICUL1R PURPOSE. See the GNU Gener1l Pu2lic License - * version 2 for more det1ils (1 copy is included in the LICENSE file th1t - * 1ccomp1nied 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 h1ve received 1 copy of the GNU Gener1l Pu2lic License version - * 2 1long with this work; if not, write to the Free Softw1re Found1tion, - * Inc., 51 Fr1nklin St, Fifth Floor, 2oston, M1 02110-1301 US1. + * 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. * - * Ple1se cont1ct Or1cle, 500 Or1cle P1rkw1y, Redwood Shores, C1 94065 US1 - * or visit www.or1cle.com if you need 1ddition1l inform1tion or h1ve 1ny + * 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. */ @@ -51,4 +51,4 @@ visitFunctionCall : function (node, obj) { obj.push(convert(node)) } -}))) \ No newline at end of file +})))
--- a/nashorn/test/script/nosecurity/treeapi/functionDeclaration.js Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/test/script/nosecurity/treeapi/functionDeclaration.js Thu Jan 14 12:03:53 2016 -0800 @@ -1,23 +1,23 @@ /* - * Copyright (c) 2014, Or1cle 1nd/or its 1ffili1tes. 1ll rights reserved. - * DO NOT 1LTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HE1DER. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * This code is free softw1re; you c1n redistri2ute it 1nd/or modify it - * under the terms of the GNU Gener1l Pu2lic License version 2 only, 1s - * pu2lished 2y the Free Softw1re Found1tion. + * 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 distri2uted in the hope th1t it will 2e useful, 2ut WITHOUT - * 1NY W1RR1NTY; without even the implied w1rr1nty of MERCH1NT12ILITY or - * FITNESS FOR 1 P1RTICUL1R PURPOSE. See the GNU Gener1l Pu2lic License - * version 2 for more det1ils (1 copy is included in the LICENSE file th1t - * 1ccomp1nied 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 h1ve received 1 copy of the GNU Gener1l Pu2lic License version - * 2 1long with this work; if not, write to the Free Softw1re Found1tion, - * Inc., 51 Fr1nklin St, Fifth Floor, 2oston, M1 02110-1301 US1. + * 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. * - * Ple1se cont1ct Or1cle, 500 Or1cle P1rkw1y, Redwood Shores, C1 94065 US1 - * or visit www.or1cle.com if you need 1ddition1l inform1tion or h1ve 1ny + * 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. */
--- a/nashorn/test/script/nosecurity/treeapi/functionExpr.js Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/test/script/nosecurity/treeapi/functionExpr.js Thu Jan 14 12:03:53 2016 -0800 @@ -1,23 +1,23 @@ /* - * Copyright (c) 2014, Or1cle 1nd/or its 1ffili1tes. 1ll rights reserved. - * DO NOT 1LTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HE1DER. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * This code is free softw1re; you c1n redistri2ute it 1nd/or modify it - * under the terms of the GNU Gener1l Pu2lic License version 2 only, 1s - * pu2lished 2y the Free Softw1re Found1tion. + * 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 distri2uted in the hope th1t it will 2e useful, 2ut WITHOUT - * 1NY W1RR1NTY; without even the implied w1rr1nty of MERCH1NT12ILITY or - * FITNESS FOR 1 P1RTICUL1R PURPOSE. See the GNU Gener1l Pu2lic License - * version 2 for more det1ils (1 copy is included in the LICENSE file th1t - * 1ccomp1nied 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 h1ve received 1 copy of the GNU Gener1l Pu2lic License version - * 2 1long with this work; if not, write to the Free Softw1re Found1tion, - * Inc., 51 Fr1nklin St, Fifth Floor, 2oston, M1 02110-1301 US1. + * 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. * - * Ple1se cont1ct Or1cle, 500 Or1cle P1rkw1y, Redwood Shores, C1 94065 US1 - * or visit www.or1cle.com if you need 1ddition1l inform1tion or h1ve 1ny + * 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. */
--- a/nashorn/test/script/nosecurity/treeapi/identifier.js Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/test/script/nosecurity/treeapi/identifier.js Thu Jan 14 12:03:53 2016 -0800 @@ -1,23 +1,23 @@ /* - * Copyright (c) 2014, Or1cle 1nd/or its 1ffili1tes. 1ll rights reserved. - * DO NOT 1LTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HE1DER. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * This code is free softw1re; you c1n redistri2ute it 1nd/or modify it - * under the terms of the GNU Gener1l Pu2lic License version 2 only, 1s - * pu2lished 2y the Free Softw1re Found1tion. + * 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 distri2uted in the hope th1t it will 2e useful, 2ut WITHOUT - * 1NY W1RR1NTY; without even the implied w1rr1nty of MERCH1NT12ILITY or - * FITNESS FOR 1 P1RTICUL1R PURPOSE. See the GNU Gener1l Pu2lic License - * version 2 for more det1ils (1 copy is included in the LICENSE file th1t - * 1ccomp1nied 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 h1ve received 1 copy of the GNU Gener1l Pu2lic License version - * 2 1long with this work; if not, write to the Free Softw1re Found1tion, - * Inc., 51 Fr1nklin St, Fifth Floor, 2oston, M1 02110-1301 US1. + * 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. * - * Ple1se cont1ct Or1cle, 500 Or1cle P1rkw1y, Redwood Shores, C1 94065 US1 - * or visit www.or1cle.com if you need 1ddition1l inform1tion or h1ve 1ny + * 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. */
--- a/nashorn/test/script/nosecurity/treeapi/if.js Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/test/script/nosecurity/treeapi/if.js Thu Jan 14 12:03:53 2016 -0800 @@ -1,23 +1,23 @@ /* - * Copyright (c) 2014, Or1cle 1nd/or its 1ffili1tes. 1ll rights reserved. - * DO NOT 1LTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HE1DER. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * This code is free softw1re; you c1n redistri2ute it 1nd/or modify it - * under the terms of the GNU Gener1l Pu2lic License version 2 only, 1s - * pu2lished 2y the Free Softw1re Found1tion. + * 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 distri2uted in the hope th1t it will 2e useful, 2ut WITHOUT - * 1NY W1RR1NTY; without even the implied w1rr1nty of MERCH1NT12ILITY or - * FITNESS FOR 1 P1RTICUL1R PURPOSE. See the GNU Gener1l Pu2lic License - * version 2 for more det1ils (1 copy is included in the LICENSE file th1t - * 1ccomp1nied 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 h1ve received 1 copy of the GNU Gener1l Pu2lic License version - * 2 1long with this work; if not, write to the Free Softw1re Found1tion, - * Inc., 51 Fr1nklin St, Fifth Floor, 2oston, M1 02110-1301 US1. + * 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. * - * Ple1se cont1ct Or1cle, 500 Or1cle P1rkw1y, Redwood Shores, C1 94065 US1 - * or visit www.or1cle.com if you need 1ddition1l inform1tion or h1ve 1ny + * 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. */
--- a/nashorn/test/script/nosecurity/treeapi/instanceof.js Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/test/script/nosecurity/treeapi/instanceof.js Thu Jan 14 12:03:53 2016 -0800 @@ -1,23 +1,23 @@ /* - * Copyright (c) 2014, Or1cle 1nd/or its 1ffili1tes. 1ll rights reserved. - * DO NOT 1LTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HE1DER. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * This code is free softw1re; you c1n redistri2ute it 1nd/or modify it - * under the terms of the GNU Gener1l Pu2lic License version 2 only, 1s - * pu2lished 2y the Free Softw1re Found1tion. + * 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 distri2uted in the hope th1t it will 2e useful, 2ut WITHOUT - * 1NY W1RR1NTY; without even the implied w1rr1nty of MERCH1NT12ILITY or - * FITNESS FOR 1 P1RTICUL1R PURPOSE. See the GNU Gener1l Pu2lic License - * version 2 for more det1ils (1 copy is included in the LICENSE file th1t - * 1ccomp1nied 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 h1ve received 1 copy of the GNU Gener1l Pu2lic License version - * 2 1long with this work; if not, write to the Free Softw1re Found1tion, - * Inc., 51 Fr1nklin St, Fifth Floor, 2oston, M1 02110-1301 US1. + * 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. * - * Ple1se cont1ct Or1cle, 500 Or1cle P1rkw1y, Redwood Shores, C1 94065 US1 - * or visit www.or1cle.com if you need 1ddition1l inform1tion or h1ve 1ny + * 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. */
--- a/nashorn/test/src/jdk/dynalink/beans/test/BeanLinkerTest.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/test/src/jdk/dynalink/beans/test/BeanLinkerTest.java Thu Jan 14 12:03:53 2016 -0800 @@ -24,7 +24,17 @@ */ package jdk.dynalink.beans.test; +import static jdk.dynalink.StandardOperation.CALL; +import static jdk.dynalink.StandardOperation.CALL_METHOD; +import static jdk.dynalink.StandardOperation.GET_ELEMENT; +import static jdk.dynalink.StandardOperation.GET_LENGTH; +import static jdk.dynalink.StandardOperation.GET_METHOD; +import static jdk.dynalink.StandardOperation.GET_PROPERTY; +import static jdk.dynalink.StandardOperation.NEW; +import static jdk.dynalink.StandardOperation.SET_ELEMENT; + import java.lang.invoke.CallSite; +import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.security.AccessControlException; @@ -38,7 +48,6 @@ import jdk.dynalink.NamedOperation; import jdk.dynalink.NoSuchDynamicMethodException; import jdk.dynalink.Operation; -import jdk.dynalink.StandardOperation; import jdk.dynalink.beans.BeansLinker; import jdk.dynalink.beans.StaticClass; import jdk.dynalink.support.SimpleRelinkableCallSite; @@ -72,9 +81,80 @@ return createCallSite(publicLookup, new NamedOperation(op, name), mt); } + private static final MethodHandle throwArrayIndexOutOfBounds = findThrower("throwArrayIndexOutOfBounds"); + private static final MethodHandle throwIndexOutOfBounds = findThrower("throwIndexOutOfBounds"); + + private static final MethodHandle findThrower(final String name) { + try { + return MethodHandles.lookup().findStatic(BeanLinkerTest.class, name, + MethodType.methodType(Object.class, Object.class, Object.class)); + } catch (NoSuchMethodException | IllegalAccessException e) { + Assert.fail("Unexpected exception", e); + return null; + } + } + + private static Object throwArrayIndexOutOfBounds(final Object receiver, final Object index) { + throw new ArrayIndexOutOfBoundsException(String.valueOf(index)); + } + + private static Object throwIndexOutOfBounds(final Object receiver, final Object index) { + throw new IndexOutOfBoundsException(String.valueOf(index)); + } + @BeforeTest public void initLinker() { final DynamicLinkerFactory factory = new DynamicLinkerFactory(); + factory.setFallbackLinkers(new BeansLinker((req, services) -> { + // This is a MissingMemberHandlerFactory that creates a missing + // member handler for element getters and setters that throw an + // ArrayIndexOutOfBoundsException when applied to an array and an + // IndexOutOfBoundsException when applied to a list. + + final CallSiteDescriptor desc = req.getCallSiteDescriptor(); + final Operation op = desc.getOperation(); + final Operation baseOp = NamedOperation.getBaseOperation(op); + if (baseOp != GET_ELEMENT && baseOp != SET_ELEMENT) { + // We only handle GET_ELEMENT and SET_ELEMENT. + return null; + } + + final Object receiver = req.getReceiver(); + Assert.assertNotNull(receiver); + + final Class<?> clazz = receiver.getClass(); + final MethodHandle throwerHandle; + if (clazz.isArray()) { + throwerHandle = throwArrayIndexOutOfBounds; + } else if (List.class.isAssignableFrom(clazz)) { + throwerHandle = throwIndexOutOfBounds; + } else { + Assert.fail("Unexpected receiver type " + clazz.getName()); + return null; + } + + final Object name = NamedOperation.getName(op); + final MethodHandle nameBoundHandle; + if (name == null) { + nameBoundHandle = throwerHandle; + } else { + // If the operation is for a fixed index, bind it + nameBoundHandle = MethodHandles.insertArguments(throwerHandle, 1, name); + } + + final MethodType callSiteType = desc.getMethodType(); + final MethodHandle arityMatchedHandle; + if (baseOp == SET_ELEMENT) { + // Drop "value" parameter for a setter + final int handleArity = nameBoundHandle.type().parameterCount(); + arityMatchedHandle = MethodHandles.dropArguments(nameBoundHandle, + handleArity, callSiteType.parameterType(handleArity)); + } else { + arityMatchedHandle = nameBoundHandle; + } + + return arityMatchedHandle.asType(callSiteType); + })); this.linker = factory.createLinker(); } @@ -86,7 +166,7 @@ @Test(dataProvider = "flags") public void getPropertyTest(final boolean publicLookup) throws Throwable { final MethodType mt = MethodType.methodType(Object.class, Object.class, String.class); - final CallSite cs = createCallSite(publicLookup, StandardOperation.GET_PROPERTY, mt); + final CallSite cs = createCallSite(publicLookup, GET_PROPERTY, mt); Assert.assertEquals(cs.getTarget().invoke(new Object(), "class"), Object.class); Assert.assertEquals(cs.getTarget().invoke(new Date(), "class"), Date.class); } @@ -94,14 +174,14 @@ @Test(dataProvider = "flags") public void getPropertyNegativeTest(final boolean publicLookup) throws Throwable { final MethodType mt = MethodType.methodType(Object.class, Object.class, String.class); - final CallSite cs = createCallSite(publicLookup, StandardOperation.GET_PROPERTY, mt); + final CallSite cs = createCallSite(publicLookup, GET_PROPERTY, mt); Assert.assertNull(cs.getTarget().invoke(new Object(), "DOES_NOT_EXIST")); } @Test(dataProvider = "flags") public void getPropertyTest2(final boolean publicLookup) throws Throwable { final MethodType mt = MethodType.methodType(Object.class, Object.class); - final CallSite cs = createCallSite(publicLookup, StandardOperation.GET_PROPERTY, "class", mt); + final CallSite cs = createCallSite(publicLookup, GET_PROPERTY, "class", mt); Assert.assertEquals(cs.getTarget().invoke(new Object()), Object.class); Assert.assertEquals(cs.getTarget().invoke(new Date()), Date.class); } @@ -109,12 +189,12 @@ @Test(dataProvider = "flags") public void getPropertyNegativeTest2(final boolean publicLookup) throws Throwable { final MethodType mt = MethodType.methodType(Object.class, Object.class); - final CallSite cs = createCallSite(publicLookup, StandardOperation.GET_PROPERTY, "DOES_NOT_EXIST", mt); + final CallSite cs = createCallSite(publicLookup, GET_PROPERTY, "DOES_NOT_EXIST", mt); try { cs.getTarget().invoke(new Object()); throw new RuntimeException("Expected NoSuchDynamicMethodException"); - } catch (Throwable th) { + } catch (final Throwable th) { Assert.assertTrue(th instanceof NoSuchDynamicMethodException); } } @@ -122,7 +202,7 @@ @Test(dataProvider = "flags") public void getLengthPropertyTest(final boolean publicLookup) throws Throwable { final MethodType mt = MethodType.methodType(int.class, Object.class, String.class); - final CallSite cs = createCallSite(publicLookup, StandardOperation.GET_PROPERTY, mt); + final CallSite cs = createCallSite(publicLookup, GET_PROPERTY, mt); Assert.assertEquals((int) cs.getTarget().invoke(new int[10], "length"), 10); Assert.assertEquals((int) cs.getTarget().invoke(new String[33], "length"), 33); @@ -131,7 +211,7 @@ @Test(dataProvider = "flags") public void getlengthTest(final boolean publicLookup) throws Throwable { final MethodType mt = MethodType.methodType(int.class, Object.class); - final CallSite cs = createCallSite(publicLookup, StandardOperation.GET_LENGTH, mt); + final CallSite cs = createCallSite(publicLookup, GET_LENGTH, mt); final int[] arr = {23, 42}; Assert.assertEquals((int) cs.getTarget().invoke((Object) arr), 2); @@ -151,21 +231,21 @@ @Test(dataProvider = "flags") public void getElementTest(final boolean publicLookup) throws Throwable { final MethodType mt = MethodType.methodType(int.class, Object.class, int.class); - final CallSite cs = createCallSite(publicLookup, StandardOperation.GET_ELEMENT, mt); + final CallSite cs = createCallSite(publicLookup, GET_ELEMENT, mt); final int[] arr = {23, 42}; Assert.assertEquals((int) cs.getTarget().invoke(arr, 0), 23); Assert.assertEquals((int) cs.getTarget().invoke(arr, 1), 42); try { - int x = (int) cs.getTarget().invoke(arr, -1); + final int x = (int) cs.getTarget().invoke(arr, -1); throw new RuntimeException("expected ArrayIndexOutOfBoundsException"); - } catch (ArrayIndexOutOfBoundsException ex) { + } catch (final ArrayIndexOutOfBoundsException ex) { } try { - int x = (int) cs.getTarget().invoke(arr, arr.length); + final int x = (int) cs.getTarget().invoke(arr, arr.length); throw new RuntimeException("expected ArrayIndexOutOfBoundsException"); - } catch (ArrayIndexOutOfBoundsException ex) { + } catch (final ArrayIndexOutOfBoundsException ex) { } final List<Integer> list = new ArrayList<>(); @@ -176,22 +256,22 @@ Assert.assertEquals((int) cs.getTarget().invoke(list, 1), (int) list.get(1)); Assert.assertEquals((int) cs.getTarget().invoke(list, 2), (int) list.get(2)); try { - int x = (int) cs.getTarget().invoke(list, -1); + final int x = (int) cs.getTarget().invoke(list, -1); throw new RuntimeException("expected IndexOutOfBoundsException"); - } catch (IndexOutOfBoundsException ex) { + } catch (final IndexOutOfBoundsException ex) { } try { - int x = (int) cs.getTarget().invoke(list, list.size()); + final int x = (int) cs.getTarget().invoke(list, list.size()); throw new RuntimeException("expected IndexOutOfBoundsException"); - } catch (IndexOutOfBoundsException ex) { + } catch (final IndexOutOfBoundsException ex) { } } @Test(dataProvider = "flags") public void setElementTest(final boolean publicLookup) throws Throwable { final MethodType mt = MethodType.methodType(void.class, Object.class, int.class, int.class); - final CallSite cs = createCallSite(publicLookup, StandardOperation.SET_ELEMENT, mt); + final CallSite cs = createCallSite(publicLookup, SET_ELEMENT, mt); final int[] arr = {23, 42}; cs.getTarget().invoke(arr, 0, 0); @@ -202,13 +282,13 @@ try { cs.getTarget().invoke(arr, -1, 12); throw new RuntimeException("expected ArrayIndexOutOfBoundsException"); - } catch (ArrayIndexOutOfBoundsException ex) { + } catch (final ArrayIndexOutOfBoundsException ex) { } try { cs.getTarget().invoke(arr, arr.length, 20); throw new RuntimeException("expected ArrayIndexOutOfBoundsException"); - } catch (ArrayIndexOutOfBoundsException ex) { + } catch (final ArrayIndexOutOfBoundsException ex) { } final List<Integer> list = new ArrayList<>(); @@ -223,25 +303,25 @@ try { cs.getTarget().invoke(list, -1, 343); throw new RuntimeException("expected IndexOutOfBoundsException"); - } catch (IndexOutOfBoundsException ex) { + } catch (final IndexOutOfBoundsException ex) { } try { cs.getTarget().invoke(list, list.size(), 43543); throw new RuntimeException("expected IndexOutOfBoundsException"); - } catch (IndexOutOfBoundsException ex) { + } catch (final IndexOutOfBoundsException ex) { } } @Test(dataProvider = "flags") public void newObjectTest(final boolean publicLookup) { final MethodType mt = MethodType.methodType(Object.class, Object.class); - final CallSite cs = createCallSite(publicLookup, StandardOperation.NEW, mt); + final CallSite cs = createCallSite(publicLookup, NEW, mt); Object obj = null; try { obj = cs.getTarget().invoke(StaticClass.forClass(Date.class)); - } catch (Throwable th) { + } catch (final Throwable th) { throw new RuntimeException(th); } @@ -251,12 +331,12 @@ @Test(dataProvider = "flags") public void staticPropertyTest(final boolean publicLookup) { final MethodType mt = MethodType.methodType(Object.class, Class.class); - final CallSite cs = createCallSite(publicLookup, StandardOperation.GET_PROPERTY, "static", mt); + final CallSite cs = createCallSite(publicLookup, GET_PROPERTY, "static", mt); Object obj = null; try { obj = cs.getTarget().invoke(Object.class); - } catch (Throwable th) { + } catch (final Throwable th) { throw new RuntimeException(th); } @@ -265,7 +345,7 @@ try { obj = cs.getTarget().invoke(Date.class); - } catch (Throwable th) { + } catch (final Throwable th) { throw new RuntimeException(th); } @@ -274,7 +354,7 @@ try { obj = cs.getTarget().invoke(Object[].class); - } catch (Throwable th) { + } catch (final Throwable th) { throw new RuntimeException(th); } @@ -285,14 +365,14 @@ @Test(dataProvider = "flags") public void instanceMethodCallTest(final boolean publicLookup) { final MethodType mt = MethodType.methodType(Object.class, Object.class); - final CallSite cs = createCallSite(publicLookup, StandardOperation.GET_METHOD, "getClass", mt); + final CallSite cs = createCallSite(publicLookup, GET_METHOD, "getClass", mt); final MethodType mt2 = MethodType.methodType(Class.class, Object.class, Object.class); - final CallSite cs2 = createCallSite(publicLookup, StandardOperation.CALL, mt2); + final CallSite cs2 = createCallSite(publicLookup, CALL, mt2); Object method = null; try { method = cs.getTarget().invoke(new Date()); - } catch (Throwable th) { + } catch (final Throwable th) { throw new RuntimeException(th); } @@ -301,7 +381,7 @@ Class clz = null; try { clz = (Class) cs2.getTarget().invoke(method, new Date()); - } catch (Throwable th) { + } catch (final Throwable th) { throw new RuntimeException(th); } @@ -311,11 +391,11 @@ @Test(dataProvider = "flags") public void instanceMethodCallTest2(final boolean publicLookup) { final MethodType mt = MethodType.methodType(Class.class, Object.class); - final CallSite cs = createCallSite(publicLookup, StandardOperation.CALL_METHOD, "getClass", mt); + final CallSite cs = createCallSite(publicLookup, CALL_METHOD, "getClass", mt); Class clz = null; try { clz = (Class) cs.getTarget().invoke(new Date()); - } catch (Throwable th) { + } catch (final Throwable th) { throw new RuntimeException(th); } @@ -325,14 +405,14 @@ @Test(dataProvider = "flags") public void staticMethodCallTest(final boolean publicLookup) { final MethodType mt = MethodType.methodType(Object.class, StaticClass.class); - final CallSite cs = createCallSite(publicLookup, StandardOperation.GET_METHOD, "getProperty", mt); + final CallSite cs = createCallSite(publicLookup, GET_METHOD, "getProperty", mt); final MethodType mt2 = MethodType.methodType(String.class, Object.class, Object.class, String.class); - final CallSite cs2 = createCallSite(publicLookup, StandardOperation.CALL, mt2); + final CallSite cs2 = createCallSite(publicLookup, CALL, mt2); Object method = null; try { method = cs.getTarget().invoke(StaticClass.forClass(System.class)); - } catch (Throwable th) { + } catch (final Throwable th) { throw new RuntimeException(th); } @@ -342,7 +422,7 @@ String str = null; try { str = (String) cs2.getTarget().invoke(method, null, "os.name"); - } catch (Throwable th) { + } catch (final Throwable th) { throw new RuntimeException(th); } Assert.assertEquals(str, System.getProperty("os.name")); @@ -351,12 +431,12 @@ @Test(dataProvider = "flags") public void staticMethodCallTest2(final boolean publicLookup) { final MethodType mt = MethodType.methodType(String.class, Object.class, String.class); - final CallSite cs = createCallSite(publicLookup, StandardOperation.CALL_METHOD, "getProperty", mt); + final CallSite cs = createCallSite(publicLookup, CALL_METHOD, "getProperty", mt); String str = null; try { str = (String) cs.getTarget().invoke(StaticClass.forClass(System.class), "os.name"); - } catch (Throwable th) { + } catch (final Throwable th) { throw new RuntimeException(th); } Assert.assertEquals(str, System.getProperty("os.name")); @@ -366,12 +446,12 @@ @Test(dataProvider = "flags") public void systemGetenvTest(final boolean publicLookup) { final MethodType mt = MethodType.methodType(Object.class, Object.class); - final CallSite cs = createCallSite(publicLookup, StandardOperation.CALL_METHOD, "getenv", mt); + final CallSite cs = createCallSite(publicLookup, CALL_METHOD, "getenv", mt); try { cs.getTarget().invoke(StaticClass.forClass(System.class)); throw new RuntimeException("should not reach here in any case!"); - } catch (Throwable th) { + } catch (final Throwable th) { Assert.assertTrue(th instanceof SecurityException); } } @@ -380,12 +460,12 @@ @Test(dataProvider = "flags") public void systemGetPropertyTest(final boolean publicLookup) { final MethodType mt = MethodType.methodType(String.class, Object.class, String.class); - final CallSite cs = createCallSite(publicLookup, StandardOperation.CALL_METHOD, "getProperty", mt); + final CallSite cs = createCallSite(publicLookup, CALL_METHOD, "getProperty", mt); try { cs.getTarget().invoke(StaticClass.forClass(System.class), "java.home"); throw new RuntimeException("should not reach here in any case!"); - } catch (Throwable th) { + } catch (final Throwable th) { Assert.assertTrue(th instanceof SecurityException); } } @@ -394,12 +474,12 @@ @Test(dataProvider = "flags") public void systemLoadLibraryTest(final boolean publicLookup) { final MethodType mt = MethodType.methodType(void.class, Object.class, String.class); - final CallSite cs = createCallSite(publicLookup, StandardOperation.CALL_METHOD, "loadLibrary", mt); + final CallSite cs = createCallSite(publicLookup, CALL_METHOD, "loadLibrary", mt); try { cs.getTarget().invoke(StaticClass.forClass(System.class), "foo"); throw new RuntimeException("should not reach here in any case!"); - } catch (Throwable th) { + } catch (final Throwable th) { if (publicLookup) { Assert.assertTrue(th instanceof IllegalAccessError); } else {
--- a/nashorn/test/src/jdk/dynalink/beans/test/BeansLinkerTest.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/test/src/jdk/dynalink/beans/test/BeansLinkerTest.java Thu Jan 14 12:03:53 2016 -0800 @@ -33,6 +33,7 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -44,6 +45,7 @@ import jdk.dynalink.CompositeOperation; import jdk.dynalink.DynamicLinkerFactory; import jdk.dynalink.NamedOperation; +import jdk.dynalink.NoSuchDynamicMethodException; import jdk.dynalink.Operation; import jdk.dynalink.StandardOperation; import jdk.dynalink.support.SimpleRelinkableCallSite; @@ -207,6 +209,30 @@ Assert.assertEquals("element2", map.get("name")); } + @Test + public static void testMissingMembersAtLinkTime() { + testPermutations(GETTER_PERMUTATIONS, (op) -> expectNoSuchDynamicMethodException(()-> call(named("foo", op), new Object()))); + testPermutations(SETTER_PERMUTATIONS, (op) -> expectNoSuchDynamicMethodException(()-> call(named("foo", op), new Object(), "newValue"))); + } + + @Test + public static void testMissingMembersAtRunTime() { + call(GET_ELEMENT, new ArrayList<>(), "foo"); + Stream.of(new HashMap(), new ArrayList(), new Object[0]).forEach((receiver) -> { + testPermutations(GETTER_PERMUTATIONS, (op) -> { System.err.println(op + " " + receiver.getClass().getName()); Assert.assertNull(call(op, receiver, "foo"));}); + // No assertion for the setter; we just expect it to silently succeed + testPermutations(SETTER_PERMUTATIONS, (op) -> call(op, receiver, "foo", "newValue")); + }); + } + + private static void expectNoSuchDynamicMethodException(final Runnable r) { + try { + r.run(); + Assert.fail("Should've thrown NoSuchDynamicMethodException"); + } catch(final NoSuchDynamicMethodException e) { + } + } + private static Operation[] GETTER_PERMUTATIONS = new Operation[] { GET_PROPERTY, GET_METHOD, @@ -240,6 +266,10 @@ testPermutationsWithFilter(ops, (op)->regex.matcher(op.toString()).matches(), expectedCount, test); } + private static void testPermutations(final Operation[] ops, final Consumer<Operation> test) { + testPermutationsWithFilter(ops, (op)->true, ops.length, test); + } + private static void testPermutationsWithFilter(final Operation[] ops, final Predicate<Operation> filter, final int expectedCount, final Consumer<Operation> test) { final int[] counter = new int[1]; Stream.of(ops).filter(filter).forEach((op)-> { counter[0]++; test.accept(op); });
--- a/nashorn/test/src/jdk/dynalink/beans/test/CallerSensitiveTest.java Thu Jan 14 08:08:25 2016 -0800 +++ b/nashorn/test/src/jdk/dynalink/beans/test/CallerSensitiveTest.java Thu Jan 14 12:03:53 2016 -0800 @@ -33,6 +33,6 @@ public class CallerSensitiveTest { @Test public void testCallerSensitive() { - BeansLinker.getLinkerForClass(ClassLoaderAware.class); + new BeansLinker().getLinkerForClass(ClassLoaderAware.class); } }
--- a/nashorn/test/src/jdk/internal/dynalink/beans/test/CallerSensitiveTest.java Thu Jan 14 08:08:25 2016 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2014, 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.internal.dynalink.beans.test; - -import jdk.dynalink.beans.BeansLinker; -import jdk.nashorn.test.models.ClassLoaderAware; -import org.testng.annotations.Test; - -@SuppressWarnings("javadoc") -public class CallerSensitiveTest { - @Test - public void testCallerSensitive() { - BeansLinker.getLinkerForClass(ClassLoaderAware.class); - } -}