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