diff --git a/teavm-jso-impl/src/main/java/org/teavm/jso/plugin/JavascriptNativeProcessor.java b/teavm-jso-impl/src/main/java/org/teavm/jso/plugin/JavascriptNativeProcessor.java index e4a822f27..a4a758aa5 100644 --- a/teavm-jso-impl/src/main/java/org/teavm/jso/plugin/JavascriptNativeProcessor.java +++ b/teavm-jso-impl/src/main/java/org/teavm/jso/plugin/JavascriptNativeProcessor.java @@ -704,6 +704,7 @@ class JavascriptNativeProcessor { insn.getArguments().add(var); insn.setReceiver(result); + replacement.add(insn); return result; } @@ -725,6 +726,7 @@ class JavascriptNativeProcessor { } insn.setReceiver(function); + replacement.add(insn); while (--degree > 1) { type = ValueType.arrayOf(type); @@ -744,9 +746,28 @@ class JavascriptNativeProcessor { insn.getArguments().add(function); function = program.createVariable(); insn.setReceiver(function); + replacement.add(insn); } - return null; + Variable cls = program.createVariable(); + ClassConstantInstruction clsInsn = new ClassConstantInstruction(); + clsInsn.setConstant(ValueType.arrayOf(type)); + clsInsn.setLocation(location.getSourceLocation()); + clsInsn.setReceiver(cls); + replacement.add(clsInsn); + + insn = new InvokeInstruction(); + insn.setMethod(new MethodReference(JS.class, "unmapArray", Class.class, JSArrayReader.class, Function.class, + Object[].class)); + insn.getArguments().add(cls); + insn.getArguments().add(var); + insn.getArguments().add(function); + insn.setReceiver(var); + insn.setType(InvocationType.SPECIAL); + insn.setLocation(location.getSourceLocation()); + replacement.add(insn); + + return var; } private MethodReference singleDimensionArrayUnwrapper(ValueType itemType) { @@ -779,26 +800,26 @@ class JavascriptNativeProcessor { if (itemType instanceof ValueType.Primitive) { switch (((ValueType.Primitive) itemType).getKind()) { case BOOLEAN: - return new MethodReference(JS.class, "booleanArrayUnwrapper", Function.class, Function.class); + return new MethodReference(JS.class, "booleanArrayUnwrapper", Function.class); case BYTE: - return new MethodReference(JS.class, "byteArrayUnwrapper", Function.class, Function.class); + return new MethodReference(JS.class, "byteArrayUnwrapper", Function.class); case SHORT: - return new MethodReference(JS.class, "shortArrayUnwrapper", Function.class, Function.class); + return new MethodReference(JS.class, "shortArrayUnwrapper", Function.class); case CHARACTER: - return new MethodReference(JS.class, "charArrayUnwrapper", Function.class, Function.class); + return new MethodReference(JS.class, "charArrayUnwrapper", Function.class); case INTEGER: - return new MethodReference(JS.class, "intArrayUnwrapper", Function.class, Function.class); + return new MethodReference(JS.class, "intArrayUnwrapper", Function.class); case FLOAT: - return new MethodReference(JS.class, "floatArrayUnwrapper", Function.class, Function.class); + return new MethodReference(JS.class, "floatArrayUnwrapper", Function.class); case DOUBLE: - return new MethodReference(JS.class, "doubleArrayUnwrapper", Function.class, Function.class); + return new MethodReference(JS.class, "doubleArrayUnwrapper", Function.class); default: break; } } else if (itemType.isObject(String.class)) { - return new MethodReference(JS.class, "stringArrayUnwrapper", Function.class, Function.class); + return new MethodReference(JS.class, "stringArrayUnwrapper", Function.class); } - return new MethodReference(JS.class, "arrayUnwrapper", Class.class, Function.class, Function.class); + return new MethodReference(JS.class, "arrayUnwrapper", Class.class, Function.class); } private Variable unwrap(Variable var, String methodName, ValueType argType, ValueType resultType, @@ -946,7 +967,11 @@ class JavascriptNativeProcessor { private ValueType getWrappedType(ValueType type) { if (type instanceof ValueType.Array) { ValueType itemType = ((ValueType.Array) type).getItemType(); - return ValueType.arrayOf(getWrappedType(itemType)); + if (itemType instanceof ValueType.Array) { + return ValueType.parse(Object[].class); + } else { + return ValueType.arrayOf(getWrappedType(itemType)); + } } else if (type instanceof ValueType.Object) { if (type.isObject(String.class)) { return type; diff --git a/teavm-jso/src/test/java/org/teavm/jso/test/ConversionTest.java b/teavm-jso/src/test/java/org/teavm/jso/test/ConversionTest.java index 784df0a4d..afa36d3e2 100644 --- a/teavm-jso/src/test/java/org/teavm/jso/test/ConversionTest.java +++ b/teavm-jso/src/test/java/org/teavm/jso/test/ConversionTest.java @@ -46,13 +46,19 @@ public class ConversionTest { } @Test - public void convertsArraysToJava() { + public void convertsPrimitiveArraysToJavaScript() { + assertEquals("true:2:3:64:4:5.5:6.5:foo", combinePrimitiveArrays(new boolean[] { true }, new byte[] { 2 }, + new short[] { 3 }, new char[] { '@' }, new int[] { 4 }, new float[] { 5.5F }, new double[] { 6.5 }, + new String[] { "foo" })); + } + + @Test + public void convertsPrimitiveArraysToJava() { PrimitiveArrays arrays = getPrimitiveArrays(); boolean[] booleanArray = arrays.getA(); - assertEquals(4, booleanArray.length); + assertEquals(1, booleanArray.length); assertTrue(booleanArray[0]); - assertFalse(booleanArray[1]); assertArrayEquals(new byte[] { 2 }, arrays.getB()); assertArrayEquals(new short[] { 3 }, arrays.getC()); @@ -63,6 +69,57 @@ public class ConversionTest { assertArrayEquals(new String[] { "foo" }, arrays.getH()); } + @Test + public void convertsPrimitiveArrays2ToJavaScript() { + assertEquals("true:2:3:64:4:5.5:6.5:foo", combinePrimitiveArrays2(new boolean[][] {{ true }}, + new byte[][] {{ 2 }}, new short[][] {{ 3 }}, new char[][] {{ '@' }}, new int[][] {{ 4 }}, + new float[][] {{ 5.5F }}, new double[][] {{ 6.5 }}, new String[][] {{ "foo" }})); + } + + @Test + public void convertsPrimitiveArrays2ToJava() { + PrimitiveArrays2 arrays = getPrimitiveArrays2(); + + boolean[][] booleanArray = arrays.getA(); + assertEquals(1, booleanArray.length); + assertEquals(1, booleanArray[0].length); + assertTrue(booleanArray[0][0]); + + assertArrayEquals(new byte[] { 2 }, arrays.getB()[0]); + assertArrayEquals(new short[] { 3 }, arrays.getC()[0]); + assertArrayEquals(new char[] { '@' }, arrays.getD()[0]); + assertArrayEquals(new int[] { 4 }, arrays.getE()[0]); + assertArrayEquals(new float[] { 5.5F }, arrays.getF()[0], 0.01F); + assertArrayEquals(new double[] { 6.5 }, arrays.getG()[0], 0.01); + assertArrayEquals(new String[] { "foo" }, arrays.getH()[0]); + } + + @Test + public void convertsPrimitiveArrays4ToJavaScript() { + assertEquals("true:2:3:64:4:5.5:6.5:foo", combinePrimitiveArrays4(new boolean[][][][] {{{{ true }}}}, + new byte[][][][] {{{{ 2 }}}}, new short[][][][] {{{{ 3 }}}}, new char[][][][] {{{{ '@' }}}}, + new int[][][][] {{{{ 4 }}}}, new float[][][][] {{{{ 5.5F }}}}, new double[][][][] {{{{ 6.5 }}}}, + new String[][][][] {{{{ "foo" }}}})); + } + + @Test + public void convertsPrimitiveArrays4ToJava() { + PrimitiveArrays4 arrays = getPrimitiveArrays4(); + + boolean[][][][] booleanArray = arrays.getA(); + assertEquals(1, booleanArray.length); + assertEquals(1, booleanArray[0][0][0].length); + assertTrue(booleanArray[0][0][0][0]); + + assertArrayEquals(new byte[] { 2 }, arrays.getB()[0][0][0]); + assertArrayEquals(new short[] { 3 }, arrays.getC()[0][0][0]); + assertArrayEquals(new char[] { '@' }, arrays.getD()[0][0][0]); + assertArrayEquals(new int[] { 4 }, arrays.getE()[0][0][0]); + assertArrayEquals(new float[] { 5.5F }, arrays.getF()[0][0][0], 0.01F); + assertArrayEquals(new double[] { 6.5 }, arrays.getG()[0][0][0], 0.01); + assertArrayEquals(new String[] { "foo" }, arrays.getH()[0][0][0]); + } + @JSBody(params = { "a", "b", "c", "d", "e", "f", "g", "h" }, script = "" + "return '' + a + ':' + b + ':' + c + ':' + d + ':' + e + ':' + f.toFixed(1) + ':'" + "+ g.toFixed(1) + ':' + h;") @@ -72,10 +129,37 @@ public class ConversionTest { @JSBody(params = {}, script = "return { a : true, b : 2, c : 3, d : 64, e : 4, f : 5.5, g : 6.5, h : 'foo' };") private static native Primitives getPrimitives(); + @JSBody(params = { "a", "b", "c", "d", "e", "f", "g", "h" }, script = "" + + "return '' + a[0] + ':' + b[0] + ':' + c[0] + ':' + d[0] + ':' + e[0] + ':' + f[0].toFixed(1) + ':'" + + "+ g[0].toFixed(1) + ':' + h[0];") + private static native String combinePrimitiveArrays(boolean[] a, byte[] b, short[] c, char[] d, int[] e, float[] f, + double[] g, String[] h); + @JSBody(params = {}, script = "return { a : [true], b : [2], c : [3], d : [64], e : [4], f : [5.5], " + "g : [6.5], h : ['foo'] };") private static native PrimitiveArrays getPrimitiveArrays(); + @JSBody(params = { "a", "b", "c", "d", "e", "f", "g", "h" }, script = "" + + "return '' + a[0][0] + ':' + b[0][0] + ':' + c[0][0] + ':' + d[0][0] + ':' + e[0][0] + ':' " + + "+ f[0][0].toFixed(1) + ':' + g[0][0].toFixed(1) + ':' + h[0][0];") + private static native String combinePrimitiveArrays2(boolean[][] a, byte[][] b, short[][] c, char[][] d, int[][] e, + float[][] f, double[][] g, String[][] h); + + @JSBody(params = {}, script = "return { a : [[true]], b : [[2]], c : [[3]], d : [[64]], e : [[4]], f : [[5.5]], " + + "g : [[6.5]], h : [['foo']] };") + private static native PrimitiveArrays2 getPrimitiveArrays2(); + + @JSBody(params = { "a", "b", "c", "d", "e", "f", "g", "h" }, script = "" + + "return '' + a[0][0][0][0] + ':' + b[0][0][0][0] + ':' + c[0][0][0][0] + ':' + d[0][0][0][0] + ':' " + + "+ e[0][0][0][0] + ':' + f[0][0][0][0].toFixed(1) + ':' + g[0][0][0][0].toFixed(1) + ':' " + + "+ h[0][0][0][0];") + private static native String combinePrimitiveArrays4(boolean[][][][] a, byte[][][][] b, short[][][][] c, + char[][][][] d, int[][][][] e, float[][][][] f, double[][][][] g, String[][][][] h); + + @JSBody(params = {}, script = "return { a : [[[[true]]]], b : [[[[2]]]], c : [[[[3]]]], d : [[[[64]]]], " + + "e : [[[[4]]]], f : [[[[5.5]]]], g : [[[[6.5]]]], h : [[[['foo']]]] };") + private static native PrimitiveArrays4 getPrimitiveArrays4(); + interface Primitives extends JSObject { @JSProperty boolean getA(); @@ -127,4 +211,56 @@ public class ConversionTest { @JSProperty String[] getH(); } + + interface PrimitiveArrays2 extends JSObject { + @JSProperty + boolean[][] getA(); + + @JSProperty + byte[][] getB(); + + @JSProperty + short[][] getC(); + + @JSProperty + char[][] getD(); + + @JSProperty + int[][] getE(); + + @JSProperty + float[][] getF(); + + @JSProperty + double[][] getG(); + + @JSProperty + String[][] getH(); + } + + interface PrimitiveArrays4 extends JSObject { + @JSProperty + boolean[][][][] getA(); + + @JSProperty + byte[][][][] getB(); + + @JSProperty + short[][][][] getC(); + + @JSProperty + char[][][][] getD(); + + @JSProperty + int[][][][] getE(); + + @JSProperty + float[][][][] getF(); + + @JSProperty + double[][][][] getG(); + + @JSProperty + String[][][][] getH(); + } } diff --git a/teavm-samples/teavm-samples-benchmark/pom.xml b/teavm-samples/teavm-samples-benchmark/pom.xml index 167860511..ed0590921 100644 --- a/teavm-samples/teavm-samples-benchmark/pom.xml +++ b/teavm-samples/teavm-samples-benchmark/pom.xml @@ -81,7 +81,6 @@ maven-jar-plugin - 2.5 prepare-package