mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
wasm gc: fix running tests in JUnit, fix remaining errors so that *few* tests pass
This commit is contained in:
parent
1aebe51256
commit
5d109236d9
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 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.classlib.impl.console;
|
||||||
|
|
||||||
|
public class JSConsoleStringPrintStream extends JsConsolePrintStream {
|
||||||
|
private StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void print(String s) {
|
||||||
|
sb.append(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -143,6 +143,35 @@ public class WasmGCModuleGenerator {
|
||||||
return caller;
|
return caller;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WasmFunction generateStringLengthFunction() {
|
||||||
|
var function = declarationsGenerator.functions().forInstanceMethod(new MethodReference(
|
||||||
|
String.class, "length", int.class));
|
||||||
|
var stringType = declarationsGenerator.typeMapper().mapType(ValueType.parse(String.class));
|
||||||
|
var caller = new WasmFunction(function.getType());
|
||||||
|
var stringLocal = new WasmLocal(stringType);
|
||||||
|
caller.add(stringLocal);
|
||||||
|
caller.getBody().add(callInitializer());
|
||||||
|
caller.getBody().add(new WasmReturn(new WasmCall(function, new WasmGetLocal(stringLocal))));
|
||||||
|
declarationsGenerator.module.functions.add(caller);
|
||||||
|
return caller;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmFunction generateCharAtFunction() {
|
||||||
|
var function = declarationsGenerator.functions().forInstanceMethod(new MethodReference(
|
||||||
|
String.class, "charAt", int.class, char.class));
|
||||||
|
var stringType = declarationsGenerator.typeMapper().mapType(ValueType.parse(String.class));
|
||||||
|
var caller = new WasmFunction(function.getType());
|
||||||
|
var stringLocal = new WasmLocal(stringType);
|
||||||
|
var indexLocal = new WasmLocal(WasmType.INT32);
|
||||||
|
caller.add(stringLocal);
|
||||||
|
caller.add(indexLocal);
|
||||||
|
caller.getBody().add(callInitializer());
|
||||||
|
caller.getBody().add(new WasmReturn(new WasmCall(function, new WasmGetLocal(stringLocal),
|
||||||
|
new WasmGetLocal(indexLocal))));
|
||||||
|
declarationsGenerator.module.functions.add(caller);
|
||||||
|
return caller;
|
||||||
|
}
|
||||||
|
|
||||||
private void createInitializer() {
|
private void createInitializer() {
|
||||||
if (initializer != null) {
|
if (initializer != null) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -146,6 +146,12 @@ public class WasmGCTarget implements TeaVMTarget {
|
||||||
var setArrayFunction = moduleGenerator.generateSetToStringArrayFunction();
|
var setArrayFunction = moduleGenerator.generateSetToStringArrayFunction();
|
||||||
setArrayFunction.setExportName("setToStringArray");
|
setArrayFunction.setExportName("setToStringArray");
|
||||||
|
|
||||||
|
var stringLengthFunction = moduleGenerator.generateStringLengthFunction();
|
||||||
|
stringLengthFunction.setExportName("stringLength");
|
||||||
|
|
||||||
|
var charAtFunction = moduleGenerator.generateCharAtFunction();
|
||||||
|
charAtFunction.setExportName("charAt");
|
||||||
|
|
||||||
moduleGenerator.generate();
|
moduleGenerator.generate();
|
||||||
adjustModuleMemory(module);
|
adjustModuleMemory(module);
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,12 @@ public class WasmGCDependencies {
|
||||||
analyzer.linkMethod(new MethodReference(StringBuilder.class, "toString", String.class))
|
analyzer.linkMethod(new MethodReference(StringBuilder.class, "toString", String.class))
|
||||||
.propagate(0, analyzer.getType("java.lang.StringBuilder"))
|
.propagate(0, analyzer.getType("java.lang.StringBuilder"))
|
||||||
.use();
|
.use();
|
||||||
|
analyzer.linkMethod(new MethodReference(String.class, "length", int.class))
|
||||||
|
.propagate(0, analyzer.getType("java.lang.String"))
|
||||||
|
.use();
|
||||||
|
analyzer.linkMethod(new MethodReference(String.class, "charAt", int.class, char.class))
|
||||||
|
.propagate(0, analyzer.getType("java.lang.String"))
|
||||||
|
.use();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void contributeWasmRuntime() {
|
private void contributeWasmRuntime() {
|
||||||
|
|
|
@ -175,6 +175,9 @@ class WasmGCVirtualTableBuilder {
|
||||||
|
|
||||||
for (var method : table.cls.getMethods()) {
|
for (var method : table.cls.getMethods()) {
|
||||||
if (!method.hasModifier(ElementModifier.STATIC) && !method.hasModifier(ElementModifier.ABSTRACT)) {
|
if (!method.hasModifier(ElementModifier.STATIC) && !method.hasModifier(ElementModifier.ABSTRACT)) {
|
||||||
|
if (method.getProgram() == null && !method.hasModifier(ElementModifier.NATIVE)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
var index = indexes.getOrDefault(method.getDescriptor(), -1);
|
var index = indexes.getOrDefault(method.getDescriptor(), -1);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
table.implementors.set(index, method.getReference());
|
table.implementors.set(index, method.getReference());
|
||||||
|
|
|
@ -127,7 +127,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
strings = new WasmGCStringPool(standardClasses, module, functionProvider);
|
strings = new WasmGCStringPool(standardClasses, module, functionProvider);
|
||||||
supertypeGenerator = new WasmGCSupertypeFunctionGenerator(module, this, names, tagRegistry, functionTypes);
|
supertypeGenerator = new WasmGCSupertypeFunctionGenerator(module, this, names, tagRegistry, functionTypes);
|
||||||
newArrayGenerator = new WasmGCNewArrayFunctionGenerator(module, functionTypes, this);
|
newArrayGenerator = new WasmGCNewArrayFunctionGenerator(module, functionTypes, this);
|
||||||
typeMapper = new WasmGCTypeMapper(this, functionTypes, module);
|
typeMapper = new WasmGCTypeMapper(classSource, this, functionTypes, module);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WasmGCSupertypeFunctionProvider getSupertypeProvider() {
|
public WasmGCSupertypeFunctionProvider getSupertypeProvider() {
|
||||||
|
@ -490,11 +490,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
@Override
|
@Override
|
||||||
public int getFieldIndex(FieldReference fieldRef) {
|
public int getFieldIndex(FieldReference fieldRef) {
|
||||||
getClassInfo(fieldRef.getClassName());
|
getClassInfo(fieldRef.getClassName());
|
||||||
var result = fieldIndexes.getOrDefault(fieldRef, -1);
|
return fieldIndexes.getOrDefault(fieldRef, -1);
|
||||||
if (result < 0) {
|
|
||||||
throw new IllegalStateException("Can't get offset of field " + fieldRef);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -22,16 +22,19 @@ import org.teavm.backend.wasm.model.WasmModule;
|
||||||
import org.teavm.backend.wasm.model.WasmPackedType;
|
import org.teavm.backend.wasm.model.WasmPackedType;
|
||||||
import org.teavm.backend.wasm.model.WasmStorageType;
|
import org.teavm.backend.wasm.model.WasmStorageType;
|
||||||
import org.teavm.backend.wasm.model.WasmType;
|
import org.teavm.backend.wasm.model.WasmType;
|
||||||
|
import org.teavm.model.ClassReaderSource;
|
||||||
import org.teavm.model.MethodDescriptor;
|
import org.teavm.model.MethodDescriptor;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
|
|
||||||
public class WasmGCTypeMapper {
|
public class WasmGCTypeMapper {
|
||||||
|
private ClassReaderSource classes;
|
||||||
private WasmGCClassInfoProvider classInfoProvider;
|
private WasmGCClassInfoProvider classInfoProvider;
|
||||||
private WasmFunctionTypes functionTypes;
|
private WasmFunctionTypes functionTypes;
|
||||||
private WasmModule module;
|
private WasmModule module;
|
||||||
|
|
||||||
WasmGCTypeMapper(WasmGCClassInfoProvider classInfoProvider, WasmFunctionTypes functionTypes,
|
WasmGCTypeMapper(ClassReaderSource classes, WasmGCClassInfoProvider classInfoProvider,
|
||||||
WasmModule module) {
|
WasmFunctionTypes functionTypes, WasmModule module) {
|
||||||
|
this.classes = classes;
|
||||||
this.classInfoProvider = classInfoProvider;
|
this.classInfoProvider = classInfoProvider;
|
||||||
this.functionTypes = functionTypes;
|
this.functionTypes = functionTypes;
|
||||||
this.module = module;
|
this.module = module;
|
||||||
|
@ -82,8 +85,32 @@ public class WasmGCTypeMapper {
|
||||||
}
|
}
|
||||||
} else if (type instanceof ValueType.Void) {
|
} else if (type instanceof ValueType.Void) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else if (type instanceof ValueType.Object) {
|
||||||
|
var className = ((ValueType.Object) type).getClassName();
|
||||||
|
var cls = classes.get(className);
|
||||||
|
if (cls == null) {
|
||||||
|
className = "java.lang.Object";
|
||||||
|
}
|
||||||
|
return classInfoProvider.getClassInfo(className).getType();
|
||||||
|
} else if (type instanceof ValueType.Array) {
|
||||||
|
var degree = 0;
|
||||||
|
while (type instanceof ValueType.Array) {
|
||||||
|
type = ((ValueType.Array) type).getItemType();
|
||||||
|
++degree;
|
||||||
|
}
|
||||||
|
if (type instanceof ValueType.Object) {
|
||||||
|
var className = ((ValueType.Object) type).getClassName();
|
||||||
|
var cls = classes.get(className);
|
||||||
|
if (cls != null) {
|
||||||
|
className = "java.lang.Object";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (degree-- > 0) {
|
||||||
|
type = ValueType.arrayOf(type);
|
||||||
|
}
|
||||||
return classInfoProvider.getClassInfo(type).getType();
|
return classInfoProvider.getClassInfo(type).getType();
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -172,13 +172,17 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
||||||
var type = (WasmType.CompositeReference) typeInference.getResult();
|
var type = (WasmType.CompositeReference) typeInference.getResult();
|
||||||
var struct = (WasmStructure) type.composite;
|
var struct = (WasmStructure) type.composite;
|
||||||
var fieldIndex = context.classInfoProvider().getFieldIndex(field);
|
var fieldIndex = context.classInfoProvider().getFieldIndex(field);
|
||||||
|
if (fieldIndex >= 0) {
|
||||||
|
accept(value, struct.getFields().get(fieldIndex).getUnpackedType());
|
||||||
|
var wasmValue = result;
|
||||||
|
|
||||||
accept(value, struct.getFields().get(fieldIndex).getUnpackedType());
|
var expr = new WasmStructSet(struct, target, fieldIndex, wasmValue);
|
||||||
var wasmValue = result;
|
expr.setLocation(location);
|
||||||
|
resultConsumer.add(expr);
|
||||||
var expr = new WasmStructSet(struct, target, fieldIndex, wasmValue);
|
} else {
|
||||||
expr.setLocation(location);
|
accept(value);
|
||||||
resultConsumer.add(expr);
|
resultConsumer.add(result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -495,31 +499,36 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
||||||
var type = (WasmType.CompositeReference) typeInference.getResult();
|
var type = (WasmType.CompositeReference) typeInference.getResult();
|
||||||
var struct = (WasmStructure) type.composite;
|
var struct = (WasmStructure) type.composite;
|
||||||
var fieldIndex = context.classInfoProvider().getFieldIndex(expr.getField());
|
var fieldIndex = context.classInfoProvider().getFieldIndex(expr.getField());
|
||||||
var structGet = new WasmStructGet(struct, target, fieldIndex);
|
if (fieldIndex >= 0) {
|
||||||
var cls = context.classes().get(expr.getField().getClassName());
|
var structGet = new WasmStructGet(struct, target, fieldIndex);
|
||||||
if (cls != null) {
|
var cls = context.classes().get(expr.getField().getClassName());
|
||||||
var field = cls.getField(expr.getField().getFieldName());
|
if (cls != null) {
|
||||||
if (field != null) {
|
var field = cls.getField(expr.getField().getFieldName());
|
||||||
var fieldType = field.getType();
|
if (field != null) {
|
||||||
if (fieldType instanceof ValueType.Primitive) {
|
var fieldType = field.getType();
|
||||||
switch (((ValueType.Primitive) fieldType).getKind()) {
|
if (fieldType instanceof ValueType.Primitive) {
|
||||||
case BYTE:
|
switch (((ValueType.Primitive) fieldType).getKind()) {
|
||||||
structGet.setSignedType(WasmSignedType.SIGNED);
|
case BYTE:
|
||||||
break;
|
structGet.setSignedType(WasmSignedType.SIGNED);
|
||||||
case SHORT:
|
break;
|
||||||
structGet.setSignedType(WasmSignedType.SIGNED);
|
case SHORT:
|
||||||
break;
|
structGet.setSignedType(WasmSignedType.SIGNED);
|
||||||
case CHARACTER:
|
break;
|
||||||
structGet.setSignedType(WasmSignedType.UNSIGNED);
|
case CHARACTER:
|
||||||
break;
|
structGet.setSignedType(WasmSignedType.UNSIGNED);
|
||||||
default:
|
break;
|
||||||
break;
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
structGet.setLocation(expr.getLocation());
|
||||||
|
result = structGet;
|
||||||
|
} else {
|
||||||
|
result = new WasmUnreachable();
|
||||||
|
result.setLocation(expr.getLocation());
|
||||||
}
|
}
|
||||||
structGet.setLocation(expr.getLocation());
|
|
||||||
result = structGet;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ import java.util.ArrayDeque;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.teavm.ast.decompilation.Decompiler;
|
import org.teavm.ast.decompilation.Decompiler;
|
||||||
|
@ -192,13 +193,17 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateMethodBody(MethodHolder method, WasmFunction function) {
|
private void generateMethodBody(MethodHolder method, WasmFunction function) {
|
||||||
var customGenerator = customGenerators.get(method.getReference());
|
try {
|
||||||
if (customGenerator != null) {
|
var customGenerator = customGenerators.get(method.getReference());
|
||||||
generateCustomMethodBody(customGenerator, method.getReference(), function);
|
if (customGenerator != null) {
|
||||||
} else if (!method.hasModifier(ElementModifier.NATIVE)) {
|
generateCustomMethodBody(customGenerator, method.getReference(), function);
|
||||||
generateRegularMethodBody(method, function);
|
} else if (!method.hasModifier(ElementModifier.NATIVE)) {
|
||||||
} else {
|
generateRegularMethodBody(method, function);
|
||||||
generateNativeMethodBody(method, function);
|
} else {
|
||||||
|
generateNativeMethodBody(method, function);
|
||||||
|
}
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
throw new RuntimeException("Failed generating method body: " + method.getReference(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,6 +213,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateRegularMethodBody(MethodHolder method, WasmFunction function) {
|
private void generateRegularMethodBody(MethodHolder method, WasmFunction function) {
|
||||||
|
Objects.requireNonNull(method.getProgram());
|
||||||
var decompiler = getDecompiler();
|
var decompiler = getDecompiler();
|
||||||
var categoryProvider = new WasmGCVariableCategoryProvider(hierarchy);
|
var categoryProvider = new WasmGCVariableCategoryProvider(hierarchy);
|
||||||
var allocator = new RegisterAllocator(categoryProvider);
|
var allocator = new RegisterAllocator(categoryProvider);
|
||||||
|
|
|
@ -82,7 +82,7 @@ public class Devirtualization {
|
||||||
BasicBlock block = program.basicBlockAt(i);
|
BasicBlock block = program.basicBlockAt(i);
|
||||||
for (Instruction insn : block) {
|
for (Instruction insn : block) {
|
||||||
if (insn instanceof InvokeInstruction) {
|
if (insn instanceof InvokeInstruction) {
|
||||||
applyToInvoke(methodDep, (InvokeInstruction) insn);
|
applyToInvoke(methodDep, program, (InvokeInstruction) insn);
|
||||||
} else if (insn instanceof CastInstruction) {
|
} else if (insn instanceof CastInstruction) {
|
||||||
applyToCast(methodDep, (CastInstruction) insn);
|
applyToCast(methodDep, (CastInstruction) insn);
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ public class Devirtualization {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyToInvoke(MethodDependencyInfo methodDep, InvokeInstruction invoke) {
|
private void applyToInvoke(MethodDependencyInfo methodDep, Program program, InvokeInstruction invoke) {
|
||||||
if (invoke.getType() != InvocationType.VIRTUAL) {
|
if (invoke.getType() != InvocationType.VIRTUAL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -112,6 +112,16 @@ public class Devirtualization {
|
||||||
}
|
}
|
||||||
System.out.println();
|
System.out.println();
|
||||||
}
|
}
|
||||||
|
if (!resolvedImplementaiton.getClassName().equals(invoke.getMethod().getClassName())) {
|
||||||
|
var cast = new CastInstruction();
|
||||||
|
cast.setValue(invoke.getInstance());
|
||||||
|
cast.setTargetType(ValueType.object(resolvedImplementaiton.getClassName()));
|
||||||
|
cast.setWeak(true);
|
||||||
|
cast.setReceiver(program.createVariable());
|
||||||
|
cast.setLocation(invoke.getLocation());
|
||||||
|
invoke.insertPrevious(cast);
|
||||||
|
invoke.setInstance(cast.getReceiver());
|
||||||
|
}
|
||||||
invoke.setType(InvocationType.SPECIAL);
|
invoke.setType(InvocationType.SPECIAL);
|
||||||
invoke.setMethod(resolvedImplementaiton);
|
invoke.setMethod(resolvedImplementaiton);
|
||||||
directCallSites++;
|
directCallSites++;
|
||||||
|
|
|
@ -53,6 +53,7 @@ TeaVM.wasm = function() {
|
||||||
return WebAssembly.instantiateStreaming(fetch(path), importObj).then((obj => {
|
return WebAssembly.instantiateStreaming(fetch(path), importObj).then((obj => {
|
||||||
let teavm = {};
|
let teavm = {};
|
||||||
teavm.main = createMain(obj.instance);
|
teavm.main = createMain(obj.instance);
|
||||||
|
teavm.instance = obj.instance;
|
||||||
return teavm;
|
return teavm;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ window.addEventListener("message", event => {
|
||||||
case "WASM_GC": {
|
case "WASM_GC": {
|
||||||
const runtimeFile = request.file.path + "-runtime.js";
|
const runtimeFile = request.file.path + "-runtime.js";
|
||||||
appendFiles([{ path: runtimeFile, type: "regular" }], 0, () => {
|
appendFiles([{ path: runtimeFile, type: "regular" }], 0, () => {
|
||||||
launchWasmTest(request.file, request.argument, response => {
|
launchWasmGCTest(request.file, request.argument, response => {
|
||||||
event.source.postMessage(response, "*");
|
event.source.postMessage(response, "*");
|
||||||
});
|
});
|
||||||
}, error => {
|
}, error => {
|
||||||
|
@ -186,6 +186,62 @@ function launchWasmTest(file, argument, callback) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function launchWasmGCTest(file, argument, callback) {
|
||||||
|
let outputBuffer = "";
|
||||||
|
let outputBufferStderr = "";
|
||||||
|
|
||||||
|
function putchar(charCode) {
|
||||||
|
if (charCode === 10) {
|
||||||
|
log.push({ message: outputBuffer, type: "stdout" });
|
||||||
|
outputBuffer = "";
|
||||||
|
} else {
|
||||||
|
outputBuffer += String.fromCharCode(charCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function putcharStderr(charCode) {
|
||||||
|
if (charCode === 10) {
|
||||||
|
log.push({ message: outputBufferStderr, type: "stderr" });
|
||||||
|
outputBufferStderr = "";
|
||||||
|
} else {
|
||||||
|
outputBufferStderr += String.fromCharCode(charCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let instance = null;
|
||||||
|
|
||||||
|
TeaVM.wasm.load(file.path, {
|
||||||
|
installImports: function(o) {
|
||||||
|
o.teavm.putcharStdout = putchar;
|
||||||
|
o.teavm.putcharStderr = putcharStderr;
|
||||||
|
o.teavmTest = {
|
||||||
|
success() {
|
||||||
|
callback(wrapResponse({ status: "OK" }));
|
||||||
|
},
|
||||||
|
failure(javaString) {
|
||||||
|
let jsString = "";
|
||||||
|
let length = instance.exports.stringLength(javaString);
|
||||||
|
for (let i = 0; i < length; ++i) {
|
||||||
|
jsString += String.fromCharCode(instance.exports.charAt(javaString, i));
|
||||||
|
}
|
||||||
|
callback(wrapResponse({
|
||||||
|
status: "failed",
|
||||||
|
errorMessage: jsString
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}).then(teavm => {
|
||||||
|
instance = teavm.instance;
|
||||||
|
return teavm.main(argument ? [argument] : []);
|
||||||
|
}).catch(err => {
|
||||||
|
callback(wrapResponse({
|
||||||
|
status: "failed",
|
||||||
|
errorMessage: err.message + '\n' + err.stack
|
||||||
|
}));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function start() {
|
function start() {
|
||||||
window.parent.postMessage("ready", "*");
|
window.parent.postMessage("ready", "*");
|
||||||
}
|
}
|
||||||
|
|
|
@ -303,27 +303,29 @@ public class TeaVMTestRunner extends Runner implements Filterable {
|
||||||
if (success && outputDir != null) {
|
if (success && outputDir != null) {
|
||||||
List<TestRun> runs = new ArrayList<>();
|
List<TestRun> runs = new ArrayList<>();
|
||||||
|
|
||||||
if (isWholeClassCompilation) {
|
try {
|
||||||
if (!classCompilationOk) {
|
if (isWholeClassCompilation) {
|
||||||
notifier.fireTestFinished(description);
|
if (!classCompilationOk) {
|
||||||
notifier.fireTestFailure(new Failure(description,
|
notifier.fireTestFailure(new Failure(description,
|
||||||
new AssertionError("Could not compile test class")));
|
new AssertionError("Could not compile test class")));
|
||||||
|
} else {
|
||||||
|
prepareTestsFromWholeClass(child, runs);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
prepareTestsFromWholeClass(child, runs);
|
prepareCompiledTest(child, notifier, runs);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
prepareCompiledTest(child, notifier, runs);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var run : runs) {
|
for (var run : runs) {
|
||||||
try {
|
try {
|
||||||
submitRun(run);
|
submitRun(run);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
notifier.fireTestFailure(new Failure(description, e));
|
notifier.fireTestFailure(new Failure(description, e));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
notifier.fireTestFinished(description);
|
||||||
}
|
}
|
||||||
notifier.fireTestFinished(description);
|
|
||||||
} else {
|
} else {
|
||||||
if (!ran) {
|
if (!ran) {
|
||||||
notifier.fireTestIgnored(description);
|
notifier.fireTestIgnored(description);
|
||||||
|
@ -378,7 +380,6 @@ public class TeaVMTestRunner extends Runner implements Filterable {
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
notifier.fireTestFailure(new Failure(describeChild(child), e));
|
notifier.fireTestFailure(new Failure(describeChild(child), e));
|
||||||
notifier.fireTestFinished(describeChild(child));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -710,7 +711,6 @@ public class TeaVMTestRunner extends Runner implements Filterable {
|
||||||
|
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
notifier.fireTestFailure(createFailure(description, result));
|
notifier.fireTestFailure(createFailure(description, result));
|
||||||
notifier.fireTestFinished(description);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.junit;
|
package org.teavm.junit;
|
||||||
|
|
||||||
import org.teavm.classlib.impl.console.JSStdoutPrintStream;
|
import org.teavm.classlib.impl.console.JSConsoleStringPrintStream;
|
||||||
|
import org.teavm.interop.Import;
|
||||||
|
|
||||||
final class TestWasmGCEntryPoint {
|
final class TestWasmGCEntryPoint {
|
||||||
private TestWasmGCEntryPoint() {
|
private TestWasmGCEntryPoint() {
|
||||||
|
@ -24,12 +25,18 @@ final class TestWasmGCEntryPoint {
|
||||||
public static void main(String[] args) throws Throwable {
|
public static void main(String[] args) throws Throwable {
|
||||||
try {
|
try {
|
||||||
TestEntryPoint.run(args.length > 0 ? args[0] : null);
|
TestEntryPoint.run(args.length > 0 ? args[0] : null);
|
||||||
new JSStdoutPrintStream().println("SUCCESS");
|
reportSuccess();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
var out = new JSStdoutPrintStream();
|
var out = new JSConsoleStringPrintStream();
|
||||||
e.printStackTrace(out);
|
e.printStackTrace(out);
|
||||||
out.println("FAILURE");
|
reportFailure(out.toString());
|
||||||
}
|
}
|
||||||
TestEntryPoint.run(args.length > 0 ? args[0] : null);
|
TestEntryPoint.run(args.length > 0 ? args[0] : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Import(module = "teavmTest", name = "success")
|
||||||
|
private static native void reportSuccess();
|
||||||
|
|
||||||
|
@Import(module = "teavmTest", name = "failure")
|
||||||
|
private static native void reportFailure(String message);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ class WebAssemblyGCPlatformSupport extends TestPlatformSupport<WasmGCTarget> {
|
||||||
TestRunStrategy createRunStrategy(File outputDir) {
|
TestRunStrategy createRunStrategy(File outputDir) {
|
||||||
var runStrategyName = System.getProperty(WASM_RUNNER);
|
var runStrategyName = System.getProperty(WASM_RUNNER);
|
||||||
return runStrategyName != null
|
return runStrategyName != null
|
||||||
? new BrowserRunStrategy(outputDir, "WASM", BrowserRunner.pickBrowser(runStrategyName))
|
? new BrowserRunStrategy(outputDir, "WASM_GC", BrowserRunner.pickBrowser(runStrategyName))
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user