diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt index 8f167bb12e3..f9a282b1eb9 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt @@ -57,6 +57,7 @@ class JsIrBackendContext( val phaseConfig = PhaseConfig(jsPhases, configuration) override var inVerbosePhase: Boolean = false + val externalNestedClasses = mutableListOf() val packageLevelJsModules = mutableListOf() val declarationLevelJsModules = mutableListOf() diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveBodilessDeclarationsToSeparatePlace.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveBodilessDeclarationsToSeparatePlace.kt index 012f9dc8d89..71cd0f275d4 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveBodilessDeclarationsToSeparatePlace.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveBodilessDeclarationsToSeparatePlace.kt @@ -58,8 +58,22 @@ fun moveBodilessDeclarationsToSeparatePlace(context: JsIrBackendContext, module: } }, FqName.ROOT) + fun collectExternalClasses(container: IrDeclarationContainer, includeCurrentLevel: Boolean): List { + val externalClasses = + container.declarations.filterIsInstance().filter { it.isEffectivelyExternal() } + + val nestedExternalClasses = + externalClasses.flatMap { collectExternalClasses(it, true) } + + return if (includeCurrentLevel) + externalClasses + nestedExternalClasses + else + nestedExternalClasses + } fun lowerFile(irFile: IrFile): IrFile? { + context.externalNestedClasses += collectExternalClasses(irFile, includeCurrentLevel = false) + if (irFile.getJsModule() != null || irFile.getJsQualifier() != null) { context.packageLevelJsModules.add(irFile) return null 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 5efc6661f1a..77c732b15e7 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 @@ -9,14 +9,12 @@ import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.ModuleType -import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext -import org.jetbrains.kotlin.ir.backend.js.utils.Namer -import org.jetbrains.kotlin.ir.backend.js.utils.getJsModule -import org.jetbrains.kotlin.ir.backend.js.utils.getJsQualifier +import org.jetbrains.kotlin.ir.backend.js.utils.* import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithVisibility import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner import org.jetbrains.kotlin.ir.util.isEffectivelyExternal +import org.jetbrains.kotlin.ir.util.parentAsClass import org.jetbrains.kotlin.js.backend.ast.* import org.jetbrains.kotlin.js.config.JSConfigurationKeys import org.jetbrains.kotlin.utils.DFS @@ -106,7 +104,7 @@ class IrModuleToJsTransformer(private val backendContext: JsIrBackendContext) : val qualifiedReference: JsNameRef if (jsModule != null) { - val internalName = rootFunction.scope.declareFreshName("moduleImport") + val internalName = rootFunction.scope.declareFreshName(sanitizeName("\$module\$$jsModule")) packageLevelJsModules += JsImportedModule(jsModule, internalName, null) qualifiedReference = @@ -131,6 +129,19 @@ class IrModuleToJsTransformer(private val backendContext: JsIrBackendContext) : } } + for (externalClass in backendContext.externalNestedClasses) { + val declName = rootContext.getNameForDeclaration(externalClass) + val parentName = rootContext.getNameForDeclaration(externalClass.parentAsClass) + importStatements.add( + JsExpressionStatement( + jsAssignment( + declName.makeRef(), + JsNameRef(externalClass.name.identifier, parentName.makeRef()) + ) + ) + ) + } + val importedJsModules = declarationLevelJsModules + packageLevelJsModules rootFunction.parameters += importedJsModules.map { JsParameter(it.internalName) } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/SimpleNameGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/SimpleNameGenerator.kt index 4acc76a1aa3..6bf496f0349 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/SimpleNameGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/SimpleNameGenerator.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.ir.types.classifierOrFail import org.jetbrains.kotlin.ir.util.isDynamic import org.jetbrains.kotlin.ir.util.isEffectivelyExternal import org.jetbrains.kotlin.ir.util.isInlined +import org.jetbrains.kotlin.ir.util.parentAsClass import org.jetbrains.kotlin.js.backend.ast.JsName import org.jetbrains.kotlin.js.naming.isES5IdentifierPart import org.jetbrains.kotlin.js.naming.isES5IdentifierStart @@ -107,12 +108,19 @@ class SimpleNameGenerator : NameGenerator { if (declaration.isEffectivelyExternal()) { // TODO: descriptors are still used here due to the corresponding declaration doesn't have enough information yet - val descriptorForName = when (descriptor) { + val descriptorName = when (descriptor) { is ConstructorDescriptor -> descriptor.constructedClass is PropertyAccessorDescriptor -> descriptor.correspondingProperty else -> descriptor + }.name + + if (declaration is IrConstructor) return@getOrPut getNameForDeclaration(declaration.parentAsClass, context) + + if (declaration is IrClass && declaration.parent is IrClass) { + val parentName = getNameForDeclaration(declaration.parentAsClass, context).ident + return@getOrPut context.currentScope.declareFreshName(parentName + "$" + descriptorName.identifier) } - return@getOrPut context.staticContext.rootScope.declareName(descriptorForName.name.asString()) + return@getOrPut context.staticContext.rootScope.declareName(descriptorName.identifier) } when (declaration) { @@ -224,11 +232,11 @@ class SimpleNameGenerator : NameGenerator { nameDeclarator(sanitizeName(nameBuilder.toString())) } - - private fun sanitizeName(name: String): String { - if (name.isEmpty()) return "_" - - val first = name.first().let { if (it.isES5IdentifierStart()) it else '_' } - return first.toString() + name.drop(1).map { if (it.isES5IdentifierPart()) it else '_' }.joinToString("") - } +} + +fun sanitizeName(name: String): String { + if (name.isEmpty()) return "_" + + val first = name.first().let { if (it.isES5IdentifierStart()) it else '_' } + return first.toString() + name.drop(1).map { if (it.isES5IdentifierPart()) it else '_' }.joinToString("") } diff --git a/js/js.translator/testData/box/inheritance/fromNestedNativeClass.kt b/js/js.translator/testData/box/inheritance/fromNestedNativeClass.kt index d752b04e3ee..13eb4d566e5 100644 --- a/js/js.translator/testData/box/inheritance/fromNestedNativeClass.kt +++ b/js/js.translator/testData/box/inheritance/fromNestedNativeClass.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1288 // FILE: foo.kt diff --git a/js/js.translator/testData/box/jsModule/externalPackage.kt b/js/js.translator/testData/box/jsModule/externalPackage.kt index 58c48166643..2eafb178e38 100644 --- a/js/js.translator/testData/box/jsModule/externalPackage.kt +++ b/js/js.translator/testData/box/jsModule/externalPackage.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1290 // FILE: a.kt // MODULE_KIND: AMD diff --git a/js/js.translator/testData/box/jsModule/externalPackagePlain.kt b/js/js.translator/testData/box/jsModule/externalPackagePlain.kt index b8068f615c2..3da9b29e522 100644 --- a/js/js.translator/testData/box/jsModule/externalPackagePlain.kt +++ b/js/js.translator/testData/box/jsModule/externalPackagePlain.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1289 // FILE: a.kt @file:JsModule("lib") diff --git a/js/js.translator/testData/box/jsName/inheritFromRenamedNativeClass.kt b/js/js.translator/testData/box/jsName/inheritFromRenamedNativeClass.kt index 3a572655f65..bb889e5df56 100644 --- a/js/js.translator/testData/box/jsName/inheritFromRenamedNativeClass.kt +++ b/js/js.translator/testData/box/jsName/inheritFromRenamedNativeClass.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1288 // FILE: main.kt diff --git a/js/js.translator/testData/box/jsName/inheritFromRenamedNativeClassMultimodule.kt b/js/js.translator/testData/box/jsName/inheritFromRenamedNativeClassMultimodule.kt index 81e384010e8..a5d3a361e38 100644 --- a/js/js.translator/testData/box/jsName/inheritFromRenamedNativeClassMultimodule.kt +++ b/js/js.translator/testData/box/jsName/inheritFromRenamedNativeClassMultimodule.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1288 // MODULE: module1 // FILE: module1.kt diff --git a/js/js.translator/testData/box/jsQualifier/classes.kt b/js/js.translator/testData/box/jsQualifier/classes.kt index df97f87c8f6..c9e7040da14 100644 --- a/js/js.translator/testData/box/jsQualifier/classes.kt +++ b/js/js.translator/testData/box/jsQualifier/classes.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1282 // MODULE: lib // FILE: lib.kt diff --git a/js/js.translator/testData/box/native/useClassFromInlineFun.kt b/js/js.translator/testData/box/native/useClassFromInlineFun.kt index 3523ba82ded..c491f21536d 100644 --- a/js/js.translator/testData/box/native/useClassFromInlineFun.kt +++ b/js/js.translator/testData/box/native/useClassFromInlineFun.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1282 // FILE: main.kt diff --git a/js/js.translator/testData/box/nestedTypes/outerNative.kt b/js/js.translator/testData/box/nestedTypes/outerNative.kt index a3f163146fe..77d02c1df0c 100644 --- a/js/js.translator/testData/box/nestedTypes/outerNative.kt +++ b/js/js.translator/testData/box/nestedTypes/outerNative.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1281 package foo