[Wasm] Add JS interop tests

This commit is contained in:
Svyatoslav Kuzmich
2021-09-13 10:57:41 +03:00
parent a32b86d016
commit 0abc798da9
9 changed files with 200 additions and 18 deletions
+25
View File
@@ -0,0 +1,25 @@
// FILE: externals.js
function createObject() {
return {};
}
function setX(obj, x) {
obj.x = x;
}
function getX(obj) {
return obj.x;
}
// FILE: externals.kt
external interface Obj
external fun createObject(): Obj
external fun setX(obj: Obj, x: Int)
external fun getX(obj: Obj): Int
fun box(): String {
val obj = createObject()
setX(obj, 100)
if (getX(obj) != 100) return "Fail 2"
return "OK"
}
+19
View File
@@ -0,0 +1,19 @@
// MODULE: main
// FILE: externals.kt
class C(val x: Int)
@JsExport
fun makeC(x: Int): C = C(x)
@JsExport
fun getX(c: C): Int = c.x
fun box(): String = "OK"
// FILE: jsExport__after.js
const c = main.makeC(300);
if (main.getX(c) !== 300) {
throw "Fail 1";
}
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.js.test.es6.semantics.AbstractIrJsTypeScriptExportES
import org.jetbrains.kotlin.js.test.ir.semantics.*
import org.jetbrains.kotlin.js.test.semantics.*
import org.jetbrains.kotlin.js.test.wasm.semantics.AbstractIrCodegenBoxWasmTest
import org.jetbrains.kotlin.js.test.wasm.semantics.AbstractIrCodegenWasmJsInteropWasmTest
import org.jetbrains.kotlin.test.TargetBackend
fun main(args: Array<String>) {
@@ -111,6 +112,14 @@ fun main(args: Array<String>) {
)
}
testClass<AbstractIrCodegenWasmJsInteropWasmTest> {
model("codegen/boxWasmJsInterop", targetBackend = TargetBackend.WASM)
}
testClass<AbstractIrCodegenWasmJsInteropJsTest> {
model("codegen/boxWasmJsInterop", targetBackend = TargetBackend.JS_IR)
}
testClass<AbstractIrJsCodegenBoxES6Test> {
model("codegen/box", targetBackend = TargetBackend.JS_IR_ES6, excludeDirs = jvmOnlyBoxTests)
}
@@ -257,14 +257,27 @@ abstract class BasicBoxTest(
val additionalCommonFiles = additionalCommonFileDirectories.flatMap { baseDir ->
JsTestUtils.getFilesInDirectoryByExtension(baseDir + "/", JavaScript.EXTENSION)
}
val inputJsFiles = inputFiles
.filter { it.fileName.endsWith(".js") }
.map { inputJsFile ->
val sourceFile = File(inputJsFile.fileName)
val targetFile = File(outputDir, inputJsFile.module.outputFileSimpleName() + "-js-" + sourceFile.name)
FileUtil.copy(File(inputJsFile.fileName), targetFile)
targetFile.absolutePath
val inputJsFilesBefore = mutableListOf<String>()
val inputJsFilesAfter = mutableListOf<String>()
fun copyInputJsFile(inputJsFile: TestFile): String {
val sourceFile = File(inputJsFile.fileName)
val targetFile = File(outputDir, inputJsFile.module.outputFileSimpleName() + "-js-" + sourceFile.name)
FileUtil.copy(File(inputJsFile.fileName), targetFile)
return targetFile.absolutePath
}
inputFiles.forEach {
val name = it.fileName
when {
name.endsWith("__after.js") ->
inputJsFilesAfter += copyInputJsFile(it)
name.endsWith(".js") ->
inputJsFilesBefore += copyInputJsFile(it)
}
}
val additionalFiles = mutableListOf<String>()
@@ -288,23 +301,23 @@ abstract class BasicBoxTest(
additionalMainFiles += additionalMainJsFile
}
val allJsFiles = additionalFiles + inputJsFiles + generatedJsFiles.map { it.first } + globalCommonFiles + localCommonFiles +
additionalCommonFiles + additionalMainFiles
val allJsFiles = additionalFiles + inputJsFilesBefore + generatedJsFiles.map { it.first } + globalCommonFiles + localCommonFiles +
additionalCommonFiles + additionalMainFiles + inputJsFilesAfter
val dceAllJsFiles = additionalFiles + inputJsFiles + generatedJsFiles.map {
val dceAllJsFiles = additionalFiles + inputJsFilesBefore + generatedJsFiles.map {
it.first.replace(
outputDir.absolutePath,
dceOutputDir.absolutePath
)
} + globalCommonFiles + localCommonFiles + additionalCommonFiles + additionalMainFiles
} + globalCommonFiles + localCommonFiles + additionalCommonFiles + additionalMainFiles + inputJsFilesAfter
val pirAllJsFiles = additionalFiles + inputJsFiles + generatedJsFiles.map {
val pirAllJsFiles = additionalFiles + inputJsFilesBefore + generatedJsFiles.map {
it.first.replace(
outputDir.absolutePath,
pirOutputDir.absolutePath
)
} +
globalCommonFiles + localCommonFiles + additionalCommonFiles + additionalMainFiles
globalCommonFiles + localCommonFiles + additionalCommonFiles + additionalMainFiles + inputJsFilesAfter
val dontRunGeneratedCode =
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.ir.backend.js.MainModule
import org.jetbrains.kotlin.ir.backend.js.ModulesStructure
import org.jetbrains.kotlin.ir.backend.js.loadKlib
import org.jetbrains.kotlin.ir.backend.js.prepareAnalyzedSourceModule
import org.jetbrains.kotlin.ir.backend.js.utils.sanitizeName
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
import org.jetbrains.kotlin.js.config.JsConfig
import org.jetbrains.kotlin.js.facade.TranslationUnit
@@ -65,11 +66,27 @@ abstract class BasicWasmBoxTest(
val outputWatFile = outputFileBase + ".wat"
val outputWasmFile = outputFileBase + ".wasm"
val outputJsFile = outputFileBase + ".js"
val languageVersionSettings = inputFiles.mapNotNull { it.languageVersionSettings }.firstOrNull()
val kotlinFiles = inputFiles.filter { it.fileName.endsWith(".kt") }
val psiFiles = createPsiFiles(kotlinFiles.map { File(it.fileName).canonicalPath }.sorted())
val kotlinFiles = mutableListOf<String>()
val jsFilesBefore = mutableListOf<String>()
val jsFilesAfter = mutableListOf<String>()
inputFiles.forEach {
val name = it.fileName
when {
name.endsWith(".kt") ->
kotlinFiles += name
name.endsWith("__after.js") ->
jsFilesAfter += name
name.endsWith(".js") ->
jsFilesBefore += name
}
}
val psiFiles = createPsiFiles(kotlinFiles.map { File(it).canonicalPath }.sorted())
val config = createConfig(languageVersionSettings)
translateFiles(
file,
@@ -87,7 +104,9 @@ abstract class BasicWasmBoxTest(
"--experimental-wasm-typed-funcref",
"--experimental-wasm-gc",
"--experimental-wasm-eh",
outputJsFile
*jsFilesBefore.toTypedArray(),
outputJsFile,
*jsFilesAfter.toTypedArray(),
)
}
}
@@ -162,6 +181,8 @@ abstract class BasicWasmBoxTest(
const wasmBinary = read(String.raw`${outputWasmFile.absoluteFile}`, 'binary');
const wasmModule = new WebAssembly.Module(wasmBinary);
wasmInstance = new WebAssembly.Instance(wasmModule, { runtime, js_code });
const ${sanitizeName(config.moduleId)} = wasmInstance.exports;
const actualResult = importStringFromWasm(wasmInstance.exports.$testFunction());
if (actualResult !== "OK")
@@ -215,7 +236,7 @@ abstract class BasicWasmBoxTest(
companion object {
const val TEST_DATA_DIR_PATH = "js/js.translator/testData/"
const val TEST_MODULE = "WASM_TESTS"
const val TEST_MODULE = "main"
private const val TEST_FUNCTION = "box"
}
}
@@ -24,6 +24,12 @@ abstract class AbstractJsCodegenInlineTest : BasicBoxTest(
"codegen/boxInline"
)
abstract class AbstractIrCodegenWasmJsInteropJsTest : BasicBoxTest(
"compiler/testData/codegen/wasmJsInterop",
"codegen/wasmJsInteropWasm"
)
abstract class AbstractJsLegacyPrimitiveArraysBoxTest : BasicBoxTest(
"compiler/testData/codegen/box/arrays/",
"codegen/box/arrays-legacy-primitivearrays/",
@@ -10,4 +10,9 @@ import org.jetbrains.kotlin.js.test.BasicWasmBoxTest
abstract class AbstractIrCodegenBoxWasmTest : BasicWasmBoxTest(
"compiler/testData/codegen/box/",
"codegen/wasmBox/"
)
abstract class AbstractIrCodegenWasmJsInteropWasmTest : BasicWasmBoxTest(
"compiler/testData/codegen/wasmJsInterop",
"codegen/wasmJsInteropJs"
)
@@ -0,0 +1,42 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.js.test.semantics;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("compiler/testData/codegen/boxWasmJsInterop")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class IrCodegenWasmJsInteropJsTestGenerated extends AbstractIrCodegenWasmJsInteropJsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInBoxWasmJsInterop() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxWasmJsInterop"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
@TestMetadata("externals.kt")
public void testExternals() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/externals.kt");
}
@TestMetadata("jsExport.kt")
public void testJsExport() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/jsExport.kt");
}
}
@@ -0,0 +1,42 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.js.test.wasm.semantics;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("compiler/testData/codegen/boxWasmJsInterop")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class IrCodegenWasmJsInteropWasmTestGenerated extends AbstractIrCodegenWasmJsInteropWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInBoxWasmJsInterop() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxWasmJsInterop"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.WASM, true);
}
@TestMetadata("externals.kt")
public void testExternals() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/externals.kt");
}
@TestMetadata("jsExport.kt")
public void testJsExport() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/jsExport.kt");
}
}