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))