mirror of
https://github.com/konsoletyper/teavm.git
synced 2024-11-21 01:00:54 +08:00
wasm gc: add support for importing modules in more cases
This commit is contained in:
parent
e4a2550cc6
commit
f3e035148d
@ -89,7 +89,7 @@ public class DisassemblyImportSectionListener extends BaseDisassemblyListener im
|
||||
}
|
||||
|
||||
@Override
|
||||
public void global(WasmHollowType type) {
|
||||
public void global(WasmHollowType type, boolean mutable) {
|
||||
writer.address().write("(import \"").write(currentModule).write("\" \"")
|
||||
.write(currentName).write("\" ");
|
||||
writer.write("(global ");
|
||||
@ -99,9 +99,15 @@ public class DisassemblyImportSectionListener extends BaseDisassemblyListener im
|
||||
writer.write(" $").write(name);
|
||||
}
|
||||
writer.endLinkTarget();
|
||||
writer.write(" (type ");
|
||||
writer.write(" ");
|
||||
if (mutable) {
|
||||
writer.write("(mut ");
|
||||
}
|
||||
writeType(type);
|
||||
writer.write("))").eol();
|
||||
if (mutable) {
|
||||
writer.write(")");
|
||||
}
|
||||
writer.write(")").eol();
|
||||
++globalIndex;
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ import org.teavm.backend.wasm.model.WasmFunction;
|
||||
import org.teavm.backend.wasm.model.WasmModule;
|
||||
import org.teavm.backend.wasm.model.WasmTag;
|
||||
import org.teavm.backend.wasm.runtime.gc.WasmGCSupport;
|
||||
import org.teavm.diagnostics.Diagnostics;
|
||||
import org.teavm.model.ClassHierarchy;
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
import org.teavm.model.ElementModifier;
|
||||
@ -67,6 +68,7 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
|
||||
private boolean strict;
|
||||
private String entryPoint;
|
||||
private Consumer<WasmGCInitializerContributor> initializerContributors;
|
||||
private Diagnostics diagnostics;
|
||||
|
||||
public WasmGCGenerationContext(WasmModule module, WasmGCVirtualTableProvider virtualTables,
|
||||
WasmGCTypeMapper typeMapper, WasmFunctionTypes functionTypes, ListableClassReaderSource classes,
|
||||
@ -75,7 +77,8 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
|
||||
WasmGCStandardClasses standardClasses, WasmGCStringProvider strings,
|
||||
WasmGCCustomGeneratorProvider customGenerators, WasmGCIntrinsicProvider intrinsics,
|
||||
WasmGCNameProvider names, boolean strict, String entryPoint,
|
||||
Consumer<WasmGCInitializerContributor> initializerContributors) {
|
||||
Consumer<WasmGCInitializerContributor> initializerContributors,
|
||||
Diagnostics diagnostics) {
|
||||
this.module = module;
|
||||
this.virtualTables = virtualTables;
|
||||
this.typeMapper = typeMapper;
|
||||
@ -94,6 +97,7 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
|
||||
this.strict = strict;
|
||||
this.entryPoint = entryPoint;
|
||||
this.initializerContributors = initializerContributors;
|
||||
this.diagnostics = diagnostics;
|
||||
}
|
||||
|
||||
public WasmGCClassInfoProvider classInfoProvider() {
|
||||
@ -202,6 +206,10 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
|
||||
return intrinsics;
|
||||
}
|
||||
|
||||
public Diagnostics diagnostics() {
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
public Collection<String> getInterfaceImplementors(String className) {
|
||||
if (interfaceImplementors == null) {
|
||||
fillInterfaceImplementors();
|
||||
|
@ -84,6 +84,7 @@ import org.teavm.backend.wasm.model.expression.WasmTest;
|
||||
import org.teavm.backend.wasm.model.expression.WasmThrow;
|
||||
import org.teavm.backend.wasm.model.expression.WasmUnreachable;
|
||||
import org.teavm.backend.wasm.runtime.StringInternPool;
|
||||
import org.teavm.diagnostics.Diagnostics;
|
||||
import org.teavm.model.ClassHierarchy;
|
||||
import org.teavm.model.ElementModifier;
|
||||
import org.teavm.model.FieldReference;
|
||||
@ -849,6 +850,16 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
||||
return context.entryPoint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Diagnostics diagnostics() {
|
||||
return context.diagnostics();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodReference currentMethod() {
|
||||
return currentMethod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToInitializer(Consumer<WasmFunction> initializerContributor) {
|
||||
context.addToInitializer(initializerContributor);
|
||||
|
@ -366,7 +366,8 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||
names,
|
||||
strict,
|
||||
entryPoint,
|
||||
initializerContributors
|
||||
initializerContributors,
|
||||
diagnostics
|
||||
);
|
||||
}
|
||||
return context;
|
||||
|
@ -30,7 +30,9 @@ import org.teavm.backend.wasm.model.WasmFunction;
|
||||
import org.teavm.backend.wasm.model.WasmModule;
|
||||
import org.teavm.backend.wasm.model.WasmTag;
|
||||
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||
import org.teavm.diagnostics.Diagnostics;
|
||||
import org.teavm.model.ClassHierarchy;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
public interface WasmGCIntrinsicContext {
|
||||
WasmExpression generate(Expr expr);
|
||||
@ -63,5 +65,9 @@ public interface WasmGCIntrinsicContext {
|
||||
|
||||
String entryPoint();
|
||||
|
||||
Diagnostics diagnostics();
|
||||
|
||||
MethodReference currentMethod();
|
||||
|
||||
void addToInitializer(Consumer<WasmFunction> initializerContributor);
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ public interface ImportSectionListener {
|
||||
default void function(int typeIndex) {
|
||||
}
|
||||
|
||||
default void global(WasmHollowType type) {
|
||||
default void global(WasmHollowType type, boolean mutable) {
|
||||
}
|
||||
|
||||
default void endEntry() {
|
||||
|
@ -45,7 +45,7 @@ public class ImportSectionParser extends BaseSectionParser {
|
||||
}
|
||||
case 3: {
|
||||
var valueType = reader.readType();
|
||||
listener.global(valueType);
|
||||
listener.global(valueType, reader.readLEB() != 0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -619,7 +619,7 @@ async function wrapImports(wasmModule, imports) {
|
||||
if (names === void 0) {
|
||||
let namesByModule = [];
|
||||
names = namesByModule;
|
||||
propertiesToAdd[name] = names;
|
||||
propertiesToAdd[module] = names;
|
||||
promises.push((async () => {
|
||||
let moduleInstance = await import(module);
|
||||
let importsByModule = {};
|
||||
|
@ -29,11 +29,14 @@ import org.teavm.backend.wasm.model.expression.WasmBlock;
|
||||
import org.teavm.backend.wasm.model.expression.WasmBranch;
|
||||
import org.teavm.backend.wasm.model.expression.WasmCall;
|
||||
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
||||
import org.teavm.backend.wasm.model.expression.WasmIsNull;
|
||||
import org.teavm.backend.wasm.model.expression.WasmThrow;
|
||||
import org.teavm.backend.wasm.runtime.gc.WasmGCSupport;
|
||||
import org.teavm.jso.JSObject;
|
||||
import org.teavm.jso.impl.JS;
|
||||
import org.teavm.jso.impl.JSMethods;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.ValueType;
|
||||
|
||||
@ -49,7 +52,6 @@ class WasmGCJSIntrinsic implements WasmGCIntrinsic {
|
||||
|
||||
@Override
|
||||
public WasmExpression apply(InvocationExpr invocation, WasmGCIntrinsicContext context) {
|
||||
var jsoContext = WasmGCJsoContext.wrap(context);
|
||||
switch (invocation.getMethod().getName()) {
|
||||
case "wrap":
|
||||
return wrapString(invocation.getArguments().get(0), context);
|
||||
@ -69,13 +71,79 @@ class WasmGCJSIntrinsic implements WasmGCIntrinsic {
|
||||
return arrayItem(invocation, context);
|
||||
case "get":
|
||||
case "getPure":
|
||||
return new WasmCall(functions.getGet(jsoContext), context.generate(invocation.getArguments().get(0)),
|
||||
context.generate(invocation.getArguments().get(1)));
|
||||
return getProperty(invocation, context);
|
||||
case "importModule":
|
||||
return importModule(invocation, context);
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
private WasmExpression getProperty(InvocationExpr invocation, WasmGCIntrinsicContext context) {
|
||||
var result = tryGetFromModule(invocation, context);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
var jsoContext = WasmGCJsoContext.wrap(context);
|
||||
return new WasmCall(functions.getGet(jsoContext), context.generate(invocation.getArguments().get(0)),
|
||||
context.generate(invocation.getArguments().get(1)));
|
||||
}
|
||||
|
||||
private WasmExpression tryGetFromModule(InvocationExpr invocation, WasmGCIntrinsicContext context) {
|
||||
var target = invocation.getArguments().get(0);
|
||||
if (!(target instanceof InvocationExpr)) {
|
||||
return null;
|
||||
}
|
||||
var targetCall = (InvocationExpr) target;
|
||||
if (!targetCall.getMethod().equals(JSMethods.IMPORT_MODULE)) {
|
||||
return null;
|
||||
}
|
||||
var moduleName = extractString(targetCall.getArguments().get(0));
|
||||
if (moduleName == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var property = invocation.getArguments().get(1);
|
||||
if (!(property instanceof InvocationExpr)) {
|
||||
return null;
|
||||
}
|
||||
var propertyCall = (InvocationExpr) property;
|
||||
if (!propertyCall.getMethod().equals(JSMethods.WRAP_STRING)) {
|
||||
return null;
|
||||
}
|
||||
var name = extractString(propertyCall.getArguments().get(0));
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var jsoContext = WasmGCJsoContext.wrap(context);
|
||||
var global = commonGen.getImportGlobal(jsoContext, moduleName, name);
|
||||
return new WasmGetGlobal(global);
|
||||
}
|
||||
|
||||
private WasmExpression importModule(InvocationExpr invocation, WasmGCIntrinsicContext context) {
|
||||
var jsoContext = WasmGCJsoContext.wrap(context);
|
||||
var nameArg = invocation.getArguments().get(0);
|
||||
var name = extractString(nameArg);
|
||||
if (name == null) {
|
||||
context.diagnostics().error(new CallLocation(context.currentMethod(), invocation.getLocation()),
|
||||
"Invalid JS module import call");
|
||||
}
|
||||
var global = commonGen.getImportGlobal(jsoContext, name, "__self__");
|
||||
return new WasmGetGlobal(global);
|
||||
}
|
||||
|
||||
private String extractString(Expr expr) {
|
||||
if (!(expr instanceof ConstantExpr)) {
|
||||
return null;
|
||||
}
|
||||
var constant = ((ConstantExpr) expr).getValue();
|
||||
if (!(constant instanceof String)) {
|
||||
return null;
|
||||
}
|
||||
return (String) constant;
|
||||
}
|
||||
|
||||
private WasmExpression wrapString(Expr stringExpr, WasmGCIntrinsicContext context) {
|
||||
if (stringExpr instanceof ConstantExpr) {
|
||||
var constantExpr = (ConstantExpr) stringExpr;
|
||||
|
@ -57,6 +57,8 @@ public final class WasmGCJso {
|
||||
jsIntrinsic);
|
||||
wasmGCHost.addIntrinsic(new MethodReference(JS.class, "getPure", JSObject.class, JSObject.class,
|
||||
JSObject.class), jsIntrinsic);
|
||||
wasmGCHost.addIntrinsic(new MethodReference(JS.class, "importModule", String.class, JSObject.class),
|
||||
jsIntrinsic);
|
||||
|
||||
var wrapperIntrinsic = new WasmGCJSWrapperIntrinsic();
|
||||
wasmGCHost.addIntrinsic(new MethodReference(JSWrapper.class, "wrap", JSObject.class, Object.class),
|
||||
|
@ -26,6 +26,7 @@ import org.teavm.junit.JsModuleTest;
|
||||
import org.teavm.junit.OnlyPlatform;
|
||||
import org.teavm.junit.ServeJS;
|
||||
import org.teavm.junit.SkipJVM;
|
||||
import org.teavm.junit.SkipPlatform;
|
||||
import org.teavm.junit.TeaVMTestRunner;
|
||||
import org.teavm.junit.TestPlatform;
|
||||
|
||||
@ -39,14 +40,14 @@ public class ImportModuleTest {
|
||||
"org/teavm/jso/test/amd.js",
|
||||
"org/teavm/jso/test/amdModule.js"
|
||||
})
|
||||
@OnlyPlatform(TestPlatform.JAVASCRIPT)
|
||||
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||
public void amd() {
|
||||
assertEquals(23, runTestFunction());
|
||||
}
|
||||
|
||||
@Test
|
||||
@AttachJavaScript("org/teavm/jso/test/commonjs.js")
|
||||
@OnlyPlatform(TestPlatform.JAVASCRIPT)
|
||||
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||
public void commonjs() {
|
||||
assertEquals(23, runTestFunction());
|
||||
}
|
||||
@ -54,7 +55,6 @@ public class ImportModuleTest {
|
||||
@Test
|
||||
@JsModuleTest
|
||||
@ServeJS(from = "org/teavm/jso/test/es2015.js", as = "testModule.js")
|
||||
@OnlyPlatform({TestPlatform.JAVASCRIPT, TestPlatform.WEBASSEMBLY_GC})
|
||||
public void es2015() {
|
||||
assertEquals(23, runTestFunction());
|
||||
}
|
||||
@ -62,7 +62,6 @@ public class ImportModuleTest {
|
||||
@Test
|
||||
@JsModuleTest
|
||||
@ServeJS(from = "org/teavm/jso/test/classWithConstructorInModule.js", as = "testModule.js")
|
||||
@OnlyPlatform(TestPlatform.JAVASCRIPT)
|
||||
public void classConstructor() {
|
||||
var o = new ClassWithConstructorInModule();
|
||||
assertEquals(99, o.getFoo());
|
||||
@ -75,7 +74,6 @@ public class ImportModuleTest {
|
||||
@Test
|
||||
@JsModuleTest
|
||||
@ServeJS(from = "org/teavm/jso/test/classWithConstructorInModule.js", as = "testModule.js")
|
||||
@OnlyPlatform(TestPlatform.JAVASCRIPT)
|
||||
public void topLevel() {
|
||||
assertEquals("top level", ClassWithConstructorInModule.topLevelFunction());
|
||||
assertEquals("top level prop", ClassWithConstructorInModule.getTopLevelProperty());
|
||||
|
Loading…
Reference in New Issue
Block a user