1.1 --- a/rt/emul/mini/src/main/java/java/lang/reflect/Array.java Tue May 06 08:38:34 2014 +0200
1.2 +++ b/rt/emul/mini/src/main/java/java/lang/reflect/Array.java Tue May 06 10:08:42 2014 +0200
1.3 @@ -642,7 +642,40 @@
1.4 @Exported
1.5 private static native Object newArray(boolean primitive, String sig, Object fn, int length);
1.6
1.7 + @Exported
1.8 + private static boolean isInstance(Object arr, String sig) {
1.9 + if (arr == null) {
1.10 + return false;
1.11 + }
1.12 + return sig.equals(arr.getClass().getName());
1.13 + }
1.14 +
1.15 + @Exported
1.16 + private static boolean isInstance(Object arr, int dimensions, Object fn) throws ClassNotFoundException {
1.17 + if (arr == null) {
1.18 + return false;
1.19 + }
1.20 +// log("isInstance for " + arr + " and " + dimensions);
1.21 + Class<?> c = arr.getClass();
1.22 + while (dimensions-- > 0) {
1.23 +// log(" class: " + c);
1.24 + c = c.getComponentType();
1.25 +// log(" next class: " + c);
1.26 + if (c == null) {
1.27 + return false;
1.28 + }
1.29 + }
1.30 + Class<?> t = classFromFn(fn);
1.31 +// log(" to check: " + t);
1.32 + return t.isAssignableFrom(c);
1.33 + }
1.34 +
1.35 + @JavaScriptBody(args = { "cntstr" }, body = "return cntstr(false).constructor.$class;")
1.36 + private static native Class<?> classFromFn(Object cntstr);
1.37
1.38 +// @JavaScriptBody(args = { "m" }, body = "java.lang.System.out.println(m.toString().toString());")
1.39 +// private static native void log(Object m);
1.40 +
1.41 @Exported
1.42 private static Object multiNewArray(String sig, int[] dims, int index)
1.43 throws IllegalArgumentException, NegativeArraySizeException {
2.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue May 06 08:38:34 2014 +0200
2.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue May 06 10:08:42 2014 +0200
2.3 @@ -2201,32 +2201,56 @@
2.4 }
2.5
2.6 private void generateInstanceOf(int indx, final StackMapper smapper) throws IOException {
2.7 - final String type = jc.getClassName(indx);
2.8 + String type = jc.getClassName(indx);
2.9 if (!type.startsWith("[")) {
2.10 emit(smapper, this,
2.11 "var @2 = @1 != null && @1['$instOf_@3'] ? 1 : 0;",
2.12 smapper.popA(), smapper.pushI(),
2.13 type.replace('/', '_'));
2.14 } else {
2.15 - emit(smapper, this,
2.16 - "var @2 = vm.java_lang_Class(false)['forName__Ljava_lang_Class_2Ljava_lang_String_2']('@3')['isInstance__ZLjava_lang_Object_2'](@1);",
2.17 - smapper.popA(), smapper.pushI(),
2.18 - type
2.19 - );
2.20 + int cnt = 0;
2.21 + while (type.charAt(cnt) == '[') {
2.22 + cnt++;
2.23 + }
2.24 + if (type.charAt(cnt) == 'L') {
2.25 + type = "vm." + mangleClassName(type.substring(cnt + 1, type.length() - 1));
2.26 + emit(smapper, this,
2.27 + "var @2 = Array.prototype['isInstance__ZLjava_lang_Object_2ILjava_lang_Object_2'](@1, @4, @3);",
2.28 + smapper.popA(), smapper.pushI(),
2.29 + type, "" + cnt
2.30 + );
2.31 + } else {
2.32 + emit(smapper, this,
2.33 + "var @2 = Array.prototype['isInstance__ZLjava_lang_Object_2Ljava_lang_String_2'](@1, '@3');",
2.34 + smapper.popA(), smapper.pushI(), type
2.35 + );
2.36 + }
2.37 }
2.38 }
2.39
2.40 private void generateCheckcast(int indx, final StackMapper smapper) throws IOException {
2.41 - final String type = jc.getClassName(indx);
2.42 + String type = jc.getClassName(indx);
2.43 if (!type.startsWith("[")) {
2.44 emitNoFlush(smapper,
2.45 "if (@1 !== null && !@1['$instOf_@2']) throw vm.java_lang_ClassCastException(true);",
2.46 smapper.getT(0, VarType.REFERENCE, false), type.replace('/', '_'));
2.47 } else {
2.48 - emitNoFlush(smapper,
2.49 - "vm.java_lang_Class(false)['forName__Ljava_lang_Class_2Ljava_lang_String_2']('@2')['cast__Ljava_lang_Object_2Ljava_lang_Object_2'](@1);",
2.50 - smapper.getT(0, VarType.REFERENCE, false), type
2.51 - );
2.52 + int cnt = 0;
2.53 + while (type.charAt(cnt) == '[') {
2.54 + cnt++;
2.55 + }
2.56 + if (type.charAt(cnt) == 'L') {
2.57 + type = "vm." + mangleClassName(type.substring(cnt + 1, type.length() - 1));
2.58 + emitNoFlush(smapper,
2.59 + "if (@1 !== null && !Array.prototype['isInstance__ZLjava_lang_Object_2ILjava_lang_Object_2'](@1, @3, @2)) throw vm.java_lang_ClassCastException(true);",
2.60 + smapper.getT(0, VarType.REFERENCE, false), type, "" + cnt
2.61 + );
2.62 + } else {
2.63 + emitNoFlush(smapper,
2.64 + "if (@1 !== null && !Array.prototype['isInstance__ZLjava_lang_Object_2Ljava_lang_String_2'](@1, '@2')) throw vm.java_lang_ClassCastException(true);",
2.65 + smapper.getT(0, VarType.REFERENCE, false), type
2.66 + );
2.67 + }
2.68 }
2.69 }
2.70
3.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/Array.java Tue May 06 08:38:34 2014 +0200
3.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/Array.java Tue May 06 10:08:42 2014 +0200
3.3 @@ -115,9 +115,42 @@
3.4 }
3.5
3.6 public static boolean instanceOfArray(Object obj) {
3.7 + if ("string-array".equals(obj)) {
3.8 + obj = new String[] { "Ahoj" };
3.9 + }
3.10 return obj instanceof Object[];
3.11 }
3.12
3.13 + public static boolean castArray(int type) {
3.14 + try {
3.15 + Object orig = new Object();
3.16 + Object res = orig;
3.17 + if (type == 0) {
3.18 + Object[] arr = new Integer[1];
3.19 + String[] str = (String[]) arr;
3.20 + res = str;
3.21 + }
3.22 + if (type == 1) {
3.23 + Object[] arr = null;
3.24 + String[] str = (String[]) arr;
3.25 + res = str;
3.26 + }
3.27 + if (type == 2) {
3.28 + Object[] arr = new String[1];
3.29 + String[] str = (String[]) arr;
3.30 + res = str;
3.31 + }
3.32 + if (type == 3) {
3.33 + Object[] arr = new String[1];
3.34 + CharSequence[] str = (CharSequence[]) arr;
3.35 + res = str;
3.36 + }
3.37 + return res != orig;
3.38 + } catch (ClassCastException ex) {
3.39 + return false;
3.40 + }
3.41 + }
3.42 +
3.43 public static int sum(int size) {
3.44 int[] arr = new int[size];
3.45 return arr[0] + arr[1];
4.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java Tue May 06 08:38:34 2014 +0200
4.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java Tue May 06 10:08:42 2014 +0200
4.3 @@ -82,9 +82,28 @@
4.4 @Test public void verifyInstanceOfArray() throws Exception {
4.5 assertExec("Returns 'false'", Array.class, "instanceOfArray__ZLjava_lang_Object_2", Double.valueOf(0), "non-array");
4.6 }
4.7 + @Test public void verifyInstanceOfArrayOnNull() throws Exception {
4.8 + assertFalse(Array.instanceOfArray(null), "Null is not an instance of array");
4.9 + assertExec("Returns 'false'", Array.class, "instanceOfArray__ZLjava_lang_Object_2", Double.valueOf(0), (Object) null);
4.10 + }
4.11 + @Test public void verifyInstanceOfArrayStrings() throws Exception {
4.12 + assertExec("Returns 'false'", Array.class, "instanceOfArray__ZLjava_lang_Object_2", Double.valueOf(1), "string-array");
4.13 + }
4.14 @Test public void verifyMultiLen() throws Exception {
4.15 assertExec("Multi len is one", Array.class, "multiLen__I", Double.valueOf(1));
4.16 }
4.17 + @Test public void upCastAnArray() throws Exception {
4.18 + assertExec("Cannot cast int to string array", Array.class, "castArray__ZI", Double.valueOf(0), Double.valueOf(0));
4.19 + }
4.20 + @Test public void upCastANullArray() throws Exception {
4.21 + assertExec("Can cast null to string array", Array.class, "castArray__ZI", Double.valueOf(1), Double.valueOf(1));
4.22 + }
4.23 + @Test public void upCastOK() throws Exception {
4.24 + assertExec("Can cast string to string array", Array.class, "castArray__ZI", Double.valueOf(1), Double.valueOf(2));
4.25 + }
4.26 + @Test public void upCastOK2() throws Exception {
4.27 + assertExec("Can cast string to char sequence array", Array.class, "castArray__ZI", Double.valueOf(1), Double.valueOf(3));
4.28 + }
4.29
4.30 private static TestVM code;
4.31