diff --git a/js/js.tests/test/org/jetbrains/kotlin/generators/tests/GenerateJsTests.kt b/js/js.tests/test/org/jetbrains/kotlin/generators/tests/GenerateJsTests.kt index eaf6212af17..f137f208249 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/generators/tests/GenerateJsTests.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/generators/tests/GenerateJsTests.kt @@ -43,7 +43,12 @@ fun main(args: Array) { } testGroup("js/js.tests/tests-gen", "compiler/testData") { - testClass { + testClass { + model("klibABI/", pattern = "^([^_](.+))$", targetBackend = TargetBackend.JS_IR, recursive = false, ) + } + } + testGroup("js/js.tests/tests-gen", "compiler/testData") { + testClass { model("klibABI/", pattern = "^([^_](.+))$", targetBackend = TargetBackend.JS_IR, recursive = false, ) } } diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/AbstractJsKLibABITestCase.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/AbstractJsKLibABITestCase.kt index 5206112e82f..bd02e06afa1 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/AbstractJsKLibABITestCase.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/AbstractJsKLibABITestCase.kt @@ -14,8 +14,11 @@ import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.config.CommonConfigurationKeys +import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.ir.backend.js.* import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity +import org.jetbrains.kotlin.ir.backend.js.ic.CacheUpdater +import org.jetbrains.kotlin.ir.backend.js.ic.JsExecutableProducer import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformerTmp import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.TranslationMode import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl @@ -28,7 +31,17 @@ import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.serialization.js.ModuleKind import java.io.File +abstract class AbstractJsKLibABIWithICTestCase : AbstractJsKLibABITestCase() { + override val useIncrementalCompiler get() = true +} + +abstract class AbstractJsKLibABINoICTestCase : AbstractJsKLibABITestCase() { + override val useIncrementalCompiler get() = false +} + abstract class AbstractJsKLibABITestCase : AbstractKlibABITestCase() { + abstract val useIncrementalCompiler: Boolean + override fun stdlibFile(): File = File("libraries/stdlib/js-ir/build/classes/kotlin/js/main").absoluteFile override fun buildKlib(moduleName: String, moduleSourceDir: File, moduleDependencies: Collection, klibFile: File) { @@ -50,37 +63,22 @@ abstract class AbstractJsKLibABITestCase : AbstractKlibABITestCase() { } override fun buildBinaryAndRun(mainModuleKlibFile: File, libraries: Collection) { - val project = environment.project - val configuration = environment.configuration + val configuration = environment.configuration.copy() configuration.put(JSConfigurationKeys.PARTIAL_LINKAGE, true) configuration.put(JSConfigurationKeys.MODULE_KIND, ModuleKind.PLAIN) configuration.put(JSConfigurationKeys.PROPERTY_LAZY_INITIALIZATION, true) configuration.put(CommonConfigurationKeys.MODULE_NAME, MAIN_MODULE_NAME) - val kLib = MainModule.Klib(mainModuleKlibFile.path) - val moduleStructure = ModulesStructure(project, kLib, configuration, libraries.map { it.path }, emptyList()) - - val ir = compile( - moduleStructure, - PhaseConfig(jsPhases), - IrFactoryImplForJsIC(WholeWorldStageController()), - exportedDeclarations = setOf(FqName("box")), - granularity = JsGenerationGranularity.PER_MODULE, - icCompatibleIr2Js = true - ) - - val transformer = IrModuleToJsTransformerTmp(ir.context, emptyList()) - - val compiledResult = transformer.generateModule(ir.allModules, setOf(TranslationMode.FULL_DCE_MINIMIZED_NAMES), false) - - val dceOutput = compiledResult.outputs[TranslationMode.FULL_DCE_MINIMIZED_NAMES] ?: error("No DCE output") + val compilationOutputs = if (useIncrementalCompiler) + buildBinaryWithIC(configuration, mainModuleKlibFile, libraries) + else + buildBinaryNoIC(configuration, mainModuleKlibFile, libraries) val binariesDir = File(buildDir, BIN_DIR_NAME).also { it.mkdirs() } - val binaries = ArrayList(libraries.size) - for ((name, code) in dceOutput.dependencies) { + for ((name, code) in compilationOutputs.dependencies) { val depBinary = binariesDir.binJsFile(name) depBinary.parentFile?.let { if (!it.exists()) it.mkdirs() } depBinary.writeText(code.jsCode) @@ -88,12 +86,73 @@ abstract class AbstractJsKLibABITestCase : AbstractKlibABITestCase() { } val mainBinary = binariesDir.binJsFile(MAIN_MODULE_NAME) - mainBinary.writeText(dceOutput.jsCode) + mainBinary.writeText(compilationOutputs.jsCode) binaries.add(mainBinary) executeAndCheckBinaries(MAIN_MODULE_NAME, binaries) } + private fun buildBinaryWithIC( + configuration: CompilerConfiguration, + mainModuleKlibFile: File, + libraries: Collection + ): CompilationOutputs { + fun cacheDir(library: File): File = buildDir.resolve("libs-cache").resolve(library.name).apply { mkdirs() } + + val cacheUpdater = CacheUpdater( + mainModule = mainModuleKlibFile.absolutePath, + allModules = libraries.map { it.absolutePath }, + icCachePaths = libraries.map { cacheDir(it).absolutePath }, + compilerConfiguration = configuration, + irFactory = { IrFactoryImplForJsIC(WholeWorldStageController()) }, + mainArguments = null, + compilerInterfaceFactory = { mainModule, cfg -> JsIrCompilerWithIC(mainModule, cfg, setOf(BOX_FUN_FQN)) } + ) + val icCaches = cacheUpdater.actualizeCaches() + + val mainModuleName = icCaches.last().moduleExternalName + val jsExecutableProducer = JsExecutableProducer( + mainModuleName = mainModuleName, + moduleKind = configuration[JSConfigurationKeys.MODULE_KIND]!!, + sourceMapsInfo = SourceMapsInfo.from(configuration), + caches = icCaches, + relativeRequirePath = true + ) + + return jsExecutableProducer.buildExecutable(multiModule = true, outJsProgram = true) {} + } + + private fun buildBinaryNoIC( + configuration: CompilerConfiguration, + mainModuleKlibFile: File, + libraries: Collection + ): CompilationOutputs { + val klib = MainModule.Klib(mainModuleKlibFile.path) + val moduleStructure = ModulesStructure(environment.project, klib, configuration, libraries.map { it.path }, emptyList()) + + val ir = compile( + moduleStructure, + PhaseConfig(jsPhases), + IrFactoryImplForJsIC(WholeWorldStageController()), + exportedDeclarations = setOf(BOX_FUN_FQN), + granularity = JsGenerationGranularity.PER_MODULE, + icCompatibleIr2Js = true + ) + + val transformer = IrModuleToJsTransformerTmp( + backendContext = ir.context, + mainArguments = emptyList() + ) + + val compiledResult = transformer.generateModule( + modules = ir.allModules, + modes = setOf(TranslationMode.FULL_DCE_MINIMIZED_NAMES), + relativeRequirePath = false + ) + + return compiledResult.outputs[TranslationMode.FULL_DCE_MINIMIZED_NAMES] ?: error("No DCE output") + } + private fun KotlinCoreEnvironment.createPsiFiles(sourceDir: File): List { val psiManager = PsiManager.getInstance(project) val fileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL) as CoreLocalFileSystem @@ -112,10 +171,11 @@ abstract class AbstractJsKLibABITestCase : AbstractKlibABITestCase() { val checker = V8IrJsTestChecker val filePaths = dependencies.map { it.canonicalPath } - checker.check(filePaths, mainModuleName, null, "box", "OK", withModuleSystem = false) + checker.check(filePaths, mainModuleName, null, BOX_FUN_FQN.asString(), "OK", withModuleSystem = false) } companion object { private const val BIN_DIR_NAME = "_bins_js" + private val BOX_FUN_FQN = FqName("box") } } diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsKLibABITestCaseGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsKLibABINoICTestCaseGenerated.java similarity index 98% rename from js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsKLibABITestCaseGenerated.java rename to js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsKLibABINoICTestCaseGenerated.java index b4d0917c45b..e65fd20e795 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsKLibABITestCaseGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsKLibABINoICTestCaseGenerated.java @@ -21,7 +21,7 @@ import java.util.regex.Pattern; @TestMetadata("compiler/testData/klibABI") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) -public class JsKLibABITestCaseGenerated extends AbstractJsKLibABITestCase { +public class JsKLibABINoICTestCaseGenerated extends AbstractJsKLibABINoICTestCase { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, TargetBackend.JS_IR, testDataFilePath); } diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsKLibABIWithICTestCaseGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsKLibABIWithICTestCaseGenerated.java new file mode 100644 index 00000000000..d202342ac17 --- /dev/null +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsKLibABIWithICTestCaseGenerated.java @@ -0,0 +1,122 @@ +/* + * Copyright 2010-2022 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; + +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.GenerateJsTestsKt}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("compiler/testData/klibABI") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class JsKLibABIWithICTestCaseGenerated extends AbstractJsKLibABIWithICTestCase { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JS_IR, testDataFilePath); + } + + public void testAllFilesPresentInKlibABI() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/klibABI"), Pattern.compile("^([^_](.+))$"), null, TargetBackend.JS_IR, false); + } + + @TestMetadata("removeAbstractFunctionFromAbstractClass") + public void testRemoveAbstractFunctionFromAbstractClass() throws Exception { + runTest("compiler/testData/klibABI/removeAbstractFunctionFromAbstractClass/"); + } + + @TestMetadata("removeAbstractFunctionFromInterface") + public void testRemoveAbstractFunctionFromInterface() throws Exception { + runTest("compiler/testData/klibABI/removeAbstractFunctionFromInterface/"); + } + + @TestMetadata("removeAbstractPropertyFromAbstractClass") + public void testRemoveAbstractPropertyFromAbstractClass() throws Exception { + runTest("compiler/testData/klibABI/removeAbstractPropertyFromAbstractClass/"); + } + + @TestMetadata("removeAbstractPropertyFromInterface") + public void testRemoveAbstractPropertyFromInterface() throws Exception { + runTest("compiler/testData/klibABI/removeAbstractPropertyFromInterface/"); + } + + @TestMetadata("removeClassAsConstructorCall") + public void testRemoveClassAsConstructorCall() throws Exception { + runTest("compiler/testData/klibABI/removeClassAsConstructorCall/"); + } + + @TestMetadata("removeClassAsParameterType") + public void testRemoveClassAsParameterType() throws Exception { + runTest("compiler/testData/klibABI/removeClassAsParameterType/"); + } + + @TestMetadata("removeClassAsReturnType") + public void testRemoveClassAsReturnType() throws Exception { + runTest("compiler/testData/klibABI/removeClassAsReturnType/"); + } + + @TestMetadata("removeClassAsSuperTypeArgument") + public void testRemoveClassAsSuperTypeArgument() throws Exception { + runTest("compiler/testData/klibABI/removeClassAsSuperTypeArgument/"); + } + + @TestMetadata("removeClassAsTypeArgument") + public void testRemoveClassAsTypeArgument() throws Exception { + runTest("compiler/testData/klibABI/removeClassAsTypeArgument/"); + } + + @TestMetadata("removeClassAsVariableType") + public void testRemoveClassAsVariableType() throws Exception { + runTest("compiler/testData/klibABI/removeClassAsVariableType/"); + } + + @TestMetadata("removeFunction") + public void testRemoveFunction() throws Exception { + runTest("compiler/testData/klibABI/removeFunction/"); + } + + @TestMetadata("removeInlinedClass") + public void testRemoveInlinedClass() throws Exception { + runTest("compiler/testData/klibABI/removeInlinedClass/"); + } + + @TestMetadata("removeInlinedFunction") + public void testRemoveInlinedFunction() throws Exception { + runTest("compiler/testData/klibABI/removeInlinedFunction/"); + } + + @TestMetadata("removeInlinedProperty") + public void testRemoveInlinedProperty() throws Exception { + runTest("compiler/testData/klibABI/removeInlinedProperty/"); + } + + @TestMetadata("removeOpenFunction") + public void testRemoveOpenFunction() throws Exception { + runTest("compiler/testData/klibABI/removeOpenFunction/"); + } + + @TestMetadata("removeOpenProperty") + public void testRemoveOpenProperty() throws Exception { + runTest("compiler/testData/klibABI/removeOpenProperty/"); + } + + @TestMetadata("removeProperty") + public void testRemoveProperty() throws Exception { + runTest("compiler/testData/klibABI/removeProperty/"); + } + + @TestMetadata("typeAliasRHSTypeChange") + public void testTypeAliasRHSTypeChange() throws Exception { + runTest("compiler/testData/klibABI/typeAliasRHSTypeChange/"); + } +}