8015267: Allow conversion of JS arrays to Java List/Deque

Thu, 23 May 2013 12:01:35 +0200

author
attila
date
Thu, 23 May 2013 12:01:35 +0200
changeset 286
1c1453863ea8
parent 285
8f7553df4503
child 287
f7eb4436410e

8015267: Allow conversion of JS arrays to Java List/Deque
Reviewed-by: lagergren, sundar

make/build.xml file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeJava.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ListAdapter.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/linker/InvokeByName.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/resources/Messages.properties file | annotate | diff | comparison | revisions
test/script/basic/JDK-8015267.js file | annotate | diff | comparison | revisions
test/script/basic/JDK-8015267.js.EXPECTED file | annotate | diff | comparison | revisions
     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

mercurial