emul/mini/src/main/java/java/lang/reflect/Array.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 26 Jan 2013 08:47:05 +0100
changeset 592 5e13b1ac2886
parent 571 62c327a1e23f
parent 554 05224402145d
permissions -rw-r--r--
In order to support fields of the same name in subclasses we are now prefixing them with name of the class that defines them. To provide convenient way to access them from generated bytecode and also directly from JavaScript, there is a getter/setter function for each field. It starts with _ followed by the field name. If called with a parameter, it sets the field, with a parameter it just returns it.
     1 /*
     2  * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 
    26 package java.lang.reflect;
    27 
    28 import org.apidesign.bck2brwsr.core.JavaScriptBody;
    29 import org.apidesign.bck2brwsr.core.JavaScriptPrototype;
    30 
    31 /**
    32  * The {@code Array} class provides static methods to dynamically create and
    33  * access Java arrays.
    34  *
    35  * <p>{@code Array} permits widening conversions to occur during a get or set
    36  * operation, but throws an {@code IllegalArgumentException} if a narrowing
    37  * conversion would occur.
    38  *
    39  * @author Nakul Saraiya
    40  */
    41 @JavaScriptPrototype(prototype = "new Array", container = "Array.prototype")
    42 public final
    43 class Array {
    44 
    45     /**
    46      * Constructor.  Class Array is not instantiable.
    47      */
    48     private Array() {}
    49 
    50     /**
    51      * Creates a new array with the specified component type and
    52      * length.
    53      * Invoking this method is equivalent to creating an array
    54      * as follows:
    55      * <blockquote>
    56      * <pre>
    57      * int[] x = {length};
    58      * Array.newInstance(componentType, x);
    59      * </pre>
    60      * </blockquote>
    61      *
    62      * @param componentType the {@code Class} object representing the
    63      * component type of the new array
    64      * @param length the length of the new array
    65      * @return the new array
    66      * @exception NullPointerException if the specified
    67      * {@code componentType} parameter is null
    68      * @exception IllegalArgumentException if componentType is {@link Void#TYPE}
    69      * @exception NegativeArraySizeException if the specified {@code length}
    70      * is negative
    71      */
    72     public static Object newInstance(Class<?> componentType, int length)
    73     throws NegativeArraySizeException {
    74         if (length < 0) {
    75             throw new NegativeArraySizeException();
    76         }
    77         String sig = findSignature(componentType);
    78         return newArray(componentType.isPrimitive(), sig, length);
    79     }
    80     
    81     private static String findSignature(Class<?> type) {
    82         if (type == Integer.TYPE) {
    83             return "[I";
    84         }
    85         if (type == Long.TYPE) {
    86             return "[J";
    87         }
    88         if (type == Double.TYPE) {
    89             return "[D";
    90         }
    91         if (type == Float.TYPE) {
    92             return "[F";
    93         }
    94         if (type == Byte.TYPE) {
    95             return "[B";
    96         }
    97         if (type == Boolean.TYPE) {
    98             return "[Z";
    99         }
   100         if (type == Short.TYPE) {
   101             return "[S";
   102         }
   103         if (type == Character.TYPE) {
   104             return "[C";
   105         }
   106         if (type.getName().equals("void")) {
   107             throw new IllegalStateException("Can't create array for " + type);
   108         }
   109         return "[L" + type.getName() + ";";
   110     }
   111     /**
   112      * Creates a new array
   113      * with the specified component type and dimensions.
   114      * If {@code componentType}
   115      * represents a non-array class or interface, the new array
   116      * has {@code dimensions.length} dimensions and
   117      * {@code componentType} as its component type. If
   118      * {@code componentType} represents an array class, the
   119      * number of dimensions of the new array is equal to the sum
   120      * of {@code dimensions.length} and the number of
   121      * dimensions of {@code componentType}. In this case, the
   122      * component type of the new array is the component type of
   123      * {@code componentType}.
   124      *
   125      * <p>The number of dimensions of the new array must not
   126      * exceed the number of array dimensions supported by the
   127      * implementation (typically 255).
   128      *
   129      * @param componentType the {@code Class} object representing the component
   130      * type of the new array
   131      * @param dimensions an array of {@code int} representing the dimensions of
   132      * the new array
   133      * @return the new array
   134      * @exception NullPointerException if the specified
   135      * {@code componentType} argument is null
   136      * @exception IllegalArgumentException if the specified {@code dimensions}
   137      * argument is a zero-dimensional array, or if the number of
   138      * requested dimensions exceeds the limit on the number of array dimensions
   139      * supported by the implementation (typically 255), or if componentType
   140      * is {@link Void#TYPE}.
   141      * @exception NegativeArraySizeException if any of the components in
   142      * the specified {@code dimensions} argument is negative.
   143      */
   144     public static Object newInstance(Class<?> componentType, int... dimensions)
   145         throws IllegalArgumentException, NegativeArraySizeException {
   146         StringBuilder sig = new StringBuilder();
   147         for (int i = 1; i < dimensions.length; i++) {
   148             sig.append('[');
   149         }
   150         sig.append(findSignature(componentType));
   151         return multiNewArray(sig.toString(), dimensions, 0);
   152     }
   153 
   154     /**
   155      * Returns the length of the specified array object, as an {@code int}.
   156      *
   157      * @param array the array
   158      * @return the length of the array
   159      * @exception IllegalArgumentException if the object argument is not
   160      * an array
   161      */
   162     public static int getLength(Object array)
   163     throws IllegalArgumentException {
   164         if (!array.getClass().isArray()) {
   165             throw new IllegalArgumentException("Argument is not an array");
   166         }
   167         return length(array);
   168     }
   169     
   170     @JavaScriptBody(args = { "arr" }, body = "return arr.length;")
   171     private static native int length(Object arr);
   172 
   173     /**
   174      * Returns the value of the indexed component in the specified
   175      * array object.  The value is automatically wrapped in an object
   176      * if it has a primitive type.
   177      *
   178      * @param array the array
   179      * @param index the index
   180      * @return the (possibly wrapped) value of the indexed component in
   181      * the specified array
   182      * @exception NullPointerException If the specified object is null
   183      * @exception IllegalArgumentException If the specified object is not
   184      * an array
   185      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
   186      * argument is negative, or if it is greater than or equal to the
   187      * length of the specified array
   188      */
   189     public static Object get(Object array, int index)
   190     throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
   191         final Class<?> t = array.getClass().getComponentType();
   192         if (t.isPrimitive()) {
   193             return fromPrimitive(t, array, index);
   194         } else {
   195             return ((Object[])array)[index];
   196         }
   197     }
   198 
   199     /**
   200      * Returns the value of the indexed component in the specified
   201      * array object, as a {@code boolean}.
   202      *
   203      * @param array the array
   204      * @param index the index
   205      * @return the value of the indexed component in the specified array
   206      * @exception NullPointerException If the specified object is null
   207      * @exception IllegalArgumentException If the specified object is not
   208      * an array, or if the indexed element cannot be converted to the
   209      * return type by an identity or widening conversion
   210      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
   211      * argument is negative, or if it is greater than or equal to the
   212      * length of the specified array
   213      * @see Array#get
   214      */
   215     public static native boolean getBoolean(Object array, int index)
   216         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
   217 
   218     /**
   219      * Returns the value of the indexed component in the specified
   220      * array object, as a {@code byte}.
   221      *
   222      * @param array the array
   223      * @param index the index
   224      * @return the value of the indexed component in the specified array
   225      * @exception NullPointerException If the specified object is null
   226      * @exception IllegalArgumentException If the specified object is not
   227      * an array, or if the indexed element cannot be converted to the
   228      * return type by an identity or widening conversion
   229      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
   230      * argument is negative, or if it is greater than or equal to the
   231      * length of the specified array
   232      * @see Array#get
   233      */
   234     public static byte getByte(Object array, int index)
   235     throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
   236         if (array.getClass().getComponentType() != Byte.TYPE) {
   237             throw new IllegalArgumentException();
   238         }
   239         byte[] arr = (byte[]) array;
   240         return arr[index];
   241     }
   242 
   243     /**
   244      * Returns the value of the indexed component in the specified
   245      * array object, as a {@code char}.
   246      *
   247      * @param array the array
   248      * @param index the index
   249      * @return the value of the indexed component in the specified array
   250      * @exception NullPointerException If the specified object is null
   251      * @exception IllegalArgumentException If the specified object is not
   252      * an array, or if the indexed element cannot be converted to the
   253      * return type by an identity or widening conversion
   254      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
   255      * argument is negative, or if it is greater than or equal to the
   256      * length of the specified array
   257      * @see Array#get
   258      */
   259     public static native char getChar(Object array, int index)
   260         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
   261 
   262     /**
   263      * Returns the value of the indexed component in the specified
   264      * array object, as a {@code short}.
   265      *
   266      * @param array the array
   267      * @param index the index
   268      * @return the value of the indexed component in the specified array
   269      * @exception NullPointerException If the specified object is null
   270      * @exception IllegalArgumentException If the specified object is not
   271      * an array, or if the indexed element cannot be converted to the
   272      * return type by an identity or widening conversion
   273      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
   274      * argument is negative, or if it is greater than or equal to the
   275      * length of the specified array
   276      * @see Array#get
   277      */
   278     public static short getShort(Object array, int index)
   279     throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
   280         final Class<?> t = array.getClass().getComponentType();
   281         if (t == Short.TYPE) {
   282             short[] arr = (short[]) array;
   283             return arr[index];
   284         }
   285         return getByte(array, index);
   286     }
   287 
   288     /**
   289      * Returns the value of the indexed component in the specified
   290      * array object, as an {@code int}.
   291      *
   292      * @param array the array
   293      * @param index the index
   294      * @return the value of the indexed component in the specified array
   295      * @exception NullPointerException If the specified object is null
   296      * @exception IllegalArgumentException If the specified object is not
   297      * an array, or if the indexed element cannot be converted to the
   298      * return type by an identity or widening conversion
   299      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
   300      * argument is negative, or if it is greater than or equal to the
   301      * length of the specified array
   302      * @see Array#get
   303      */
   304     public static int getInt(Object array, int index) 
   305     throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
   306         final Class<?> t = array.getClass().getComponentType();
   307         if (t == Integer.TYPE) {
   308             int[] arr = (int[]) array;
   309             return arr[index];
   310         }
   311         return getShort(array, index);
   312     }
   313 
   314     /**
   315      * Returns the value of the indexed component in the specified
   316      * array object, as a {@code long}.
   317      *
   318      * @param array the array
   319      * @param index the index
   320      * @return the value of the indexed component in the specified array
   321      * @exception NullPointerException If the specified object is null
   322      * @exception IllegalArgumentException If the specified object is not
   323      * an array, or if the indexed element cannot be converted to the
   324      * return type by an identity or widening conversion
   325      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
   326      * argument is negative, or if it is greater than or equal to the
   327      * length of the specified array
   328      * @see Array#get
   329      */
   330     public static long getLong(Object array, int index)
   331     throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
   332         final Class<?> t = array.getClass().getComponentType();
   333         if (t == Long.TYPE) {
   334             long[] arr = (long[]) array;
   335             return arr[index];
   336         }
   337         return getInt(array, index);
   338     }
   339 
   340     /**
   341      * Returns the value of the indexed component in the specified
   342      * array object, as a {@code float}.
   343      *
   344      * @param array the array
   345      * @param index the index
   346      * @return the value of the indexed component in the specified array
   347      * @exception NullPointerException If the specified object is null
   348      * @exception IllegalArgumentException If the specified object is not
   349      * an array, or if the indexed element cannot be converted to the
   350      * return type by an identity or widening conversion
   351      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
   352      * argument is negative, or if it is greater than or equal to the
   353      * length of the specified array
   354      * @see Array#get
   355      */
   356     public static float getFloat(Object array, int index)
   357     throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
   358         final Class<?> t = array.getClass().getComponentType();
   359         if (t == Float.TYPE) {
   360             float[] arr = (float[]) array;
   361             return arr[index];
   362         }
   363         return getLong(array, index);
   364     }
   365 
   366     /**
   367      * Returns the value of the indexed component in the specified
   368      * array object, as a {@code double}.
   369      *
   370      * @param array the array
   371      * @param index the index
   372      * @return the value of the indexed component in the specified array
   373      * @exception NullPointerException If the specified object is null
   374      * @exception IllegalArgumentException If the specified object is not
   375      * an array, or if the indexed element cannot be converted to the
   376      * return type by an identity or widening conversion
   377      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
   378      * argument is negative, or if it is greater than or equal to the
   379      * length of the specified array
   380      * @see Array#get
   381      */
   382     public static double getDouble(Object array, int index)
   383     throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
   384         final Class<?> t = array.getClass().getComponentType();
   385         if (t == Double.TYPE) {
   386             double[] arr = (double[]) array;
   387             return arr[index];
   388         }
   389         return getFloat(array, index);
   390     }
   391 
   392     /**
   393      * Sets the value of the indexed component of the specified array
   394      * object to the specified new value.  The new value is first
   395      * automatically unwrapped if the array has a primitive component
   396      * type.
   397      * @param array the array
   398      * @param index the index into the array
   399      * @param value the new value of the indexed component
   400      * @exception NullPointerException If the specified object argument
   401      * is null
   402      * @exception IllegalArgumentException If the specified object argument
   403      * is not an array, or if the array component type is primitive and
   404      * an unwrapping conversion fails
   405      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
   406      * argument is negative, or if it is greater than or equal to
   407      * the length of the specified array
   408      */
   409     public static void set(Object array, int index, Object value)
   410     throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
   411         if (array.getClass().getComponentType().isPrimitive()) {
   412             throw new IllegalArgumentException();
   413         } else {
   414             Object[] arr = (Object[])array;
   415             arr[index] = value;
   416         }
   417     }
   418 
   419     /**
   420      * Sets the value of the indexed component of the specified array
   421      * object to the specified {@code boolean} value.
   422      * @param array the array
   423      * @param index the index into the array
   424      * @param z the new value of the indexed component
   425      * @exception NullPointerException If the specified object argument
   426      * is null
   427      * @exception IllegalArgumentException If the specified object argument
   428      * is not an array, or if the specified value cannot be converted
   429      * to the underlying array's component type by an identity or a
   430      * primitive widening conversion
   431      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
   432      * argument is negative, or if it is greater than or equal to
   433      * the length of the specified array
   434      * @see Array#set
   435      */
   436     public static native void setBoolean(Object array, int index, boolean z)
   437         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
   438 
   439     /**
   440      * Sets the value of the indexed component of the specified array
   441      * object to the specified {@code byte} value.
   442      * @param array the array
   443      * @param index the index into the array
   444      * @param b the new value of the indexed component
   445      * @exception NullPointerException If the specified object argument
   446      * is null
   447      * @exception IllegalArgumentException If the specified object argument
   448      * is not an array, or if the specified value cannot be converted
   449      * to the underlying array's component type by an identity or a
   450      * primitive widening conversion
   451      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
   452      * argument is negative, or if it is greater than or equal to
   453      * the length of the specified array
   454      * @see Array#set
   455      */
   456     public static void setByte(Object array, int index, byte b)
   457     throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
   458         Class<?> t = array.getClass().getComponentType();
   459         if (t == Byte.TYPE) {
   460             byte[] arr = (byte[]) array;
   461             arr[index] = b;
   462         } else {
   463             setShort(array, index, b);
   464         }
   465     }
   466 
   467     /**
   468      * Sets the value of the indexed component of the specified array
   469      * object to the specified {@code char} value.
   470      * @param array the array
   471      * @param index the index into the array
   472      * @param c the new value of the indexed component
   473      * @exception NullPointerException If the specified object argument
   474      * is null
   475      * @exception IllegalArgumentException If the specified object argument
   476      * is not an array, or if the specified value cannot be converted
   477      * to the underlying array's component type by an identity or a
   478      * primitive widening conversion
   479      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
   480      * argument is negative, or if it is greater than or equal to
   481      * the length of the specified array
   482      * @see Array#set
   483      */
   484     public static native void setChar(Object array, int index, char c)
   485         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
   486 
   487     /**
   488      * Sets the value of the indexed component of the specified array
   489      * object to the specified {@code short} value.
   490      * @param array the array
   491      * @param index the index into the array
   492      * @param s the new value of the indexed component
   493      * @exception NullPointerException If the specified object argument
   494      * is null
   495      * @exception IllegalArgumentException If the specified object argument
   496      * is not an array, or if the specified value cannot be converted
   497      * to the underlying array's component type by an identity or a
   498      * primitive widening conversion
   499      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
   500      * argument is negative, or if it is greater than or equal to
   501      * the length of the specified array
   502      * @see Array#set
   503      */
   504     public static void setShort(Object array, int index, short s)
   505     throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
   506         Class<?> t = array.getClass().getComponentType();
   507         if (t == Short.TYPE) {
   508             short[] arr = (short[]) array;
   509             arr[index] = s;
   510         } else {
   511             setInt(array, index, s);
   512         }
   513         
   514     }
   515     
   516     /**
   517      * Sets the value of the indexed component of the specified array
   518      * object to the specified {@code int} value.
   519      * @param array the array
   520      * @param index the index into the array
   521      * @param i the new value of the indexed component
   522      * @exception NullPointerException If the specified object argument
   523      * is null
   524      * @exception IllegalArgumentException If the specified object argument
   525      * is not an array, or if the specified value cannot be converted
   526      * to the underlying array's component type by an identity or a
   527      * primitive widening conversion
   528      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
   529      * argument is negative, or if it is greater than or equal to
   530      * the length of the specified array
   531      * @see Array#set
   532      */
   533     public static void setInt(Object array, int index, int i)
   534     throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
   535         Class<?> t = array.getClass().getComponentType();
   536         if (t == Integer.TYPE) {
   537             int[] arr = (int[]) array;
   538             arr[index] = i;
   539         } else {
   540             setLong(array, index, i);
   541         }
   542     }
   543 
   544     /**
   545      * Sets the value of the indexed component of the specified array
   546      * object to the specified {@code long} value.
   547      * @param array the array
   548      * @param index the index into the array
   549      * @param l the new value of the indexed component
   550      * @exception NullPointerException If the specified object argument
   551      * is null
   552      * @exception IllegalArgumentException If the specified object argument
   553      * is not an array, or if the specified value cannot be converted
   554      * to the underlying array's component type by an identity or a
   555      * primitive widening conversion
   556      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
   557      * argument is negative, or if it is greater than or equal to
   558      * the length of the specified array
   559      * @see Array#set
   560      */
   561     public static void setLong(Object array, int index, long l)
   562     throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
   563         Class<?> t = array.getClass().getComponentType();
   564         if (t == Long.TYPE) {
   565             long[] arr = (long[]) array;
   566             arr[index] = l;
   567         } else {
   568             setFloat(array, index, l);
   569         }
   570     }
   571 
   572     /**
   573      * Sets the value of the indexed component of the specified array
   574      * object to the specified {@code float} value.
   575      * @param array the array
   576      * @param index the index into the array
   577      * @param f the new value of the indexed component
   578      * @exception NullPointerException If the specified object argument
   579      * is null
   580      * @exception IllegalArgumentException If the specified object argument
   581      * is not an array, or if the specified value cannot be converted
   582      * to the underlying array's component type by an identity or a
   583      * primitive widening conversion
   584      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
   585      * argument is negative, or if it is greater than or equal to
   586      * the length of the specified array
   587      * @see Array#set
   588      */
   589     public static void setFloat(Object array, int index, float f)
   590     throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
   591         Class<?> t = array.getClass().getComponentType();
   592         if (t == Float.TYPE) {
   593             float[] arr = (float[])array;
   594             arr[index] = f;
   595         } else {
   596             setDouble(array, index, f);
   597         }
   598     }
   599 
   600     /**
   601      * Sets the value of the indexed component of the specified array
   602      * object to the specified {@code double} value.
   603      * @param array the array
   604      * @param index the index into the array
   605      * @param d the new value of the indexed component
   606      * @exception NullPointerException If the specified object argument
   607      * is null
   608      * @exception IllegalArgumentException If the specified object argument
   609      * is not an array, or if the specified value cannot be converted
   610      * to the underlying array's component type by an identity or a
   611      * primitive widening conversion
   612      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
   613      * argument is negative, or if it is greater than or equal to
   614      * the length of the specified array
   615      * @see Array#set
   616      */
   617     public static void setDouble(Object array, int index, double d)
   618     throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
   619         Class<?> t = array.getClass().getComponentType();
   620         if (t == Double.TYPE) {
   621             double[] arr = (double[])array;
   622             arr[index] = d;
   623         } else {
   624             throw new IllegalArgumentException("argument type mismatch");
   625         }
   626     }
   627 
   628     /*
   629      * Private
   630      */
   631 
   632     @JavaScriptBody(args = { "primitive", "sig", "length" }, body =
   633           "var arr = new Array(length);\n"
   634         + "var value = primitive ? 0 : null;\n"
   635         + "for(var i = 0; i < length; i++) arr[i] = value;\n"
   636         + "arr.jvmName = sig;\n"
   637         + "return arr;"
   638     )
   639     private static native Object newArray(boolean primitive, String sig, int length);
   640 
   641     private static Object multiNewArray(String sig, int[] dims, int index)
   642     throws IllegalArgumentException, NegativeArraySizeException {
   643         if (dims.length == index + 1) {
   644             return newArray(sig.length() == 2, sig, dims[index]);
   645         }
   646         Object arr = newArray(false, sig, dims[index]);
   647         String compsig = sig.substring(1);
   648         int len = getLength(arr);
   649         for (int i = 0; i < len; i++) {
   650             setArray(arr, i, multiNewArray(compsig, dims, index + 1));
   651         }
   652         return arr;
   653     }
   654     private static Object fromPrimitive(Class<?> t, Object array, int index) {
   655         return Method.fromPrimitive(t, atArray(array, index));
   656     }
   657     
   658     @JavaScriptBody(args = { "array", "index" }, body = "return array[index];")
   659     private static native Object atArray(Object array, int index);
   660 
   661     @JavaScriptBody(args = { "array", "index", "v" }, body = "array[index] = v;")
   662     private static native Object setArray(Object array, int index, Object v);
   663 }