8024847: Java.to should accept mirror and external JSObjects as array-like objects as well

Mon, 16 Sep 2013 15:08:36 +0530

author
sundar
date
Mon, 16 Sep 2013 15:08:36 +0530
changeset 554
38378024a332
parent 553
5683eca2967a
child 555
f1fd5f0bc84c

8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
Reviewed-by: hannesw, attila, lagergren

src/jdk/nashorn/internal/objects/NativeJava.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ECMAErrors.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/JSObjectListAdapter.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/JSType.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ListAdapter.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ScriptObjectListAdapter.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/ArrayData.java file | annotate | diff | comparison | revisions
test/script/basic/JDK-8024847.js file | annotate | diff | comparison | revisions
test/script/basic/JDK-8024847.js.EXPECTED file | annotate | diff | comparison | revisions
     1.1 --- a/src/jdk/nashorn/internal/objects/NativeJava.java	Fri Sep 13 17:50:18 2013 +0530
     1.2 +++ b/src/jdk/nashorn/internal/objects/NativeJava.java	Mon Sep 16 15:08:36 2013 +0530
     1.3 @@ -34,6 +34,7 @@
     1.4  import java.util.List;
     1.5  import jdk.internal.dynalink.beans.StaticClass;
     1.6  import jdk.internal.dynalink.support.TypeUtilities;
     1.7 +import jdk.nashorn.api.scripting.JSObject;
     1.8  import jdk.nashorn.internal.objects.annotations.Attribute;
     1.9  import jdk.nashorn.internal.objects.annotations.Function;
    1.10  import jdk.nashorn.internal.objects.annotations.ScriptClass;
    1.11 @@ -43,6 +44,7 @@
    1.12  import jdk.nashorn.internal.runtime.ListAdapter;
    1.13  import jdk.nashorn.internal.runtime.PropertyMap;
    1.14  import jdk.nashorn.internal.runtime.ScriptObject;
    1.15 +import jdk.nashorn.internal.runtime.ScriptRuntime;
    1.16  import jdk.nashorn.internal.runtime.linker.Bootstrap;
    1.17  import jdk.nashorn.internal.runtime.linker.JavaAdapterFactory;
    1.18  
    1.19 @@ -288,7 +290,9 @@
    1.20              return null;
    1.21          }
    1.22  
    1.23 -        Global.checkObject(obj);
    1.24 +        if (!(obj instanceof ScriptObject) && !(obj instanceof JSObject)) {
    1.25 +            throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
    1.26 +        }
    1.27  
    1.28          final Class<?> targetClass;
    1.29          if(objType == UNDEFINED) {
    1.30 @@ -304,11 +308,11 @@
    1.31          }
    1.32  
    1.33          if(targetClass.isArray()) {
    1.34 -            return ((ScriptObject)obj).getArray().asArrayOfType(targetClass.getComponentType());
    1.35 +            return JSType.toJavaArray(obj, targetClass.getComponentType());
    1.36          }
    1.37  
    1.38          if(targetClass == List.class || targetClass == Deque.class) {
    1.39 -            return new ListAdapter((ScriptObject)obj);
    1.40 +            return ListAdapter.create(obj);
    1.41          }
    1.42  
    1.43          throw typeError("unsupported.java.to.type", targetClass.getName());
     2.1 --- a/src/jdk/nashorn/internal/runtime/ECMAErrors.java	Fri Sep 13 17:50:18 2013 +0530
     2.2 +++ b/src/jdk/nashorn/internal/runtime/ECMAErrors.java	Mon Sep 16 15:08:36 2013 +0530
     2.3 @@ -28,7 +28,6 @@
     2.4  import java.text.MessageFormat;
     2.5  import java.util.Locale;
     2.6  import java.util.ResourceBundle;
     2.7 -
     2.8  import jdk.nashorn.api.scripting.NashornException;
     2.9  import jdk.nashorn.internal.scripts.JS;
    2.10  
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/jdk/nashorn/internal/runtime/JSObjectListAdapter.java	Mon Sep 16 15:08:36 2013 +0530
     3.3 @@ -0,0 +1,56 @@
     3.4 +/*
     3.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.7 + *
     3.8 + * This code is free software; you can redistribute it and/or modify it
     3.9 + * under the terms of the GNU General Public License version 2 only, as
    3.10 + * published by the Free Software Foundation.  Oracle designates this
    3.11 + * particular file as subject to the "Classpath" exception as provided
    3.12 + * by Oracle in the LICENSE file that accompanied this code.
    3.13 + *
    3.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    3.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    3.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    3.17 + * version 2 for more details (a copy is included in the LICENSE file that
    3.18 + * accompanied this code).
    3.19 + *
    3.20 + * You should have received a copy of the GNU General Public License version
    3.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    3.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    3.23 + *
    3.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    3.25 + * or visit www.oracle.com if you need additional information or have any
    3.26 + * questions.
    3.27 + */
    3.28 +
    3.29 +package jdk.nashorn.internal.runtime;
    3.30 +
    3.31 +import jdk.nashorn.api.scripting.JSObject;
    3.32 +
    3.33 +/**
    3.34 + * A ListAdapter that can wraps a JSObject.
    3.35 + */
    3.36 +public final class JSObjectListAdapter extends ListAdapter {
    3.37 +    /**
    3.38 +     * Creates a new list wrapper for the specified JSObject.
    3.39 +     * @param obj JSOcript the object to wrap
    3.40 +     */
    3.41 +    public JSObjectListAdapter(final JSObject obj) {
    3.42 +        super(obj);
    3.43 +    }
    3.44 +
    3.45 +    @Override
    3.46 +    public int size() {
    3.47 +        return JSType.toInt32(((JSObject)obj).getMember("length"));
    3.48 +    }
    3.49 +
    3.50 +    @Override
    3.51 +    protected Object getAt(int index) {
    3.52 +        return ((JSObject)obj).getSlot(index);
    3.53 +    }
    3.54 +
    3.55 +    @Override
    3.56 +    protected void setAt(int index, Object element) {
    3.57 +        ((JSObject)obj).setSlot(index, element);
    3.58 +    }
    3.59 +}
     4.1 --- a/src/jdk/nashorn/internal/runtime/JSType.java	Fri Sep 13 17:50:18 2013 +0530
     4.2 +++ b/src/jdk/nashorn/internal/runtime/JSType.java	Mon Sep 16 15:08:36 2013 +0530
     4.3 @@ -28,10 +28,14 @@
     4.4  import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
     4.5  import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
     4.6  
     4.7 +import java.lang.invoke.MethodHandle;
     4.8  import java.lang.invoke.MethodHandles;
     4.9 +import java.lang.reflect.Array;
    4.10  import jdk.internal.dynalink.beans.StaticClass;
    4.11 +import jdk.nashorn.api.scripting.JSObject;
    4.12  import jdk.nashorn.internal.codegen.CompilerConstants.Call;
    4.13  import jdk.nashorn.internal.parser.Lexer;
    4.14 +import jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator;
    4.15  import jdk.nashorn.internal.runtime.linker.Bootstrap;
    4.16  
    4.17  /**
    4.18 @@ -860,6 +864,53 @@
    4.19      }
    4.20  
    4.21      /**
    4.22 +     * Script object to Java array conversion.
    4.23 +     *
    4.24 +     * @param obj script object to be converted to Java array
    4.25 +     * @param componentType component type of the destination array required
    4.26 +     * @return converted Java array
    4.27 +     */
    4.28 +    public static Object toJavaArray(final Object obj, final Class<?> componentType) {
    4.29 +        if (obj instanceof ScriptObject) {
    4.30 +            return convertArray(((ScriptObject)obj).getArray().asObjectArray(), componentType);
    4.31 +        } else if (obj instanceof JSObject) {
    4.32 +            final ArrayLikeIterator itr = ArrayLikeIterator.arrayLikeIterator(obj);
    4.33 +            final int len = (int) itr.getLength();
    4.34 +            final Object[] res = new Object[len];
    4.35 +            int idx = 0;
    4.36 +            while (itr.hasNext()) {
    4.37 +                res[idx++] = itr.next();
    4.38 +            }
    4.39 +            return convertArray(res, componentType);
    4.40 +        } else {
    4.41 +            throw new IllegalArgumentException("not a script object");
    4.42 +        }
    4.43 +    }
    4.44 +
    4.45 +    /**
    4.46 +     * Java array to java array conversion - but using type conversions implemented by linker.
    4.47 +     *
    4.48 +     * @param src source array
    4.49 +     * @param componentType component type of the destination array required
    4.50 +     * @return converted Java array
    4.51 +     */
    4.52 +    public static Object convertArray(final Object[] src, final Class<?> componentType) {
    4.53 +        final int l = src.length;
    4.54 +        final Object dst = Array.newInstance(componentType, l);
    4.55 +        final MethodHandle converter = Bootstrap.getLinkerServices().getTypeConverter(Object.class, componentType);
    4.56 +        try {
    4.57 +            for (int i = 0; i < src.length; i++) {
    4.58 +                Array.set(dst, i, invoke(converter, src[i]));
    4.59 +            }
    4.60 +        } catch (final RuntimeException | Error e) {
    4.61 +            throw e;
    4.62 +        } catch (final Throwable t) {
    4.63 +            throw new RuntimeException(t);
    4.64 +        }
    4.65 +        return dst;
    4.66 +    }
    4.67 +
    4.68 +    /**
    4.69       * Check if an object is null or undefined
    4.70       *
    4.71       * @param obj object to check
    4.72 @@ -964,4 +1015,13 @@
    4.73          return Double.NaN;
    4.74      }
    4.75  
    4.76 +    private static Object invoke(final MethodHandle mh, final Object arg) {
    4.77 +        try {
    4.78 +            return mh.invoke(arg);
    4.79 +        } catch (final RuntimeException | Error e) {
    4.80 +            throw e;
    4.81 +        } catch (final Throwable t) {
    4.82 +            throw new RuntimeException(t);
    4.83 +        }
    4.84 +    }
    4.85  }
     5.1 --- a/src/jdk/nashorn/internal/runtime/ListAdapter.java	Fri Sep 13 17:50:18 2013 +0530
     5.2 +++ b/src/jdk/nashorn/internal/runtime/ListAdapter.java	Mon Sep 16 15:08:36 2013 +0530
     5.3 @@ -32,6 +32,7 @@
     5.4  import java.util.NoSuchElementException;
     5.5  import java.util.RandomAccess;
     5.6  import java.util.concurrent.Callable;
     5.7 +import jdk.nashorn.api.scripting.JSObject;
     5.8  import jdk.nashorn.internal.runtime.linker.Bootstrap;
     5.9  import jdk.nashorn.internal.runtime.linker.InvokeByName;
    5.10  
    5.11 @@ -48,7 +49,7 @@
    5.12   * operations respectively, while {@link #addLast(Object)} and {@link #removeLast()} will translate to {@code push} and
    5.13   * {@code pop}.
    5.14   */
    5.15 -public final class ListAdapter extends AbstractList<Object> implements RandomAccess, Deque<Object> {
    5.16 +public abstract class ListAdapter extends AbstractList<Object> implements RandomAccess, Deque<Object> {
    5.17      // These add to the back and front of the list
    5.18      private static final Object PUSH    = new Object();
    5.19      private static InvokeByName getPUSH() {
    5.20 @@ -56,7 +57,7 @@
    5.21                  new Callable<InvokeByName>() {
    5.22                      @Override
    5.23                      public InvokeByName call() {
    5.24 -                        return new InvokeByName("push", ScriptObject.class, void.class, Object.class);
    5.25 +                        return new InvokeByName("push", Object.class, void.class, Object.class);
    5.26                      }
    5.27                  });
    5.28      }
    5.29 @@ -67,7 +68,7 @@
    5.30                  new Callable<InvokeByName>() {
    5.31                      @Override
    5.32                      public InvokeByName call() {
    5.33 -                        return new InvokeByName("unshift", ScriptObject.class, void.class, Object.class);
    5.34 +                        return new InvokeByName("unshift", Object.class, void.class, Object.class);
    5.35                      }
    5.36                  });
    5.37      }
    5.38 @@ -79,7 +80,7 @@
    5.39                  new Callable<InvokeByName>() {
    5.40                      @Override
    5.41                      public InvokeByName call() {
    5.42 -                        return new InvokeByName("pop", ScriptObject.class, Object.class);
    5.43 +                        return new InvokeByName("pop", Object.class, Object.class);
    5.44                      }
    5.45                  });
    5.46      }
    5.47 @@ -90,7 +91,7 @@
    5.48                  new Callable<InvokeByName>() {
    5.49                      @Override
    5.50                      public InvokeByName call() {
    5.51 -                        return new InvokeByName("shift", ScriptObject.class, Object.class);
    5.52 +                        return new InvokeByName("shift", Object.class, Object.class);
    5.53                      }
    5.54                  });
    5.55      }
    5.56 @@ -102,7 +103,7 @@
    5.57                  new Callable<InvokeByName>() {
    5.58                      @Override
    5.59                      public InvokeByName call() {
    5.60 -                        return new InvokeByName("splice", ScriptObject.class, void.class, int.class, int.class, Object.class);
    5.61 +                        return new InvokeByName("splice", Object.class, void.class, int.class, int.class, Object.class);
    5.62                      }
    5.63                  });
    5.64      }
    5.65 @@ -113,40 +114,52 @@
    5.66                  new Callable<InvokeByName>() {
    5.67                      @Override
    5.68                      public InvokeByName call() {
    5.69 -                        return new InvokeByName("splice", ScriptObject.class, void.class, int.class, int.class);
    5.70 +                        return new InvokeByName("splice", Object.class, void.class, int.class, int.class);
    5.71                      }
    5.72                  });
    5.73      }
    5.74  
    5.75 -    private final ScriptObject obj;
    5.76 +    protected final Object obj;
    5.77  
    5.78 -    /**
    5.79 -     * Creates a new list wrapper for the specified script object.
    5.80 -     * @param obj script the object to wrap
    5.81 -     */
    5.82 -    public ListAdapter(ScriptObject obj) {
    5.83 +    // allow subclasses only in this package
    5.84 +    ListAdapter(Object obj) {
    5.85          this.obj = obj;
    5.86      }
    5.87  
    5.88 -    @Override
    5.89 -    public int size() {
    5.90 -        return JSType.toInt32(obj.getLength());
    5.91 +    /**
    5.92 +     * Factory to create a ListAdapter for a given script object.
    5.93 +     *
    5.94 +     * @param obj script object to wrap as a ListAdapter
    5.95 +     * @return A ListAdapter wrapper object
    5.96 +     */
    5.97 +    public static ListAdapter create(final Object obj) {
    5.98 +        if (obj instanceof ScriptObject) {
    5.99 +            return new ScriptObjectListAdapter((ScriptObject)obj);
   5.100 +        } else if (obj instanceof JSObject) {
   5.101 +            return new JSObjectListAdapter((JSObject)obj);
   5.102 +        } else {
   5.103 +            throw new IllegalArgumentException("ScriptObject or JSObject expected");
   5.104 +        }
   5.105      }
   5.106  
   5.107      @Override
   5.108 -    public Object get(int index) {
   5.109 +    public final Object get(int index) {
   5.110          checkRange(index);
   5.111 -        return obj.get(index);
   5.112 +        return getAt(index);
   5.113      }
   5.114  
   5.115 +    protected abstract Object getAt(final int index);
   5.116 +
   5.117      @Override
   5.118      public Object set(int index, Object element) {
   5.119          checkRange(index);
   5.120 -        final Object prevValue = get(index);
   5.121 -        obj.set(index, element, false);
   5.122 +        final Object prevValue = getAt(index);
   5.123 +        setAt(index, element);
   5.124          return prevValue;
   5.125      }
   5.126  
   5.127 +    protected abstract void setAt(int index, Object element);
   5.128 +
   5.129      private void checkRange(int index) {
   5.130          if(index < 0 || index >= size()) {
   5.131              throw invalidIndex(index);
   5.132 @@ -154,18 +167,18 @@
   5.133      }
   5.134  
   5.135      @Override
   5.136 -    public void push(Object e) {
   5.137 +    public final void push(Object e) {
   5.138          addFirst(e);
   5.139      }
   5.140  
   5.141      @Override
   5.142 -    public boolean add(Object e) {
   5.143 +    public final boolean add(Object e) {
   5.144          addLast(e);
   5.145          return true;
   5.146      }
   5.147  
   5.148      @Override
   5.149 -    public void addFirst(Object e) {
   5.150 +    public final void addFirst(Object e) {
   5.151          try {
   5.152              final InvokeByName unshiftInvoker = getUNSHIFT();
   5.153              final Object fn = unshiftInvoker.getGetter().invokeExact(obj);
   5.154 @@ -179,7 +192,7 @@
   5.155      }
   5.156  
   5.157      @Override
   5.158 -    public void addLast(Object e) {
   5.159 +    public final void addLast(Object e) {
   5.160          try {
   5.161              final InvokeByName pushInvoker = getPUSH();
   5.162              final Object fn = pushInvoker.getGetter().invokeExact(obj);
   5.163 @@ -193,7 +206,7 @@
   5.164      }
   5.165  
   5.166      @Override
   5.167 -    public void add(int index, Object e) {
   5.168 +    public final void add(int index, Object e) {
   5.169          try {
   5.170              if(index < 0) {
   5.171                  throw invalidIndex(index);
   5.172 @@ -229,40 +242,40 @@
   5.173      }
   5.174  
   5.175      @Override
   5.176 -    public boolean offer(Object e) {
   5.177 +    public final boolean offer(Object e) {
   5.178          return offerLast(e);
   5.179      }
   5.180  
   5.181      @Override
   5.182 -    public boolean offerFirst(Object e) {
   5.183 +    public final boolean offerFirst(Object e) {
   5.184          addFirst(e);
   5.185          return true;
   5.186      }
   5.187  
   5.188      @Override
   5.189 -    public boolean offerLast(Object e) {
   5.190 +    public final boolean offerLast(Object e) {
   5.191          addLast(e);
   5.192          return true;
   5.193      }
   5.194  
   5.195      @Override
   5.196 -    public Object pop() {
   5.197 +    public final Object pop() {
   5.198          return removeFirst();
   5.199      }
   5.200  
   5.201      @Override
   5.202 -    public Object remove() {
   5.203 +    public final Object remove() {
   5.204          return removeFirst();
   5.205      }
   5.206  
   5.207      @Override
   5.208 -    public Object removeFirst() {
   5.209 +    public final Object removeFirst() {
   5.210          checkNonEmpty();
   5.211          return invokeShift();
   5.212      }
   5.213  
   5.214      @Override
   5.215 -    public Object removeLast() {
   5.216 +    public final Object removeLast() {
   5.217          checkNonEmpty();
   5.218          return invokePop();
   5.219      }
   5.220 @@ -274,7 +287,7 @@
   5.221      }
   5.222  
   5.223      @Override
   5.224 -    public Object remove(int index) {
   5.225 +    public final Object remove(int index) {
   5.226          if(index < 0) {
   5.227              throw invalidIndex(index);
   5.228          } else if (index == 0) {
   5.229 @@ -320,7 +333,7 @@
   5.230      }
   5.231  
   5.232      @Override
   5.233 -    protected void removeRange(int fromIndex, int toIndex) {
   5.234 +    protected final void removeRange(int fromIndex, int toIndex) {
   5.235          invokeSpliceRemove(fromIndex, toIndex - fromIndex);
   5.236      }
   5.237  
   5.238 @@ -338,54 +351,54 @@
   5.239      }
   5.240  
   5.241      @Override
   5.242 -    public Object poll() {
   5.243 +    public final Object poll() {
   5.244          return pollFirst();
   5.245      }
   5.246  
   5.247      @Override
   5.248 -    public Object pollFirst() {
   5.249 +    public final Object pollFirst() {
   5.250          return isEmpty() ? null : invokeShift();
   5.251      }
   5.252  
   5.253      @Override
   5.254 -    public Object pollLast() {
   5.255 +    public final Object pollLast() {
   5.256          return isEmpty() ? null : invokePop();
   5.257      }
   5.258  
   5.259      @Override
   5.260 -    public Object peek() {
   5.261 +    public final Object peek() {
   5.262          return peekFirst();
   5.263      }
   5.264  
   5.265      @Override
   5.266 -    public Object peekFirst() {
   5.267 +    public final Object peekFirst() {
   5.268          return isEmpty() ? null : get(0);
   5.269      }
   5.270  
   5.271      @Override
   5.272 -    public Object peekLast() {
   5.273 +    public final Object peekLast() {
   5.274          return isEmpty() ? null : get(size() - 1);
   5.275      }
   5.276  
   5.277      @Override
   5.278 -    public Object element() {
   5.279 +    public final Object element() {
   5.280          return getFirst();
   5.281      }
   5.282  
   5.283      @Override
   5.284 -    public Object getFirst() {
   5.285 +    public final Object getFirst() {
   5.286          checkNonEmpty();
   5.287          return get(0);
   5.288      }
   5.289  
   5.290      @Override
   5.291 -    public Object getLast() {
   5.292 +    public final Object getLast() {
   5.293          checkNonEmpty();
   5.294          return get(size() - 1);
   5.295      }
   5.296  
   5.297      @Override
   5.298 -    public Iterator<Object> descendingIterator() {
   5.299 +    public final Iterator<Object> descendingIterator() {
   5.300          final ListIterator<Object> it = listIterator(size());
   5.301          return new Iterator<Object>() {
   5.302              @Override
   5.303 @@ -406,12 +419,12 @@
   5.304      }
   5.305  
   5.306      @Override
   5.307 -    public boolean removeFirstOccurrence(Object o) {
   5.308 +    public final boolean removeFirstOccurrence(Object o) {
   5.309          return removeOccurrence(o, iterator());
   5.310      }
   5.311  
   5.312      @Override
   5.313 -    public boolean removeLastOccurrence(Object o) {
   5.314 +    public final boolean removeLastOccurrence(Object o) {
   5.315          return removeOccurrence(o, descendingIterator());
   5.316      }
   5.317  
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObjectListAdapter.java	Mon Sep 16 15:08:36 2013 +0530
     6.3 @@ -0,0 +1,54 @@
     6.4 +/*
     6.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     6.7 + *
     6.8 + * This code is free software; you can redistribute it and/or modify it
     6.9 + * under the terms of the GNU General Public License version 2 only, as
    6.10 + * published by the Free Software Foundation.  Oracle designates this
    6.11 + * particular file as subject to the "Classpath" exception as provided
    6.12 + * by Oracle in the LICENSE file that accompanied this code.
    6.13 + *
    6.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    6.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    6.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    6.17 + * version 2 for more details (a copy is included in the LICENSE file that
    6.18 + * accompanied this code).
    6.19 + *
    6.20 + * You should have received a copy of the GNU General Public License version
    6.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    6.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    6.23 + *
    6.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    6.25 + * or visit www.oracle.com if you need additional information or have any
    6.26 + * questions.
    6.27 + */
    6.28 +
    6.29 +package jdk.nashorn.internal.runtime;
    6.30 +
    6.31 +/**
    6.32 + * A ListAdapter that can wrap a ScriptObject.
    6.33 + */
    6.34 +public final class ScriptObjectListAdapter extends ListAdapter {
    6.35 +    /**
    6.36 +     * Creates a new list wrapper for the specified ScriptObject.
    6.37 +     * @param obj script the object to wrap
    6.38 +     */
    6.39 +    public ScriptObjectListAdapter(final ScriptObject obj) {
    6.40 +        super(obj);
    6.41 +    }
    6.42 +
    6.43 +    @Override
    6.44 +    public int size() {
    6.45 +        return JSType.toInt32(((ScriptObject)obj).getLength());
    6.46 +    }
    6.47 +
    6.48 +    @Override
    6.49 +    protected Object getAt(int index) {
    6.50 +        return ((ScriptObject)obj).get(index);
    6.51 +    }
    6.52 +
    6.53 +    @Override
    6.54 +    protected void setAt(int index, Object element) {
    6.55 +        ((ScriptObject)obj).set(index, element, false);
    6.56 +    }
    6.57 +}
     7.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java	Fri Sep 13 17:50:18 2013 +0530
     7.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java	Mon Sep 16 15:08:36 2013 +0530
     7.3 @@ -26,10 +26,9 @@
     7.4  package jdk.nashorn.internal.runtime.arrays;
     7.5  
     7.6  import java.lang.invoke.MethodHandle;
     7.7 -import java.lang.reflect.Array;
     7.8  import jdk.nashorn.internal.runtime.GlobalObject;
     7.9 +import jdk.nashorn.internal.runtime.JSType;
    7.10  import jdk.nashorn.internal.runtime.PropertyDescriptor;
    7.11 -import jdk.nashorn.internal.runtime.linker.Bootstrap;
    7.12  
    7.13  /**
    7.14   * ArrayData - abstraction for wrapping array elements
    7.15 @@ -204,20 +203,7 @@
    7.16       * @return and array of the given type
    7.17       */
    7.18      public Object asArrayOfType(final Class<?> componentType) {
    7.19 -        final Object[] src = asObjectArray();
    7.20 -        final int l = src.length;
    7.21 -        final Object dst = Array.newInstance(componentType, l);
    7.22 -        final MethodHandle converter = Bootstrap.getLinkerServices().getTypeConverter(Object.class, componentType);
    7.23 -        try {
    7.24 -            for (int i = 0; i < src.length; i++) {
    7.25 -                Array.set(dst, i, invoke(converter, src[i]));
    7.26 -            }
    7.27 -        } catch (final RuntimeException | Error e) {
    7.28 -            throw e;
    7.29 -        } catch (final Throwable t) {
    7.30 -            throw new RuntimeException(t);
    7.31 -        }
    7.32 -        return dst;
    7.33 +        return JSType.convertArray(asObjectArray(), componentType);
    7.34      }
    7.35  
    7.36      /**
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/test/script/basic/JDK-8024847.js	Mon Sep 16 15:08:36 2013 +0530
     8.3 @@ -0,0 +1,102 @@
     8.4 +/*
     8.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     8.7 + * 
     8.8 + * This code is free software; you can redistribute it and/or modify it
     8.9 + * under the terms of the GNU General Public License version 2 only, as
    8.10 + * published by the Free Software Foundation.
    8.11 + * 
    8.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    8.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    8.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    8.15 + * version 2 for more details (a copy is included in the LICENSE file that
    8.16 + * accompanied this code).
    8.17 + * 
    8.18 + * You should have received a copy of the GNU General Public License version
    8.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    8.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    8.21 + * 
    8.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    8.23 + * or visit www.oracle.com if you need additional information or have any
    8.24 + * questions.
    8.25 + */
    8.26 +
    8.27 +/**
    8.28 + * JDK-8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
    8.29 + *
    8.30 + * @test
    8.31 + * @run
    8.32 + */
    8.33 +
    8.34 +var global = loadWithNewGlobal({ name: "test", script:"this" });
    8.35 +var arr = new global.Array(2, 4, 6, 8);
    8.36 +var jarr = Java.to(arr, "int[]");
    8.37 +for (var i in jarr) {
    8.38 +    print(jarr[i]);
    8.39 +}
    8.40 +
    8.41 +arr = null;
    8.42 +jarr = null;
    8.43 +
    8.44 +// external JSObjects
    8.45 +var JSObject = Java.type("jdk.nashorn.api.scripting.JSObject");
    8.46 +var arr = new JSObject() {
    8.47 +    getMember: function(name) {
    8.48 +        return name == "length"? 4 : undefined;
    8.49 +    },
    8.50 +
    8.51 +    hasMember: function(name) {
    8.52 +        return name == "length";
    8.53 +    },
    8.54 +
    8.55 +    getSlot: function(idx) {
    8.56 +        return idx*idx;
    8.57 +    },
    8.58 +
    8.59 +    hasSlot: function(idx) {
    8.60 +        return true;
    8.61 +    }
    8.62 +};
    8.63 +
    8.64 +var jarr = Java.to(arr, "int[]");
    8.65 +for (var i in jarr) {
    8.66 +    print(jarr[i]);
    8.67 +}
    8.68 +
    8.69 +arr = null;
    8.70 +jarr = null;
    8.71 +
    8.72 +// List conversion
    8.73 +var arr = global.Array("hello", "world");
    8.74 +var jlist = Java.to(arr, java.util.List);
    8.75 +print(jlist instanceof java.util.List);
    8.76 +print(jlist);
    8.77 +
    8.78 +arr = null;
    8.79 +jlist = null;
    8.80 +
    8.81 +// external JSObject
    8.82 +var __array__ =  [ "nashorn", "js" ];
    8.83 +
    8.84 +var obj = new JSObject() {
    8.85 +    
    8.86 +    hasMember: function(name) {
    8.87 +        return name in __array__;
    8.88 +    },
    8.89 +
    8.90 +    hasSlot: function(idx) {
    8.91 +        return idx in __array__;
    8.92 +    },
    8.93 +
    8.94 +    getMember: function(name) {
    8.95 +        return __array__[name];
    8.96 +    },
    8.97 +
    8.98 +    getSlot: function(idx) {
    8.99 +        return __array__[idx];
   8.100 +    }
   8.101 +}
   8.102 +
   8.103 +var jlist = Java.to(obj, java.util.List);
   8.104 +print(jlist instanceof java.util.List);
   8.105 +print(jlist);
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/test/script/basic/JDK-8024847.js.EXPECTED	Mon Sep 16 15:08:36 2013 +0530
     9.3 @@ -0,0 +1,12 @@
     9.4 +2
     9.5 +4
     9.6 +6
     9.7 +8
     9.8 +0
     9.9 +1
    9.10 +4
    9.11 +9
    9.12 +true
    9.13 +[hello, world]
    9.14 +true
    9.15 +[nashorn, js]

mercurial