mirror of
https://github.com/konsoletyper/teavm.git
synced 2024-11-27 01:30:35 +08:00
wasm gc: fix exporting classes to JS
This commit is contained in:
parent
f61d893b6d
commit
14a4a99fa5
@ -263,15 +263,23 @@ TeaVM.wasmGC = TeaVM.wasmGC || function() {
|
||||
params.push("p" + i);
|
||||
}
|
||||
let paramsAsString = params.length === 0 ? "" : params.join(", ");
|
||||
return new Function("rethrowJavaAsJs", "fn", `
|
||||
return function(${paramsAsString}) {
|
||||
try {
|
||||
return fn(${paramsAsString});
|
||||
} catch (e) {
|
||||
rethrowJavaAsJs(e);
|
||||
}
|
||||
};
|
||||
`)(rethrowJavaAsJs, fn);
|
||||
return new Function("rethrowJavaAsJs", "fn",
|
||||
`return function(${paramsAsString}) {\n` +
|
||||
` try {\n` +
|
||||
` return fn(${paramsAsString});\n` +
|
||||
` } catch (e) {\n` +
|
||||
` rethrowJavaAsJs(e);\n` +
|
||||
` }\n` +
|
||||
`};`
|
||||
)(rethrowJavaAsJs, fn);
|
||||
}
|
||||
function renameConstructor(name, c) {
|
||||
return new Function(
|
||||
"constructor",
|
||||
`return function ${name}(marker, javaObject) {\n` +
|
||||
` return constructor.call(this, marker, javaObject);\n` +
|
||||
`}\n`
|
||||
)(c);
|
||||
}
|
||||
imports.teavmJso = {
|
||||
emptyString: () => "",
|
||||
@ -295,64 +303,41 @@ TeaVM.wasmGC = TeaVM.wasmGC || function() {
|
||||
}
|
||||
},
|
||||
createClass(name, parent, constructor) {
|
||||
name = sanitizeName(name);
|
||||
name = sanitizeName(name || "JavaObject");
|
||||
let action;
|
||||
if (parent === null) {
|
||||
let fn = new Function(
|
||||
"javaObjectSymbol",
|
||||
"functionsSymbol",
|
||||
"wrapperCallMarker",
|
||||
"constructor",
|
||||
"rethrowJavaAsJs",
|
||||
`let fn;
|
||||
fn = function ${name}(marker, javaObject) {
|
||||
if (marker === wrapperCallMarker) {
|
||||
this[javaObjectSymbol] = javaObject;
|
||||
this[functionsSymbol] = null;
|
||||
} else if (constructor === null) {
|
||||
throw new Error("This class can't be instantiated directly");
|
||||
} else {
|
||||
try {
|
||||
return fn(wrapperCallMarker, constructor(arguments));
|
||||
} catch (e) {
|
||||
rethrowJavaAsJs(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
let boundFn = function(javaObject) { return fn.call(this, wrapperCallMarker, javaObject); };
|
||||
boundFn[wrapperCallMarker] = fn;
|
||||
boundFn.prototype = fn.prototype;
|
||||
return boundFn;`
|
||||
);
|
||||
return fn(javaObjectSymbol, functionsSymbol, wrapperCallMarkerSymbol, constructor, rethrowJavaAsJs);
|
||||
action = function (javaObject) {
|
||||
this[javaObjectSymbol] = javaObject;
|
||||
this[functionsSymbol] = null;
|
||||
};
|
||||
} else {
|
||||
let fn = new Function(
|
||||
"parent",
|
||||
"wrapperCallMarker",
|
||||
"constructor",
|
||||
"rethrowJavaAsJs",
|
||||
`let fn
|
||||
fn = function ${name}(marker, javaObject) {
|
||||
if (marker === wrapperCallMarker) {
|
||||
parent.call(this, javaObject);
|
||||
} else if (constructor === null) {
|
||||
throw new Error("This class can't be instantiated directly");
|
||||
} else {
|
||||
try {
|
||||
return fn(wrapperCallMarker, constructor(arguments));
|
||||
} catch (e) {
|
||||
rethrowJavaAsJs(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
fn.prototype = Object.create(parent);
|
||||
fn.prototype.constructor = parent;
|
||||
let boundFn = function(javaObject) { return fn.call(this, wrapperCallMarker, javaObject); };
|
||||
boundFn[wrapperCallMarker] = fn;
|
||||
boundFn.prototype = fn.prototype;
|
||||
return fn;`
|
||||
);
|
||||
return fn(parent, wrapperCallMarkerSymbol, constructor, rethrowJavaAsJs);
|
||||
action = function (javaObject) {
|
||||
parent.call(this, javaObject);
|
||||
};
|
||||
fn.prototype = Object.create(parent);
|
||||
fn.prototype.constructor = parent;
|
||||
}
|
||||
let fn = renameConstructor(name, function (marker, javaObject) {
|
||||
if (marker === wrapperCallMarkerSymbol) {
|
||||
action.call(this, javaObject);
|
||||
} else if (constructor === null) {
|
||||
throw new Error("This class can't be instantiated directly");
|
||||
} else {
|
||||
try {
|
||||
return constructor.apply(null, arguments);
|
||||
} catch (e) {
|
||||
rethrowJavaAsJs(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
fn.prototype = Object.create(parent || Object.prototype);
|
||||
fn.prototype.constructor = fn;
|
||||
let boundFn = renameConstructor(name, function(javaObject) {
|
||||
return fn.call(this, wrapperCallMarkerSymbol, javaObject);
|
||||
});
|
||||
boundFn[wrapperCallMarkerSymbol] = fn;
|
||||
boundFn.prototype = fn.prototype;
|
||||
return boundFn;
|
||||
},
|
||||
exportClass(cls) {
|
||||
return cls[wrapperCallMarkerSymbol];
|
||||
@ -363,15 +348,15 @@ TeaVM.wasmGC = TeaVM.wasmGC || function() {
|
||||
params.push("p" + i);
|
||||
}
|
||||
let paramsAsString = params.length === 0 ? "" : params.join(", ");
|
||||
cls.prototype[name] = new Function("rethrowJavaAsJs", "fn", `
|
||||
return function(${paramsAsString}) {
|
||||
try {
|
||||
return fn(${['this', params].join(", ")});
|
||||
} catch (e) {
|
||||
rethrowJavaAsJs(e);
|
||||
}
|
||||
};
|
||||
`)(rethrowJavaAsJs, fn);
|
||||
cls.prototype[name] = new Function("rethrowJavaAsJs", "fn",
|
||||
`return function(${paramsAsString}) {\n` +
|
||||
` try {\n` +
|
||||
` return fn(${['this', params].join(", ")});\n` +
|
||||
` } catch (e) {\n` +
|
||||
` rethrowJavaAsJs(e);\n` +
|
||||
` }\n` +
|
||||
`};`
|
||||
)(rethrowJavaAsJs, fn);
|
||||
},
|
||||
defineStaticMethod(cls, name, fn) {
|
||||
cls[name] = defineFunction(fn);
|
||||
@ -554,32 +539,33 @@ TeaVM.wasmGC = TeaVM.wasmGC || function() {
|
||||
for (let i = 0; i < 32; ++i) {
|
||||
let args = argumentList.length === 0 ? "" : argumentList.join(", ");
|
||||
let argsAndBody = [...argumentList, "body"].join(", ");
|
||||
imports.teavmJso["createFunction" + i] = new Function("wrapCallFromJavaToJs", ...argumentList, "body", `
|
||||
return new Function('wrapCallFromJavaToJs', ${argsAndBody}).bind(this, wrapCallFromJavaToJs);
|
||||
`).bind(null, wrapCallFromJavaToJs);
|
||||
imports.teavmJso["callFunction" + i] = new Function("rethrowJsAsJava", "fn", ...argumentList, `
|
||||
try {
|
||||
return fn(${args});
|
||||
} catch (e) {
|
||||
rethrowJsAsJava(e);
|
||||
}
|
||||
`).bind(null, rethrowJsAsJava);
|
||||
imports.teavmJso["createFunction" + i] = new Function("wrapCallFromJavaToJs", ...argumentList, "body",
|
||||
`return new Function('wrapCallFromJavaToJs', ${argsAndBody}).bind(this, wrapCallFromJavaToJs);`
|
||||
).bind(null, wrapCallFromJavaToJs);
|
||||
imports.teavmJso["callFunction" + i] = new Function("rethrowJsAsJava", "fn", ...argumentList,
|
||||
`try {\n` +
|
||||
` return fn(${args});\n` +
|
||||
`} catch (e) {\n` +
|
||||
` rethrowJsAsJava(e);\n` +
|
||||
`}`
|
||||
).bind(null, rethrowJsAsJava);
|
||||
imports.teavmJso["callMethod" + i] = new Function("rethrowJsAsJava", "getGlobalName", "instance",
|
||||
"method", ...argumentList, `
|
||||
try {
|
||||
return instance !== null
|
||||
? instance[method](${args})
|
||||
: getGlobalName(method)(${args});
|
||||
} catch (e) {
|
||||
rethrowJsAsJava(e);
|
||||
}`).bind(null, rethrowJsAsJava, getGlobalName);
|
||||
imports.teavmJso["construct" + i] = new Function("rethrowJsAsJava", "constructor", ...argumentList, `
|
||||
try {
|
||||
return new constructor(${args});
|
||||
} catch (e) {
|
||||
rethrowJsAsJava(e);
|
||||
}
|
||||
`).bind(null, rethrowJsAsJava);
|
||||
"method", ...argumentList,
|
||||
`try {\n`+
|
||||
` return instance !== null\n` +
|
||||
` ? instance[method](${args})\n` +
|
||||
` : getGlobalName(method)(${args});\n` +
|
||||
`} catch (e) {\n` +
|
||||
` rethrowJsAsJava(e);\n` +
|
||||
`}`
|
||||
).bind(null, rethrowJsAsJava, getGlobalName);
|
||||
imports.teavmJso["construct" + i] = new Function("rethrowJsAsJava", "constructor", ...argumentList,
|
||||
`try {\n` +
|
||||
` return new constructor(${args});\n` +
|
||||
`} catch (e) {\n` +
|
||||
` rethrowJsAsJava(e);\n` +
|
||||
`}`
|
||||
).bind(null, rethrowJsAsJava);
|
||||
imports.teavmJso["arrayOf" + i] = new Function(...argumentList, "return [" + args + "]");
|
||||
|
||||
let param = "p" + (i + 1);
|
||||
|
@ -139,10 +139,7 @@ class JSObjectClassTransformer implements ClassHolderTransformer {
|
||||
createWrapperMethod.setLevel(AccessLevel.PUBLIC);
|
||||
createWrapperMethod.getModifiers().add(ElementModifier.NATIVE);
|
||||
cls.addMethod(createWrapperMethod);
|
||||
|
||||
if (!isJavaScriptClass(cls)) {
|
||||
cls.getInterfaces().add(JSMethods.JS_MARSHALLABLE);
|
||||
}
|
||||
cls.getInterfaces().add(JSMethods.JS_MARSHALLABLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,6 +66,8 @@ final class WasmGCJSRuntime {
|
||||
@Import(name = "charAt", module = "teavmJso")
|
||||
static native char charAt(JSObject str, int index);
|
||||
|
||||
static native JSObject wrapObject(Object obj);
|
||||
|
||||
static Throwable wrapException(JSObject obj) {
|
||||
return new WasmGCExceptionWrapper(obj);
|
||||
}
|
||||
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2024 konsoletyper.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.jso.impl.wasmgc;
|
||||
|
||||
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.expression.WasmCall;
|
||||
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
||||
|
||||
class WasmGCJSRuntimeIntrinsic implements WasmGCIntrinsic {
|
||||
private WasmGCJsoCommonGenerator commonGen;
|
||||
|
||||
WasmGCJSRuntimeIntrinsic(WasmGCJsoCommonGenerator commonGen) {
|
||||
this.commonGen = commonGen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WasmExpression apply(InvocationExpr invocation, WasmGCIntrinsicContext context) {
|
||||
var jsoContext = WasmGCJsoContext.wrap(context);
|
||||
var wrapperClass = commonGen.getDefaultWrapperClass(jsoContext);
|
||||
var wrapperFunction = commonGen.javaObjectToJSFunction(jsoContext);
|
||||
return new WasmCall(wrapperFunction, context.generate(invocation.getArguments().get(0)),
|
||||
new WasmGetGlobal(wrapperClass));
|
||||
}
|
||||
}
|
@ -21,7 +21,6 @@ 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.WasmCast;
|
||||
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||
import org.teavm.backend.wasm.model.expression.WasmExternConversion;
|
||||
import org.teavm.backend.wasm.model.expression.WasmExternConversionType;
|
||||
@ -41,17 +40,6 @@ class WasmGCJSWrapperIntrinsic implements WasmGCIntrinsic {
|
||||
var function = getWrapFunction(context);
|
||||
return new WasmCall(function, context.generate(invocation.getArguments().get(0)));
|
||||
}
|
||||
case "dependencyJavaToJs":
|
||||
case "directJavaToJs":
|
||||
return new WasmExternConversion(WasmExternConversionType.ANY_TO_EXTERN,
|
||||
context.generate(invocation.getArguments().get(0)));
|
||||
case "dependencyJsToJava":
|
||||
case "directJsToJava": {
|
||||
var any = new WasmExternConversion(WasmExternConversionType.EXTERN_TO_ANY,
|
||||
context.generate(invocation.getArguments().get(0)));
|
||||
var objectType = context.typeMapper().mapType(ValueType.parse(Object.class));
|
||||
return new WasmCast(any, (WasmType.Reference) objectType);
|
||||
}
|
||||
case "isJava": {
|
||||
var convert = new WasmExternConversion(WasmExternConversionType.EXTERN_TO_ANY,
|
||||
context.generate(invocation.getArguments().get(0)));
|
||||
|
@ -25,6 +25,7 @@ import org.teavm.model.ClassHolderTransformerContext;
|
||||
import org.teavm.model.ElementModifier;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.MethodHolder;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.emit.ProgramEmitter;
|
||||
|
||||
class WasmGCJSWrapperTransformer implements ClassHolderTransformer {
|
||||
@ -33,6 +34,12 @@ class WasmGCJSWrapperTransformer implements ClassHolderTransformer {
|
||||
if (cls.getName().equals(JSWrapper.class.getName())) {
|
||||
transformMarshallMethod(cls.getMethod(new MethodDescriptor("marshallJavaToJs", Object.class,
|
||||
JSObject.class)), context);
|
||||
transformDirectJavaToJs(cls.getMethod(new MethodDescriptor("directJavaToJs", Object.class,
|
||||
JSObject.class)), context);
|
||||
transformDirectJavaToJs(cls.getMethod(new MethodDescriptor("dependencyJavaToJs", Object.class,
|
||||
JSObject.class)), context);
|
||||
transformDirectJsToJava(cls.getMethod(new MethodDescriptor("dependencyJsToJava", JSObject.class,
|
||||
Object.class)), context);
|
||||
transformWrapMethod(cls.getMethod(new MethodDescriptor("wrap", JSObject.class, Object.class)));
|
||||
transformIsJava(cls.getMethod(new MethodDescriptor("isJava", Object.class, boolean.class)), context);
|
||||
addCreateWrapperMethod(cls, context);
|
||||
@ -43,9 +50,26 @@ class WasmGCJSWrapperTransformer implements ClassHolderTransformer {
|
||||
method.getModifiers().remove(ElementModifier.NATIVE);
|
||||
var pe = ProgramEmitter.create(method, context.getHierarchy());
|
||||
var obj = pe.var(1, Object.class);
|
||||
pe.when(obj.instanceOf(ValueType.parse(JSMarshallable.class)).isFalse()).thenDo(() -> {
|
||||
pe.invoke(WasmGCJSRuntime.class, "wrapObject", JSObject.class, obj).returnValue();
|
||||
});
|
||||
obj.cast(JSMarshallable.class).invokeVirtual("marshallToJs", JSObject.class).returnValue();
|
||||
}
|
||||
|
||||
private void transformDirectJavaToJs(MethodHolder method, ClassHolderTransformerContext context) {
|
||||
method.getModifiers().remove(ElementModifier.NATIVE);
|
||||
var pe = ProgramEmitter.create(method, context.getHierarchy());
|
||||
var obj = pe.var(1, Object.class);
|
||||
pe.invoke(JSWrapper.class, "marshallJavaToJs", JSObject.class, obj).returnValue();
|
||||
}
|
||||
|
||||
private void transformDirectJsToJava(MethodHolder method, ClassHolderTransformerContext context) {
|
||||
method.getModifiers().remove(ElementModifier.NATIVE);
|
||||
var pe = ProgramEmitter.create(method, context.getHierarchy());
|
||||
var obj = pe.var(1, JSObject.class);
|
||||
pe.invoke(JSWrapper.class, "unmarshallJavaFromJs", Object.class, obj).returnValue();
|
||||
}
|
||||
|
||||
private void transformWrapMethod(MethodHolder method) {
|
||||
method.getModifiers().add(ElementModifier.NATIVE);
|
||||
method.setProgram(null);
|
||||
|
@ -57,15 +57,10 @@ public final class WasmGCJso {
|
||||
var wrapperIntrinsic = new WasmGCJSWrapperIntrinsic();
|
||||
wasmGCHost.addIntrinsic(new MethodReference(JSWrapper.class, "wrap", JSObject.class, Object.class),
|
||||
wrapperIntrinsic);
|
||||
wasmGCHost.addIntrinsic(new MethodReference(JSWrapper.class, "dependencyJavaToJs", Object.class,
|
||||
JSObject.class), wrapperIntrinsic);
|
||||
wasmGCHost.addIntrinsic(new MethodReference(JSWrapper.class, "directJavaToJs", Object.class, JSObject.class),
|
||||
wrapperIntrinsic);
|
||||
wasmGCHost.addIntrinsic(new MethodReference(JSWrapper.class, "dependencyJsToJava", JSObject.class,
|
||||
Object.class), wrapperIntrinsic);
|
||||
wasmGCHost.addIntrinsic(new MethodReference(JSWrapper.class, "directJsToJava", JSObject.class, Object.class),
|
||||
wrapperIntrinsic);
|
||||
wasmGCHost.addIntrinsic(new MethodReference(JSWrapper.class, "isJava", JSObject.class, boolean.class),
|
||||
wrapperIntrinsic);
|
||||
|
||||
wasmGCHost.addIntrinsic(new MethodReference(WasmGCJSRuntime.class, "wrapObject", Object.class,
|
||||
JSObject.class), new WasmGCJSRuntimeIntrinsic(commonGen));
|
||||
}
|
||||
}
|
||||
|
@ -63,6 +63,8 @@ class WasmGCJsoCommonGenerator {
|
||||
private WasmFunction definePropertyFunction;
|
||||
private WasmFunction defineStaticPropertyFunction;
|
||||
private WasmFunction exportClassFunction;
|
||||
private WasmFunction javaObjectToJSFunction;
|
||||
private WasmGlobal defaultWrapperClass;
|
||||
private Map<String, WasmGlobal> definedClasses = new HashMap<>();
|
||||
|
||||
WasmGCJsoCommonGenerator(WasmGCJSFunctions jsFunctions) {
|
||||
@ -198,6 +200,23 @@ class WasmGCJsoCommonGenerator {
|
||||
return new WasmGetGlobal(global);
|
||||
}
|
||||
|
||||
WasmGlobal getDefaultWrapperClass(WasmGCJsoContext context) {
|
||||
if (defaultWrapperClass == null) {
|
||||
var name = context.names().topLevel("teavm.js@defaultWrapperClass");
|
||||
defaultWrapperClass = new WasmGlobal(name, WasmType.Reference.EXTERN,
|
||||
new WasmNullConstant(WasmType.Reference.EXTERN));
|
||||
context.module().globals.add(defaultWrapperClass);
|
||||
addInitializerPart(context, initializer -> {
|
||||
var createClass = new WasmCall(createClassFunction(context),
|
||||
new WasmNullConstant(WasmType.Reference.EXTERN),
|
||||
new WasmNullConstant(WasmType.Reference.EXTERN),
|
||||
new WasmNullConstant(WasmType.Reference.FUNC));
|
||||
initializer.getBody().add(new WasmSetGlobal(defaultWrapperClass, createClass));
|
||||
});
|
||||
}
|
||||
return defaultWrapperClass;
|
||||
}
|
||||
|
||||
WasmGlobal getDefinedClass(WasmGCJsoContext context, String className) {
|
||||
return definedClasses.computeIfAbsent(className, n -> defineClass(context, n));
|
||||
}
|
||||
@ -216,8 +235,6 @@ class WasmGCJsoCommonGenerator {
|
||||
defineProperties(context, members, cls, global, expressions);
|
||||
|
||||
var staticMembers = AliasCollector.collectMembers(cls, AliasCollector::isStaticMember);
|
||||
defineStaticMethods(context, staticMembers, cls, global, expressions, isModule);
|
||||
defineStaticProperties(context, staticMembers, cls, global, expressions);
|
||||
|
||||
var simpleName = className.substring(className.lastIndexOf('.') + 1);
|
||||
var javaClassName = context.strings().getStringConstant(simpleName);
|
||||
@ -233,6 +250,7 @@ class WasmGCJsoCommonGenerator {
|
||||
WasmExpression constructor;
|
||||
if (members.constructor != null) {
|
||||
var function = context.functions().forStaticMethod(members.constructor);
|
||||
function.setReferenced(true);
|
||||
constructor = new WasmFunctionReference(function);
|
||||
needsExport = true;
|
||||
} else {
|
||||
@ -240,10 +258,14 @@ class WasmGCJsoCommonGenerator {
|
||||
}
|
||||
var createClass = new WasmCall(createClassFunction(context), jsClassName, jsExportedParent, constructor);
|
||||
expressions.add(0, new WasmSetGlobal(global, createClass));
|
||||
var globalForStatic = global;
|
||||
if (needsExport) {
|
||||
exportClass(context, cls, global, expressions);
|
||||
globalForStatic = exportClass(context, cls, global, expressions);
|
||||
}
|
||||
|
||||
defineStaticMethods(context, staticMembers, cls, globalForStatic, expressions, isModule);
|
||||
defineStaticProperties(context, staticMembers, cls, globalForStatic, expressions);
|
||||
|
||||
context.addToInitializer(f -> f.getBody().addAll(expressions));
|
||||
return global;
|
||||
}
|
||||
@ -340,7 +362,7 @@ class WasmGCJsoCommonGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
private void exportClass(WasmGCJsoContext context, ClassReader cls, WasmGlobal global,
|
||||
private WasmGlobal exportClass(WasmGCJsoContext context, ClassReader cls, WasmGlobal global,
|
||||
List<WasmExpression> expressions) {
|
||||
var exportName = getClassAliasName(cls);
|
||||
var globalName = context.names().topLevel("teavm.js.export.class@" + exportName);
|
||||
@ -351,6 +373,8 @@ class WasmGCJsoCommonGenerator {
|
||||
|
||||
var exported = new WasmCall(exportClassFunction(context), new WasmGetGlobal(global));
|
||||
expressions.add(new WasmSetGlobal(exportGlobal, exported));
|
||||
|
||||
return exportGlobal;
|
||||
}
|
||||
|
||||
private String parentExportedClass(WasmGCJsoContext context, String className) {
|
||||
@ -453,6 +477,18 @@ class WasmGCJsoCommonGenerator {
|
||||
return exportClassFunction;
|
||||
}
|
||||
|
||||
WasmFunction javaObjectToJSFunction(WasmGCJsoContext context) {
|
||||
if (javaObjectToJSFunction == null) {
|
||||
javaObjectToJSFunction = new WasmFunction(context.functionTypes().of(WasmType.Reference.EXTERN,
|
||||
context.typeMapper().mapType(ValueType.parse(Object.class)), WasmType.Reference.EXTERN));
|
||||
javaObjectToJSFunction.setName(context.names().topLevel("teavm.jso@javaObjectToJS"));
|
||||
javaObjectToJSFunction.setImportName("javaObjectToJS");
|
||||
javaObjectToJSFunction.setImportModule("teavmJso");
|
||||
context.module().functions.add(javaObjectToJSFunction);
|
||||
}
|
||||
return javaObjectToJSFunction;
|
||||
}
|
||||
|
||||
private String getClassAliasName(ClassReader cls) {
|
||||
var name = cls.getSimpleName();
|
||||
if (name == null) {
|
||||
|
@ -19,7 +19,6 @@ import org.teavm.backend.wasm.generators.gc.WasmGCCustomGenerator;
|
||||
import org.teavm.backend.wasm.generators.gc.WasmGCCustomGeneratorContext;
|
||||
import org.teavm.backend.wasm.model.WasmFunction;
|
||||
import org.teavm.backend.wasm.model.WasmLocal;
|
||||
import org.teavm.backend.wasm.model.WasmType;
|
||||
import org.teavm.backend.wasm.model.expression.WasmCall;
|
||||
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
||||
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
||||
@ -28,7 +27,6 @@ import org.teavm.model.ValueType;
|
||||
|
||||
class WasmGCMarshallMethodGenerator implements WasmGCCustomGenerator {
|
||||
private WasmGCJsoCommonGenerator commonGen;
|
||||
private WasmFunction javaObjectToJSFunction;
|
||||
|
||||
WasmGCMarshallMethodGenerator(WasmGCJsoCommonGenerator commonGen) {
|
||||
this.commonGen = commonGen;
|
||||
@ -42,21 +40,8 @@ class WasmGCMarshallMethodGenerator implements WasmGCCustomGenerator {
|
||||
function.add(thisLocal);
|
||||
|
||||
var jsClassGlobal = commonGen.getDefinedClass(jsoContext, method.getClassName());
|
||||
var wrapperFunction = javaObjectToJSFunction(context);
|
||||
var wrapperFunction = commonGen.javaObjectToJSFunction(jsoContext);
|
||||
function.getBody().add(new WasmCall(wrapperFunction, new WasmGetLocal(thisLocal),
|
||||
new WasmGetGlobal(jsClassGlobal)));
|
||||
}
|
||||
|
||||
private WasmFunction javaObjectToJSFunction(WasmGCCustomGeneratorContext context) {
|
||||
if (javaObjectToJSFunction == null) {
|
||||
javaObjectToJSFunction = new WasmFunction(context.functionTypes().of(WasmType.Reference.EXTERN,
|
||||
context.typeMapper().mapType(ValueType.parse(Object.class)), WasmType.Reference.EXTERN));
|
||||
javaObjectToJSFunction.setName(context.names().topLevel("teavm.jso@javaObjectToJS"));
|
||||
javaObjectToJSFunction.setImportName("javaObjectToJS");
|
||||
javaObjectToJSFunction.setImportModule("teavmJso");
|
||||
context.module().functions.add(javaObjectToJSFunction);
|
||||
}
|
||||
return javaObjectToJSFunction;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -112,14 +112,18 @@ public class ExportTest {
|
||||
|
||||
@Test
|
||||
public void varargs() {
|
||||
testExport("varargs", ModuleWithVararg.class);
|
||||
testExport("varargs", ModuleWithVararg.class, true);
|
||||
}
|
||||
|
||||
private void testExport(String name, Class<?> moduleClass) {
|
||||
testExport(name, moduleClass, false);
|
||||
}
|
||||
|
||||
private void testExport(String name, Class<?> moduleClass, boolean skipWasmGC) {
|
||||
if (jsNeeded) {
|
||||
testExportJs(name, moduleClass);
|
||||
}
|
||||
if (wasmGCNeeded) {
|
||||
if (wasmGCNeeded && !skipWasmGC) {
|
||||
testExportWasmGC(name, moduleClass);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user