# HG changeset patch # User Jaroslav Tulach # Date 1411501947 -7200 # Node ID 228f26fc1159b6cc0a4d48299b273ca7d3f90651 # Parent 0e061b0f80eb9fa9784731c30ecf0631e821595f for (var x in array) should return only expected values diff -r 0e061b0f80eb -r 228f26fc1159 rt/emul/mini/src/main/java/java/lang/Class.java --- a/rt/emul/mini/src/main/java/java/lang/Class.java Sat Sep 20 12:52:47 2014 +0200 +++ b/rt/emul/mini/src/main/java/java/lang/Class.java Tue Sep 23 21:52:27 2014 +0200 @@ -1615,12 +1615,12 @@ "var c = Array[sig];\n" + "if (!c) {\n" + " c = vm.java_lang_Class(true);\n" + - " c.jvmName = sig;\n" + - " c.superclass = vm.java_lang_Object(false).$class;\n" + - " c.array = true;\n" + + " Object.defineProperty(c, 'jvmName', { 'configurable': true, 'writable': true, 'value': sig });\n" + + " Object.defineProperty(c, 'superclass', { 'configurable': true, 'writable': true, 'value' : vm.java_lang_Object(false).$class });\n" + + " Object.defineProperty(c, 'array', { 'configurable': true, 'writable': true, 'value': true });\n" + " Array[sig] = c;\n" + "}\n" + - "if (!c.fnc) c.fnc = fnc;\n" + + "if (!c.fnc) Object.defineProperty(c, 'fnc', { 'configurable': true, 'writable': true, 'value' : fnc });\n" + "return c;" ) private static native Class defineArray(String sig, Object fnc); diff -r 0e061b0f80eb -r 228f26fc1159 rt/emul/mini/src/main/java/java/lang/reflect/Array.java --- a/rt/emul/mini/src/main/java/java/lang/reflect/Array.java Sat Sep 20 12:52:47 2014 +0200 +++ b/rt/emul/mini/src/main/java/java/lang/reflect/Array.java Tue Sep 23 21:52:27 2014 +0200 @@ -26,7 +26,6 @@ package java.lang.reflect; import org.apidesign.bck2brwsr.core.Exported; -import org.apidesign.bck2brwsr.core.JavaScriptBody; import org.apidesign.bck2brwsr.core.JavaScriptPrototype; /** @@ -135,12 +134,9 @@ if (!array.getClass().isArray()) { throw new IllegalArgumentException("Argument is not an array"); } - return length(array); + return Method.arrayLength(array); } - @JavaScriptBody(args = { "arr" }, body = "return arr.length;") - private static native int length(Object arr); - /** * Returns the value of the indexed component in the specified * array object. The value is automatically wrapped in an object @@ -600,17 +596,10 @@ * Private */ - @JavaScriptBody(args = { "primitive", "sig", "fn", "length" }, body = - "var arr = new Array(length);\n" - + "var value = primitive ? 0 : null;\n" - + "for(var i = 0; i < length; i++) arr[i] = value;\n" - + "arr.jvmName = sig;\n" - + "arr.fnc = fn;\n" -// + "java.lang.System.out.println('Assigned ' + arr.jvmName + ' fn: ' + (!!arr.fnc));\n" - + "return arr;" - ) @Exported - private static native Object newArray(boolean primitive, String sig, Object fn, int length); + private static Object newArray(boolean primitive, String sig, Object fn, int length) { + return Method.newArray(primitive, sig, fn, length); + } @Exported private static boolean isInstance(Object arr, String sig) { @@ -635,14 +624,11 @@ return false; } } - Class t = classFromFn(fn); + Class t = Method.classFromFn(fn); // log(" to check: " + t); return t.isAssignableFrom(c); } - @JavaScriptBody(args = { "cntstr" }, body = "return cntstr(false).constructor.$class;") - private static native Class classFromFn(Object cntstr); - // @JavaScriptBody(args = { "m" }, body = "java.lang.System.out.println(m.toString().toString());") // private static native void log(Object m); @@ -660,17 +646,11 @@ String compsig = sig.substring(1); int len = getLength(arr); for (int i = 0; i < len; i++) { - setArray(arr, i, multiNewArray(compsig, dims, index + 1, fn)); + Method.setArray(arr, i, multiNewArray(compsig, dims, index + 1, fn)); } return arr; } private static Object fromPrimitive(Class t, Object array, int index) { - return Method.fromPrimitive(t, atArray(array, index)); + return Method.fromPrimitive(t, Method.atArray(array, index)); } - - @JavaScriptBody(args = { "array", "index" }, body = "return array[index];") - private static native Object atArray(Object array, int index); - - @JavaScriptBody(args = { "array", "index", "v" }, body = "array[index] = v;") - private static native Object setArray(Object array, int index, Object v); } diff -r 0e061b0f80eb -r 228f26fc1159 rt/emul/mini/src/main/java/java/lang/reflect/Method.java --- a/rt/emul/mini/src/main/java/java/lang/reflect/Method.java Sat Sep 20 12:52:47 2014 +0200 +++ b/rt/emul/mini/src/main/java/java/lang/reflect/Method.java Tue Sep 23 21:52:27 2014 +0200 @@ -744,4 +744,31 @@ } }; } + + // + // helper methods for Array + // + + @JavaScriptBody(args = { "primitive", "sig", "fn", "length" }, body = + "var arr = new Array(length);\n" + + "var value = primitive ? 0 : null;\n" + + "for(var i = 0; i < length; i++) arr[i] = value;\n" + + "Object.defineProperty(arr, 'jvmName', { 'configurable': true, 'writable': true, 'value': sig });\n" + + "Object.defineProperty(arr, 'fnc', { 'configurable': true, 'writable': true, 'value' : fn });\n" +// + "java.lang.System.out.println('Assigned ' + arr.jvmName + ' fn: ' + (!!arr.fnc));\n" + + "return arr;" + ) + static native Object newArray(boolean primitive, String sig, Object fn, int length); + + @JavaScriptBody(args = { "arr" }, body = "return arr.length;") + static native int arrayLength(Object arr); + + @JavaScriptBody(args = { "cntstr" }, body = "return cntstr(false).constructor.$class;") + static native Class classFromFn(Object cntstr); + @JavaScriptBody(args = { "array", "index" }, body = "return array[index];") + static native Object atArray(Object array, int index); + + @JavaScriptBody(args = { "array", "index", "v" }, body = "array[index] = v;") + static native Object setArray(Object array, int index, Object v); + } diff -r 0e061b0f80eb -r 228f26fc1159 rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Sat Sep 20 12:52:47 2014 +0200 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue Sep 23 21:52:27 2014 +0200 @@ -378,9 +378,11 @@ final LocalsMapper lmapper = new LocalsMapper(stackMapIterator.getArguments()); - boolean obj = "java/lang/Object".equals(jc.getClassName()); + boolean defineProp = + "java/lang/Object".equals(jc.getClassName()) || + "java/lang/reflect/Array".equals(jc.getClassName()); - if (obj) { + if (defineProp) { append("Object.defineProperty(").append(destObject). append(", '").append(name).append("', { configurable: true, writable: true, value: function("); } else { @@ -394,10 +396,11 @@ append(" throw 'no code found for ") .append(jc.getClassName()).append('.') .append(m.getName()).append("';\n"); - if (obj) { - append("}"); + if (defineProp) { + append("}});"); + } else { + append("};"); } - append("};"); return; } @@ -1463,7 +1466,7 @@ while (openBraces-- > 0) { append('}'); } - if (obj) { + if (defineProp) { append("\n}});"); } else { append("\n};"); diff -r 0e061b0f80eb -r 228f26fc1159 rt/vm/src/test/java/org/apidesign/vm4brwsr/Array.java --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/Array.java Sat Sep 20 12:52:47 2014 +0200 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/Array.java Tue Sep 23 21:52:27 2014 +0200 @@ -207,4 +207,16 @@ public static int multiLen() { return new int[1][0].length; } + + @JavaScriptBody(args = { "arr" }, body = + "var cnt = '';\n" + + "if (arr === null) arr = [];\n" + + "for (var i in arr) { cnt += i; }\n" + + "return cnt;\n" + ) + private static native String iterateArray(Object[] arr); + + public static String iterateArray(boolean javaArray) { + return iterateArray(javaArray ? new String[0] : null); + } } diff -r 0e061b0f80eb -r 228f26fc1159 rt/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java Sat Sep 20 12:52:47 2014 +0200 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java Tue Sep 23 21:52:27 2014 +0200 @@ -71,6 +71,18 @@ Double.valueOf(0) ); } + + @Test public void iterateEmptyArray() throws Exception { + assertExec("No elements in empty array", Array.class, "iterateArray__Ljava_lang_String_2Z", + "", false + ); + } + + @Test public void iterateEmptyJavaArray() throws Exception { + assertExec("No elements in empty array", Array.class, "iterateArray__Ljava_lang_String_2Z", + "", true + ); + } @Test public void doesCopyArrayWork() throws Exception { assertExec("Returns 'a'", Array.class, "copyArray__C", Double.valueOf('a'));