mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -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 javaObjectSymbol = Symbol("javaObject");
|
||||||
let functionsSymbol = Symbol("functions");
|
let functionsSymbol = Symbol("functions");
|
||||||
|
let functionOriginSymbol = Symbol("functionOrigin");
|
||||||
let javaWrappers = new WeakMap();
|
let javaWrappers = new WeakMap();
|
||||||
function defaults(imports) {
|
function defaults(imports) {
|
||||||
let stderr = "";
|
let stderr = "";
|
||||||
|
@ -135,7 +136,7 @@ TeaVM.wasm = function() {
|
||||||
this[functionsSymbol] = null;
|
this[functionsSymbol] = null;
|
||||||
};`
|
};`
|
||||||
);
|
);
|
||||||
return fn(javaObjectSymbol, functionsSymbol);
|
return fn(javaObjectSymbol, functionsSymbol, functionOriginSymbol);
|
||||||
},
|
},
|
||||||
defineMethod(cls, name, fn) {
|
defineMethod(cls, name, fn) {
|
||||||
cls.prototype[name] = function(...args) {
|
cls.prototype[name] = function(...args) {
|
||||||
|
@ -181,9 +182,20 @@ TeaVM.wasm = function() {
|
||||||
result = function() {
|
result = function() {
|
||||||
return instance[propertyName].apply(instance, arguments);
|
return instance[propertyName].apply(instance, arguments);
|
||||||
}
|
}
|
||||||
|
result[functionOriginSymbol] = instance;
|
||||||
functions[propertyName] = result;
|
functions[propertyName] = result;
|
||||||
}
|
}
|
||||||
return 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",
|
for (let name of ["wrapByte", "wrapShort", "wrapChar", "wrapInt", "wrapFloat", "wrapDouble", "unwrapByte",
|
||||||
|
|
|
@ -743,6 +743,7 @@ public final class JS {
|
||||||
|
|
||||||
@GeneratedBy(JSNativeGenerator.class)
|
@GeneratedBy(JSNativeGenerator.class)
|
||||||
@PluggableDependency(JSNativeInjector.class)
|
@PluggableDependency(JSNativeInjector.class)
|
||||||
|
@Import(name = "functionAsObject", module = "teavmJso")
|
||||||
public static native JSObject functionAsObject(JSObject instance, JSObject property);
|
public static native JSObject functionAsObject(JSObject instance, JSObject property);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
|
|
|
@ -87,7 +87,7 @@ class JSObjectClassTransformer implements ClassHolderTransformer {
|
||||||
processor.setClassFilter(classFilter);
|
processor.setClassFilter(classFilter);
|
||||||
}
|
}
|
||||||
processor.processClass(cls);
|
processor.processClass(cls);
|
||||||
if (typeHelper.isJavaScriptClass(cls.getName())) {
|
if (isJavaScriptClass(cls)) {
|
||||||
processor.processMemberMethods(cls);
|
processor.processMemberMethods(cls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,17 +122,17 @@ class JSObjectClassTransformer implements ClassHolderTransformer {
|
||||||
exposeMethods(cls, exposedClass, context.getDiagnostics(), functorMethod);
|
exposeMethods(cls, exposedClass, context.getDiagnostics(), functorMethod);
|
||||||
exportStaticMethods(cls, context.getDiagnostics());
|
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()));
|
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);
|
var createWrapperMethod = new MethodHolder(JSMethods.MARSHALL_TO_JS);
|
||||||
createWrapperMethod.setLevel(AccessLevel.PUBLIC);
|
createWrapperMethod.setLevel(AccessLevel.PUBLIC);
|
||||||
createWrapperMethod.getModifiers().add(ElementModifier.NATIVE);
|
createWrapperMethod.getModifiers().add(ElementModifier.NATIVE);
|
||||||
cls.addMethod(createWrapperMethod);
|
cls.addMethod(createWrapperMethod);
|
||||||
|
|
||||||
if (typeHelper.isJavaScriptImplementation(cls.getName())) {
|
if (isJavaScriptImplementation(cls)) {
|
||||||
cls.getInterfaces().add(JSMethods.JS_MARSHALLABLE);
|
cls.getInterfaces().add(JSMethods.JS_MARSHALLABLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -387,6 +387,21 @@ class JSObjectClassTransformer implements ClassHolderTransformer {
|
||||||
return false;
|
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) {
|
private boolean addInterfaces(ExposedClass exposedCls, ClassReader cls) {
|
||||||
boolean added = false;
|
boolean added = false;
|
||||||
for (String ifaceName : cls.getInterfaces()) {
|
for (String ifaceName : cls.getInterfaces()) {
|
||||||
|
|
|
@ -26,12 +26,13 @@ import org.teavm.jso.JSProperty;
|
||||||
import org.teavm.junit.EachTestCompiledSeparately;
|
import org.teavm.junit.EachTestCompiledSeparately;
|
||||||
import org.teavm.junit.OnlyPlatform;
|
import org.teavm.junit.OnlyPlatform;
|
||||||
import org.teavm.junit.SkipJVM;
|
import org.teavm.junit.SkipJVM;
|
||||||
|
import org.teavm.junit.SkipPlatform;
|
||||||
import org.teavm.junit.TeaVMTestRunner;
|
import org.teavm.junit.TeaVMTestRunner;
|
||||||
import org.teavm.junit.TestPlatform;
|
import org.teavm.junit.TestPlatform;
|
||||||
|
|
||||||
@RunWith(TeaVMTestRunner.class)
|
@RunWith(TeaVMTestRunner.class)
|
||||||
@SkipJVM
|
@SkipJVM
|
||||||
@OnlyPlatform(TestPlatform.JAVASCRIPT)
|
@OnlyPlatform({TestPlatform.JAVASCRIPT, TestPlatform.WEBASSEMBLY_GC})
|
||||||
@EachTestCompiledSeparately
|
@EachTestCompiledSeparately
|
||||||
public class FunctorTest {
|
public class FunctorTest {
|
||||||
@Test
|
@Test
|
||||||
|
@ -45,6 +46,7 @@ public class FunctorTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||||
public void functorIdentityPreserved() {
|
public void functorIdentityPreserved() {
|
||||||
JSBiFunction javaFunction = (a, b) -> a + b;
|
JSBiFunction javaFunction = (a, b) -> a + b;
|
||||||
JSObject firstRef = getFunction(javaFunction);
|
JSObject firstRef = getFunction(javaFunction);
|
||||||
|
@ -89,6 +91,7 @@ public class FunctorTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||||
public void castToFunctor() {
|
public void castToFunctor() {
|
||||||
JSBiFunction f = getBiFunctionAsObject().cast();
|
JSBiFunction f = getBiFunctionAsObject().cast();
|
||||||
assertEquals(23042, f.foo(23, 42));
|
assertEquals(23042, f.foo(23, 42));
|
||||||
|
|
Loading…
Reference in New Issue
Block a user