mirror of
https://github.com/konsoletyper/teavm.git
synced 2024-11-27 01:30:35 +08:00
wasm gc: basic support for functors in JSO
This commit is contained in:
parent
383fee67c5
commit
4b76396332
@ -22,6 +22,7 @@ TeaVM.wasm = function() {
|
||||
}
|
||||
let javaObjectSymbol = Symbol("javaObject");
|
||||
let functionsSymbol = Symbol("functions");
|
||||
let functionOriginSymbol = Symbol("functionOrigin");
|
||||
let javaWrappers = new WeakMap();
|
||||
function defaults(imports) {
|
||||
let stderr = "";
|
||||
@ -135,7 +136,7 @@ TeaVM.wasm = function() {
|
||||
this[functionsSymbol] = null;
|
||||
};`
|
||||
);
|
||||
return fn(javaObjectSymbol, functionsSymbol);
|
||||
return fn(javaObjectSymbol, functionsSymbol, functionOriginSymbol);
|
||||
},
|
||||
defineMethod(cls, name, fn) {
|
||||
cls.prototype[name] = function(...args) {
|
||||
@ -181,9 +182,20 @@ TeaVM.wasm = function() {
|
||||
result = function() {
|
||||
return instance[propertyName].apply(instance, arguments);
|
||||
}
|
||||
result[functionOriginSymbol] = instance;
|
||||
functions[propertyName] = result;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
functionAsObject(fn, property) {
|
||||
let origin = fn[functionOriginSymbol];
|
||||
if (typeof origin !== 'undefined') {
|
||||
let functions = origin[functionsSymbol];
|
||||
if (functions !== void 0 && functions[property] === fn) {
|
||||
return origin;
|
||||
}
|
||||
}
|
||||
return { [property]: fn };
|
||||
}
|
||||
};
|
||||
for (let name of ["wrapByte", "wrapShort", "wrapChar", "wrapInt", "wrapFloat", "wrapDouble", "unwrapByte",
|
||||
|
@ -743,6 +743,7 @@ public final class JS {
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "functionAsObject", module = "teavmJso")
|
||||
public static native JSObject functionAsObject(JSObject instance, JSObject property);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
|
@ -87,7 +87,7 @@ class JSObjectClassTransformer implements ClassHolderTransformer {
|
||||
processor.setClassFilter(classFilter);
|
||||
}
|
||||
processor.processClass(cls);
|
||||
if (typeHelper.isJavaScriptClass(cls.getName())) {
|
||||
if (isJavaScriptClass(cls)) {
|
||||
processor.processMemberMethods(cls);
|
||||
}
|
||||
|
||||
@ -122,17 +122,17 @@ class JSObjectClassTransformer implements ClassHolderTransformer {
|
||||
exposeMethods(cls, exposedClass, context.getDiagnostics(), functorMethod);
|
||||
exportStaticMethods(cls, context.getDiagnostics());
|
||||
|
||||
if (typeHelper.isJavaScriptImplementation(cls.getName()) || !exposedClass.methods.isEmpty()) {
|
||||
if (isJavaScriptImplementation(cls) || !exposedClass.methods.isEmpty()) {
|
||||
cls.getAnnotations().add(new AnnotationHolder(JSClassToExpose.class.getName()));
|
||||
}
|
||||
|
||||
if (wasmGC && (!exposedClass.methods.isEmpty() || typeHelper.isJavaScriptClass(cls.getName()))) {
|
||||
if (wasmGC && (!exposedClass.methods.isEmpty() || isJavaScriptClass(cls))) {
|
||||
var createWrapperMethod = new MethodHolder(JSMethods.MARSHALL_TO_JS);
|
||||
createWrapperMethod.setLevel(AccessLevel.PUBLIC);
|
||||
createWrapperMethod.getModifiers().add(ElementModifier.NATIVE);
|
||||
cls.addMethod(createWrapperMethod);
|
||||
|
||||
if (typeHelper.isJavaScriptImplementation(cls.getName())) {
|
||||
if (isJavaScriptImplementation(cls)) {
|
||||
cls.getInterfaces().add(JSMethods.JS_MARSHALLABLE);
|
||||
}
|
||||
}
|
||||
@ -387,6 +387,21 @@ class JSObjectClassTransformer implements ClassHolderTransformer {
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isJavaScriptImplementation(ClassReader cls) {
|
||||
if (typeHelper.isJavaScriptImplementation(cls.getName())) {
|
||||
return true;
|
||||
}
|
||||
if (cls.getAnnotations().get(JSClass.class.getName()) != null) {
|
||||
return false;
|
||||
}
|
||||
if (cls.getParent() != null) {
|
||||
if (typeHelper.isJavaScriptClass(cls.getParent())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return cls.getInterfaces().stream().anyMatch(typeHelper::isJavaScriptClass);
|
||||
}
|
||||
|
||||
private boolean addInterfaces(ExposedClass exposedCls, ClassReader cls) {
|
||||
boolean added = false;
|
||||
for (String ifaceName : cls.getInterfaces()) {
|
||||
|
@ -26,12 +26,13 @@ import org.teavm.jso.JSProperty;
|
||||
import org.teavm.junit.EachTestCompiledSeparately;
|
||||
import org.teavm.junit.OnlyPlatform;
|
||||
import org.teavm.junit.SkipJVM;
|
||||
import org.teavm.junit.SkipPlatform;
|
||||
import org.teavm.junit.TeaVMTestRunner;
|
||||
import org.teavm.junit.TestPlatform;
|
||||
|
||||
@RunWith(TeaVMTestRunner.class)
|
||||
@SkipJVM
|
||||
@OnlyPlatform(TestPlatform.JAVASCRIPT)
|
||||
@OnlyPlatform({TestPlatform.JAVASCRIPT, TestPlatform.WEBASSEMBLY_GC})
|
||||
@EachTestCompiledSeparately
|
||||
public class FunctorTest {
|
||||
@Test
|
||||
@ -45,6 +46,7 @@ public class FunctorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||
public void functorIdentityPreserved() {
|
||||
JSBiFunction javaFunction = (a, b) -> a + b;
|
||||
JSObject firstRef = getFunction(javaFunction);
|
||||
@ -89,6 +91,7 @@ public class FunctorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||
public void castToFunctor() {
|
||||
JSBiFunction f = getBiFunctionAsObject().cast();
|
||||
assertEquals(23042, f.foo(23, 42));
|
||||
|
Loading…
Reference in New Issue
Block a user