From 7bd9462ffb1e5f0ccbcc9bec8e1477e0474a836c Mon Sep 17 00:00:00 2001 From: Anton Bannykh Date: Wed, 30 Sep 2020 13:35:36 +0300 Subject: [PATCH] [JS IR] save the desired JS output file name in the klib. This is only usedful for code splitting. The output .js file name is provided by the build system during the module compilation. It is desirable to keep the .js output file names same as in old BE, but calculating those name during the klib -> js phase is tricky. Thus the desired names are saved in the klib, and used later on. --- .../cli/cli-js-klib/src/GenerateJsIrKlib.kt | 0 .../jetbrains/kotlin/cli/js/K2JsIrCompiler.kt | 4 +- .../kotlin/ir/backend/js/compiler.kt | 8 ++-- .../irToJs/IrModuleToJsTransformer.kt | 7 +-- .../jetbrains/kotlin/ir/backend/js/klib.kt | 46 +++++++++++++++---- .../kotlin/benchmarks/GenerateIrRuntime.kt | 3 +- .../kotlin/js/test/BasicIrBoxTest.kt | 3 +- 7 files changed, 51 insertions(+), 20 deletions(-) create mode 100644 compiler/cli/cli-js-klib/src/GenerateJsIrKlib.kt diff --git a/compiler/cli/cli-js-klib/src/GenerateJsIrKlib.kt b/compiler/cli/cli-js-klib/src/GenerateJsIrKlib.kt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt index 67534c81b0c..4ffae7ad7c4 100644 --- a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt +++ b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt @@ -205,8 +205,8 @@ class K2JsIrCompiler : CLICompiler() { friendDependencies = friendDependencies, irFactory = PersistentIrFactory(), // TODO IrFactoryImpl? outputKlibPath = outputFile.path, - nopack = arguments.irProduceKlibDir - ) + nopack = arguments.irProduceKlibDir, + jsOutputName = FileUtil.getNameWithoutExtension(outputFile),) } if (arguments.irProduceJs) { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt index 985a5323594..c6e5ff00864 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt @@ -54,7 +54,7 @@ fun compile( propertyLazyInitialization: Boolean, legacyPropertyAccess: Boolean = false, ): CompilerResult { - val (moduleFragment: IrModuleFragment, dependencyModules, irBuiltIns, symbolTable, deserializer) = + val (moduleFragment: IrModuleFragment, dependencyModules, irBuiltIns, symbolTable, deserializer, moduleToName) = loadIr(project, mainModule, analyzer, configuration, allDependencies, friendDependencies, irFactory) val moduleDescriptor = moduleFragment.descriptor @@ -109,7 +109,8 @@ fun compile( fullJs = true, dceJs = false, multiModule = multiModule, - relativeRequirePath = relativeRequirePath + relativeRequirePath = relativeRequirePath, + moduleToName = moduleToName, ) return transformer.generateModule(allModules) } else { @@ -120,7 +121,8 @@ fun compile( fullJs = generateFullJs, dceJs = generateDceJs, multiModule = multiModule, - relativeRequirePath = relativeRequirePath + relativeRequirePath = relativeRequirePath, + moduleToName = moduleToName, ) return transformer.generateModule(allModules) } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt index 588d383c4cc..455ff4fb085 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt @@ -31,7 +31,8 @@ class IrModuleToJsTransformer( private val fullJs: Boolean = true, private val dceJs: Boolean = false, private val multiModule: Boolean = false, - private val relativeRequirePath: Boolean = false + private val relativeRequirePath: Boolean = false, + private val moduleToName: Map = emptyMap() ) { private val generateRegionComments = backendContext.configuration.getBoolean(JSConfigurationKeys.GENERATE_REGION_COMMENTS) @@ -91,7 +92,7 @@ class IrModuleToJsTransformer( ) val dependencies = others.mapIndexed { index, module -> - val moduleName = sanitizeName(module.safeName) + val moduleName = moduleToName[module] ?: sanitizeName(module.safeName) val exportedDeclarations = ExportModelGenerator(backendContext).let { module.files.flatMap { file -> it.generateExport(file) } } @@ -206,7 +207,7 @@ class IrModuleToJsTransformer( } val moduleName = declareFreshGlobal(module.safeName) - modules += JsImportedModule(moduleName.ident, moduleName, moduleName.makeRef(), relativeRequirePath) + modules += JsImportedModule(moduleToName[module] ?: moduleName.ident, moduleName, moduleName.makeRef(), relativeRequirePath) names.forEach { imports += JsVars(JsVars.JsVar(JsName(it), JsNameRef(it, JsNameRef("\$crossModule\$", moduleName.makeRef())))) diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt index 9d9436d1875..600668197a5 100644 --- a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt @@ -70,6 +70,7 @@ import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.utils.DFS import java.io.File +import java.util.* import org.jetbrains.kotlin.konan.file.File as KFile val KotlinLibrary.moduleName: String @@ -104,7 +105,8 @@ fun generateKLib( friendDependencies: List, irFactory: IrFactory, outputKlibPath: String, - nopack: Boolean + nopack: Boolean, + jsOutputName: String?, ) { val incrementalDataProvider = configuration.get(JSConfigurationKeys.INCREMENTAL_DATA_PROVIDER) val errorPolicy = configuration.get(JSConfigurationKeys.ERROR_TOLERANCE_POLICY) ?: ErrorTolerancePolicy.DEFAULT @@ -194,7 +196,8 @@ fun generateKLib( icData, nopack, perFile = false, - hasErrors + hasErrors, + jsOutputName ) } @@ -203,7 +206,8 @@ data class IrModuleInfo( val allDependencies: List, val bultins: IrBuiltIns, val symbolTable: SymbolTable, - val deserializer: JsIrLinker + val deserializer: JsIrLinker, + val moduleFragmentToUniqueName: Map, ) private fun sortDependencies(dependencies: List, mapping: Map): Collection { @@ -238,9 +242,14 @@ fun loadIr( val feContext = psi2IrContext.run { JsIrLinker.JsFePluginContext(moduleDescriptor, symbolTable, typeTranslator, irBuiltIns) } + val moduleFragmentToUniqueName = mutableMapOf() val irLinker = JsIrLinker(psi2IrContext.moduleDescriptor, messageLogger, irBuiltIns, symbolTable, functionFactory, feContext, null) - val deserializedModuleFragments = sortDependencies(allDependencies.getFullList(), depsDescriptors.descriptors).map { - irLinker.deserializeIrModuleHeader(depsDescriptors.getModuleDescriptor(it), it) + val deserializedModuleFragments = sortDependencies(allDependencies.getFullList(), depsDescriptors.descriptors).map { klib -> + irLinker.deserializeIrModuleHeader(depsDescriptors.getModuleDescriptor(klib), klib).also { moduleFragment -> + klib.manifestProperties.getProperty(KLIB_PROPERTY_JS_OUTPUT_NAME)?.let { + moduleFragmentToUniqueName[moduleFragment] = it + } + } } val moduleFragment = psi2IrContext.generateModuleFragmentWithPlugins(project, mainModule.files, irLinker, messageLogger) @@ -257,7 +266,7 @@ fun loadIr( irBuiltIns.knownBuiltins.forEach { it.acceptVoid(mangleChecker) } - return IrModuleInfo(moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, irLinker) + return IrModuleInfo(moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, irLinker, moduleFragmentToUniqueName) } is MainModule.Klib -> { val moduleDescriptor = depsDescriptors.getModuleDescriptor(mainModule.lib) @@ -271,14 +280,20 @@ fun loadIr( val irLinker = JsIrLinker(null, messageLogger, irBuiltIns, symbolTable, functionFactory, null, null) - val deserializedModuleFragments = sortDependencies(allDependencies.getFullList(), depsDescriptors.descriptors).map { + val moduleFragmentToUniqueName = mutableMapOf() + + val deserializedModuleFragments = sortDependencies(allDependencies.getFullList(), depsDescriptors.descriptors).map { klib -> val strategy = if (it == mainModule.lib) DeserializationStrategy.ALL else DeserializationStrategy.EXPLICITLY_EXPORTED - irLinker.deserializeIrModuleHeader(depsDescriptors.getModuleDescriptor(it), it, strategy) + irLinker.deserializeIrModuleHeader(depsDescriptors.getModuleDescriptor(klib), klib, strategy).also { moduleFragment -> + klib.manifestProperties.getProperty(KLIB_PROPERTY_JS_OUTPUT_NAME)?.let { + moduleFragmentToUniqueName[moduleFragment] = it + } + } } irBuiltIns.functionFactory = functionFactory @@ -288,7 +303,7 @@ fun loadIr( ExternalDependenciesGenerator(symbolTable, listOf(irLinker)).generateUnboundSymbolsAsDependencies() irLinker.postProcess() - return IrModuleInfo(moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, irLinker) + return IrModuleInfo(moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, irLinker, moduleFragmentToUniqueName) } } } @@ -475,7 +490,8 @@ fun serializeModuleIntoKlib( cleanFiles: List, nopack: Boolean, perFile: Boolean, - containsErrorCode: Boolean = false + containsErrorCode: Boolean = false, + jsOutputName: String?, ) { assert(files.size == moduleFragment.files.size) @@ -551,6 +567,14 @@ fun serializeModuleIntoKlib( } } else null + val properties = Properties().also { p -> + if (jsOutputName != null) { + p.setProperty(KLIB_PROPERTY_JS_OUTPUT_NAME, jsOutputName) + } + if (containsErrorCode) { + p.setProperty(KLIB_PROPERTY_CONTAINS_ERROR_CODE, "true") + } + buildKotlinLibrary( linkDependencies = dependencies, ir = fullSerializedIr, @@ -566,6 +590,8 @@ fun serializeModuleIntoKlib( ) } +const val KLIB_PROPERTY_JS_OUTPUT_NAME = "jsOutputName" + private fun KlibMetadataIncrementalSerializer.serializeScope( ktFile: KtFile, bindingContext: BindingContext, diff --git a/js/js.tests/test/org/jetbrains/kotlin/benchmarks/GenerateIrRuntime.kt b/js/js.tests/test/org/jetbrains/kotlin/benchmarks/GenerateIrRuntime.kt index 8efb7d91545..81904cf75fb 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/benchmarks/GenerateIrRuntime.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/benchmarks/GenerateIrRuntime.kt @@ -491,7 +491,8 @@ class GenerateIrRuntime { mutableMapOf(), emptyList(), true, - perFile + perFile, + null ) return tmpKlibDir diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt index 16cebd39fd1..75b2ed85127 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt @@ -188,7 +188,8 @@ abstract class BasicIrBoxTest( friendDependencies = emptyList(), irFactory = IrFactoryImpl, outputKlibPath = actualOutputFile, - nopack = true + nopack = true, + null ) logger.logFile("Output klib", File(actualOutputFile))