Thu, 23 May 2013 12:01:35 +0200
8015267: Allow conversion of JS arrays to Java List/Deque
Reviewed-by: lagergren, sundar
1.1 --- a/make/build.xml Wed May 22 16:43:48 2013 +0200 1.2 +++ b/make/build.xml Thu May 23 12:01:35 2013 +0200 1.3 @@ -42,8 +42,6 @@ 1.4 <condition property="hg.executable" value="/usr/local/bin/hg" else="hg"> 1.5 <available file="/usr/local/bin/hg"/> 1.6 </condition> 1.7 - <!-- check if JDK already has ASM classes --> 1.8 - <available property="asm.available" classname="jdk.internal.org.objectweb.asm.Type"/> 1.9 <!-- check if testng.jar is avaiable --> 1.10 <available property="testng.available" file="${file.reference.testng.jar}"/> 1.11 1.12 @@ -80,19 +78,7 @@ 1.13 <delete dir="${dist.dir}"/> 1.14 </target> 1.15 1.16 - <!-- do it only if ASM is not available --> 1.17 - <target name="compile-asm" depends="prepare" unless="asm.available"> 1.18 - <javac srcdir="${jdk.asm.src.dir}" 1.19 - destdir="${build.classes.dir}" 1.20 - excludes="**/optimizer/* **/xml/* **/attrs/*" 1.21 - source="${javac.source}" 1.22 - target="${javac.target}" 1.23 - debug="${javac.debug}" 1.24 - encoding="${javac.encoding}" 1.25 - includeantruntime="false"/> 1.26 - </target> 1.27 - 1.28 - <target name="compile" depends="compile-asm" description="Compiles nashorn"> 1.29 + <target name="compile" depends="prepare" description="Compiles nashorn"> 1.30 <javac srcdir="${src.dir}" 1.31 destdir="${build.classes.dir}" 1.32 classpath="${javac.classpath}"
2.1 --- a/src/jdk/nashorn/internal/objects/NativeJava.java Wed May 22 16:43:48 2013 +0200 2.2 +++ b/src/jdk/nashorn/internal/objects/NativeJava.java Thu May 23 12:01:35 2013 +0200 2.3 @@ -30,6 +30,8 @@ 2.4 2.5 import java.lang.reflect.Array; 2.6 import java.util.Collection; 2.7 +import java.util.Deque; 2.8 +import java.util.List; 2.9 import jdk.internal.dynalink.beans.StaticClass; 2.10 import jdk.internal.dynalink.support.TypeUtilities; 2.11 import jdk.nashorn.internal.objects.annotations.Attribute; 2.12 @@ -37,6 +39,7 @@ 2.13 import jdk.nashorn.internal.objects.annotations.ScriptClass; 2.14 import jdk.nashorn.internal.objects.annotations.Where; 2.15 import jdk.nashorn.internal.runtime.JSType; 2.16 +import jdk.nashorn.internal.runtime.ListAdapter; 2.17 import jdk.nashorn.internal.runtime.ScriptObject; 2.18 import jdk.nashorn.internal.runtime.linker.JavaAdapterFactory; 2.19 2.20 @@ -240,8 +243,8 @@ 2.21 } 2.22 2.23 /** 2.24 - * Given a script object and a Java type, converts the script object into the desired Java type. Currently it only 2.25 - * performs shallow creation of Java arrays, but might be extended for other types in the future. Example: 2.26 + * Given a script object and a Java type, converts the script object into the desired Java type. Currently it 2.27 + * performs shallow creation of Java arrays, as well as wrapping of objects in Lists and Dequeues. Example: 2.28 * <pre> 2.29 * var anArray = [1, "13", false] 2.30 * var javaIntArray = Java.to(anArray, "int[]") 2.31 @@ -250,42 +253,46 @@ 2.32 * print(javaIntArray[2]) // prints 0, as boolean false was converted to number 0 as per ECMAScript ToNumber conversion 2.33 * </pre> 2.34 * @param self not used 2.35 - * @param objArray the script object. Can be null. 2.36 + * @param obj the script object. Can be null. 2.37 * @param objType either a {@link #type(Object, Object) type object} or a String describing the type of the Java 2.38 * object to create. Can not be null. If undefined, a "default" conversion is presumed (allowing the argument to be 2.39 * omitted). 2.40 * @return a Java object whose value corresponds to the original script object's value. Specifically, for array 2.41 * target types, returns a Java array of the same type with contents converted to the array's component type. Does 2.42 - * not recursively convert for multidimensional arrays. 2.43 - * type. Returns null if scriptObject is null. 2.44 + * not recursively convert for multidimensional arrays. For {@link List} or {@link Deque}, returns a live wrapper 2.45 + * around the object, see {@link ListAdapter} for details. Returns null if obj is null. 2.46 * @throws ClassNotFoundException if the class described by objType is not found 2.47 */ 2.48 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) 2.49 - public static Object to(final Object self, final Object objArray, final Object objType) throws ClassNotFoundException { 2.50 - if (objArray == null) { 2.51 + public static Object to(final Object self, final Object obj, final Object objType) throws ClassNotFoundException { 2.52 + if (obj == null) { 2.53 return null; 2.54 } 2.55 2.56 - final Class<?> componentType; 2.57 + Global.checkObject(obj); 2.58 + 2.59 + final Class<?> targetClass; 2.60 if(objType == UNDEFINED) { 2.61 - componentType = Object.class; 2.62 + targetClass = Object[].class; 2.63 } else { 2.64 - final StaticClass arrayType; 2.65 + final StaticClass targetType; 2.66 if(objType instanceof StaticClass) { 2.67 - arrayType = (StaticClass)objType; 2.68 + targetType = (StaticClass)objType; 2.69 } else { 2.70 - arrayType = type(objType); 2.71 + targetType = type(objType); 2.72 } 2.73 - final Class<?> arrayClass = arrayType.getRepresentedClass(); 2.74 - if(!arrayClass.isArray()) { 2.75 - throw typeError("to.expects.array.type", arrayClass.getName()); 2.76 - } 2.77 - componentType = arrayClass.getComponentType(); 2.78 + targetClass = targetType.getRepresentedClass(); 2.79 } 2.80 2.81 - Global.checkObject(objArray); 2.82 + if(targetClass.isArray()) { 2.83 + return ((ScriptObject)obj).getArray().asArrayOfType(targetClass.getComponentType()); 2.84 + } 2.85 2.86 - return ((ScriptObject)objArray).getArray().asArrayOfType(componentType); 2.87 + if(targetClass == List.class || targetClass == Deque.class) { 2.88 + return new ListAdapter((ScriptObject)obj); 2.89 + } 2.90 + 2.91 + throw typeError("unsupported.java.to.type", targetClass.getName()); 2.92 } 2.93 2.94 /**
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/src/jdk/nashorn/internal/runtime/ListAdapter.java Thu May 23 12:01:35 2013 +0200 3.3 @@ -0,0 +1,337 @@ 3.4 +package jdk.nashorn.internal.runtime; 3.5 + 3.6 +import java.util.AbstractList; 3.7 +import java.util.Deque; 3.8 +import java.util.Iterator; 3.9 +import java.util.ListIterator; 3.10 +import java.util.NoSuchElementException; 3.11 +import java.util.RandomAccess; 3.12 +import jdk.nashorn.internal.runtime.linker.InvokeByName; 3.13 + 3.14 +/** 3.15 + * An adapter that can wrap any ECMAScript Array-like object (that adheres to the array rules for the property 3.16 + * {@code length} and having conforming {@code push}, {@code pop}, {@code shift}, {@code unshift}, and {@code splice} 3.17 + * methods) and expose it as both a Java list and double-ended queue. While script arrays aren't necessarily efficient 3.18 + * as dequeues, it's still slightly more efficient to be able to translate dequeue operations into pushes, pops, shifts, 3.19 + * and unshifts, than to blindly translate all list's add/remove operations into splices. Also, it is conceivable that a 3.20 + * custom script object that implements an Array-like API can have a background data representation that is optimized 3.21 + * for dequeue-like access. Note that with ECMAScript arrays, {@code push} and {@pop} operate at the end of the array, 3.22 + * while in Java {@code Deque} they operate on the front of the queue and as such the Java dequeue {@link #push(Object)} 3.23 + * and {@link #pop()} operations will translate to {@code unshift} and {@code shift} script operations respectively, 3.24 + * while {@link #addLast(Object)} and {@link #removeLast()} will translate to {@code push} and {@code pop}. 3.25 + */ 3.26 +public class ListAdapter extends AbstractList<Object> implements RandomAccess, Deque<Object> { 3.27 + // These add to the back and front of the list 3.28 + private static final InvokeByName PUSH = new InvokeByName("push", ScriptObject.class, void.class, Object.class); 3.29 + private static final InvokeByName UNSHIFT = new InvokeByName("unshift", ScriptObject.class, void.class, Object.class); 3.30 + 3.31 + // These remove from the back and front of the list 3.32 + private static final InvokeByName POP = new InvokeByName("pop", ScriptObject.class, Object.class); 3.33 + private static final InvokeByName SHIFT = new InvokeByName("shift", ScriptObject.class, Object.class); 3.34 + 3.35 + // These insert and remove in the middle of the list 3.36 + private static final InvokeByName SPLICE_ADD = new InvokeByName("splice", ScriptObject.class, void.class, int.class, int.class, Object.class); 3.37 + private static final InvokeByName SPLICE_REMOVE = new InvokeByName("splice", ScriptObject.class, void.class, int.class, int.class); 3.38 + 3.39 + private final ScriptObject obj; 3.40 + 3.41 + /** 3.42 + * Creates a new list wrapper for the specified script object. 3.43 + * @param obj script the object to wrap 3.44 + */ 3.45 + public ListAdapter(ScriptObject obj) { 3.46 + this.obj = obj; 3.47 + } 3.48 + 3.49 + @Override 3.50 + public int size() { 3.51 + return JSType.toInt32(obj.getLength()); 3.52 + } 3.53 + 3.54 + @Override 3.55 + public Object get(int index) { 3.56 + checkRange(index); 3.57 + return obj.get(index); 3.58 + } 3.59 + 3.60 + @Override 3.61 + public Object set(int index, Object element) { 3.62 + checkRange(index); 3.63 + final Object prevValue = get(index); 3.64 + obj.set(index, element, false); 3.65 + return prevValue; 3.66 + } 3.67 + 3.68 + private void checkRange(int index) { 3.69 + if(index < 0 || index >= size()) { 3.70 + throw invalidIndex(index); 3.71 + } 3.72 + } 3.73 + 3.74 + @Override 3.75 + public void push(Object e) { 3.76 + addFirst(e); 3.77 + } 3.78 + 3.79 + @Override 3.80 + public boolean add(Object e) { 3.81 + addLast(e); 3.82 + return true; 3.83 + } 3.84 + 3.85 + @Override 3.86 + public void addFirst(Object e) { 3.87 + try { 3.88 + final Object fn = UNSHIFT.getGetter().invokeExact(obj); 3.89 + checkFunction(fn, UNSHIFT); 3.90 + UNSHIFT.getInvoker().invokeExact(fn, obj, e); 3.91 + } catch(RuntimeException | Error ex) { 3.92 + throw ex; 3.93 + } catch(Throwable t) { 3.94 + throw new RuntimeException(t); 3.95 + } 3.96 + } 3.97 + 3.98 + @Override 3.99 + public void addLast(Object e) { 3.100 + try { 3.101 + final Object fn = PUSH.getGetter().invokeExact(obj); 3.102 + checkFunction(fn, PUSH); 3.103 + PUSH.getInvoker().invokeExact(fn, obj, e); 3.104 + } catch(RuntimeException | Error ex) { 3.105 + throw ex; 3.106 + } catch(Throwable t) { 3.107 + throw new RuntimeException(t); 3.108 + } 3.109 + } 3.110 + 3.111 + @Override 3.112 + public void add(int index, Object e) { 3.113 + try { 3.114 + if(index < 0) { 3.115 + throw invalidIndex(index); 3.116 + } else if(index == 0) { 3.117 + addFirst(e); 3.118 + } else { 3.119 + final int size = size(); 3.120 + if(index < size) { 3.121 + final Object fn = SPLICE_ADD.getGetter().invokeExact(obj); 3.122 + checkFunction(fn, SPLICE_ADD); 3.123 + SPLICE_ADD.getInvoker().invokeExact(fn, obj, index, 0, e); 3.124 + } else if(index == size) { 3.125 + addLast(e); 3.126 + } else { 3.127 + throw invalidIndex(index); 3.128 + } 3.129 + } 3.130 + } catch(RuntimeException | Error ex) { 3.131 + throw ex; 3.132 + } catch(Throwable t) { 3.133 + throw new RuntimeException(t); 3.134 + } 3.135 + } 3.136 + private static void checkFunction(Object fn, InvokeByName invoke) { 3.137 + if(!(fn instanceof ScriptFunction)) { 3.138 + throw new UnsupportedOperationException("The script object doesn't have a function named " + invoke.getName()); 3.139 + } 3.140 + } 3.141 + 3.142 + private static IndexOutOfBoundsException invalidIndex(int index) { 3.143 + return new IndexOutOfBoundsException(String.valueOf(index)); 3.144 + } 3.145 + 3.146 + @Override 3.147 + public boolean offer(Object e) { 3.148 + return offerLast(e); 3.149 + } 3.150 + 3.151 + @Override 3.152 + public boolean offerFirst(Object e) { 3.153 + addFirst(e); 3.154 + return true; 3.155 + } 3.156 + 3.157 + @Override 3.158 + public boolean offerLast(Object e) { 3.159 + addLast(e); 3.160 + return true; 3.161 + } 3.162 + 3.163 + @Override 3.164 + public Object pop() { 3.165 + return removeFirst(); 3.166 + } 3.167 + 3.168 + @Override 3.169 + public Object remove() { 3.170 + return removeFirst(); 3.171 + } 3.172 + 3.173 + @Override 3.174 + public Object removeFirst() { 3.175 + checkNonEmpty(); 3.176 + return invokeShift(); 3.177 + } 3.178 + 3.179 + @Override 3.180 + public Object removeLast() { 3.181 + checkNonEmpty(); 3.182 + return invokePop(); 3.183 + } 3.184 + 3.185 + private void checkNonEmpty() { 3.186 + if(isEmpty()) { 3.187 + throw new NoSuchElementException(); 3.188 + } 3.189 + } 3.190 + 3.191 + @Override 3.192 + public Object remove(int index) { 3.193 + if(index < 0) { 3.194 + throw invalidIndex(index); 3.195 + } else if (index == 0) { 3.196 + return invokeShift(); 3.197 + } else { 3.198 + final int maxIndex = size() - 1; 3.199 + if(index < maxIndex) { 3.200 + final Object prevValue = get(index); 3.201 + invokeSpliceRemove(index, 1); 3.202 + return prevValue; 3.203 + } else if(index == maxIndex) { 3.204 + return invokePop(); 3.205 + } else { 3.206 + throw invalidIndex(index); 3.207 + } 3.208 + } 3.209 + } 3.210 + 3.211 + private Object invokeShift() { 3.212 + try { 3.213 + final Object fn = SHIFT.getGetter().invokeExact(obj); 3.214 + checkFunction(fn, SHIFT); 3.215 + return SHIFT.getInvoker().invokeExact(fn, obj); 3.216 + } catch(RuntimeException | Error ex) { 3.217 + throw ex; 3.218 + } catch(Throwable t) { 3.219 + throw new RuntimeException(t); 3.220 + } 3.221 + } 3.222 + 3.223 + private Object invokePop() { 3.224 + try { 3.225 + final Object fn = POP.getGetter().invokeExact(obj); 3.226 + checkFunction(fn, POP); 3.227 + return POP.getInvoker().invokeExact(fn, obj); 3.228 + } catch(RuntimeException | Error ex) { 3.229 + throw ex; 3.230 + } catch(Throwable t) { 3.231 + throw new RuntimeException(t); 3.232 + } 3.233 + } 3.234 + 3.235 + @Override 3.236 + protected void removeRange(int fromIndex, int toIndex) { 3.237 + invokeSpliceRemove(fromIndex, toIndex - fromIndex); 3.238 + } 3.239 + 3.240 + private void invokeSpliceRemove(int fromIndex, int count) { 3.241 + try { 3.242 + final Object fn = SPLICE_REMOVE.getGetter().invokeExact(obj); 3.243 + checkFunction(fn, SPLICE_REMOVE); 3.244 + SPLICE_REMOVE.getInvoker().invokeExact(fn, obj, fromIndex, count); 3.245 + } catch(RuntimeException | Error ex) { 3.246 + throw ex; 3.247 + } catch(Throwable t) { 3.248 + throw new RuntimeException(t); 3.249 + } 3.250 + } 3.251 + 3.252 + @Override 3.253 + public Object poll() { 3.254 + return pollFirst(); 3.255 + } 3.256 + 3.257 + @Override 3.258 + public Object pollFirst() { 3.259 + return isEmpty() ? null : invokeShift(); 3.260 + } 3.261 + 3.262 + @Override 3.263 + public Object pollLast() { 3.264 + return isEmpty() ? null : invokePop(); 3.265 + } 3.266 + 3.267 + @Override 3.268 + public Object peek() { 3.269 + return peekFirst(); 3.270 + } 3.271 + 3.272 + @Override 3.273 + public Object peekFirst() { 3.274 + return isEmpty() ? null : get(0); 3.275 + } 3.276 + 3.277 + @Override 3.278 + public Object peekLast() { 3.279 + return isEmpty() ? null : get(size() - 1); 3.280 + } 3.281 + 3.282 + @Override 3.283 + public Object element() { 3.284 + return getFirst(); 3.285 + } 3.286 + 3.287 + @Override 3.288 + public Object getFirst() { 3.289 + checkNonEmpty(); 3.290 + return get(0); 3.291 + } 3.292 + 3.293 + @Override 3.294 + public Object getLast() { 3.295 + checkNonEmpty(); 3.296 + return get(size() - 1); 3.297 + } 3.298 + 3.299 + @Override 3.300 + public Iterator<Object> descendingIterator() { 3.301 + final ListIterator<Object> it = listIterator(size()); 3.302 + return new Iterator<Object>() { 3.303 + @Override 3.304 + public boolean hasNext() { 3.305 + return it.hasPrevious(); 3.306 + } 3.307 + 3.308 + @Override 3.309 + public Object next() { 3.310 + return it.previous(); 3.311 + } 3.312 + 3.313 + @Override 3.314 + public void remove() { 3.315 + it.remove(); 3.316 + } 3.317 + }; 3.318 + } 3.319 + 3.320 + @Override 3.321 + public boolean removeFirstOccurrence(Object o) { 3.322 + return removeOccurrence(o, iterator()); 3.323 + } 3.324 + 3.325 + @Override 3.326 + public boolean removeLastOccurrence(Object o) { 3.327 + return removeOccurrence(o, descendingIterator()); 3.328 + } 3.329 + 3.330 + private static boolean removeOccurrence(Object o, Iterator<Object> it) { 3.331 + while(it.hasNext()) { 3.332 + final Object e = it.next(); 3.333 + if(o == null ? e == null : o.equals(e)) { 3.334 + it.remove(); 3.335 + return true; 3.336 + } 3.337 + } 3.338 + return false; 3.339 + } 3.340 +}
4.1 --- a/src/jdk/nashorn/internal/runtime/linker/InvokeByName.java Wed May 22 16:43:48 2013 +0200 4.2 +++ b/src/jdk/nashorn/internal/runtime/linker/InvokeByName.java Thu May 23 12:01:35 2013 +0200 4.3 @@ -40,7 +40,7 @@ 4.4 * private static final InvokeByName TO_JSON = new InvokeByName("toJSON", Object.class, Object.class, Object.class); 4.5 * ... 4.6 * final Object toJSONFn = TO_JSON.getGetter().invokeExact(obj); 4.7 - * value = TO_JSON.getInvoker().invokeExact(toJSON, obj, key); 4.8 + * value = TO_JSON.getInvoker().invokeExact(toJSONFn, obj, key); 4.9 * </pre> 4.10 * In practice, you can have stronger type assumptions if it makes sense for your code, just remember that you must use 4.11 * the same parameter types as the formal types of the arguments for {@code invokeExact} to work: 4.12 @@ -50,7 +50,7 @@ 4.13 * final ScriptObject sobj = (ScriptObject)obj; 4.14 * final Object toJSONFn = TO_JSON.getGetter().invokeExact(sobj); 4.15 * if(toJSONFn instanceof ScriptFunction) { 4.16 - * value = TO_JSON.getInvoker().invokeExact(toJSON, sobj, key); 4.17 + * value = TO_JSON.getInvoker().invokeExact(toJSONFn, sobj, key); 4.18 * } 4.19 * </pre> 4.20 * Note that in general you will not want to reuse a single instance of this class for implementing more than one call 4.21 @@ -59,6 +59,7 @@ 4.22 * separate instance of this class for every place. 4.23 */ 4.24 public class InvokeByName { 4.25 + private final String name; 4.26 private final MethodHandle getter; 4.27 private final MethodHandle invoker; 4.28 4.29 @@ -81,6 +82,7 @@ 4.30 * @param ptypes the parameter types of the function. 4.31 */ 4.32 public InvokeByName(final String name, final Class<?> targetClass, final Class<?> rtype, final Class<?>... ptypes) { 4.33 + this.name = name; 4.34 getter = Bootstrap.createDynamicInvoker("dyn:getMethod|getProp|getItem:" + name, Object.class, targetClass); 4.35 4.36 final Class<?>[] finalPtypes; 4.37 @@ -97,6 +99,14 @@ 4.38 } 4.39 4.40 /** 4.41 + * Returns the name of the function retrieved through this invoker. 4.42 + * @return the name of the function retrieved through this invoker. 4.43 + */ 4.44 + public String getName() { 4.45 + return name; 4.46 + } 4.47 + 4.48 + /** 4.49 * Returns the property getter that can be invoked on an object to retrieve the function object that will be 4.50 * subsequently invoked by the invoker returned by {@link #getInvoker()}. 4.51 * @return the property getter method handle for the function.
5.1 --- a/src/jdk/nashorn/internal/runtime/resources/Messages.properties Wed May 22 16:43:48 2013 +0200 5.2 +++ b/src/jdk/nashorn/internal/runtime/resources/Messages.properties Thu May 23 12:01:35 2013 +0200 5.3 @@ -125,7 +125,7 @@ 5.4 type.error.no.method.matches.args=Can not invoke method {0} with the passed arguments; they do not match any of its method signatures. 5.5 type.error.method.not.constructor=Java method {0} can't be used as a constructor. 5.6 type.error.env.not.object=$ENV must be an Object. 5.7 -type.error.to.expects.array.type=Java.to() expects an array target type. {0} is not an array type. 5.8 +type.error.unsupported.java.to.type=Unsupported Java.to target type {0}. 5.9 range.error.inappropriate.array.length=inappropriate array length: {0} 5.10 range.error.invalid.fraction.digits=fractionDigits argument to {0} must be in [0, 20] 5.11 range.error.invalid.precision=precision argument toPrecision() must be in [1, 21]
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/test/script/basic/JDK-8015267.js Thu May 23 12:01:35 2013 +0200 6.3 @@ -0,0 +1,109 @@ 6.4 +/* 6.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.7 + * 6.8 + * This code is free software; you can redistribute it and/or modify it 6.9 + * under the terms of the GNU General Public License version 2 only, as 6.10 + * published by the Free Software Foundation. 6.11 + * 6.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 6.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 6.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 6.15 + * version 2 for more details (a copy is included in the LICENSE file that 6.16 + * accompanied this code). 6.17 + * 6.18 + * You should have received a copy of the GNU General Public License version 6.19 + * 2 along with this work; if not, write to the Free Software Foundation, 6.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 6.21 + * 6.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 6.23 + * or visit www.oracle.com if you need additional information or have any 6.24 + * questions. 6.25 + */ 6.26 + 6.27 +/** 6.28 + * JDK-8015267: have a List/Deque adapter for JS array-like objects 6.29 + * 6.30 + * @test 6.31 + * @run 6.32 + */ 6.33 + 6.34 +var a = ['a', 'b', 'c', 'd'] 6.35 + 6.36 +var l = Java.to(a, java.util.List) 6.37 +print(l instanceof java.util.List) 6.38 +print(l instanceof java.util.Deque) 6.39 + 6.40 +print(l[0]) 6.41 +print(l[1]) 6.42 +print(l[2]) 6.43 +print(l[3]) 6.44 + 6.45 +print(l.size()) 6.46 + 6.47 +l.push('x') 6.48 +print(a) 6.49 + 6.50 +l.addLast('y') 6.51 +print(a) 6.52 + 6.53 +print(l.pop()) 6.54 +print(l.removeLast()) 6.55 +print(a) 6.56 + 6.57 +l.add('e') 6.58 +l.add(5, 'f') 6.59 +print(a) 6.60 + 6.61 +l.add(0, 'z') 6.62 +print(a) 6.63 + 6.64 +l.add(2, 'x') 6.65 +print(a) 6.66 + 6.67 +l[7] = 'g' 6.68 +print(a) 6.69 + 6.70 +try { l.add(15, '') } catch(e) { print(e.class) } 6.71 +try { l.remove(15) } catch(e) { print(e.class) } 6.72 +try { l.add(-1, '') } catch(e) { print(e.class) } 6.73 +try { l.remove(-1) } catch(e) { print(e.class) } 6.74 + 6.75 +l.remove(7) 6.76 +l.remove(2) 6.77 +l.remove(0) 6.78 +print(a) 6.79 + 6.80 +print(l.peek()) 6.81 +print(l.peekFirst()) 6.82 +print(l.peekLast()) 6.83 + 6.84 +print(l.element()) 6.85 +print(l.getFirst()) 6.86 +print(l.getLast()) 6.87 + 6.88 +l.offer('1') 6.89 +l.offerFirst('2') 6.90 +l.offerLast('3') 6.91 +print(a) 6.92 + 6.93 +a = ['1', '2', 'x', '3', '4', 'x', '5', '6', 'x', '7', '8'] 6.94 +print(a) 6.95 +var l = Java.to(a, java.util.List) 6.96 +l.removeFirstOccurrence('x') 6.97 +print(a) 6.98 +l.removeLastOccurrence('x') 6.99 +print(a) 6.100 + 6.101 +var empty = Java.to([], java.util.List) 6.102 +try { empty.pop() } catch(e) { print(e.class) } 6.103 +try { empty.removeFirst() } catch(e) { print(e.class) } 6.104 +try { empty.removeLast() } catch(e) { print(e.class) } 6.105 + 6.106 +try { empty.element() } catch(e) { print(e.class) } 6.107 +try { empty.getFirst() } catch(e) { print(e.class) } 6.108 +try { empty.getLast() } catch(e) { print(e.class) } 6.109 + 6.110 +print(empty.peek()) 6.111 +print(empty.peekFirst()) 6.112 +print(empty.peekLast())
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/test/script/basic/JDK-8015267.js.EXPECTED Thu May 23 12:01:35 2013 +0200 7.3 @@ -0,0 +1,40 @@ 7.4 +true 7.5 +true 7.6 +a 7.7 +b 7.8 +c 7.9 +d 7.10 +4 7.11 +x,a,b,c,d 7.12 +x,a,b,c,d,y 7.13 +x 7.14 +y 7.15 +a,b,c,d 7.16 +a,b,c,d,e,f 7.17 +z,a,b,c,d,e,f 7.18 +z,a,x,b,c,d,e,f 7.19 +z,a,x,b,c,d,e,g 7.20 +class java.lang.IndexOutOfBoundsException 7.21 +class java.lang.IndexOutOfBoundsException 7.22 +class java.lang.IndexOutOfBoundsException 7.23 +class java.lang.IndexOutOfBoundsException 7.24 +a,b,c,d,e 7.25 +a 7.26 +a 7.27 +e 7.28 +a 7.29 +a 7.30 +e 7.31 +2,a,b,c,d,e,1,3 7.32 +1,2,x,3,4,x,5,6,x,7,8 7.33 +1,2,3,4,x,5,6,x,7,8 7.34 +1,2,3,4,x,5,6,7,8 7.35 +class java.util.NoSuchElementException 7.36 +class java.util.NoSuchElementException 7.37 +class java.util.NoSuchElementException 7.38 +class java.util.NoSuchElementException 7.39 +class java.util.NoSuchElementException 7.40 +class java.util.NoSuchElementException 7.41 +null 7.42 +null 7.43 +null