diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.kt index fd1d9e5b9b3..8263ec44682 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.kt @@ -137,6 +137,9 @@ class K2JSCompilerArguments : CommonCompilerArguments() { @Argument(value = "-Xir-property-lazy-initialization", description = "Perform lazy initialization for properties") var irPropertyLazyInitialization: Boolean by FreezableVar(true) + @Argument(value = "-Xir-minimized-member-names", description = "Perform minimization for names of members") + var irMinimizedMemberNames: Boolean by FreezableVar(false) + @Argument(value = "-Xir-only", description = "Disables pre-IR backend") var irOnly: Boolean by FreezableVar(false) 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 7c4bc247b93..27743d43994 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 @@ -291,7 +291,7 @@ class K2JsIrCompiler : CLICompiler() { val moduleKind = configurationJs[JSConfigurationKeys.MODULE_KIND]!! - val translationMode = TranslationMode.fromFlags(false, arguments.irPerModule) + val translationMode = TranslationMode.fromFlags(false, arguments.irPerModule, false) val compiledModule = generateJsFromAst( moduleName, @@ -410,7 +410,10 @@ class K2JsIrCompiler : CLICompiler() { moduleToName = ir.moduleFragmentToUniqueName ) - transformer.generateModule(ir.allModules, setOf(TranslationMode.fromFlags(arguments.irDce, arguments.irPerModule))) + transformer.generateModule( + ir.allModules, + setOf(TranslationMode.fromFlags(arguments.irDce, arguments.irPerModule, arguments.irMinimizedMemberNames)) + ) } else { val transformer = IrModuleToJsTransformer( ir.context, diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/DeclarationOrigins.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/DeclarationOrigins.kt index 805e6bedab6..52461ff417e 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/DeclarationOrigins.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/DeclarationOrigins.kt @@ -13,6 +13,7 @@ object JsLoweredDeclarationOrigin : IrDeclarationOrigin { object JS_CLOSURE_BOX_CLASS_DECLARATION : IrDeclarationOriginImpl("JS_CLOSURE_BOX_CLASS_DECLARATION") object BRIDGE_WITH_STABLE_NAME : IrDeclarationOriginImpl("BRIDGE_WITH_STABLE_NAME") object BRIDGE_WITHOUT_STABLE_NAME : IrDeclarationOriginImpl("BRIDGE_WITHOUT_STABLE_NAME") + object BRIDGE_PROPERTY_ACCESSOR : IrDeclarationOriginImpl("BRIDGE_PROPERTY_ACCESSOR") object OBJECT_GET_INSTANCE_FUNCTION : IrDeclarationOriginImpl("OBJECT_GET_INSTANCE_FUNCTION") object JS_SHADOWED_EXPORT : IrDeclarationOriginImpl("JS_SHADOWED_EXPORT") object JS_SHADOWED_DEFAULT_PARAMETER : IrDeclarationOriginImpl("JS_SHADOWED_DEFAULT_PARAMETER") 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 c3dc3c846ce..5f10ea98b1c 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 @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder import org.jetbrains.kotlin.ir.backend.js.lower.JsInnerClassesSupport import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.JsPolyfills import org.jetbrains.kotlin.ir.backend.js.utils.JsInlineClassesUtils +import org.jetbrains.kotlin.ir.backend.js.utils.MinimizedNameGenerator import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames import org.jetbrains.kotlin.ir.builders.declarations.addFunction import org.jetbrains.kotlin.ir.declarations.* @@ -72,6 +73,11 @@ class JsIrBackendContext( val localClassNames: MutableMap = mutableMapOf() val extractedLocalClasses: MutableSet = hashSetOf() + val minimizedNameGenerator: MinimizedNameGenerator = + MinimizedNameGenerator() + + val fieldDataCache = mutableMapOf>() + override val builtIns = module.builtIns override val typeSystem: IrTypeSystemContext = IrTypeSystemContextImpl(irBuiltIns) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt index 37b415dc92e..e9c2b345dbe 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt @@ -549,6 +549,7 @@ class ExportModelGenerator( if (function.isFakeOverride && !function.isAllowedFakeOverriddenDeclaration(context)) return Exportability.NotNeeded if (function.origin == JsLoweredDeclarationOrigin.BRIDGE_WITHOUT_STABLE_NAME || + function.origin == JsLoweredDeclarationOrigin.BRIDGE_PROPERTY_ACCESSOR || function.origin == JsLoweredDeclarationOrigin.BRIDGE_WITH_STABLE_NAME || function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER || function.origin == JsLoweredDeclarationOrigin.OBJECT_GET_INSTANCE_FUNCTION || diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsBridgesConstruction.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsBridgesConstruction.kt index 2caf6b3a85b..4a1456275db 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsBridgesConstruction.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsBridgesConstruction.kt @@ -52,10 +52,11 @@ class JsBridgesConstruction(context: JsIrBackendContext) : BridgesConstruction JsLoweredDeclarationOrigin.BRIDGE_WITH_STABLE_NAME + bridge.correspondingPropertySymbol != null -> JsLoweredDeclarationOrigin.BRIDGE_PROPERTY_ACCESSOR + else -> JsLoweredDeclarationOrigin.BRIDGE_WITHOUT_STABLE_NAME + } override fun extractValueParameters( blockBodyBuilder: IrBlockBodyBuilder, diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsPropertyAccessorInlineLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsPropertyAccessorInlineLowering.kt index 1f296b8fde6..fcc7a61e309 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsPropertyAccessorInlineLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsPropertyAccessorInlineLowering.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.ir.backend.js.lower +import org.jetbrains.kotlin.backend.common.ir.isTopLevel import org.jetbrains.kotlin.backend.common.lower.optimizations.PropertyAccessorInlineLowering import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity @@ -19,6 +20,9 @@ class JsPropertyAccessorInlineLowering( if (!isSafeToInlineInClosedWorld()) return false + // Member properties could be safely inlined, because initialization processed via parent declaration + if (!isTopLevel) return true + // TODO: teach the deserializer to load constant property initializers if (context.icCompatibleIr2Js) { val accessFile = accessContainer.fileOrNull ?: return false 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 21e2ed51b89..d0eba890169 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 @@ -68,7 +68,7 @@ class IrModuleToJsTransformer( val code = EnumMap(TranslationMode::class.java) - if (fullJs) code[TranslationMode.fromFlags(false, multiModule)] = generateWrappedModuleBody(modules, exportedModule, namer) + if (fullJs) code[TranslationMode.fromFlags(false, multiModule, false)] = generateWrappedModuleBody(modules, exportedModule, namer) if (dceJs) { eliminateDeadDeclarations(modules, backendContext, removeUnusedAssociatedObjects) @@ -76,7 +76,7 @@ class IrModuleToJsTransformer( // TODO: is this mode relevant for scripting? If yes, refactor so that the external name tables are used here when needed. val namer = NameTables(emptyList(), context = backendContext) namer.merge(modules.flatMap { it.files }, additionalPackages) - code[TranslationMode.fromFlags(true, multiModule)] = generateWrappedModuleBody(modules, exportedModule, namer) + code[TranslationMode.fromFlags(true, multiModule, false)] = generateWrappedModuleBody(modules, exportedModule, namer) } return CompilerResult(code, dts) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformerTmp.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformerTmp.kt index 61a152cea4d..0c35df44c60 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformerTmp.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformerTmp.kt @@ -33,18 +33,30 @@ import java.io.ByteArrayOutputStream import java.io.File import java.util.* -enum class TranslationMode(val dce: Boolean, val perModule: Boolean) { - FULL(dce = false, perModule = false), - FULL_DCE(dce = true, perModule = false), - PER_MODULE(dce = false, perModule = true), - PER_MODULE_DCE(dce = true, perModule = true); +enum class TranslationMode( + val dce: Boolean, + val perModule: Boolean, + val minimizedMemberNames: Boolean, +) { + FULL(dce = false, perModule = false, minimizedMemberNames = false), + FULL_DCE(dce = true, perModule = false, minimizedMemberNames = false), + FULL_DCE_MINIMIZED_NAMES(dce = true, perModule = false, minimizedMemberNames = true), + PER_MODULE(dce = false, perModule = true, minimizedMemberNames = false), + PER_MODULE_DCE(dce = true, perModule = true, minimizedMemberNames = false), + PER_MODULE_DCE_MINIMIZED_NAMES(dce = true, perModule = true, minimizedMemberNames = true); companion object { - fun fromFlags(dce: Boolean, perModule: Boolean): TranslationMode { + fun fromFlags(dce: Boolean, perModule: Boolean, minimizedMemberNames: Boolean): TranslationMode { return if (perModule) { - if (dce) PER_MODULE_DCE else PER_MODULE + if (dce) { + if (minimizedMemberNames) PER_MODULE_DCE_MINIMIZED_NAMES + else PER_MODULE_DCE + } else PER_MODULE } else { - if (dce) FULL_DCE else FULL + if (dce) { + if (minimizedMemberNames) FULL_DCE_MINIMIZED_NAMES + else FULL_DCE + } else FULL } } } @@ -78,11 +90,11 @@ class IrModuleToJsTransformerTmp( module.files.forEach { StaticMembersLowering(backendContext).lower(it) } } - fun compilationOutput(multiModule: Boolean) = generateWrappedModuleBody( + fun compilationOutput(multiModule: Boolean, minimizedMemberNames: Boolean) = generateWrappedModuleBody( multiModule, mainModuleName, moduleKind, - generateProgramFragments(modules, exportData), + generateProgramFragments(modules, exportData, minimizedMemberNames), SourceMapsInfo.from(backendContext.configuration), relativeRequirePath, generateScriptModule, @@ -91,7 +103,11 @@ class IrModuleToJsTransformerTmp( val result = EnumMap(TranslationMode::class.java) modes.filter { !it.dce }.forEach { - result[it] = compilationOutput(it.perModule) + if (it.minimizedMemberNames) { + backendContext.fieldDataCache.clear() + backendContext.minimizedNameGenerator.clear() + } + result[it] = compilationOutput(it.perModule, it.minimizedMemberNames) } if (modes.any { it.dce }) { @@ -99,7 +115,11 @@ class IrModuleToJsTransformerTmp( } modes.filter { it.dce }.forEach { - result[it] = compilationOutput(it.perModule) + if (it.minimizedMemberNames) { + backendContext.fieldDataCache.clear() + backendContext.minimizedNameGenerator.clear() + } + result[it] = compilationOutput(it.perModule, it.minimizedMemberNames) } return CompilerResult(result, dts) @@ -123,7 +143,7 @@ class IrModuleToJsTransformerTmp( val result = mutableMapOf() files.forEach { f -> val exports = exportData[f]!! // TODO - val fragment = generateProgramFragment(f, exports) + val fragment = generateProgramFragment(f, exports, minimizedMemberNames = false) val output = ByteArrayOutputStream() serializer.serialize(fragment, output) val binaryAst = output.toByteArray() @@ -146,6 +166,7 @@ class IrModuleToJsTransformerTmp( private fun generateProgramFragments( modules: Iterable, exportData: Map>>, + minimizedMemberNames: Boolean ): JsIrProgram { return JsIrProgram( modules.map { m -> @@ -154,7 +175,7 @@ class IrModuleToJsTransformerTmp( m.externalModuleName(), m.files.map { val exports = exportData[m]!![it]!! - generateProgramFragment(it, exports) + generateProgramFragment(it, exports, minimizedMemberNames) }, ) } @@ -164,8 +185,8 @@ class IrModuleToJsTransformerTmp( private val generateFilePaths = backendContext.configuration.getBoolean(JSConfigurationKeys.GENERATE_COMMENTS_WITH_FILE_PATH) private val pathPrefixMap = backendContext.configuration.getMap(JSConfigurationKeys.FILE_PATHS_PREFIX_MAP) - private fun generateProgramFragment(file: IrFile, exports: List): JsIrProgramFragment { - val nameGenerator = JsNameLinkingNamer(backendContext) + private fun generateProgramFragment(file: IrFile, exports: List, minimizedMemberNames: Boolean): JsIrProgramFragment { + val nameGenerator = JsNameLinkingNamer(backendContext, minimizedMemberNames) val globalNameScope = NameTable() diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIrProgramFragment.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIrProgramFragment.kt index 7e51e0ce8d6..9eec7e47b85 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIrProgramFragment.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIrProgramFragment.kt @@ -5,7 +5,7 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs -import org.jetbrains.kotlin.ir.backend.js.utils.sanitizeName +import org.jetbrains.kotlin.ir.backend.js.utils.toJsIdentifier import org.jetbrains.kotlin.js.backend.ast.* class JsIrProgramFragment(val packageFqn: String) { @@ -75,19 +75,15 @@ private class JsIrModuleCrossModuleReferecenceBuilder(val module: JsIrModule, va val exports = mutableSetOf() var transitiveJsExportFrom = emptyList() - private lateinit var exportNames: Map // tag -> name + private lateinit var exportNames: Map // tag -> index private fun buildUniqueNames() { - val names = module.fragments.flatMap { it.nameBindings.entries }.associate { it.key to sanitizeName(it.value.ident) } - val nameToCnt = mutableMapOf() - val result = mutableMapOf() + var index = 0 + exports.sorted().forEach { tag -> - val suggestedName = names[tag] ?: error("Name not found for tag $tag") - val suffix = nameToCnt[suggestedName]?.let { "_$it" } ?: "" - nameToCnt[suggestedName] = nameToCnt.getOrDefault(suggestedName, 0) + 1 - result[tag] = suggestedName + suffix + result[tag] = index++.toJsIdentifier() } exportNames = result @@ -132,7 +128,7 @@ private class JsIrModuleCrossModuleReferecenceBuilder(val module: JsIrModule, va class CrossModuleReferences( val importedModules: List, // additional Kotlin imported modules val imports: Map, // tag -> import statement - val exports: Map, // tag -> name + val exports: Map, // tag -> index val transitiveJsExportFrom: List // the list of modules which provide their js exports for transitive export ) { companion object { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsNameLinkingNamer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsNameLinkingNamer.kt index 3ba2f91cf76..19ae35da703 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsNameLinkingNamer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsNameLinkingNamer.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext +import org.jetbrains.kotlin.ir.backend.js.export.isExported import org.jetbrains.kotlin.ir.backend.js.utils.* import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.symbols.IrClassSymbol @@ -17,13 +18,15 @@ import org.jetbrains.kotlin.js.backend.ast.* import org.jetbrains.kotlin.utils.DFS import org.jetbrains.kotlin.utils.addToStdlib.safeAs -class JsNameLinkingNamer(private val context: JsIrBackendContext) : IrNamerBase() { +class JsNameLinkingNamer(private val context: JsIrBackendContext, private val minimizedMemberNames: Boolean) : IrNamerBase() { val nameMap = mutableMapOf() private fun IrDeclarationWithName.getName(prefix: String = ""): JsName { return nameMap.getOrPut(this) { - val name = (this as? IrClass)?.let { context.localClassNames[this] } ?: getJsNameOrKotlinName().asString() + val name = (this as? IrClass)?.let { context.localClassNames[this] } ?: let { + this.nameIfPropertyAccessor() ?: getJsNameOrKotlinName().asString() + } JsName(sanitizeName(prefix + name), true) } } @@ -82,7 +85,11 @@ class JsNameLinkingNamer(private val context: JsIrBackendContext) : IrNamerBase( override fun getNameForMemberFunction(function: IrSimpleFunction): JsName { require(function.dispatchReceiverParameter != null) val signature = jsFunctionSignature(function, context) - return signature.toJsName() + val result = if (minimizedMemberNames && !function.hasStableJsName(context)) { + function.parentAsClass.fieldData() + context.minimizedNameGenerator.nameBySignature(signature) + } else signature + return result.toJsName() } override fun getNameForMemberField(field: IrField): JsName { @@ -91,10 +98,8 @@ class JsNameLinkingNamer(private val context: JsIrBackendContext) : IrNamerBase( return JsName(field.parentAsClass.fieldData()[field]!!, false) } - private val fieldDataCache = mutableMapOf>() - private fun IrClass.fieldData(): Map { - return fieldDataCache.getOrPut(this) { + return context.fieldDataCache.getOrPut(this) { val nameCnt = mutableMapOf() val allClasses = DFS.topologicalOrder(listOf(this)) { node -> @@ -105,11 +110,37 @@ class JsNameLinkingNamer(private val context: JsIrBackendContext) : IrNamerBase( val result = mutableMapOf() + if (minimizedMemberNames) { + allClasses.reversed().forEach { + it.declarations.forEach { declaration -> + when { + declaration is IrFunction && declaration.dispatchReceiverParameter != null -> { + val property = (declaration as? IrSimpleFunction)?.correspondingPropertySymbol?.owner + if (property?.isExported(context) == true || property?.isEffectivelyExternal() == true) { + context.minimizedNameGenerator.reserveName(property.name.asString()) + } + if (declaration.hasStableJsName(context)) { + val signature = jsFunctionSignature(declaration, context) + context.minimizedNameGenerator.reserveName(signature) + } + } + declaration is IrProperty -> { + if (declaration.isExported(context)) { + context.minimizedNameGenerator.reserveName(declaration.name.asString()) + } + } + } + } + } + } + allClasses.reversed().forEach { it.declarations.forEach { when { it is IrField -> { - val safeName = it.safeName() + val safeName = if (minimizedMemberNames) { + context.minimizedNameGenerator.generateNextName() + } else it.safeName() val suffix = nameCnt.getOrDefault(safeName, 0) + 1 nameCnt[safeName] = suffix result[it] = safeName + "_$suffix" @@ -121,7 +152,7 @@ class JsNameLinkingNamer(private val context: JsIrBackendContext) : IrNamerBase( } } - return result + result } } } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/Merger.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/Merger.kt index 8b72533fbb8..a9fefae296c 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/Merger.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/Merger.kt @@ -71,10 +71,10 @@ class Merger( ).makeStmt() additionalExports += createExportBlock - crossModuleReferences.exports.entries.forEach { (tag, name) -> + crossModuleReferences.exports.entries.forEach { (tag, hash) -> val internalName = nameMap[tag] ?: error("Missing name for declaration '$tag'") val crossModuleRef = ReservedJsNames.makeCrossModuleNameRef(ReservedJsNames.makeInternalModuleName()) - additionalExports += jsAssignment(JsNameRef(name, crossModuleRef), JsNameRef(internalName)).makeStmt() + additionalExports += jsAssignment(JsNameRef(hash, crossModuleRef), JsNameRef(internalName)).makeStmt() } } } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/ReservedJsNames.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/ReservedJsNames.kt index e44caeba0cf..d77c9f2aab7 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/ReservedJsNames.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/ReservedJsNames.kt @@ -12,6 +12,6 @@ class ReservedJsNames { companion object { fun makeInternalModuleName() = JsName("_", false) fun makeJsExporterName() = JsName("\$jsExportAll\$", false) - fun makeCrossModuleNameRef(moduleName: JsName) = JsNameRef("\$crossModule\$", moduleName.makeRef()) + fun makeCrossModuleNameRef(moduleName: JsName) = JsNameRef("\$_\$", moduleName.makeRef()) } } \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/MinimizedNameGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/MinimizedNameGenerator.kt new file mode 100644 index 00000000000..d27218d267f --- /dev/null +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/MinimizedNameGenerator.kt @@ -0,0 +1,36 @@ +/* + * 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.ir.backend.js.utils + +class MinimizedNameGenerator { + private var index = 0 + private val functionSignatureToName = mutableMapOf() + private val reservedNames = mutableSetOf() + + fun generateNextName(): String { + var candidate = index++.toJsIdentifier() + while (candidate in reservedNames) { + candidate = index++.toJsIdentifier() + } + return candidate + } + + fun nameBySignature(signature: String): String { + return functionSignatureToName.getOrPut(signature) { + generateNextName() + } + } + + fun reserveName(signature: String) { + reservedNames.add(signature) + } + + fun clear() { + index = 0 + functionSignatureToName.clear() + reservedNames.clear() + } +} \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NameTables.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NameTables.kt index 64f3baa8e7f..d16335ddcad 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NameTables.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NameTables.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.backend.js.utils import org.jetbrains.kotlin.backend.common.ir.isTopLevel import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext +import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerIr import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* @@ -105,11 +106,21 @@ fun NameTable.dump(): String = private const val RESERVED_MEMBER_NAME_SUFFIX = "_k$" +fun Int.toJsIdentifier(): String { + val first = ('a'.code + (this % 26)).toChar().toString() + val other = this / 26 + return if (other == 0) { + first + } else { + first + other.toString(Character.MAX_RADIX) + } +} + fun jsFunctionSignature(declaration: IrFunction, context: JsIrBackendContext): String { require(!declaration.isStaticMethodOfClass) require(declaration.dispatchReceiverParameter != null) - val declarationName = declaration.getJsNameOrKotlinName().asString() + var declarationName = declaration.getJsNameOrKotlinName().asString() if (declaration.hasStableJsName(context)) { // TODO: Handle reserved suffix in FE @@ -119,6 +130,10 @@ fun jsFunctionSignature(declaration: IrFunction, context: JsIrBackendContext): S return declarationName } + declaration.nameIfPropertyAccessor()?.let { + declarationName = it + } + val nameBuilder = StringBuilder() nameBuilder.append(declarationName) @@ -139,7 +154,10 @@ fun jsFunctionSignature(declaration: IrFunction, context: JsIrBackendContext): S val signature = nameBuilder.toString() // TODO: Use better hashCode - return sanitizeName(declarationName) + "_" + abs(signature.hashCode()).toString(Character.MAX_RADIX) + RESERVED_MEMBER_NAME_SUFFIX + return sanitizeName( + declarationName, + withHash = false + ) + "_" + abs(signature.hashCode()).toString(Character.MAX_RADIX) + RESERVED_MEMBER_NAME_SUFFIX } class NameTables( @@ -295,8 +313,10 @@ class NameTables( } } - else -> - globalNames.declareFreshName(declaration, declaration.name.asString()) + else -> { + val name = declaration.nameIfPropertyAccessor() ?: declaration.name.asString() + globalNames.declareFreshName(declaration, name) + } } } @@ -393,12 +413,38 @@ fun sanitizeName(name: String, withHash: Boolean = true): String { } return if (withHash) { - "${builder}_${name.hashCode().toUInt()}" + "${builder}_${abs(name.hashCode()).toString(Character.MAX_RADIX)}" } else { builder.toString() } } +fun IrDeclarationWithName.nameIfPropertyAccessor(): String? { + if (this is IrSimpleFunction) { + return when { + this.correspondingPropertySymbol != null -> { + val property = this.correspondingPropertySymbol!!.owner + val name = property.getJsNameOrKotlinName().asString() + val prefix = when (this) { + property.getter -> "get_" + property.setter -> "set_" + else -> error("") + } + prefix + name + } + this.origin == JsLoweredDeclarationOrigin.BRIDGE_PROPERTY_ACCESSOR -> { + this.getJsNameOrKotlinName().asString() + .removePrefix("<") + .removeSuffix(">") + .replaceFirst("get-", "get_") + .replaceFirst("set-", "set_") + } + else -> null + } + } + return null +} + private inline fun Char.mangleIfNot(predicate: Char.() -> Boolean) = if (predicate()) this else '_' diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NewNamer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NewNamer.kt index 134b49f39ae..a0db720c621 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NewNamer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NewNamer.kt @@ -157,7 +157,8 @@ class NewNamerImpl( } else { // Non-external declaration - staticNames.declareFreshName(declaration, declaration.name.asString()) + val name = declaration.nameIfPropertyAccessor() ?: declaration.name.asString() + staticNames.declareFreshName(declaration, name) val unitReference = unit.referenceCodegenUnitOfDeclaration(declaration) if (unitReference is IrToJs.OtherUnitReference) { registerImport(unitReference.importPath, exportId(declaration)) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/misc.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/misc.kt index a9839411dbd..7ec33bc9bbb 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/misc.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/misc.kt @@ -8,17 +8,16 @@ package org.jetbrains.kotlin.ir.backend.js.utils import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny import org.jetbrains.kotlin.backend.common.ir.isTopLevel import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin import org.jetbrains.kotlin.ir.backend.js.export.isExported import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl -import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.expressions.IrBlockBody +import org.jetbrains.kotlin.ir.expressions.IrBody +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrExpressionBody import org.jetbrains.kotlin.ir.types.getClass import org.jetbrains.kotlin.ir.types.isNullableAny import org.jetbrains.kotlin.ir.util.isEffectivelyExternal @@ -38,7 +37,8 @@ fun IrFunction.hasStableJsName(context: JsIrBackendContext): Boolean { if ( origin == JsLoweredDeclarationOrigin.JS_SHADOWED_EXPORT || origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER || - origin == JsLoweredDeclarationOrigin.BRIDGE_WITHOUT_STABLE_NAME + origin == JsLoweredDeclarationOrigin.BRIDGE_WITHOUT_STABLE_NAME || + origin == JsLoweredDeclarationOrigin.BRIDGE_PROPERTY_ACCESSOR ) { return false } diff --git a/compiler/testData/cli/js/jsExtraHelp.out b/compiler/testData/cli/js/jsExtraHelp.out index 3cecb78ba0a..ece6fe4d6d4 100644 --- a/compiler/testData/cli/js/jsExtraHelp.out +++ b/compiler/testData/cli/js/jsExtraHelp.out @@ -17,6 +17,7 @@ where advanced options include: Print declarations' reachability info to stdout during performing DCE -Xir-dce-runtime-diagnostic={log|exception} Enable runtime diagnostics when performing DCE instead of removing declarations + -Xir-minimized-member-names Perform minimization for names of members -Xir-module-name= Specify a compilation module name for IR backend -Xir-new-ir2js New fragment-based ir2js -Xir-only Disables pre-IR backend diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/JsEnvironmentConfigurator.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/JsEnvironmentConfigurator.kt index d673f3ac075..743bce6b8e0 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/JsEnvironmentConfigurator.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/JsEnvironmentConfigurator.kt @@ -56,9 +56,9 @@ class JsEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfigu // Keep names short to keep path lengths under 255 for Windows private val outputDirByMode = mapOf( TranslationMode.FULL to "out", - TranslationMode.FULL_DCE to "outMin", + TranslationMode.FULL_DCE_MINIMIZED_NAMES to "outMin", TranslationMode.PER_MODULE to "outPm", - TranslationMode.PER_MODULE_DCE to "outPmMin" + TranslationMode.PER_MODULE_DCE_MINIMIZED_NAMES to "outPmMin" ) private const val OUTPUT_KLIB_DIR_NAME = "outputKlibDir" 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 294c882a95b..32ac3937f8e 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 @@ -76,9 +76,9 @@ abstract class AbstractJsKLibABITestCase : AbstractKlibABITestCase() { relativeRequirePath = false ) - val compiledResult = transformer.generateModule(ir.allModules, setOf(TranslationMode.FULL_DCE)) + val compiledResult = transformer.generateModule(ir.allModules, setOf(TranslationMode.FULL_DCE_MINIMIZED_NAMES)) - val dceOutput = compiledResult.outputs[TranslationMode.FULL_DCE] ?: error("No DCE output") + val dceOutput = compiledResult.outputs[TranslationMode.FULL_DCE_MINIMIZED_NAMES] ?: error("No DCE output") val binariesDir = File(buildDir, BIN_DIR_NAME).also { it.mkdirs() } diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/converters/JsIrBackendFacade.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/converters/JsIrBackendFacade.kt index f12aeb3bb6c..64124829d7c 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/converters/JsIrBackendFacade.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/converters/JsIrBackendFacade.kt @@ -160,7 +160,7 @@ class JsIrBackendFacade( val perModuleOnly = JsEnvironmentConfigurationDirectives.SPLIT_PER_MODULE in module.directives val outputFile = File(JsEnvironmentConfigurator.getJsModuleArtifactPath(testServices, module.name, TranslationMode.FULL) + ".js") - val dceOutputFile = File(JsEnvironmentConfigurator.getJsModuleArtifactPath(testServices, module.name, TranslationMode.FULL_DCE) + ".js") + val dceOutputFile = File(JsEnvironmentConfigurator.getJsModuleArtifactPath(testServices, module.name, TranslationMode.FULL_DCE_MINIMIZED_NAMES) + ".js") if (!esModules) { if (runNewIr2Js) { val transformer = IrModuleToJsTransformerTmp( @@ -172,7 +172,10 @@ class JsIrBackendFacade( // If runIrDce then include DCE results // If perModuleOnly then skip whole program // (it.dce => runIrDce) && (perModuleOnly => it.perModule) - val translationModes = TranslationMode.values().filter { (!it.dce || runIrDce) && (!perModuleOnly || it.perModule) }.toSet() + val translationModes = TranslationMode.values() + .filter { (!it.dce || runIrDce) && (!perModuleOnly || it.perModule) } + .filter { it.dce == it.minimizedMemberNames } + .toSet() return BinaryArtifacts.Js.JsIrArtifact(outputFile, transformer.generateModule(loweredIr.allModules, translationModes)).dump(module) } else { val transformer = IrModuleToJsTransformer( diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/handlers/JsArtifactsDumpHandler.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/handlers/JsArtifactsDumpHandler.kt index dc0f1e0faef..241fd2acef6 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/handlers/JsArtifactsDumpHandler.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/handlers/JsArtifactsDumpHandler.kt @@ -39,9 +39,9 @@ class JsArtifactsDumpHandler(testServices: TestServices) : AfterAnalysisChecker( val minOutputDir = File(dceOutputDir, originalFile.nameWithoutExtension) copy(JsEnvironmentConfigurator.getJsArtifactsOutputDir(testServices), outputDir) - copy(JsEnvironmentConfigurator.getJsArtifactsOutputDir(testServices, TranslationMode.FULL_DCE), dceOutputDir) + copy(JsEnvironmentConfigurator.getJsArtifactsOutputDir(testServices, TranslationMode.FULL_DCE_MINIMIZED_NAMES), dceOutputDir) copy(JsEnvironmentConfigurator.getJsArtifactsOutputDir(testServices, TranslationMode.PER_MODULE), perModuleOutputDir) - copy(JsEnvironmentConfigurator.getJsArtifactsOutputDir(testServices, TranslationMode.PER_MODULE_DCE), preModuleDceOutputDir) + copy(JsEnvironmentConfigurator.getJsArtifactsOutputDir(testServices, TranslationMode.PER_MODULE_DCE_MINIMIZED_NAMES), preModuleDceOutputDir) copy(JsEnvironmentConfigurator.getMinificationJsArtifactsOutputDir(testServices), minOutputDir) } diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/handlers/JsBoxRunner.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/handlers/JsBoxRunner.kt index 4327eb16b58..e4db3930c57 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/handlers/JsBoxRunner.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/handlers/JsBoxRunner.kt @@ -53,7 +53,7 @@ class JsBoxRunner(testServices: TestServices) : AbstractJsArtifactsCollector(tes val globalDirectives = testServices.moduleStructure.allDirectives val esmOutputDir = JsEnvironmentConfigurator.getJsArtifactsOutputDir(testServices).esModulesSubDir - val esmDceOutputDir = JsEnvironmentConfigurator.getJsArtifactsOutputDir(testServices, TranslationMode.FULL_DCE).esModulesSubDir + val esmDceOutputDir = JsEnvironmentConfigurator.getJsArtifactsOutputDir(testServices, TranslationMode.FULL_DCE_MINIMIZED_NAMES).esModulesSubDir val dontSkipRegularMode = JsEnvironmentConfigurationDirectives.SKIP_REGULAR_MODE !in globalDirectives val runIrDce = JsEnvironmentConfigurationDirectives.RUN_IR_DCE in globalDirectives diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/utils/RunnerUtils.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/utils/RunnerUtils.kt index 6a9a7ad5370..eb09778ad7c 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/utils/RunnerUtils.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/utils/RunnerUtils.kt @@ -129,7 +129,7 @@ fun getAllFilesForRunner( } else { // Old BE and ES modules val outputDir = JsEnvironmentConfigurator.getJsArtifactsOutputDir(testServices) - val dceOutputDir = JsEnvironmentConfigurator.getJsArtifactsOutputDir(testServices, TranslationMode.FULL_DCE) + val dceOutputDir = JsEnvironmentConfigurator.getJsArtifactsOutputDir(testServices, TranslationMode.FULL_DCE_MINIMIZED_NAMES) val artifactsPaths = modulesToArtifact.values.map { it.outputFile.absolutePath }.filter { !File(it).isDirectory } val allJsFiles = additionalFiles + inputJsFilesBefore +artifactsPaths + commonFiles + additionalMainFiles + inputJsFilesAfter @@ -141,7 +141,7 @@ fun getAllFilesForRunner( if (runIrDce) { val dceJsFiles = artifactsPaths.map { it.replace(outputDir.absolutePath, dceOutputDir.absolutePath) } val dceAllJsFiles = additionalFiles + inputJsFilesBefore + dceJsFiles + commonFiles + additionalMainFiles + inputJsFilesAfter - result[TranslationMode.FULL_DCE] = dceAllJsFiles + result[TranslationMode.FULL_DCE_MINIMIZED_NAMES] = dceAllJsFiles } return result diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java index 5245688a58e..ee99ae02cb9 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java @@ -2088,6 +2088,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { runTest("js/js.translator/testData/box/export/exportAllFile.kt"); } + @Test + @TestMetadata("exportClassWithInternal.kt") + public void testExportClassWithInternal() throws Exception { + runTest("js/js.translator/testData/box/export/exportClassWithInternal.kt"); + } + @Test @TestMetadata("exportEnumClass.kt") public void testExportEnumClass() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java index 8daa9c6da97..497afc6b135 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java @@ -2484,6 +2484,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest { runTest("js/js.translator/testData/box/export/exportAllFile.kt"); } + @Test + @TestMetadata("exportClassWithInternal.kt") + public void testExportClassWithInternal() throws Exception { + runTest("js/js.translator/testData/box/export/exportClassWithInternal.kt"); + } + @Test @TestMetadata("exportEnumClass.kt") public void testExportEnumClass() throws Exception { diff --git a/js/js.translator/testData/box/export/exportClassWithInternal.kt b/js/js.translator/testData/box/export/exportClassWithInternal.kt new file mode 100644 index 00000000000..bb8a09165c7 --- /dev/null +++ b/js/js.translator/testData/box/export/exportClassWithInternal.kt @@ -0,0 +1,11 @@ +// FILE: lib.kt +@JsExport +class Foo(internal val constructorParameter: String) + +// FILE: main.kt +fun box():String { + val foo = Foo("foo") + if (foo.constructorParameter != "foo") return "fail" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/inline/privateProperty.kt b/js/js.translator/testData/box/inline/privateProperty.kt index 51074b3869d..e0395df0237 100644 --- a/js/js.translator/testData/box/inline/privateProperty.kt +++ b/js/js.translator/testData/box/inline/privateProperty.kt @@ -3,100 +3,74 @@ package test var a = 0 -// CHECK_FUNCTION_EXISTS: get_p1 TARGET_BACKENDS=JS -// CHECK_NOT_CALLED_IN_SCOPE: function=get_p1 scope=box TARGET_BACKENDS=JS -// CHECK_FUNCTION_EXISTS: set_p1 TARGET_BACKENDS=JS -// CHECK_NOT_CALLED_IN_SCOPE: function=set_p1 scope=box TARGET_BACKENDS=JS -// CHECK_FUNCTION_EXISTS: _get_p1__1413126122 IGNORED_BACKENDS=JS -// CHECK_NOT_CALLED_IN_SCOPE: function=_get_p1_ scope=box IGNORED_BACKENDS=JS -// CHECK_FUNCTION_EXISTS: _set_p1__3473235702 IGNORED_BACKENDS=JS -// CHECK_NOT_CALLED_IN_SCOPE: function=_set_p1__3473235702 scope=box IGNORED_BACKENDS=JS +// CHECK_FUNCTION_EXISTS: get_p1 +// CHECK_NOT_CALLED_IN_SCOPE: function=get_p1 scope=box +// CHECK_FUNCTION_EXISTS: set_p1 +// CHECK_NOT_CALLED_IN_SCOPE: function=set_p1 scope=box private inline var p1: Int get() = a + 10000 set(v) { a = v + 100 } -// CHECK_FUNCTION_EXISTS: get_p2 TARGET_BACKENDS=JS -// CHECK_NOT_CALLED_IN_SCOPE: function=get_p2 scope=box TARGET_BACKENDS=JS -// CHECK_CALLED_IN_SCOPE: function=set_p2 scope=box TARGET_BACKENDS=JS -// CHECK_FUNCTION_EXISTS: _get_p2__1413126153 IGNORED_BACKENDS=JS -// CHECK_NOT_CALLED_IN_SCOPE: function=_get_p2__1413126153 scope=box IGNORED_BACKENDS=JS -// CHECK_CALLED_IN_SCOPE: function=_set_p2__3473235733 scope=box IGNORED_BACKENDS=JS +// CHECK_FUNCTION_EXISTS: get_p2 +// CHECK_NOT_CALLED_IN_SCOPE: function=get_p2 scope=box +// CHECK_CALLED_IN_SCOPE: function=set_p2 scope=box private var p2: Int inline get() = a + 20000 set(v) { a = v + 200 } -// CHECK_CALLED_IN_SCOPE: function=get_p3 scope=box TARGET_BACKENDS=JS -// CHECK_FUNCTION_EXISTS: set_p3 TARGET_BACKENDS=JS -// CHECK_NOT_CALLED_IN_SCOPE: function=set_p3 scope=box TARGET_BACKENDS=JS -// CHECK_CALLED_IN_SCOPE: function=_get_p3__1413126184 scope=box IGNORED_BACKENDS=JS -// CHECK_FUNCTION_EXISTS: _set_p3__3473235764 IGNORED_BACKENDS=JS -// CHECK_NOT_CALLED_IN_SCOPE: function=_set_p3__3473235764 scope=box IGNORED_BACKENDS=JS +// CHECK_CALLED_IN_SCOPE: function=get_p3 scope=box +// CHECK_FUNCTION_EXISTS: set_p3 +// CHECK_NOT_CALLED_IN_SCOPE: function=set_p3 scope=box var p3: Int get() = a + 30000 private inline set(v) { a = v + 300 } -// CHECK_CALLED_IN_SCOPE: function=get_p4 scope=box TARGET_BACKENDS=JS -// CHECK_FUNCTION_EXISTS: set_p4 TARGET_BACKENDS=JS -// CHECK_NOT_CALLED_IN_SCOPE: function=set_p4 scope=box TARGET_BACKENDS=JS -// CHECK_CALLED_IN_SCOPE: function=_get_p4__1413126215 scope=box IGNORED_BACKENDS=JS -// CHECK_FUNCTION_EXISTS: _set_p4__3473235795 IGNORED_BACKENDS=JS -// CHECK_NOT_CALLED_IN_SCOPE: function=_set_p4__3473235795 scope=box IGNORED_BACKENDS=JS +// CHECK_CALLED_IN_SCOPE: function=get_p4 scope=box +// CHECK_FUNCTION_EXISTS: set_p4 +// CHECK_NOT_CALLED_IN_SCOPE: function=set_p4 scope=box private var p4: Int get() = a + 40000 inline set(v) { a = v + 400 } -// CHECK_FUNCTION_EXISTS: get_p5 TARGET_BACKENDS=JS -// CHECK_NOT_CALLED_IN_SCOPE: function=get_p5 scope=box TARGET_BACKENDS=JS -// CHECK_FUNCTION_EXISTS: set_p5 TARGET_BACKENDS=JS -// CHECK_NOT_CALLED_IN_SCOPE: function=set_p5 scope=box TARGET_BACKENDS=JS -// CHECK_FUNCTION_EXISTS: _get_p5__1413126246 IGNORED_BACKENDS=JS -// CHECK_NOT_CALLED_IN_SCOPE: function=_get_p5__1413126246 scope=box IGNORED_BACKENDS=JS -// CHECK_FUNCTION_EXISTS: _set_p5__3473235826 IGNORED_BACKENDS=JS -// CHECK_NOT_CALLED_IN_SCOPE: function=_set_p5__3473235826 scope=box IGNORED_BACKENDS=JS +// CHECK_FUNCTION_EXISTS: get_p5 +// CHECK_NOT_CALLED_IN_SCOPE: function=get_p5 scope=box +// CHECK_FUNCTION_EXISTS: set_p5 +// CHECK_NOT_CALLED_IN_SCOPE: function=set_p5 scope=box private inline var Int.p5: Int get() = this * 100 + a + 50000 set(v) { a = this + v + 500 } -// CHECK_FUNCTION_EXISTS: get_p6 TARGET_BACKENDS=JS -// CHECK_NOT_CALLED_IN_SCOPE: function=get_p6 scope=box TARGET_BACKENDS=JS -// CHECK_CALLED_IN_SCOPE: function=set_p6 scope=box TARGET_BACKENDS=JS -// CHECK_FUNCTION_EXISTS: _get_p6__1413126277 IGNORED_BACKENDS=JS -// CHECK_NOT_CALLED_IN_SCOPE: function=_get_p6__1413126277 scope=box IGNORED_BACKENDS=JS -// CHECK_CALLED_IN_SCOPE: function=_set_p6__3473235857 scope=box IGNORED_BACKENDS=JS +// CHECK_FUNCTION_EXISTS: get_p6 +// CHECK_NOT_CALLED_IN_SCOPE: function=get_p6 scope=box +// CHECK_CALLED_IN_SCOPE: function=set_p6 scope=box private var Int.p6: Int inline get() = this * 100 + a + 60000 set(v) { a = this + v + 600 } -// CHECK_CALLED_IN_SCOPE: function=get_p7 scope=box TARGET_BACKENDS=JS -// CHECK_FUNCTION_EXISTS: set_p7 TARGET_BACKENDS=JS -// CHECK_NOT_CALLED_IN_SCOPE: function=set_p7 scope=box TARGET_BACKENDS=JS -// CHECK_CALLED_IN_SCOPE: function=_get_p7__1413126308 scope=box IGNORED_BACKENDS=JS -// CHECK_FUNCTION_EXISTS: _set_p7__3473235888 IGNORED_BACKENDS=JS -// CHECK_NOT_CALLED_IN_SCOPE: function=_set_p7__3473235888 scope=box IGNORED_BACKENDS=JS +// CHECK_CALLED_IN_SCOPE: function=get_p7 scope=box +// CHECK_FUNCTION_EXISTS: set_p7 +// CHECK_NOT_CALLED_IN_SCOPE: function=set_p7 scope=box var Int.p7: Int get() = this * 100 + a + 70000 private inline set(v) { a = this + v + 700 } -// CHECK_CALLED_IN_SCOPE: function=get_p8 scope=box TARGET_BACKENDS=JS -// CHECK_FUNCTION_EXISTS: set_p8 TARGET_BACKENDS=JS -// CHECK_NOT_CALLED_IN_SCOPE: function=set_p8 scope=box TARGET_BACKENDS=JS -// CHECK_CALLED_IN_SCOPE: function=_get_p8__1413126339 scope=box IGNORED_BACKENDS=JS -// CHECK_FUNCTION_EXISTS: _set_p8__3473235919 IGNORED_BACKENDS=JS -// CHECK_NOT_CALLED_IN_SCOPE: function=_set_p8__3473235919 scope=box IGNORED_BACKENDS=JS +// CHECK_CALLED_IN_SCOPE: function=get_p8 scope=box +// CHECK_FUNCTION_EXISTS: set_p8 +// CHECK_NOT_CALLED_IN_SCOPE: function=set_p8 scope=box private var Int.p8: Int get() = this * 100 + a + 80000 inline set(v) { @@ -130,7 +104,8 @@ private class A { // CHECK_NOT_CALLED_IN_SCOPE: function=get_p12_s8ev3n$ scope=box TARGET_BACKENDS=JS // CHECK_FUNCTION_EXISTS: set_p12_dqglrj$ TARGET_BACKENDS=JS // CHECK_NOT_CALLED_IN_SCOPE: function=set_p12_dqglrj$ scope=box TARGET_BACKENDS=JS - // CHECK_NOT_CALLED_IN_SCOPE: function=_get_p12__quadv7_k$ scope=box IGNORED_BACKENDS=JS + // CHECK_NOT_CALLED_IN_SCOPE: function=get_p12_jvqn3p_k$ scope=box IGNORED_BACKENDS=JS + // CHECK_NOT_CALLED_IN_SCOPE: function=set_p12_na24b5_k$ scope=box IGNORED_BACKENDS=JS inline var Int.p12: Int get() = this * 100 + a + 120000 set(v) { @@ -140,6 +115,9 @@ private class A { // CHECK_FUNCTION_EXISTS: get_p13_s8ev3n$ TARGET_BACKENDS=JS // CHECK_NOT_CALLED_IN_SCOPE: function=get_p13_s8ev3n$ scope=box TARGET_BACKENDS=JS // CHECK_CALLED_IN_SCOPE: function=set_p13_dqglrj$ scope=box TARGET_BACKENDS=JS + // CHECK_FUNCTION_EXISTS: get_p13_s8qimu_k$ IGNORED_BACKENDS=JS + // CHECK_NOT_CALLED_IN_SCOPE: function=get_p13_s8qimu_k$ scope=box IGNORED_BACKENDS=JS + // CHECK_CALLED_IN_SCOPE: function=set_p13_8qdsq6_k$ scope=box IGNORED_BACKENDS=JS var Int.p13: Int inline get() = this * 100 + a + 130000 set(v) { @@ -149,6 +127,9 @@ private class A { // CHECK_CALLED_IN_SCOPE: function=get_p14_s8ev3n$ scope=box TARGET_BACKENDS=JS // CHECK_FUNCTION_EXISTS: set_p14_dqglrj$ TARGET_BACKENDS=JS // CHECK_NOT_CALLED_IN_SCOPE: function=set_p14_dqglrj$ scope=box TARGET_BACKENDS=JS + // CHECK_CALLED_IN_SCOPE: function=get_p14_yfdnt5_k$ scope=box IGNORED_BACKENDS=JS + // CHECK_FUNCTION_EXISTS: set_p14_uaac7n_k$ IGNORED_BACKENDS=JS + // CHECK_NOT_CALLED_IN_SCOPE: function=set_p14_uaac7n_k$ scope=box IGNORED_BACKENDS=JS var Int.p14: Int get() = this * 100 + a + 140000 inline set(v) { @@ -160,10 +141,10 @@ private class A { // CHECK_NOT_CALLED_IN_SCOPE: function=get_p15 scope=box TARGET_BACKENDS=JS // CHECK_FUNCTION_EXISTS: set_p15 TARGET_BACKENDS=JS // CHECK_NOT_CALLED_IN_SCOPE: function=set_p15 scope=box TARGET_BACKENDS=JS -// CHECK_FUNCTION_EXISTS: _get_p15__857236605 IGNORED_BACKENDS=JS -// CHECK_NOT_CALLED_IN_SCOPE: function=_get_p15__857236605 scope=box IGNORED_BACKENDS=JS -// CHECK_FUNCTION_EXISTS: _set_p15__296124145 IGNORED_BACKENDS=JS -// CHECK_NOT_CALLED_IN_SCOPE: function=_set_p15__296124145 scope=box IGNORED_BACKENDS=JS +// CHECK_FUNCTION_EXISTS: get_p15 IGNORED_BACKENDS=JS +// CHECK_NOT_CALLED_IN_SCOPE: function=get_p15 scope=box IGNORED_BACKENDS=JS +// CHECK_FUNCTION_EXISTS: set_p15 IGNORED_BACKENDS=JS +// CHECK_NOT_CALLED_IN_SCOPE: function=set_p15 scope=box IGNORED_BACKENDS=JS private inline var A.p15: Int get() = a + 150000 set(v) { @@ -173,9 +154,9 @@ private inline var A.p15: Int // CHECK_FUNCTION_EXISTS: get_p16 TARGET_BACKENDS=JS // CHECK_NOT_CALLED_IN_SCOPE: function=get_p16 scope=box TARGET_BACKENDS=JS // CHECK_CALLED_IN_SCOPE: function=set_p16 scope=box TARGET_BACKENDS=JS -// CHECK_FUNCTION_EXISTS: _get_p16__857236636 IGNORED_BACKENDS=JS -// CHECK_NOT_CALLED_IN_SCOPE: function=_get_p16__857236636 scope=box IGNORED_BACKENDS=JS -// CHECK_CALLED_IN_SCOPE: function=_set_p16__296124176 scope=box IGNORED_BACKENDS=JS +// CHECK_FUNCTION_EXISTS: set_p16 IGNORED_BACKENDS=JS +// CHECK_NOT_CALLED_IN_SCOPE: function=get_p16 scope=box IGNORED_BACKENDS=JS +// CHECK_CALLED_IN_SCOPE: function=set_p16 scope=box IGNORED_BACKENDS=JS private var A.p16: Int inline get() = a + 160000 set(v) { @@ -185,9 +166,9 @@ private var A.p16: Int // CHECK_CALLED_IN_SCOPE: function=get_p17 scope=box TARGET_BACKENDS=JS // CHECK_FUNCTION_EXISTS: set_p17 TARGET_BACKENDS=JS // CHECK_NOT_CALLED_IN_SCOPE: function=set_p17 scope=box TARGET_BACKENDS=JS -// CHECK_CALLED_IN_SCOPE: function=_get_p17__857236667 scope=box IGNORED_BACKENDS=JS -// CHECK_FUNCTION_EXISTS: _set_p17__296124207 IGNORED_BACKENDS=JS -// CHECK_NOT_CALLED_IN_SCOPE: function=_set_p17__296124207 scope=box IGNORED_BACKENDS=JS +// CHECK_CALLED_IN_SCOPE: function=get_p17 scope=box IGNORED_BACKENDS=JS +// CHECK_FUNCTION_EXISTS: set_p17 IGNORED_BACKENDS=JS +// CHECK_NOT_CALLED_IN_SCOPE: function=set_p17 scope=box IGNORED_BACKENDS=JS private var A.p17: Int get() = a + 170000 inline set(v) { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/CompilerFlags.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/CompilerFlags.kt index 2d792ecfa82..8ab9f5ba377 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/CompilerFlags.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/CompilerFlags.kt @@ -22,6 +22,8 @@ internal const val PRODUCE_JS = "-Xir-produce-js" internal const val PRODUCE_UNZIPPED_KLIB = "-Xir-produce-klib-dir" internal const val PRODUCE_ZIPPED_KLIB = "-Xir-produce-klib-file" +internal const val MINIMIZED_MEMBER_NAMES = "-Xir-minimized-member-names" + internal const val MODULE_NAME = "-Xir-module-name" internal const val PER_MODULE = "-Xir-per-module" diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrLink.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrLink.kt index 24c0e0bfe0a..b24678b0417 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrLink.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrLink.kt @@ -171,7 +171,7 @@ abstract class KotlinJsIrLink @Inject constructor( override fun setupCompilerArgs(args: K2JSCompilerArguments, defaultsOnly: Boolean, ignoreClasspathResolutionErrors: Boolean) { when (mode) { PRODUCTION -> { - kotlinOptions.configureOptions(ENABLE_DCE, GENERATE_D_TS) + kotlinOptions.configureOptions(ENABLE_DCE, GENERATE_D_TS, MINIMIZED_MEMBER_NAMES) } DEVELOPMENT -> { kotlinOptions.configureOptions(GENERATE_D_TS)