Skip to content

Commit

Permalink
wasm gc: basic support for functors in JSO
Browse files Browse the repository at this point in the history
  • Loading branch information
konsoletyper committed Oct 1, 2024
1 parent 383fee6 commit 4b76396
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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 = "";
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions jso/impl/src/main/java/org/teavm/jso/impl/JS.java
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,7 @@ public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JS

@GeneratedBy(JSNativeGenerator.class)
@PluggableDependency(JSNativeInjector.class)
@Import(name = "functionAsObject", module = "teavmJso")
public static native JSObject functionAsObject(JSObject instance, JSObject property);

@InjectedBy(JSNativeInjector.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public void transformClass(ClassHolder cls, ClassHolderTransformerContext contex
processor.setClassFilter(classFilter);
}
processor.processClass(cls);
if (typeHelper.isJavaScriptClass(cls.getName())) {
if (isJavaScriptClass(cls)) {
processor.processMemberMethods(cls);
}

Expand Down Expand Up @@ -122,17 +122,17 @@ public void transformClass(ClassHolder cls, ClassHolderTransformerContext contex
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);
}
}
Expand Down Expand Up @@ -387,6 +387,21 @@ private boolean isJavaScriptClass(ClassReader cls) {
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()) {
Expand Down
5 changes: 4 additions & 1 deletion tests/src/test/java/org/teavm/jso/test/FunctorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@
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
Expand All @@ -45,6 +46,7 @@ public void functorParamsMarshaled() {
}

@Test
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
public void functorIdentityPreserved() {
JSBiFunction javaFunction = (a, b) -> a + b;
JSObject firstRef = getFunction(javaFunction);
Expand Down Expand Up @@ -89,6 +91,7 @@ public void functorParamsMarshaledBack() {
}

@Test
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
public void castToFunctor() {
JSBiFunction f = getBiFunctionAsObject().cast();
assertEquals(23042, f.foo(23, 42));
Expand Down

0 comments on commit 4b76396

Please sign in to comment.