diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt index 43a25af1f57..95a9df8210a 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt @@ -42,7 +42,19 @@ public class FunctionReader(private val context: TranslationContext) { * Maps module name to .js file content, that contains this module definition. * One file can contain more than one module definition. */ - private val moduleJsDefinition = hashMapOf(); + private val moduleJsDefinition = hashMapOf() + + /** + * Maps module name to variable, that is used to call functions inside module. + * The default variable is _, but it can be renamed by minifier. + */ + private val moduleRootVariable = hashMapOf() + + /** + * Maps moduleName to kotlin object variable. + * The default variable is Kotlin, but it can be renamed by minifier. + */ + private val moduleKotlinVariable = hashMapOf(); { val config = context.getConfig() as LibrarySourcesConfig @@ -55,8 +67,12 @@ public class FunctionReader(private val context: TranslationContext) { while (matcher.find()) { val moduleName = matcher.group(3) + val moduleVariable = matcher.group(4) + val kotlinVariable = matcher.group(1) assert(moduleName !in moduleJsDefinition) { "Module is defined in more, than one file" } moduleJsDefinition[moduleName] = file + moduleRootVariable[moduleName] = moduleVariable + moduleKotlinVariable[moduleName] = kotlinVariable } } } @@ -93,6 +109,13 @@ public class FunctionReader(private val context: TranslationContext) { } val function = metadata.function + val moduleName = getExternalModuleName(descriptor)!! + val moduleNameLiteral = context.program().getStringLiteral(moduleName) + val moduleReference = context.namer().getModuleReference(moduleNameLiteral) + + val replacements = hashMapOf(moduleRootVariable[moduleName] to moduleReference, + moduleKotlinVariable[moduleName] to Namer.KOTLIN_OBJECT_REF) + replaceExternalNames(function, replacements) return function } @@ -108,3 +131,21 @@ public class FunctionReader(private val context: TranslationContext) { } } } + +private fun replaceExternalNames(function: JsFunction, externalReplacements: Map) { + val replacements = externalReplacements.filterKeys { !function.getScope().hasOwnName(it) } + + if (replacements.isEmpty()) return + + val visitor = object: JsVisitorWithContextImpl() { + override fun endVisit(x: JsNameRef?, ctx: JsContext?) { + if (x == null || x.getQualifier() != null) return + + replacements[x.getIdent()]?.let { + ctx?.replaceMe(it) + } + } + } + + visitor.accept(function) +} diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java index 26556025216..1424687b2b3 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java @@ -268,6 +268,9 @@ public final class Namer { @NotNull private final JsName isTypeName; + @NotNull + private final JsExpression modulesMap; + private Namer(@NotNull JsScope rootScope) { kotlinName = rootScope.declareName(KOTLIN_NAME); kotlinScope = JsObjectScope(rootScope, "Kotlin standard object"); @@ -290,6 +293,7 @@ public final class Namer { callableRefForExtensionProperty = kotlinScope.declareName(CALLABLE_REF_FOR_EXTENSION_PROPERTY); isTypeName = kotlinScope.declareName("isType"); + modulesMap = kotlin("modules"); } @NotNull @@ -421,4 +425,9 @@ public final class Namer { public JsExpression getCallSetProperty() { return callSetProperty; } + + @NotNull + public JsExpression getModuleReference(@NotNull JsStringLiteral moduleName) { + return new JsArrayAccess(modulesMap, moduleName); + } } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java index 0010bbdac4f..ce9b7beb8fa 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java @@ -481,7 +481,7 @@ public final class StaticContext { } return JsAstUtils.replaceRootReference( - result, new JsArrayAccess(namer.kotlin("modules"), program.getStringLiteral(moduleName))); + result, namer.getModuleReference(program.getStringLiteral(moduleName))); } }; Rule constructorOrDefaultObjectHasTheSameQualifierAsTheClass = new Rule() {