mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -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;
|
package org.teavm.backend.wasm.generate.gc;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
|
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
|
||||||
|
@ -46,6 +47,7 @@ public class WasmGCDeclarationsGenerator {
|
||||||
public final WasmFunctionTypes functionTypes;
|
public final WasmFunctionTypes functionTypes;
|
||||||
private final WasmGCClassGenerator classGenerator;
|
private final WasmGCClassGenerator classGenerator;
|
||||||
private final WasmGCMethodGenerator methodGenerator;
|
private final WasmGCMethodGenerator methodGenerator;
|
||||||
|
private List<WasmGCInitializerContributor> initializerContributors = new ArrayList<>();
|
||||||
|
|
||||||
public WasmGCDeclarationsGenerator(
|
public WasmGCDeclarationsGenerator(
|
||||||
WasmModule module,
|
WasmModule module,
|
||||||
|
@ -77,7 +79,8 @@ public class WasmGCDeclarationsGenerator {
|
||||||
diagnostics,
|
diagnostics,
|
||||||
customGenerators,
|
customGenerators,
|
||||||
intrinsics,
|
intrinsics,
|
||||||
strict
|
strict,
|
||||||
|
initializerContributors::add
|
||||||
);
|
);
|
||||||
var tags = new TagRegistry(classes, hierarchy);
|
var tags = new TagRegistry(classes, hierarchy);
|
||||||
var metadataRequirements = new ClassMetadataRequirements(dependencyInfo);
|
var metadataRequirements = new ClassMetadataRequirements(dependencyInfo);
|
||||||
|
@ -132,7 +135,8 @@ public class WasmGCDeclarationsGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void contributeToInitializer(WasmFunction function) {
|
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) {
|
for (var contributor : contributors) {
|
||||||
contributor.contributeToInitializerDefinitions(function);
|
contributor.contributeToInitializerDefinitions(function);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,10 +21,12 @@ import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
|
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
|
||||||
import org.teavm.backend.wasm.WasmFunctionTypes;
|
import org.teavm.backend.wasm.WasmFunctionTypes;
|
||||||
import org.teavm.backend.wasm.gc.vtable.WasmGCVirtualTableProvider;
|
import org.teavm.backend.wasm.gc.vtable.WasmGCVirtualTableProvider;
|
||||||
import org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationContext;
|
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.WasmGCNameProvider;
|
||||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
|
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
|
||||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCStandardClasses;
|
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 Map<String, Set<String>> interfaceImplementors;
|
||||||
private WasmGCNameProvider names;
|
private WasmGCNameProvider names;
|
||||||
private boolean strict;
|
private boolean strict;
|
||||||
|
private Consumer<WasmGCInitializerContributor> initializerContributors;
|
||||||
|
|
||||||
public WasmGCGenerationContext(WasmModule module, WasmGCVirtualTableProvider virtualTables,
|
public WasmGCGenerationContext(WasmModule module, WasmGCVirtualTableProvider virtualTables,
|
||||||
WasmGCTypeMapper typeMapper, WasmFunctionTypes functionTypes, ListableClassReaderSource classes,
|
WasmGCTypeMapper typeMapper, WasmFunctionTypes functionTypes, ListableClassReaderSource classes,
|
||||||
|
@ -70,7 +73,7 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
|
||||||
WasmGCSupertypeFunctionProvider supertypeFunctions, WasmGCClassInfoProvider classInfoProvider,
|
WasmGCSupertypeFunctionProvider supertypeFunctions, WasmGCClassInfoProvider classInfoProvider,
|
||||||
WasmGCStandardClasses standardClasses, WasmGCStringProvider strings,
|
WasmGCStandardClasses standardClasses, WasmGCStringProvider strings,
|
||||||
WasmGCCustomGeneratorProvider customGenerators, WasmGCIntrinsicProvider intrinsics,
|
WasmGCCustomGeneratorProvider customGenerators, WasmGCIntrinsicProvider intrinsics,
|
||||||
WasmGCNameProvider names, boolean strict) {
|
WasmGCNameProvider names, boolean strict, Consumer<WasmGCInitializerContributor> initializerContributors) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.virtualTables = virtualTables;
|
this.virtualTables = virtualTables;
|
||||||
this.typeMapper = typeMapper;
|
this.typeMapper = typeMapper;
|
||||||
|
@ -87,6 +90,7 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
|
||||||
this.intrinsics = intrinsics;
|
this.intrinsics = intrinsics;
|
||||||
this.names = names;
|
this.names = names;
|
||||||
this.strict = strict;
|
this.strict = strict;
|
||||||
|
this.initializerContributors = initializerContributors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WasmGCClassInfoProvider classInfoProvider() {
|
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.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import org.teavm.ast.ArrayFromDataExpr;
|
import org.teavm.ast.ArrayFromDataExpr;
|
||||||
import org.teavm.ast.ArrayType;
|
import org.teavm.ast.ArrayType;
|
||||||
|
@ -816,5 +817,10 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
||||||
public WasmTag exceptionTag() {
|
public WasmTag exceptionTag() {
|
||||||
return context.getExceptionTag();
|
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.Objects;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import org.teavm.ast.RegularMethodNode;
|
import org.teavm.ast.RegularMethodNode;
|
||||||
import org.teavm.ast.decompilation.Decompiler;
|
import org.teavm.ast.decompilation.Decompiler;
|
||||||
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
|
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.PreciseValueType;
|
||||||
import org.teavm.backend.wasm.gc.WasmGCVariableCategoryProvider;
|
import org.teavm.backend.wasm.gc.WasmGCVariableCategoryProvider;
|
||||||
import org.teavm.backend.wasm.gc.vtable.WasmGCVirtualTableProvider;
|
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.WasmGCNameProvider;
|
||||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
|
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
|
||||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCStandardClasses;
|
import org.teavm.backend.wasm.generate.gc.classes.WasmGCStandardClasses;
|
||||||
|
@ -86,6 +88,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||||
private WasmGCStandardClasses standardClasses;
|
private WasmGCStandardClasses standardClasses;
|
||||||
private WasmGCStringProvider strings;
|
private WasmGCStringProvider strings;
|
||||||
private boolean strict;
|
private boolean strict;
|
||||||
|
private Consumer<WasmGCInitializerContributor> initializerContributors;
|
||||||
|
|
||||||
public WasmGCMethodGenerator(
|
public WasmGCMethodGenerator(
|
||||||
WasmModule module,
|
WasmModule module,
|
||||||
|
@ -99,7 +102,8 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||||
Diagnostics diagnostics,
|
Diagnostics diagnostics,
|
||||||
WasmGCCustomGeneratorProvider customGenerators,
|
WasmGCCustomGeneratorProvider customGenerators,
|
||||||
WasmGCIntrinsicProvider intrinsics,
|
WasmGCIntrinsicProvider intrinsics,
|
||||||
boolean strict
|
boolean strict,
|
||||||
|
Consumer<WasmGCInitializerContributor> initializerContributors
|
||||||
) {
|
) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.hierarchy = hierarchy;
|
this.hierarchy = hierarchy;
|
||||||
|
@ -113,6 +117,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||||
this.customGenerators = customGenerators;
|
this.customGenerators = customGenerators;
|
||||||
this.intrinsics = intrinsics;
|
this.intrinsics = intrinsics;
|
||||||
this.strict = strict;
|
this.strict = strict;
|
||||||
|
this.initializerContributors = initializerContributors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTypeMapper(WasmGCTypeMapper typeMapper) {
|
public void setTypeMapper(WasmGCTypeMapper typeMapper) {
|
||||||
|
@ -356,7 +361,8 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||||
customGenerators,
|
customGenerators,
|
||||||
intrinsics,
|
intrinsics,
|
||||||
names,
|
names,
|
||||||
strict
|
strict,
|
||||||
|
initializerContributors
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return context;
|
return context;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.backend.wasm.intrinsics.gc;
|
package org.teavm.backend.wasm.intrinsics.gc;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
import org.teavm.ast.Expr;
|
import org.teavm.ast.Expr;
|
||||||
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
|
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
|
||||||
import org.teavm.backend.wasm.WasmFunctionTypes;
|
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.WasmGCClassInfoProvider;
|
||||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCTypeMapper;
|
import org.teavm.backend.wasm.generate.gc.classes.WasmGCTypeMapper;
|
||||||
import org.teavm.backend.wasm.generate.gc.strings.WasmGCStringProvider;
|
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.WasmModule;
|
||||||
import org.teavm.backend.wasm.model.WasmTag;
|
import org.teavm.backend.wasm.model.WasmTag;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||||
|
@ -58,4 +60,6 @@ public interface WasmGCIntrinsicContext {
|
||||||
ClassLoader classLoader();
|
ClassLoader classLoader();
|
||||||
|
|
||||||
WasmTag exceptionTag();
|
WasmTag exceptionTag();
|
||||||
|
|
||||||
|
void addToInitializer(Consumer<WasmFunction> initializerContributor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
var TeaVM = TeaVM || {};
|
var TeaVM = TeaVM || {};
|
||||||
TeaVM.wasm = function() {
|
TeaVM.wasm = function() {
|
||||||
let exports;
|
let exports;
|
||||||
|
let getGlobalName = function(name) {
|
||||||
|
return eval("return " + {name});
|
||||||
|
}
|
||||||
function defaults(imports) {
|
function defaults(imports) {
|
||||||
let stderr = "";
|
let stderr = "";
|
||||||
let stdout = "";
|
let stdout = "";
|
||||||
|
@ -92,18 +95,51 @@ TeaVM.wasm = function() {
|
||||||
}
|
}
|
||||||
return weakRef;
|
return weakRef;
|
||||||
},
|
},
|
||||||
deref(weakRef) {
|
deref: weakRef => weakRef.deref(),
|
||||||
return weakRef.deref();
|
|
||||||
},
|
|
||||||
createStringWeakRef(value, heldValue) {
|
createStringWeakRef(value, heldValue) {
|
||||||
let weakRef = new WeakRef(value);
|
let weakRef = new WeakRef(value);
|
||||||
stringFinalizationRegistry.register(value, heldValue)
|
stringFinalizationRegistry.register(value, heldValue)
|
||||||
return weakRef;
|
return weakRef;
|
||||||
},
|
},
|
||||||
stringDeref(weakRef) {
|
stringDeref: weakRef => weakRef.deref()
|
||||||
return 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;
|
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.GeneratedBy;
|
||||||
import org.teavm.backend.javascript.spi.InjectedBy;
|
import org.teavm.backend.javascript.spi.InjectedBy;
|
||||||
import org.teavm.dependency.PluggableDependency;
|
import org.teavm.dependency.PluggableDependency;
|
||||||
|
import org.teavm.interop.Import;
|
||||||
import org.teavm.interop.NoSideEffects;
|
import org.teavm.interop.NoSideEffects;
|
||||||
import org.teavm.jso.JSBody;
|
import org.teavm.jso.JSBody;
|
||||||
import org.teavm.jso.JSObject;
|
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.JSNumber;
|
||||||
import org.teavm.jso.core.JSString;
|
import org.teavm.jso.core.JSString;
|
||||||
|
|
||||||
final class JS {
|
public final class JS {
|
||||||
private JS() {
|
private JS() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,30 +78,37 @@ final class JS {
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@NoSideEffects
|
@NoSideEffects
|
||||||
|
@Import(name = "wrapByte", module = "teavmJso")
|
||||||
public static native JSObject wrap(byte value);
|
public static native JSObject wrap(byte value);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@NoSideEffects
|
@NoSideEffects
|
||||||
|
@Import(name = "wrapShort", module = "teavmJso")
|
||||||
public static native JSObject wrap(short value);
|
public static native JSObject wrap(short value);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@NoSideEffects
|
@NoSideEffects
|
||||||
|
@Import(name = "wrapInt", module = "teavmJso")
|
||||||
public static native JSObject wrap(int value);
|
public static native JSObject wrap(int value);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@NoSideEffects
|
@NoSideEffects
|
||||||
|
@Import(name = "wrapChar", module = "teavmJso")
|
||||||
public static native JSObject wrap(char value);
|
public static native JSObject wrap(char value);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@NoSideEffects
|
@NoSideEffects
|
||||||
|
@Import(name = "wrapFloat", module = "teavmJso")
|
||||||
public static native JSObject wrap(float value);
|
public static native JSObject wrap(float value);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@NoSideEffects
|
@NoSideEffects
|
||||||
|
@Import(name = "wrapDouble", module = "teavmJso")
|
||||||
public static native JSObject wrap(double value);
|
public static native JSObject wrap(double value);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@NoSideEffects
|
@NoSideEffects
|
||||||
|
@Import(name = "wrapBoolean", module = "teavmJso")
|
||||||
public static native JSObject wrap(boolean value);
|
public static native JSObject wrap(boolean value);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
|
@ -109,30 +117,37 @@ final class JS {
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@NoSideEffects
|
@NoSideEffects
|
||||||
|
@Import(name = "unwrapByte", module = "teavmJso")
|
||||||
public static native byte unwrapByte(JSObject value);
|
public static native byte unwrapByte(JSObject value);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@NoSideEffects
|
@NoSideEffects
|
||||||
|
@Import(name = "unwrapChar", module = "teavmJso")
|
||||||
public static native char unwrapCharacter(JSObject value);
|
public static native char unwrapCharacter(JSObject value);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@NoSideEffects
|
@NoSideEffects
|
||||||
|
@Import(name = "unwrapShort", module = "teavmJso")
|
||||||
public static native short unwrapShort(JSObject value);
|
public static native short unwrapShort(JSObject value);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@NoSideEffects
|
@NoSideEffects
|
||||||
|
@Import(name = "unwrapInt", module = "teavmJso")
|
||||||
public static native int unwrapInt(JSObject value);
|
public static native int unwrapInt(JSObject value);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@NoSideEffects
|
@NoSideEffects
|
||||||
|
@Import(name = "unwrapFloat", module = "teavmJso")
|
||||||
public static native float unwrapFloat(JSObject value);
|
public static native float unwrapFloat(JSObject value);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@NoSideEffects
|
@NoSideEffects
|
||||||
|
@Import(name = "unwrapDouble", module = "teavmJso")
|
||||||
public static native double unwrapDouble(JSObject value);
|
public static native double unwrapDouble(JSObject value);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@NoSideEffects
|
@NoSideEffects
|
||||||
|
@Import(name = "unwrapBoolean", module = "teavmJso")
|
||||||
public static native boolean unwrapBoolean(JSObject value);
|
public static native boolean unwrapBoolean(JSObject value);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
|
@ -466,68 +481,82 @@ final class JS {
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(JSNativeInjector.class)
|
@PluggableDependency(JSNativeInjector.class)
|
||||||
|
@Import(name = "callMethod0", module = "teavmJso")
|
||||||
public static native JSObject invoke(JSObject instance, JSObject method);
|
public static native JSObject invoke(JSObject instance, JSObject method);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(JSNativeInjector.class)
|
@PluggableDependency(JSNativeInjector.class)
|
||||||
|
@Import(name = "callMethod1", module = "teavmJso")
|
||||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a);
|
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(JSNativeInjector.class)
|
@PluggableDependency(JSNativeInjector.class)
|
||||||
|
@Import(name = "callMethod2", module = "teavmJso")
|
||||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b);
|
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(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);
|
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(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,
|
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
||||||
JSObject d);
|
JSObject d);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(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,
|
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
||||||
JSObject d, JSObject e);
|
JSObject d, JSObject e);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(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,
|
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
||||||
JSObject d, JSObject e, JSObject f);
|
JSObject d, JSObject e, JSObject f);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(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,
|
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
||||||
JSObject d, JSObject e, JSObject f, JSObject g);
|
JSObject d, JSObject e, JSObject f, JSObject g);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(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,
|
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 d, JSObject e, JSObject f, JSObject g, JSObject h);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(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,
|
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 d, JSObject e, JSObject f, JSObject g, JSObject h, JSObject i);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(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,
|
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 d, JSObject e, JSObject f, JSObject g, JSObject h, JSObject i, JSObject j);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(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,
|
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 d, JSObject e, JSObject f, JSObject g, JSObject h, JSObject i, JSObject j, JSObject k);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(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,
|
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 d, JSObject e, JSObject f, JSObject g, JSObject h, JSObject i, JSObject j, JSObject k,
|
||||||
JSObject l);
|
JSObject l);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(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,
|
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 d, JSObject e, JSObject f, JSObject g, JSObject h, JSObject i, JSObject j, JSObject k,
|
||||||
JSObject l, JSObject m);
|
JSObject l, JSObject m);
|
||||||
|
@ -608,85 +637,103 @@ final class JS {
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(JSNativeInjector.class)
|
@PluggableDependency(JSNativeInjector.class)
|
||||||
|
@Import(name = "construct0", module = "teavmJso")
|
||||||
public static native JSObject construct(JSObject cls);
|
public static native JSObject construct(JSObject cls);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(JSNativeInjector.class)
|
@PluggableDependency(JSNativeInjector.class)
|
||||||
|
@Import(name = "construct1", module = "teavmJso")
|
||||||
public static native JSObject construct(JSObject cls, JSObject a);
|
public static native JSObject construct(JSObject cls, JSObject a);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(JSNativeInjector.class)
|
@PluggableDependency(JSNativeInjector.class)
|
||||||
|
@Import(name = "construct2", module = "teavmJso")
|
||||||
public static native JSObject construct(JSObject cls, JSObject a, JSObject b);
|
public static native JSObject construct(JSObject cls, JSObject a, JSObject b);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(JSNativeInjector.class)
|
@PluggableDependency(JSNativeInjector.class)
|
||||||
|
@Import(name = "construct3", module = "teavmJso")
|
||||||
public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c);
|
public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(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);
|
public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c, JSObject d);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(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);
|
public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(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,
|
public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e,
|
||||||
JSObject f);
|
JSObject f);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(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,
|
public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e,
|
||||||
JSObject f, JSObject g);
|
JSObject f, JSObject g);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(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,
|
public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e,
|
||||||
JSObject f, JSObject g, JSObject h);
|
JSObject f, JSObject g, JSObject h);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(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,
|
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 f, JSObject g, JSObject h, JSObject i);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(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,
|
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 f, JSObject g, JSObject h, JSObject i, JSObject j);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(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,
|
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 f, JSObject g, JSObject h, JSObject i, JSObject j, JSObject k);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(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,
|
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 f, JSObject g, JSObject h, JSObject i, JSObject j, JSObject k, JSObject l);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@PluggableDependency(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,
|
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);
|
JSObject f, JSObject g, JSObject h, JSObject i, JSObject j, JSObject k, JSObject l, JSObject m);
|
||||||
|
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@JSBody(params = { "instance", "index" }, script = "return instance[index];")
|
@JSBody(params = { "instance", "index" }, script = "return instance[index];")
|
||||||
|
@Import(name = "getProperty", module = "teavmJso")
|
||||||
public static native JSObject get(JSObject instance, JSObject index);
|
public static native JSObject get(JSObject instance, JSObject index);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@JSBody(params = { "instance", "index" }, script = "return instance[index];")
|
@JSBody(params = { "instance", "index" }, script = "return instance[index];")
|
||||||
@NoSideEffects
|
@NoSideEffects
|
||||||
|
@Import(name = "getPropertyPure", module = "teavmJso")
|
||||||
public static native JSObject getPure(JSObject instance, JSObject index);
|
public static native JSObject getPure(JSObject instance, JSObject index);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@JSBody(params = { "instance", "index", "obj" }, script = "instance[index] = obj;")
|
@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);
|
public static native void set(JSObject instance, JSObject index, JSObject obj);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@JSBody(params = { "instance", "index", "obj" }, script = "instance[index] = obj;")
|
@JSBody(params = { "instance", "index", "obj" }, script = "instance[index] = obj;")
|
||||||
@NoSideEffects
|
@NoSideEffects
|
||||||
|
@Import(name = "setPropertyPure", module = "teavmJso")
|
||||||
public static native void setPure(JSObject instance, JSObject index, JSObject obj);
|
public static native void setPure(JSObject instance, JSObject index, JSObject obj);
|
||||||
|
|
||||||
@GeneratedBy(JSNativeGenerator.class)
|
@GeneratedBy(JSNativeGenerator.class)
|
||||||
|
@ -699,6 +746,7 @@ final class JS {
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
@NoSideEffects
|
@NoSideEffects
|
||||||
|
@Import(name = "global", module = "teavmJso")
|
||||||
public static native JSObject global(String name);
|
public static native JSObject global(String name);
|
||||||
|
|
||||||
@InjectedBy(JSNativeInjector.class)
|
@InjectedBy(JSNativeInjector.class)
|
||||||
|
|
|
@ -26,22 +26,39 @@ import org.teavm.backend.javascript.spi.GeneratorContext;
|
||||||
import org.teavm.backend.javascript.spi.InjectorContext;
|
import org.teavm.backend.javascript.spi.InjectorContext;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
class JSBodyAstEmitter implements JSBodyEmitter {
|
public class JSBodyAstEmitter implements JSBodyEmitter {
|
||||||
private boolean isStatic;
|
private boolean isStatic;
|
||||||
private AstNode ast;
|
private final MethodReference method;
|
||||||
private AstNode rootAst;
|
public final AstNode ast;
|
||||||
|
public final AstNode rootAst;
|
||||||
private String[] parameterNames;
|
private String[] parameterNames;
|
||||||
private JsBodyImportInfo[] imports;
|
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) {
|
JsBodyImportInfo[] imports) {
|
||||||
this.isStatic = isStatic;
|
this.isStatic = isStatic;
|
||||||
|
this.method = method;
|
||||||
this.ast = ast;
|
this.ast = ast;
|
||||||
this.rootAst = rootAst;
|
this.rootAst = rootAst;
|
||||||
this.parameterNames = parameterNames;
|
this.parameterNames = parameterNames;
|
||||||
this.imports = imports;
|
this.imports = imports;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MethodReference method() {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isStatic() {
|
||||||
|
return isStatic;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] parameterNames() {
|
||||||
|
return parameterNames.clone();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void emit(InjectorContext context) {
|
public void emit(InjectorContext context) {
|
||||||
var astWriter = new AstWriter(context.getWriter(), new DefaultGlobalNameWriter());
|
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.backend.javascript.spi.InjectorContext;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
class JSBodyBloatedEmitter implements JSBodyEmitter {
|
public class JSBodyBloatedEmitter implements JSBodyEmitter {
|
||||||
private boolean isStatic;
|
private boolean isStatic;
|
||||||
private MethodReference method;
|
private MethodReference method;
|
||||||
private String script;
|
public final String script;
|
||||||
private String[] parameterNames;
|
private String[] parameterNames;
|
||||||
private JsBodyImportInfo[] imports;
|
private JsBodyImportInfo[] imports;
|
||||||
|
|
||||||
|
@ -36,6 +36,21 @@ class JSBodyBloatedEmitter implements JSBodyEmitter {
|
||||||
this.imports = imports;
|
this.imports = imports;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MethodReference method() {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isStatic() {
|
||||||
|
return isStatic;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] parameterNames() {
|
||||||
|
return parameterNames.clone();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void emit(InjectorContext context) {
|
public void emit(InjectorContext context) {
|
||||||
emit(context.getWriter(), new EmissionStrategy() {
|
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.backend.javascript.spi.InjectorContext;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
interface JSBodyEmitter {
|
public interface JSBodyEmitter {
|
||||||
|
MethodReference method();
|
||||||
|
|
||||||
void emit(InjectorContext context);
|
void emit(InjectorContext context);
|
||||||
|
|
||||||
void emit(GeneratorContext context, SourceWriter writer, MethodReference methodRef);
|
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 java.util.Set;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
class JSBodyRepository {
|
public class JSBodyRepository {
|
||||||
final Map<MethodReference, JSBodyEmitter> emitters = new HashMap<>();
|
public final Map<MethodReference, JSBodyEmitter> emitters = new HashMap<>();
|
||||||
final Map<MethodReference, JsBodyImportInfo[]> imports = new HashMap<>();
|
public final Map<MethodReference, JsBodyImportInfo[]> imports = new HashMap<>();
|
||||||
final Map<MethodReference, MethodReference> methodMap = new HashMap<>();
|
public final Map<MethodReference, MethodReference> methodMap = new HashMap<>();
|
||||||
final Set<MethodReference> processedMethods = new HashSet<>();
|
public final Set<MethodReference> processedMethods = new HashSet<>();
|
||||||
final Set<MethodReference> inlineMethods = new HashSet<>();
|
public final Set<MethodReference> inlineMethods = new HashSet<>();
|
||||||
final Map<MethodReference, MethodReference> callbackCallees = new HashMap<>();
|
public final Map<MethodReference, MethodReference> callbackCallees = new HashMap<>();
|
||||||
final Map<MethodReference, Set<MethodReference>> callbackMethods = 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) {
|
for (int i = 0; i < signature.length; ++i) {
|
||||||
staticSignature[i + 1] = signature[i];
|
staticSignature[i + 1] = signature[i];
|
||||||
}
|
}
|
||||||
staticSignature[0] = ValueType.object(method.getClassName());
|
staticSignature[0] = ValueType.object(JSObject.class.getName());
|
||||||
return staticSignature;
|
return staticSignature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1139,7 +1139,8 @@ class JSClassProcessor {
|
||||||
expr = body;
|
expr = body;
|
||||||
}
|
}
|
||||||
javaInvocationProcessor.process(location, expr);
|
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);
|
repository.emitters.put(proxyMethod, emitter);
|
||||||
}
|
}
|
||||||
if (imports.length > 0) {
|
if (imports.length > 0) {
|
||||||
|
|
|
@ -16,8 +16,10 @@
|
||||||
package org.teavm.jso.impl;
|
package org.teavm.jso.impl;
|
||||||
|
|
||||||
import org.teavm.backend.javascript.TeaVMJavaScriptHost;
|
import org.teavm.backend.javascript.TeaVMJavaScriptHost;
|
||||||
|
import org.teavm.backend.wasm.gc.TeaVMWasmGCHost;
|
||||||
import org.teavm.jso.JSExceptions;
|
import org.teavm.jso.JSExceptions;
|
||||||
import org.teavm.jso.JSObject;
|
import org.teavm.jso.JSObject;
|
||||||
|
import org.teavm.jso.impl.wasmgc.WasmGCJso;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.platform.plugin.PlatformPlugin;
|
import org.teavm.platform.plugin.PlatformPlugin;
|
||||||
import org.teavm.vm.TeaVMPluginUtil;
|
import org.teavm.vm.TeaVMPluginUtil;
|
||||||
|
@ -29,19 +31,36 @@ import org.teavm.vm.spi.TeaVMPlugin;
|
||||||
public class JSOPlugin implements TeaVMPlugin {
|
public class JSOPlugin implements TeaVMPlugin {
|
||||||
@Override
|
@Override
|
||||||
public void install(TeaVMHost host) {
|
public void install(TeaVMHost host) {
|
||||||
TeaVMJavaScriptHost jsHost = host.getExtension(TeaVMJavaScriptHost.class);
|
|
||||||
if (jsHost == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSBodyRepository repository = new JSBodyRepository();
|
JSBodyRepository repository = new JSBodyRepository();
|
||||||
host.registerService(JSBodyRepository.class, repository);
|
host.registerService(JSBodyRepository.class, repository);
|
||||||
host.add(new JSObjectClassTransformer(repository));
|
host.add(new JSObjectClassTransformer(repository));
|
||||||
JSDependencyListener dependencyListener = new JSDependencyListener(repository);
|
JSDependencyListener dependencyListener = new JSDependencyListener(repository);
|
||||||
JSAliasRenderer aliasRenderer = new JSAliasRenderer();
|
|
||||||
host.add(dependencyListener);
|
host.add(dependencyListener);
|
||||||
host.add(new JSExceptionsDependencyListener());
|
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.add(aliasRenderer);
|
||||||
jsHost.addGeneratorProvider(new GeneratorAnnotationInstaller<>(new JSBodyGenerator(),
|
jsHost.addGeneratorProvider(new GeneratorAnnotationInstaller<>(new JSBodyGenerator(),
|
||||||
DynamicGenerator.class.getName()));
|
DynamicGenerator.class.getName()));
|
||||||
|
@ -50,7 +69,7 @@ public class JSOPlugin implements TeaVMPlugin {
|
||||||
jsHost.addVirtualMethods(aliasRenderer);
|
jsHost.addVirtualMethods(aliasRenderer);
|
||||||
jsHost.addForcedFunctionMethods(new JSExportedMethodAsFunction());
|
jsHost.addForcedFunctionMethods(new JSExportedMethodAsFunction());
|
||||||
|
|
||||||
JSExceptionsGenerator exceptionsGenerator = new JSExceptionsGenerator();
|
var exceptionsGenerator = new JSExceptionsGenerator();
|
||||||
jsHost.add(new MethodReference(JSExceptions.class, "getJavaException", JSObject.class, Throwable.class),
|
jsHost.add(new MethodReference(JSExceptions.class, "getJavaException", JSObject.class, Throwable.class),
|
||||||
exceptionsGenerator);
|
exceptionsGenerator);
|
||||||
jsHost.add(new MethodReference(JSExceptions.class, "getJSException", Throwable.class, JSObject.class),
|
jsHost.add(new MethodReference(JSExceptions.class, "getJSException", Throwable.class, JSObject.class),
|
||||||
|
@ -75,14 +94,5 @@ public class JSOPlugin implements TeaVMPlugin {
|
||||||
wrapperGenerator);
|
wrapperGenerator);
|
||||||
jsHost.add(new MethodReference(JSWrapper.class, "isJSImplementation", Object.class, boolean.class),
|
jsHost.add(new MethodReference(JSWrapper.class, "isJSImplementation", Object.class, boolean.class),
|
||||||
wrapperGenerator);
|
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;
|
package org.teavm.jso.impl;
|
||||||
|
|
||||||
class JsBodyImportInfo {
|
public class JsBodyImportInfo {
|
||||||
final String alias;
|
public final String alias;
|
||||||
final String fromModule;
|
public final String fromModule;
|
||||||
|
|
||||||
JsBodyImportInfo(String alias, String fromModule) {
|
public JsBodyImportInfo(String alias, String fromModule) {
|
||||||
this.alias = alias;
|
this.alias = alias;
|
||||||
this.fromModule = fromModule;
|
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)
|
@RunWith(TeaVMTestRunner.class)
|
||||||
@SkipJVM
|
@SkipJVM
|
||||||
@OnlyPlatform(TestPlatform.JAVASCRIPT)
|
@OnlyPlatform({TestPlatform.JAVASCRIPT, TestPlatform.WEBASSEMBLY_GC})
|
||||||
@EachTestCompiledSeparately
|
@EachTestCompiledSeparately
|
||||||
public class AnnotationsTest {
|
public class AnnotationsTest {
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -29,12 +29,13 @@ import org.teavm.jso.core.JSString;
|
||||||
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 ConversionTest {
|
public class ConversionTest {
|
||||||
@Test
|
@Test
|
||||||
|
@ -57,6 +58,7 @@ public class ConversionTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||||
public void convertsPrimitiveArraysToJavaScript() {
|
public void convertsPrimitiveArraysToJavaScript() {
|
||||||
assertEquals("true:2:3:64:4:5.5:6.5:foo", combinePrimitiveArrays(new boolean[] { true }, new byte[] { 2 },
|
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 },
|
new short[] { 3 }, new char[] { '@' }, new int[] { 4 }, new float[] { 5.5F }, new double[] { 6.5 },
|
||||||
|
@ -64,6 +66,7 @@ public class ConversionTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||||
public void convertsPrimitiveArraysToJava() {
|
public void convertsPrimitiveArraysToJava() {
|
||||||
PrimitiveArrays arrays = getPrimitiveArrays();
|
PrimitiveArrays arrays = getPrimitiveArrays();
|
||||||
|
|
||||||
|
@ -81,6 +84,7 @@ public class ConversionTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||||
public void convertsPrimitiveArrays2ToJavaScript() {
|
public void convertsPrimitiveArrays2ToJavaScript() {
|
||||||
assertEquals("true:2:3:64:4:5.5:6.5:foo", combinePrimitiveArrays2(new boolean[][] {{ true }},
|
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 }},
|
new byte[][] {{ 2 }}, new short[][] {{ 3 }}, new char[][] {{ '@' }}, new int[][] {{ 4 }},
|
||||||
|
@ -88,6 +92,7 @@ public class ConversionTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||||
public void convertsPrimitiveArrays2ToJava() {
|
public void convertsPrimitiveArrays2ToJava() {
|
||||||
PrimitiveArrays2 arrays = getPrimitiveArrays2();
|
PrimitiveArrays2 arrays = getPrimitiveArrays2();
|
||||||
|
|
||||||
|
@ -106,6 +111,7 @@ public class ConversionTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||||
public void convertsPrimitiveArrays4ToJavaScript() {
|
public void convertsPrimitiveArrays4ToJavaScript() {
|
||||||
assertEquals("true:2:3:64:4:5.5:6.5:foo", combinePrimitiveArrays4(new boolean[][][][] {{{{ true }}}},
|
assertEquals("true:2:3:64:4:5.5:6.5:foo", combinePrimitiveArrays4(new boolean[][][][] {{{{ true }}}},
|
||||||
new byte[][][][] {{{{ 2 }}}}, new short[][][][] {{{{ 3 }}}}, new char[][][][] {{{{ '@' }}}},
|
new byte[][][][] {{{{ 2 }}}}, new short[][][][] {{{{ 3 }}}}, new char[][][][] {{{{ '@' }}}},
|
||||||
|
@ -114,6 +120,7 @@ public class ConversionTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||||
public void convertsPrimitiveArrays4ToJava() {
|
public void convertsPrimitiveArrays4ToJava() {
|
||||||
PrimitiveArrays4 arrays = getPrimitiveArrays4();
|
PrimitiveArrays4 arrays = getPrimitiveArrays4();
|
||||||
|
|
||||||
|
@ -137,6 +144,7 @@ public class ConversionTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||||
public void convertsArrayOfJSObject() {
|
public void convertsArrayOfJSObject() {
|
||||||
assertEquals("(foo)", surround(new JSString[] { JSString.valueOf("foo") })[0].stringValue());
|
assertEquals("(foo)", surround(new JSString[] { JSString.valueOf("foo") })[0].stringValue());
|
||||||
assertEquals("(foo)", surround(new JSString[][] {{ JSString.valueOf("foo") }})[0][0].stringValue());
|
assertEquals("(foo)", surround(new JSString[][] {{ JSString.valueOf("foo") }})[0][0].stringValue());
|
||||||
|
@ -145,6 +153,7 @@ public class ConversionTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||||
public void copiesArray() {
|
public void copiesArray() {
|
||||||
int[] array = { 23 };
|
int[] array = { 23 };
|
||||||
assertEquals(24, mutate(array));
|
assertEquals(24, mutate(array));
|
||||||
|
@ -152,6 +161,7 @@ public class ConversionTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||||
public void passesArrayByRef() {
|
public void passesArrayByRef() {
|
||||||
int[] array = { 23, 42 };
|
int[] array = { 23, 42 };
|
||||||
|
|
||||||
|
@ -165,6 +175,7 @@ public class ConversionTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||||
public void returnsArrayByRef() {
|
public void returnsArrayByRef() {
|
||||||
int[] first = { 23, 42 };
|
int[] first = { 23, 42 };
|
||||||
int[] second = rewrap(first);
|
int[] second = rewrap(first);
|
||||||
|
|
|
@ -23,12 +23,13 @@ import org.teavm.jso.JSObject;
|
||||||
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 ImplementationTest {
|
public class ImplementationTest {
|
||||||
@Test
|
@Test
|
||||||
|
@ -44,6 +45,7 @@ public class ImplementationTest {
|
||||||
static native int mul(int a, int b);
|
static native int mul(int a, int b);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||||
public void inliningUsageCounterWorksProperly() {
|
public void inliningUsageCounterWorksProperly() {
|
||||||
ForInliningTest instance = ForInliningTest.create();
|
ForInliningTest instance = ForInliningTest.create();
|
||||||
wrongInlineCandidate(instance.foo());
|
wrongInlineCandidate(instance.foo());
|
||||||
|
|
Loading…
Reference in New Issue
Block a user