mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 00:04:10 -08:00
wasm gc: implement simple features from JSO
This commit is contained in:
parent
33f4537f43
commit
bbf45760b8
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package org.teavm.backend.wasm.generate.gc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
|
||||
|
@ -46,6 +47,7 @@ public class WasmGCDeclarationsGenerator {
|
|||
public final WasmFunctionTypes functionTypes;
|
||||
private final WasmGCClassGenerator classGenerator;
|
||||
private final WasmGCMethodGenerator methodGenerator;
|
||||
private List<WasmGCInitializerContributor> initializerContributors = new ArrayList<>();
|
||||
|
||||
public WasmGCDeclarationsGenerator(
|
||||
WasmModule module,
|
||||
|
@ -77,7 +79,8 @@ public class WasmGCDeclarationsGenerator {
|
|||
diagnostics,
|
||||
customGenerators,
|
||||
intrinsics,
|
||||
strict
|
||||
strict,
|
||||
initializerContributors::add
|
||||
);
|
||||
var tags = new TagRegistry(classes, hierarchy);
|
||||
var metadataRequirements = new ClassMetadataRequirements(dependencyInfo);
|
||||
|
@ -132,7 +135,8 @@ public class WasmGCDeclarationsGenerator {
|
|||
}
|
||||
|
||||
public void contributeToInitializer(WasmFunction function) {
|
||||
var contributors = List.of(classGenerator, classGenerator.strings);
|
||||
var contributors = new ArrayList<>(List.of(classGenerator, classGenerator.strings));
|
||||
contributors.addAll(initializerContributors);
|
||||
for (var contributor : contributors) {
|
||||
contributor.contributeToInitializerDefinitions(function);
|
||||
}
|
||||
|
|
|
@ -21,10 +21,12 @@ import java.util.LinkedHashSet;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
|
||||
import org.teavm.backend.wasm.WasmFunctionTypes;
|
||||
import org.teavm.backend.wasm.gc.vtable.WasmGCVirtualTableProvider;
|
||||
import org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationContext;
|
||||
import org.teavm.backend.wasm.generate.gc.WasmGCInitializerContributor;
|
||||
import org.teavm.backend.wasm.generate.gc.WasmGCNameProvider;
|
||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
|
||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCStandardClasses;
|
||||
|
@ -63,6 +65,7 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
|
|||
private Map<String, Set<String>> interfaceImplementors;
|
||||
private WasmGCNameProvider names;
|
||||
private boolean strict;
|
||||
private Consumer<WasmGCInitializerContributor> initializerContributors;
|
||||
|
||||
public WasmGCGenerationContext(WasmModule module, WasmGCVirtualTableProvider virtualTables,
|
||||
WasmGCTypeMapper typeMapper, WasmFunctionTypes functionTypes, ListableClassReaderSource classes,
|
||||
|
@ -70,7 +73,7 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
|
|||
WasmGCSupertypeFunctionProvider supertypeFunctions, WasmGCClassInfoProvider classInfoProvider,
|
||||
WasmGCStandardClasses standardClasses, WasmGCStringProvider strings,
|
||||
WasmGCCustomGeneratorProvider customGenerators, WasmGCIntrinsicProvider intrinsics,
|
||||
WasmGCNameProvider names, boolean strict) {
|
||||
WasmGCNameProvider names, boolean strict, Consumer<WasmGCInitializerContributor> initializerContributors) {
|
||||
this.module = module;
|
||||
this.virtualTables = virtualTables;
|
||||
this.typeMapper = typeMapper;
|
||||
|
@ -87,6 +90,7 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
|
|||
this.intrinsics = intrinsics;
|
||||
this.names = names;
|
||||
this.strict = strict;
|
||||
this.initializerContributors = initializerContributors;
|
||||
}
|
||||
|
||||
public WasmGCClassInfoProvider classInfoProvider() {
|
||||
|
@ -222,4 +226,17 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addToInitializer(Consumer<WasmFunction> initializer) {
|
||||
initializerContributors.accept(new WasmGCInitializerContributor() {
|
||||
@Override
|
||||
public void contributeToInitializerDefinitions(WasmFunction function) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contributeToInitializer(WasmFunction function) {
|
||||
initializer.accept(function);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ package org.teavm.backend.wasm.generate.gc.methods;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import org.teavm.ast.ArrayFromDataExpr;
|
||||
import org.teavm.ast.ArrayType;
|
||||
|
@ -816,5 +817,10 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
|||
public WasmTag exceptionTag() {
|
||||
return context.getExceptionTag();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToInitializer(Consumer<WasmFunction> initializerContributor) {
|
||||
context.addToInitializer(initializerContributor);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.util.Map;
|
|||
import java.util.Objects;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import org.teavm.ast.RegularMethodNode;
|
||||
import org.teavm.ast.decompilation.Decompiler;
|
||||
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
|
||||
|
@ -32,6 +33,7 @@ import org.teavm.backend.wasm.gc.PreciseTypeInference;
|
|||
import org.teavm.backend.wasm.gc.PreciseValueType;
|
||||
import org.teavm.backend.wasm.gc.WasmGCVariableCategoryProvider;
|
||||
import org.teavm.backend.wasm.gc.vtable.WasmGCVirtualTableProvider;
|
||||
import org.teavm.backend.wasm.generate.gc.WasmGCInitializerContributor;
|
||||
import org.teavm.backend.wasm.generate.gc.WasmGCNameProvider;
|
||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
|
||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCStandardClasses;
|
||||
|
@ -86,6 +88,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
|||
private WasmGCStandardClasses standardClasses;
|
||||
private WasmGCStringProvider strings;
|
||||
private boolean strict;
|
||||
private Consumer<WasmGCInitializerContributor> initializerContributors;
|
||||
|
||||
public WasmGCMethodGenerator(
|
||||
WasmModule module,
|
||||
|
@ -99,7 +102,8 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
|||
Diagnostics diagnostics,
|
||||
WasmGCCustomGeneratorProvider customGenerators,
|
||||
WasmGCIntrinsicProvider intrinsics,
|
||||
boolean strict
|
||||
boolean strict,
|
||||
Consumer<WasmGCInitializerContributor> initializerContributors
|
||||
) {
|
||||
this.module = module;
|
||||
this.hierarchy = hierarchy;
|
||||
|
@ -113,6 +117,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
|||
this.customGenerators = customGenerators;
|
||||
this.intrinsics = intrinsics;
|
||||
this.strict = strict;
|
||||
this.initializerContributors = initializerContributors;
|
||||
}
|
||||
|
||||
public void setTypeMapper(WasmGCTypeMapper typeMapper) {
|
||||
|
@ -356,7 +361,8 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
|||
customGenerators,
|
||||
intrinsics,
|
||||
names,
|
||||
strict
|
||||
strict,
|
||||
initializerContributors
|
||||
);
|
||||
}
|
||||
return context;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package org.teavm.backend.wasm.intrinsics.gc;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import org.teavm.ast.Expr;
|
||||
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
|
||||
import org.teavm.backend.wasm.WasmFunctionTypes;
|
||||
|
@ -25,6 +26,7 @@ import org.teavm.backend.wasm.generate.gc.WasmGCNameProvider;
|
|||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
|
||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCTypeMapper;
|
||||
import org.teavm.backend.wasm.generate.gc.strings.WasmGCStringProvider;
|
||||
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;
|
||||
|
@ -58,4 +60,6 @@ public interface WasmGCIntrinsicContext {
|
|||
ClassLoader classLoader();
|
||||
|
||||
WasmTag exceptionTag();
|
||||
|
||||
void addToInitializer(Consumer<WasmFunction> initializerContributor);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
var TeaVM = TeaVM || {};
|
||||
TeaVM.wasm = function() {
|
||||
let exports;
|
||||
let getGlobalName = function(name) {
|
||||
return eval("return " + {name});
|
||||
}
|
||||
function defaults(imports) {
|
||||
let stderr = "";
|
||||
let stdout = "";
|
||||
|
@ -92,18 +95,51 @@ TeaVM.wasm = function() {
|
|||
}
|
||||
return weakRef;
|
||||
},
|
||||
deref(weakRef) {
|
||||
return weakRef.deref();
|
||||
},
|
||||
deref: weakRef => weakRef.deref(),
|
||||
createStringWeakRef(value, heldValue) {
|
||||
let weakRef = new WeakRef(value);
|
||||
stringFinalizationRegistry.register(value, heldValue)
|
||||
return weakRef;
|
||||
},
|
||||
stringDeref(weakRef) {
|
||||
return weakRef.deref();
|
||||
}
|
||||
stringDeref: weakRef => weakRef.deref()
|
||||
};
|
||||
function identity(value) {
|
||||
return value;
|
||||
}
|
||||
imports.teavmJso = {
|
||||
emptyString: () => "",
|
||||
stringFromCharCode: code => String.fromCharCode(code),
|
||||
concatStrings: (a, b) => a + b,
|
||||
stringLength: s => s.length,
|
||||
charAt: (s, index) => s.charCodeAt(index),
|
||||
emptyArray: () => [],
|
||||
appendToArray: (array, e) => array.push(e),
|
||||
unwrapBoolean: value => value ? 1 : 0,
|
||||
wrapBoolean: value => !!value,
|
||||
getProperty: (obj, prop) => obj[prop],
|
||||
getPropertyPure: (obj, prop) => obj[prop],
|
||||
setProperty: (obj, prop, value) => obj[prop] = value,
|
||||
setPropertyPure: (obj, prop) => obj[prop] = value,
|
||||
global: getGlobalName
|
||||
};
|
||||
for (let name of ["wrapByte", "wrapShort", "wrapChar", "wrapInt", "wrapFloat", "wrapDouble", "unwrapByte",
|
||||
"unwrapShort", "unwrapChar", "unwrapInt", "unwrapFloat", "unwrapDouble"]) {
|
||||
imports.teavmJso[name] = identity;
|
||||
}
|
||||
for (let i = 0; i < 32; ++i) {
|
||||
imports.teavmJso["createFunction" + i] = function() {
|
||||
return new Function(...arguments);
|
||||
};
|
||||
imports.teavmJso["callFunction" + i] = function(fn, ...args) {
|
||||
return fn(...args);
|
||||
};
|
||||
imports.teavmJso["callMethod" + i] = function(instance, method, ...args) {
|
||||
return instance[method](...args);
|
||||
};
|
||||
imports.teavmJso["construct" + i] = function(constructor, ...args) {
|
||||
return new constructor(...args);
|
||||
};
|
||||
}
|
||||
imports.teavmMath = Math;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import java.lang.reflect.Array;
|
|||
import org.teavm.backend.javascript.spi.GeneratedBy;
|
||||
import org.teavm.backend.javascript.spi.InjectedBy;
|
||||
import org.teavm.dependency.PluggableDependency;
|
||||
import org.teavm.interop.Import;
|
||||
import org.teavm.interop.NoSideEffects;
|
||||
import org.teavm.jso.JSBody;
|
||||
import org.teavm.jso.JSObject;
|
||||
|
@ -28,7 +29,7 @@ import org.teavm.jso.core.JSBoolean;
|
|||
import org.teavm.jso.core.JSNumber;
|
||||
import org.teavm.jso.core.JSString;
|
||||
|
||||
final class JS {
|
||||
public final class JS {
|
||||
private JS() {
|
||||
}
|
||||
|
||||
|
@ -77,30 +78,37 @@ final class JS {
|
|||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@NoSideEffects
|
||||
@Import(name = "wrapByte", module = "teavmJso")
|
||||
public static native JSObject wrap(byte value);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@NoSideEffects
|
||||
@Import(name = "wrapShort", module = "teavmJso")
|
||||
public static native JSObject wrap(short value);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@NoSideEffects
|
||||
@Import(name = "wrapInt", module = "teavmJso")
|
||||
public static native JSObject wrap(int value);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@NoSideEffects
|
||||
@Import(name = "wrapChar", module = "teavmJso")
|
||||
public static native JSObject wrap(char value);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@NoSideEffects
|
||||
@Import(name = "wrapFloat", module = "teavmJso")
|
||||
public static native JSObject wrap(float value);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@NoSideEffects
|
||||
@Import(name = "wrapDouble", module = "teavmJso")
|
||||
public static native JSObject wrap(double value);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@NoSideEffects
|
||||
@Import(name = "wrapBoolean", module = "teavmJso")
|
||||
public static native JSObject wrap(boolean value);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
|
@ -109,30 +117,37 @@ final class JS {
|
|||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@NoSideEffects
|
||||
@Import(name = "unwrapByte", module = "teavmJso")
|
||||
public static native byte unwrapByte(JSObject value);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@NoSideEffects
|
||||
@Import(name = "unwrapChar", module = "teavmJso")
|
||||
public static native char unwrapCharacter(JSObject value);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@NoSideEffects
|
||||
@Import(name = "unwrapShort", module = "teavmJso")
|
||||
public static native short unwrapShort(JSObject value);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@NoSideEffects
|
||||
@Import(name = "unwrapInt", module = "teavmJso")
|
||||
public static native int unwrapInt(JSObject value);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@NoSideEffects
|
||||
@Import(name = "unwrapFloat", module = "teavmJso")
|
||||
public static native float unwrapFloat(JSObject value);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@NoSideEffects
|
||||
@Import(name = "unwrapDouble", module = "teavmJso")
|
||||
public static native double unwrapDouble(JSObject value);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@NoSideEffects
|
||||
@Import(name = "unwrapBoolean", module = "teavmJso")
|
||||
public static native boolean unwrapBoolean(JSObject value);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
|
@ -466,68 +481,82 @@ final class JS {
|
|||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "callMethod0", module = "teavmJso")
|
||||
public static native JSObject invoke(JSObject instance, JSObject method);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "callMethod1", module = "teavmJso")
|
||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "callMethod2", module = "teavmJso")
|
||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "callMethod3", module = "teavmJso")
|
||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "callMethod4", module = "teavmJso")
|
||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
||||
JSObject d);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "callMethod5", module = "teavmJso")
|
||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
||||
JSObject d, JSObject e);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "callMethod6", module = "teavmJso")
|
||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
||||
JSObject d, JSObject e, JSObject f);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "callMethod7", module = "teavmJso")
|
||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
||||
JSObject d, JSObject e, JSObject f, JSObject g);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "callMethod8", module = "teavmJso")
|
||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
||||
JSObject d, JSObject e, JSObject f, JSObject g, JSObject h);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "callMethod9", module = "teavmJso")
|
||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
||||
JSObject d, JSObject e, JSObject f, JSObject g, JSObject h, JSObject i);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "callMethod10", module = "teavmJso")
|
||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
||||
JSObject d, JSObject e, JSObject f, JSObject g, JSObject h, JSObject i, JSObject j);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "callMethod11", module = "teavmJso")
|
||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
||||
JSObject d, JSObject e, JSObject f, JSObject g, JSObject h, JSObject i, JSObject j, JSObject k);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "callMethod12", module = "teavmJso")
|
||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
||||
JSObject d, JSObject e, JSObject f, JSObject g, JSObject h, JSObject i, JSObject j, JSObject k,
|
||||
JSObject l);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "callMethod13", module = "teavmJso")
|
||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
||||
JSObject d, JSObject e, JSObject f, JSObject g, JSObject h, JSObject i, JSObject j, JSObject k,
|
||||
JSObject l, JSObject m);
|
||||
|
@ -608,85 +637,103 @@ final class JS {
|
|||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "construct0", module = "teavmJso")
|
||||
public static native JSObject construct(JSObject cls);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "construct1", module = "teavmJso")
|
||||
public static native JSObject construct(JSObject cls, JSObject a);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "construct2", module = "teavmJso")
|
||||
public static native JSObject construct(JSObject cls, JSObject a, JSObject b);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "construct3", module = "teavmJso")
|
||||
public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "construct4", module = "teavmJso")
|
||||
public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c, JSObject d);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "construct5", module = "teavmJso")
|
||||
public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "construct6", module = "teavmJso")
|
||||
public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e,
|
||||
JSObject f);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "construct7", module = "teavmJso")
|
||||
public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e,
|
||||
JSObject f, JSObject g);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "construct8", module = "teavmJso")
|
||||
public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e,
|
||||
JSObject f, JSObject g, JSObject h);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "construct9", module = "teavmJso")
|
||||
public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e,
|
||||
JSObject f, JSObject g, JSObject h, JSObject i);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "construct10", module = "teavmJso")
|
||||
public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e,
|
||||
JSObject f, JSObject g, JSObject h, JSObject i, JSObject j);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "construct11", module = "teavmJso")
|
||||
public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e,
|
||||
JSObject f, JSObject g, JSObject h, JSObject i, JSObject j, JSObject k);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "construct12", module = "teavmJso")
|
||||
public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e,
|
||||
JSObject f, JSObject g, JSObject h, JSObject i, JSObject j, JSObject k, JSObject l);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@PluggableDependency(JSNativeInjector.class)
|
||||
@Import(name = "construct13", module = "teavmJso")
|
||||
public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e,
|
||||
JSObject f, JSObject g, JSObject h, JSObject i, JSObject j, JSObject k, JSObject l, JSObject m);
|
||||
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@JSBody(params = { "instance", "index" }, script = "return instance[index];")
|
||||
@Import(name = "getProperty", module = "teavmJso")
|
||||
public static native JSObject get(JSObject instance, JSObject index);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@JSBody(params = { "instance", "index" }, script = "return instance[index];")
|
||||
@NoSideEffects
|
||||
@Import(name = "getPropertyPure", module = "teavmJso")
|
||||
public static native JSObject getPure(JSObject instance, JSObject index);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@JSBody(params = { "instance", "index", "obj" }, script = "instance[index] = obj;")
|
||||
@Import(name = "setProperty", module = "teavmJso")
|
||||
public static native void set(JSObject instance, JSObject index, JSObject obj);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@JSBody(params = { "instance", "index", "obj" }, script = "instance[index] = obj;")
|
||||
@NoSideEffects
|
||||
@Import(name = "setPropertyPure", module = "teavmJso")
|
||||
public static native void setPure(JSObject instance, JSObject index, JSObject obj);
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
|
@ -699,6 +746,7 @@ final class JS {
|
|||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
@NoSideEffects
|
||||
@Import(name = "global", module = "teavmJso")
|
||||
public static native JSObject global(String name);
|
||||
|
||||
@InjectedBy(JSNativeInjector.class)
|
||||
|
|
|
@ -26,22 +26,39 @@ import org.teavm.backend.javascript.spi.GeneratorContext;
|
|||
import org.teavm.backend.javascript.spi.InjectorContext;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
class JSBodyAstEmitter implements JSBodyEmitter {
|
||||
public class JSBodyAstEmitter implements JSBodyEmitter {
|
||||
private boolean isStatic;
|
||||
private AstNode ast;
|
||||
private AstNode rootAst;
|
||||
private final MethodReference method;
|
||||
public final AstNode ast;
|
||||
public final AstNode rootAst;
|
||||
private String[] parameterNames;
|
||||
private JsBodyImportInfo[] imports;
|
||||
|
||||
JSBodyAstEmitter(boolean isStatic, AstNode ast, AstNode rootAst, String[] parameterNames,
|
||||
JSBodyAstEmitter(boolean isStatic, MethodReference method, AstNode ast, AstNode rootAst, String[] parameterNames,
|
||||
JsBodyImportInfo[] imports) {
|
||||
this.isStatic = isStatic;
|
||||
this.method = method;
|
||||
this.ast = ast;
|
||||
this.rootAst = rootAst;
|
||||
this.parameterNames = parameterNames;
|
||||
this.imports = imports;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodReference method() {
|
||||
return method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStatic() {
|
||||
return isStatic;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] parameterNames() {
|
||||
return parameterNames.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emit(InjectorContext context) {
|
||||
var astWriter = new AstWriter(context.getWriter(), new DefaultGlobalNameWriter());
|
||||
|
|
|
@ -20,10 +20,10 @@ import org.teavm.backend.javascript.spi.GeneratorContext;
|
|||
import org.teavm.backend.javascript.spi.InjectorContext;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
class JSBodyBloatedEmitter implements JSBodyEmitter {
|
||||
public class JSBodyBloatedEmitter implements JSBodyEmitter {
|
||||
private boolean isStatic;
|
||||
private MethodReference method;
|
||||
private String script;
|
||||
public final String script;
|
||||
private String[] parameterNames;
|
||||
private JsBodyImportInfo[] imports;
|
||||
|
||||
|
@ -36,6 +36,21 @@ class JSBodyBloatedEmitter implements JSBodyEmitter {
|
|||
this.imports = imports;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodReference method() {
|
||||
return method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStatic() {
|
||||
return isStatic;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] parameterNames() {
|
||||
return parameterNames.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emit(InjectorContext context) {
|
||||
emit(context.getWriter(), new EmissionStrategy() {
|
||||
|
|
|
@ -20,8 +20,14 @@ import org.teavm.backend.javascript.spi.GeneratorContext;
|
|||
import org.teavm.backend.javascript.spi.InjectorContext;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
interface JSBodyEmitter {
|
||||
public interface JSBodyEmitter {
|
||||
MethodReference method();
|
||||
|
||||
void emit(InjectorContext context);
|
||||
|
||||
void emit(GeneratorContext context, SourceWriter writer, MethodReference methodRef);
|
||||
|
||||
String[] parameterNames();
|
||||
|
||||
boolean isStatic();
|
||||
}
|
||||
|
|
|
@ -21,12 +21,12 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
class JSBodyRepository {
|
||||
final Map<MethodReference, JSBodyEmitter> emitters = new HashMap<>();
|
||||
final Map<MethodReference, JsBodyImportInfo[]> imports = new HashMap<>();
|
||||
final Map<MethodReference, MethodReference> methodMap = new HashMap<>();
|
||||
final Set<MethodReference> processedMethods = new HashSet<>();
|
||||
final Set<MethodReference> inlineMethods = new HashSet<>();
|
||||
final Map<MethodReference, MethodReference> callbackCallees = new HashMap<>();
|
||||
final Map<MethodReference, Set<MethodReference>> callbackMethods = new HashMap<>();
|
||||
public class JSBodyRepository {
|
||||
public final Map<MethodReference, JSBodyEmitter> emitters = new HashMap<>();
|
||||
public final Map<MethodReference, JsBodyImportInfo[]> imports = new HashMap<>();
|
||||
public final Map<MethodReference, MethodReference> methodMap = new HashMap<>();
|
||||
public final Set<MethodReference> processedMethods = new HashSet<>();
|
||||
public final Set<MethodReference> inlineMethods = new HashSet<>();
|
||||
public final Map<MethodReference, MethodReference> callbackCallees = new HashMap<>();
|
||||
public final Map<MethodReference, Set<MethodReference>> callbackMethods = new HashMap<>();
|
||||
}
|
||||
|
|
|
@ -227,7 +227,7 @@ class JSClassProcessor {
|
|||
for (int i = 0; i < signature.length; ++i) {
|
||||
staticSignature[i + 1] = signature[i];
|
||||
}
|
||||
staticSignature[0] = ValueType.object(method.getClassName());
|
||||
staticSignature[0] = ValueType.object(JSObject.class.getName());
|
||||
return staticSignature;
|
||||
}
|
||||
|
||||
|
@ -1139,7 +1139,8 @@ class JSClassProcessor {
|
|||
expr = body;
|
||||
}
|
||||
javaInvocationProcessor.process(location, expr);
|
||||
var emitter = new JSBodyAstEmitter(isStatic, expr, rootNode, parameterNames, imports);
|
||||
var emitter = new JSBodyAstEmitter(isStatic, methodToProcess.getReference(), expr, rootNode,
|
||||
parameterNames, imports);
|
||||
repository.emitters.put(proxyMethod, emitter);
|
||||
}
|
||||
if (imports.length > 0) {
|
||||
|
|
|
@ -16,8 +16,10 @@
|
|||
package org.teavm.jso.impl;
|
||||
|
||||
import org.teavm.backend.javascript.TeaVMJavaScriptHost;
|
||||
import org.teavm.backend.wasm.gc.TeaVMWasmGCHost;
|
||||
import org.teavm.jso.JSExceptions;
|
||||
import org.teavm.jso.JSObject;
|
||||
import org.teavm.jso.impl.wasmgc.WasmGCJso;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.platform.plugin.PlatformPlugin;
|
||||
import org.teavm.vm.TeaVMPluginUtil;
|
||||
|
@ -29,19 +31,36 @@ import org.teavm.vm.spi.TeaVMPlugin;
|
|||
public class JSOPlugin implements TeaVMPlugin {
|
||||
@Override
|
||||
public void install(TeaVMHost host) {
|
||||
TeaVMJavaScriptHost jsHost = host.getExtension(TeaVMJavaScriptHost.class);
|
||||
if (jsHost == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
JSBodyRepository repository = new JSBodyRepository();
|
||||
host.registerService(JSBodyRepository.class, repository);
|
||||
host.add(new JSObjectClassTransformer(repository));
|
||||
JSDependencyListener dependencyListener = new JSDependencyListener(repository);
|
||||
JSAliasRenderer aliasRenderer = new JSAliasRenderer();
|
||||
host.add(dependencyListener);
|
||||
host.add(new JSExceptionsDependencyListener());
|
||||
|
||||
var wrapperDependency = new JSWrapperDependency();
|
||||
host.add(new MethodReference(JSWrapper.class, "jsToWrapper", JSObject.class, JSWrapper.class),
|
||||
wrapperDependency);
|
||||
host.add(new MethodReference(JSWrapper.class, "dependencyJavaToJs", Object.class, JSObject.class),
|
||||
wrapperDependency);
|
||||
host.add(new MethodReference(JSWrapper.class, "dependencyJsToJava", JSObject.class, Object.class),
|
||||
wrapperDependency);
|
||||
|
||||
TeaVMPluginUtil.handleNatives(host, JS.class);
|
||||
|
||||
var jsHost = host.getExtension(TeaVMJavaScriptHost.class);
|
||||
if (jsHost != null) {
|
||||
installForJS(jsHost);
|
||||
}
|
||||
|
||||
var wasmGCHost = host.getExtension(TeaVMWasmGCHost.class);
|
||||
if (wasmGCHost != null) {
|
||||
WasmGCJso.install(host, wasmGCHost, repository);
|
||||
}
|
||||
}
|
||||
|
||||
private void installForJS(TeaVMJavaScriptHost jsHost) {
|
||||
var aliasRenderer = new JSAliasRenderer();
|
||||
jsHost.add(aliasRenderer);
|
||||
jsHost.addGeneratorProvider(new GeneratorAnnotationInstaller<>(new JSBodyGenerator(),
|
||||
DynamicGenerator.class.getName()));
|
||||
|
@ -50,7 +69,7 @@ public class JSOPlugin implements TeaVMPlugin {
|
|||
jsHost.addVirtualMethods(aliasRenderer);
|
||||
jsHost.addForcedFunctionMethods(new JSExportedMethodAsFunction());
|
||||
|
||||
JSExceptionsGenerator exceptionsGenerator = new JSExceptionsGenerator();
|
||||
var exceptionsGenerator = new JSExceptionsGenerator();
|
||||
jsHost.add(new MethodReference(JSExceptions.class, "getJavaException", JSObject.class, Throwable.class),
|
||||
exceptionsGenerator);
|
||||
jsHost.add(new MethodReference(JSExceptions.class, "getJSException", Throwable.class, JSObject.class),
|
||||
|
@ -75,14 +94,5 @@ public class JSOPlugin implements TeaVMPlugin {
|
|||
wrapperGenerator);
|
||||
jsHost.add(new MethodReference(JSWrapper.class, "isJSImplementation", Object.class, boolean.class),
|
||||
wrapperGenerator);
|
||||
|
||||
host.add(new MethodReference(JSWrapper.class, "jsToWrapper", JSObject.class, JSWrapper.class),
|
||||
wrapperGenerator);
|
||||
host.add(new MethodReference(JSWrapper.class, "dependencyJavaToJs", Object.class, JSObject.class),
|
||||
wrapperGenerator);
|
||||
host.add(new MethodReference(JSWrapper.class, "dependencyJsToJava", JSObject.class, Object.class),
|
||||
wrapperGenerator);
|
||||
|
||||
TeaVMPluginUtil.handleNatives(host, JS.class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright 2023 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;
|
||||
|
||||
import org.teavm.dependency.DependencyAgent;
|
||||
import org.teavm.dependency.DependencyNode;
|
||||
import org.teavm.dependency.DependencyPlugin;
|
||||
import org.teavm.dependency.MethodDependency;
|
||||
|
||||
public class JSWrapperDependency implements DependencyPlugin {
|
||||
private DependencyNode externalClassesNode;
|
||||
|
||||
@Override
|
||||
public void methodReached(DependencyAgent agent, MethodDependency method) {
|
||||
switch (method.getMethod().getName()) {
|
||||
case "jsToWrapper":
|
||||
method.getResult().propagate(agent.getType(JSWrapper.class.getName()));
|
||||
break;
|
||||
case "dependencyJavaToJs":
|
||||
method.getVariable(1).connect(getExternalClassesNode(agent));
|
||||
break;
|
||||
case "dependencyJsToJava":
|
||||
getExternalClassesNode(agent).connect(method.getResult());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private DependencyNode getExternalClassesNode(DependencyAgent agent) {
|
||||
if (externalClassesNode == null) {
|
||||
externalClassesNode = agent.createNode();
|
||||
}
|
||||
return externalClassesNode;
|
||||
}
|
||||
}
|
|
@ -15,11 +15,11 @@
|
|||
*/
|
||||
package org.teavm.jso.impl;
|
||||
|
||||
class JsBodyImportInfo {
|
||||
final String alias;
|
||||
final String fromModule;
|
||||
public class JsBodyImportInfo {
|
||||
public final String alias;
|
||||
public final String fromModule;
|
||||
|
||||
JsBodyImportInfo(String alias, String fromModule) {
|
||||
public JsBodyImportInfo(String alias, String fromModule) {
|
||||
this.alias = alias;
|
||||
this.fromModule = fromModule;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright 2024 Alexey Andreev.
|
||||
*
|
||||
* 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 static org.teavm.jso.impl.wasmgc.WasmGCJSConstants.STRING_TO_JS;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import org.teavm.backend.javascript.rendering.AstWriter;
|
||||
import org.teavm.backend.wasm.intrinsics.gc.WasmGCIntrinsicContext;
|
||||
import org.teavm.backend.wasm.model.WasmFunction;
|
||||
import org.teavm.backend.wasm.model.WasmGlobal;
|
||||
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.WasmNullConstant;
|
||||
import org.teavm.backend.wasm.model.expression.WasmSetGlobal;
|
||||
import org.teavm.jso.impl.JSBodyAstEmitter;
|
||||
import org.teavm.jso.impl.JSBodyBloatedEmitter;
|
||||
import org.teavm.jso.impl.JSBodyEmitter;
|
||||
|
||||
class WasmGCBodyGenerator {
|
||||
private WasmGCJSFunctions jsFunctions;
|
||||
private boolean initialized;
|
||||
private List<Consumer<WasmFunction>> initializerParts = new ArrayList<>();
|
||||
|
||||
WasmGCBodyGenerator(WasmGCJSFunctions jsFunctions) {
|
||||
this.jsFunctions = jsFunctions;
|
||||
}
|
||||
|
||||
private void initialize(WasmGCIntrinsicContext context) {
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
context.addToInitializer(this::writeToInitializer);
|
||||
}
|
||||
|
||||
|
||||
private void writeToInitializer(WasmFunction function) {
|
||||
for (var part : initializerParts) {
|
||||
part.accept(function);
|
||||
}
|
||||
}
|
||||
|
||||
WasmGlobal addBody(WasmGCIntrinsicContext context, JSBodyEmitter emitter, boolean inlined) {
|
||||
initialize(context);
|
||||
var paramCount = emitter.method().parameterCount();
|
||||
if (!emitter.isStatic()) {
|
||||
paramCount++;
|
||||
}
|
||||
var global = new WasmGlobal(context.names().suggestForMethod(emitter.method()),
|
||||
WasmType.Reference.EXTERN, new WasmNullConstant(WasmType.Reference.EXTERN));
|
||||
context.module().globals.add(global);
|
||||
var body = "";
|
||||
if (emitter instanceof JSBodyBloatedEmitter) {
|
||||
body = ((JSBodyBloatedEmitter) emitter).script;
|
||||
} else if (emitter instanceof JSBodyAstEmitter) {
|
||||
var writer = new WasmGCJSBodyWriter();
|
||||
if (inlined) {
|
||||
writer.sb.append("return ");
|
||||
}
|
||||
var astEmitter = (JSBodyAstEmitter) emitter;
|
||||
var astWriter = new AstWriter(writer, name -> (w, prec) -> w.append(name));
|
||||
if (!emitter.isStatic()) {
|
||||
astWriter.declareNameEmitter("this", (w, prec) -> w.append("__this__"));
|
||||
}
|
||||
astWriter.print(astEmitter.ast);
|
||||
if (inlined) {
|
||||
writer.sb.append(";");
|
||||
}
|
||||
body = writer.sb.toString();
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
var constructor = new WasmCall(jsFunctions.getFunctionConstructor(context,
|
||||
paramCount));
|
||||
var stringToJs = context.functions().forStaticMethod(STRING_TO_JS);
|
||||
var paramNames = new ArrayList<String>();
|
||||
if (!emitter.isStatic()) {
|
||||
paramNames.add("__this__");
|
||||
}
|
||||
paramNames.addAll(List.of(emitter.parameterNames()));
|
||||
for (var parameter : paramNames) {
|
||||
var paramName = new WasmGetGlobal(context.strings().getStringConstant(parameter).global);
|
||||
constructor.getArguments().add(new WasmCall(stringToJs, paramName));
|
||||
}
|
||||
var functionBody = new WasmGetGlobal(context.strings().getStringConstant(body).global);
|
||||
constructor.getArguments().add(new WasmCall(stringToJs, functionBody));
|
||||
initializerParts.add(initializer -> initializer.getBody().add(new WasmSetGlobal(global, constructor)));
|
||||
|
||||
return global;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright 2024 Alexey Andreev.
|
||||
*
|
||||
* 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.WasmGlobal;
|
||||
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.jso.impl.JSBodyEmitter;
|
||||
|
||||
class WasmGCBodyIntrinsic implements WasmGCIntrinsic {
|
||||
private JSBodyEmitter emitter;
|
||||
private boolean inlined;
|
||||
private WasmGCBodyGenerator bodyGenerator;
|
||||
private WasmGlobal global;
|
||||
private WasmGCJSFunctions jsFunctions;
|
||||
|
||||
WasmGCBodyIntrinsic(JSBodyEmitter emitter, boolean inlined, WasmGCBodyGenerator bodyGenerator,
|
||||
WasmGCJSFunctions jsFunctions) {
|
||||
this.emitter = emitter;
|
||||
this.inlined = inlined;
|
||||
this.bodyGenerator = bodyGenerator;
|
||||
this.jsFunctions = jsFunctions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WasmExpression apply(InvocationExpr invocation, WasmGCIntrinsicContext context) {
|
||||
if (global == null) {
|
||||
global = bodyGenerator.addBody(context, emitter, inlined);
|
||||
}
|
||||
var call = new WasmCall(jsFunctions.getFunctionCaller(context, invocation.getArguments().size()));
|
||||
call.getArguments().add(new WasmGetGlobal(global));
|
||||
for (var arg : invocation.getArguments()) {
|
||||
call.getArguments().add(context.generate(arg));
|
||||
}
|
||||
return call;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright 2024 Alexey Andreev.
|
||||
*
|
||||
* 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.backend.wasm.intrinsics.gc.WasmGCIntrinsic;
|
||||
import org.teavm.backend.wasm.intrinsics.gc.WasmGCIntrinsicFactory;
|
||||
import org.teavm.backend.wasm.intrinsics.gc.WasmGCIntrinsicFactoryContext;
|
||||
import org.teavm.jso.impl.JSBodyRepository;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
class WasmGCJSBodyRenderer implements WasmGCIntrinsicFactory {
|
||||
private JSBodyRepository repository;
|
||||
private WasmGCJSFunctions jsFunctions;
|
||||
private WasmGCBodyGenerator bodyGenerator;
|
||||
|
||||
WasmGCJSBodyRenderer(JSBodyRepository repository) {
|
||||
this.repository = repository;
|
||||
jsFunctions = new WasmGCJSFunctions();
|
||||
bodyGenerator = new WasmGCBodyGenerator(jsFunctions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WasmGCIntrinsic createIntrinsic(MethodReference methodRef, WasmGCIntrinsicFactoryContext context) {
|
||||
var emitter = repository.emitters.get(methodRef);
|
||||
if (emitter == null) {
|
||||
return null;
|
||||
}
|
||||
var inlined = repository.inlineMethods.contains(emitter.method());
|
||||
return new WasmGCBodyIntrinsic(emitter, inlined, bodyGenerator, jsFunctions);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* Copyright 2024 Alexey Andreev.
|
||||
*
|
||||
* 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.backend.javascript.codegen.SourceWriter;
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
class WasmGCJSBodyWriter extends SourceWriter {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
|
||||
@Override
|
||||
public SourceWriter append(char value) {
|
||||
sb.append(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter append(CharSequence csq, int start, int end) {
|
||||
sb.append(csq, start, end);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter appendClass(String cls) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter appendField(FieldReference field) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter appendStaticField(FieldReference field) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter appendVirtualMethod(MethodDescriptor method) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter appendMethod(MethodReference method) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter appendFunction(String name) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter startFunctionDeclaration() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter startVariableDeclaration() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter endDeclaration() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter declareVariable() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter appendGlobal(String name) {
|
||||
sb.append(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter appendInit(MethodReference method) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter appendClassInit(String className) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter newLine() {
|
||||
sb.append('\n');
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter ws() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter sameLineWs() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter tokenBoundary() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter softNewLine() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter indent() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter outdent() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter emitLocation(String fileName, int line) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter enterLocation() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter exitLocation() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter emitStatementStart() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter emitVariables(String[] names, String jsName) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitMethod(MethodDescriptor method) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitClass(String className) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markClassStart(String className) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markClassEnd() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markSectionStart(int id) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markSectionEnd() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2024 Alexey Andreev.
|
||||
*
|
||||
* 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.jso.JSObject;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
final class WasmGCJSConstants {
|
||||
private WasmGCJSConstants() {
|
||||
}
|
||||
|
||||
static final MethodReference STRING_TO_JS = new MethodReference(WasmGCJSRuntime.class,
|
||||
"stringToJs", String.class, JSObject.class);
|
||||
static final MethodReference JS_TO_STRING = new MethodReference(WasmGCJSRuntime.class,
|
||||
"jsToString", JSObject.class, String.class);
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright 2024 Alexey Andreev.
|
||||
*
|
||||
* 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 static org.teavm.jso.impl.wasmgc.WasmGCJSConstants.JS_TO_STRING;
|
||||
import static org.teavm.jso.impl.wasmgc.WasmGCJSConstants.STRING_TO_JS;
|
||||
import org.teavm.dependency.AbstractDependencyListener;
|
||||
import org.teavm.dependency.DependencyAgent;
|
||||
|
||||
class WasmGCJSDependencies extends AbstractDependencyListener {
|
||||
@Override
|
||||
public void started(DependencyAgent agent) {
|
||||
agent.linkMethod(STRING_TO_JS)
|
||||
.propagate(1, agent.getType("java.lang.String"))
|
||||
.use();
|
||||
|
||||
var jsToString = agent.linkMethod(JS_TO_STRING);
|
||||
jsToString.getResult().propagate(agent.getType("java.lang.String"));
|
||||
jsToString.use();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright 2024 Alexey Andreev.
|
||||
*
|
||||
* 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 java.util.Arrays;
|
||||
import org.teavm.backend.wasm.intrinsics.gc.WasmGCIntrinsicContext;
|
||||
import org.teavm.backend.wasm.model.WasmFunction;
|
||||
import org.teavm.backend.wasm.model.WasmType;
|
||||
|
||||
class WasmGCJSFunctions {
|
||||
private WasmFunction[] constructors = new WasmFunction[32];
|
||||
private WasmFunction[] callers = new WasmFunction[32];
|
||||
|
||||
WasmFunction getFunctionConstructor(WasmGCIntrinsicContext context, int index) {
|
||||
var function = constructors[index];
|
||||
if (function == null) {
|
||||
var extern = WasmType.SpecialReferenceKind.EXTERN.asNonNullType();
|
||||
var constructorParamTypes = new WasmType[index + 1];
|
||||
Arrays.fill(constructorParamTypes, extern);
|
||||
var functionType = context.functionTypes().of(extern, constructorParamTypes);
|
||||
function = new WasmFunction(functionType);
|
||||
function.setName(context.names().topLevel("teavm.js:createFunction" + index));
|
||||
function.setImportModule("teavmJso");
|
||||
function.setImportName("createFunction" + index);
|
||||
context.module().functions.add(function);
|
||||
constructors[index] = function;
|
||||
}
|
||||
return function;
|
||||
}
|
||||
|
||||
WasmFunction getFunctionCaller(WasmGCIntrinsicContext context, int index) {
|
||||
var function = callers[index];
|
||||
if (function == null) {
|
||||
var extern = WasmType.SpecialReferenceKind.EXTERN.asNonNullType();
|
||||
var paramTypes = new WasmType[index + 1];
|
||||
Arrays.fill(paramTypes, extern);
|
||||
paramTypes[0] = WasmType.Reference.EXTERN;
|
||||
var functionType = context.functionTypes().of(extern, paramTypes);
|
||||
function = new WasmFunction(functionType);
|
||||
function.setName(context.names().topLevel("teavm.js:callFunction" + index));
|
||||
function.setImportModule("teavmJso");
|
||||
function.setImportName("callFunction" + index);
|
||||
context.module().functions.add(function);
|
||||
callers[index] = function;
|
||||
}
|
||||
return function;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright 2024 Alexey Andreev.
|
||||
*
|
||||
* 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 static org.teavm.jso.impl.wasmgc.WasmGCJSConstants.JS_TO_STRING;
|
||||
import static org.teavm.jso.impl.wasmgc.WasmGCJSConstants.STRING_TO_JS;
|
||||
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;
|
||||
|
||||
class WasmGCJSIntrinsic implements WasmGCIntrinsic {
|
||||
@Override
|
||||
public WasmExpression apply(InvocationExpr invocation, WasmGCIntrinsicContext context) {
|
||||
switch (invocation.getMethod().getName()) {
|
||||
case "wrap": {
|
||||
var function = context.functions().forStaticMethod(STRING_TO_JS);
|
||||
return new WasmCall(function, context.generate(invocation.getArguments().get(0)));
|
||||
}
|
||||
case "unwrapString": {
|
||||
var function = context.functions().forStaticMethod(JS_TO_STRING);
|
||||
return new WasmCall(function, context.generate(invocation.getArguments().get(0)));
|
||||
}
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright 2024 Alexey Andreev.
|
||||
*
|
||||
* 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.interop.Import;
|
||||
import org.teavm.jso.JSObject;
|
||||
|
||||
final class WasmGCJSRuntime {
|
||||
private WasmGCJSRuntime() {
|
||||
}
|
||||
|
||||
static JSObject stringToJs(String str) {
|
||||
if (str.isEmpty()) {
|
||||
return emptyString();
|
||||
}
|
||||
var jsStr = stringFromCharCode(str.charAt(0));
|
||||
for (var i = 1; i < str.length(); ++i) {
|
||||
jsStr = concatStrings(jsStr, stringFromCharCode(str.charAt(i)));
|
||||
}
|
||||
return jsStr;
|
||||
}
|
||||
|
||||
static String jsToString(JSObject obj) {
|
||||
var length = stringLength(obj);
|
||||
if (length == 0) {
|
||||
return "";
|
||||
}
|
||||
var chars = new char[length];
|
||||
for (var i = 0; i < length; ++i) {
|
||||
chars[i] = charAt(obj, i);
|
||||
}
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
@Import(name = "emptyString", module = "teavmJso")
|
||||
static native JSObject emptyString();
|
||||
|
||||
@Import(name = "stringFromCharCode", module = "teavmJso")
|
||||
static native JSObject stringFromCharCode(char c);
|
||||
|
||||
@Import(name = "concatStrings", module = "teavmJso")
|
||||
static native JSObject concatStrings(JSObject a, JSObject b);
|
||||
|
||||
@Import(name = "emptyArray", module = "teavmJso")
|
||||
static native JSObject emptyArray();
|
||||
|
||||
@Import(name = "appendToArray", module = "teavmJso")
|
||||
static native JSObject appendToArray(JSObject array, JSObject element);
|
||||
|
||||
@Import(name = "stringLength", module = "teavmJso")
|
||||
static native int stringLength(JSObject str);
|
||||
|
||||
@Import(name = "charAt", module = "teavmJso")
|
||||
static native char charAt(JSObject str, int index);
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright 2024 Alexey Andreev.
|
||||
*
|
||||
* 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.backend.wasm.generate.gc.classes.WasmGCCustomTypeMapper;
|
||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCCustomTypeMapperFactory;
|
||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCCustomTypeMapperFactoryContext;
|
||||
import org.teavm.backend.wasm.model.WasmType;
|
||||
import org.teavm.jso.JSObject;
|
||||
|
||||
class WasmGCJSTypeMapper implements WasmGCCustomTypeMapper, WasmGCCustomTypeMapperFactory {
|
||||
@Override
|
||||
public WasmType map(String className) {
|
||||
if (className.equals(JSObject.class.getName())) {
|
||||
return WasmType.SpecialReferenceKind.EXTERN.asNonNullType();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WasmGCCustomTypeMapper createTypeMapper(WasmGCCustomTypeMapperFactoryContext context) {
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright 2024 Alexey Andreev.
|
||||
*
|
||||
* 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.backend.wasm.gc.TeaVMWasmGCHost;
|
||||
import org.teavm.jso.JSObject;
|
||||
import org.teavm.jso.impl.JS;
|
||||
import org.teavm.jso.impl.JSBodyRepository;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.vm.spi.TeaVMHost;
|
||||
|
||||
public final class WasmGCJso {
|
||||
private WasmGCJso() {
|
||||
}
|
||||
|
||||
public static void install(TeaVMHost host, TeaVMWasmGCHost wasmGCHost, JSBodyRepository jsBodyRepository) {
|
||||
host.add(new WasmGCJSDependencies());
|
||||
wasmGCHost.addCustomTypeMapperFactory(new WasmGCJSTypeMapper());
|
||||
wasmGCHost.addIntrinsicFactory(new WasmGCJSBodyRenderer(jsBodyRepository));
|
||||
|
||||
var jsIntrinsic = new WasmGCJSIntrinsic();
|
||||
wasmGCHost.addIntrinsic(new MethodReference(JS.class, "wrap", String.class, JSObject.class), jsIntrinsic);
|
||||
wasmGCHost.addIntrinsic(new MethodReference(JS.class, "unwrapString", JSObject.class, String.class),
|
||||
jsIntrinsic);
|
||||
}
|
||||
}
|
|
@ -30,7 +30,7 @@ import org.teavm.junit.TestPlatform;
|
|||
|
||||
@RunWith(TeaVMTestRunner.class)
|
||||
@SkipJVM
|
||||
@OnlyPlatform(TestPlatform.JAVASCRIPT)
|
||||
@OnlyPlatform({TestPlatform.JAVASCRIPT, TestPlatform.WEBASSEMBLY_GC})
|
||||
@EachTestCompiledSeparately
|
||||
public class AnnotationsTest {
|
||||
@Test
|
||||
|
|
|
@ -29,12 +29,13 @@ import org.teavm.jso.core.JSString;
|
|||
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 ConversionTest {
|
||||
@Test
|
||||
|
@ -57,6 +58,7 @@ public class ConversionTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||
public void convertsPrimitiveArraysToJavaScript() {
|
||||
assertEquals("true:2:3:64:4:5.5:6.5:foo", combinePrimitiveArrays(new boolean[] { true }, new byte[] { 2 },
|
||||
new short[] { 3 }, new char[] { '@' }, new int[] { 4 }, new float[] { 5.5F }, new double[] { 6.5 },
|
||||
|
@ -64,6 +66,7 @@ public class ConversionTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||
public void convertsPrimitiveArraysToJava() {
|
||||
PrimitiveArrays arrays = getPrimitiveArrays();
|
||||
|
||||
|
@ -81,6 +84,7 @@ public class ConversionTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||
public void convertsPrimitiveArrays2ToJavaScript() {
|
||||
assertEquals("true:2:3:64:4:5.5:6.5:foo", combinePrimitiveArrays2(new boolean[][] {{ true }},
|
||||
new byte[][] {{ 2 }}, new short[][] {{ 3 }}, new char[][] {{ '@' }}, new int[][] {{ 4 }},
|
||||
|
@ -88,6 +92,7 @@ public class ConversionTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||
public void convertsPrimitiveArrays2ToJava() {
|
||||
PrimitiveArrays2 arrays = getPrimitiveArrays2();
|
||||
|
||||
|
@ -106,6 +111,7 @@ public class ConversionTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||
public void convertsPrimitiveArrays4ToJavaScript() {
|
||||
assertEquals("true:2:3:64:4:5.5:6.5:foo", combinePrimitiveArrays4(new boolean[][][][] {{{{ true }}}},
|
||||
new byte[][][][] {{{{ 2 }}}}, new short[][][][] {{{{ 3 }}}}, new char[][][][] {{{{ '@' }}}},
|
||||
|
@ -114,6 +120,7 @@ public class ConversionTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||
public void convertsPrimitiveArrays4ToJava() {
|
||||
PrimitiveArrays4 arrays = getPrimitiveArrays4();
|
||||
|
||||
|
@ -137,6 +144,7 @@ public class ConversionTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||
public void convertsArrayOfJSObject() {
|
||||
assertEquals("(foo)", surround(new JSString[] { JSString.valueOf("foo") })[0].stringValue());
|
||||
assertEquals("(foo)", surround(new JSString[][] {{ JSString.valueOf("foo") }})[0][0].stringValue());
|
||||
|
@ -145,6 +153,7 @@ public class ConversionTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||
public void copiesArray() {
|
||||
int[] array = { 23 };
|
||||
assertEquals(24, mutate(array));
|
||||
|
@ -152,6 +161,7 @@ public class ConversionTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||
public void passesArrayByRef() {
|
||||
int[] array = { 23, 42 };
|
||||
|
||||
|
@ -165,6 +175,7 @@ public class ConversionTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||
public void returnsArrayByRef() {
|
||||
int[] first = { 23, 42 };
|
||||
int[] second = rewrap(first);
|
||||
|
|
|
@ -23,12 +23,13 @@ import org.teavm.jso.JSObject;
|
|||
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 ImplementationTest {
|
||||
@Test
|
||||
|
@ -44,6 +45,7 @@ public class ImplementationTest {
|
|||
static native int mul(int a, int b);
|
||||
|
||||
@Test
|
||||
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||
public void inliningUsageCounterWorksProperly() {
|
||||
ForInliningTest instance = ForInliningTest.create();
|
||||
wrongInlineCandidate(instance.foo());
|
||||
|
|
Loading…
Reference in New Issue
Block a user