From 5ad4496c342202e9523890c3f61f7bc9ff3e752e Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Sat, 28 Sep 2024 19:52:14 +0200 Subject: [PATCH] wasm gc: support primitive array conversion to JavaScript in JSO --- .../org/teavm/backend/wasm/wasm-gc-runtime.js | 2 +- .../src/main/java/org/teavm/jso/impl/JS.java | 1 - .../jso/impl/wasmgc/WasmGCJSFunctions.java | 8 +++--- .../jso/impl/wasmgc/WasmGCJSIntrinsic.java | 25 +++++++++++++++++++ .../jso/impl/wasmgc/WasmGCJSTypeMapper.java | 6 +++-- .../org/teavm/jso/impl/wasmgc/WasmGCJso.java | 1 + .../org/teavm/jso/test/ConversionTest.java | 4 --- 7 files changed, 34 insertions(+), 13 deletions(-) diff --git a/core/src/main/resources/org/teavm/backend/wasm/wasm-gc-runtime.js b/core/src/main/resources/org/teavm/backend/wasm/wasm-gc-runtime.js index a9531e5a7d..515f4477b5 100644 --- a/core/src/main/resources/org/teavm/backend/wasm/wasm-gc-runtime.js +++ b/core/src/main/resources/org/teavm/backend/wasm/wasm-gc-runtime.js @@ -18,7 +18,7 @@ var TeaVM = TeaVM || {}; TeaVM.wasm = function() { let exports; let getGlobalName = function(name) { - return eval("return " + {name}); + return eval(name); } function defaults(imports) { let stderr = ""; diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/JS.java b/jso/impl/src/main/java/org/teavm/jso/impl/JS.java index 1a3481cdd5..222f37d6aa 100644 --- a/jso/impl/src/main/java/org/teavm/jso/impl/JS.java +++ b/jso/impl/src/main/java/org/teavm/jso/impl/JS.java @@ -746,7 +746,6 @@ public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JS @InjectedBy(JSNativeInjector.class) @NoSideEffects - @Import(name = "global", module = "teavmJso") public static native JSObject global(String name); @InjectedBy(JSNativeInjector.class) diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJSFunctions.java b/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJSFunctions.java index e73713940b..aea83e10fc 100644 --- a/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJSFunctions.java +++ b/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJSFunctions.java @@ -29,7 +29,7 @@ WasmFunction getFunctionConstructor(WasmGCIntrinsicContext context, int index) { if (function == null) { var extern = WasmType.SpecialReferenceKind.EXTERN.asNonNullType(); var constructorParamTypes = new WasmType[index + 1]; - Arrays.fill(constructorParamTypes, extern); + Arrays.fill(constructorParamTypes, WasmType.Reference.EXTERN); var functionType = context.functionTypes().of(extern, constructorParamTypes); function = new WasmFunction(functionType); function.setName(context.names().topLevel("teavm.js:createFunction" + index)); @@ -44,11 +44,9 @@ WasmFunction getFunctionConstructor(WasmGCIntrinsicContext context, int index) { WasmFunction getFunctionCaller(WasmGCIntrinsicContext context, int index) { var function = callers[index]; if (function == null) { - var extern = WasmType.SpecialReferenceKind.EXTERN.asNonNullType(); var paramTypes = new WasmType[index + 1]; - Arrays.fill(paramTypes, extern); - paramTypes[0] = WasmType.Reference.EXTERN; - var functionType = context.functionTypes().of(extern, paramTypes); + Arrays.fill(paramTypes, WasmType.Reference.EXTERN); + var functionType = context.functionTypes().of(WasmType.Reference.EXTERN, paramTypes); function = new WasmFunction(functionType); function.setName(context.names().topLevel("teavm.js:callFunction" + index)); function.setImportModule("teavmJso"); diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJSIntrinsic.java b/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJSIntrinsic.java index 05c91a800f..94d9035521 100644 --- a/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJSIntrinsic.java +++ b/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJSIntrinsic.java @@ -20,10 +20,17 @@ import org.teavm.ast.InvocationExpr; import org.teavm.backend.wasm.intrinsics.gc.WasmGCIntrinsic; import org.teavm.backend.wasm.intrinsics.gc.WasmGCIntrinsicContext; +import org.teavm.backend.wasm.model.WasmFunction; +import org.teavm.backend.wasm.model.WasmType; import org.teavm.backend.wasm.model.expression.WasmCall; import org.teavm.backend.wasm.model.expression.WasmExpression; +import org.teavm.jso.JSObject; +import org.teavm.jso.impl.JS; +import org.teavm.model.MethodReference; class WasmGCJSIntrinsic implements WasmGCIntrinsic { + private WasmFunction globalFunction; + @Override public WasmExpression apply(InvocationExpr invocation, WasmGCIntrinsicContext context) { switch (invocation.getMethod().getName()) { @@ -35,8 +42,26 @@ public WasmExpression apply(InvocationExpr invocation, WasmGCIntrinsicContext co var function = context.functions().forStaticMethod(JS_TO_STRING); return new WasmCall(function, context.generate(invocation.getArguments().get(0))); } + case "global": { + var stringToJs = context.functions().forStaticMethod(STRING_TO_JS); + var name = new WasmCall(stringToJs, context.generate(invocation.getArguments().get(0))); + return new WasmCall(getGlobalFunction(context), name); + } default: throw new IllegalArgumentException(); } } + + private WasmFunction getGlobalFunction(WasmGCIntrinsicContext context) { + if (globalFunction == null) { + globalFunction = new WasmFunction(context.functionTypes().of(WasmType.Reference.EXTERN, + WasmType.Reference.EXTERN)); + globalFunction.setName(context.names().suggestForMethod(new MethodReference(JS.class, + "global", String.class, JSObject.class))); + globalFunction.setImportName("global"); + globalFunction.setImportModule("teavmJso"); + context.module().functions.add(globalFunction); + } + return globalFunction; + } } diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJSTypeMapper.java b/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJSTypeMapper.java index 24e359af4a..a676d68106 100644 --- a/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJSTypeMapper.java +++ b/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJSTypeMapper.java @@ -20,12 +20,14 @@ import org.teavm.backend.wasm.generate.gc.classes.WasmGCCustomTypeMapperFactoryContext; import org.teavm.backend.wasm.model.WasmType; import org.teavm.jso.JSObject; +import org.teavm.jso.core.JSArray; class WasmGCJSTypeMapper implements WasmGCCustomTypeMapper, WasmGCCustomTypeMapperFactory { @Override public WasmType map(String className) { - if (className.equals(JSObject.class.getName())) { - return WasmType.SpecialReferenceKind.EXTERN.asNonNullType(); + if (className.equals(JSObject.class.getName()) + || className.equals(JSArray.class.getName())) { + return WasmType.Reference.EXTERN; } return null; } diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJso.java b/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJso.java index 7ba1ce3288..fa437cc8e3 100644 --- a/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJso.java +++ b/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJso.java @@ -35,5 +35,6 @@ public static void install(TeaVMHost host, TeaVMWasmGCHost wasmGCHost, JSBodyRep wasmGCHost.addIntrinsic(new MethodReference(JS.class, "wrap", String.class, JSObject.class), jsIntrinsic); wasmGCHost.addIntrinsic(new MethodReference(JS.class, "unwrapString", JSObject.class, String.class), jsIntrinsic); + wasmGCHost.addIntrinsic(new MethodReference(JS.class, "global", String.class, JSObject.class), jsIntrinsic); } } diff --git a/tests/src/test/java/org/teavm/jso/test/ConversionTest.java b/tests/src/test/java/org/teavm/jso/test/ConversionTest.java index e32029e97a..c828a6f338 100644 --- a/tests/src/test/java/org/teavm/jso/test/ConversionTest.java +++ b/tests/src/test/java/org/teavm/jso/test/ConversionTest.java @@ -58,7 +58,6 @@ public void convertsPrimitivesToJava() { } @Test - @SkipPlatform(TestPlatform.WEBASSEMBLY_GC) 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 }, @@ -84,7 +83,6 @@ public void convertsPrimitiveArraysToJava() { } @Test - @SkipPlatform(TestPlatform.WEBASSEMBLY_GC) 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 }}, @@ -111,7 +109,6 @@ public void convertsPrimitiveArrays2ToJava() { } @Test - @SkipPlatform(TestPlatform.WEBASSEMBLY_GC) 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[][][][] {{{{ '@' }}}}, @@ -153,7 +150,6 @@ public void convertsArrayOfJSObject() { } @Test - @SkipPlatform(TestPlatform.WEBASSEMBLY_GC) public void copiesArray() { int[] array = { 23 }; assertEquals(24, mutate(array));