[K/JS] Rework ES modules part with squashed JsImport and right renaming strategy inside import/export statements
This commit is contained in:
@@ -90,6 +90,7 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
|
||||
moduleKindMap.put(K2JsArgumentConstants.MODULE_COMMONJS, ModuleKind.COMMON_JS);
|
||||
moduleKindMap.put(K2JsArgumentConstants.MODULE_AMD, ModuleKind.AMD);
|
||||
moduleKindMap.put(K2JsArgumentConstants.MODULE_UMD, ModuleKind.UMD);
|
||||
moduleKindMap.put(K2JsArgumentConstants.MODULE_ES, ModuleKind.ES);
|
||||
|
||||
sourceMapContentEmbeddingMap.put(K2JsArgumentConstants.SOURCE_MAP_SOURCE_CONTENT_ALWAYS, SourceMapSourceEmbedding.ALWAYS);
|
||||
sourceMapContentEmbeddingMap.put(K2JsArgumentConstants.SOURCE_MAP_SOURCE_CONTENT_NEVER, SourceMapSourceEmbedding.NEVER);
|
||||
|
||||
@@ -44,6 +44,8 @@ interface DelegateFactory {
|
||||
}
|
||||
|
||||
object DefaultDelegateFactory : DelegateFactory {
|
||||
fun <K : IrDeclaration, V> newDeclarationToValueMapping(): Mapping.Delegate<K, V> = newMappingImpl()
|
||||
|
||||
override fun <K : IrDeclaration, V : IrDeclaration> newDeclarationToDeclarationMapping(): Mapping.Delegate<K, V> = newMappingImpl()
|
||||
|
||||
override fun <K : IrDeclaration, V : Collection<IrDeclaration>> newDeclarationToDeclarationCollectionMapping(): Mapping.Delegate<K, V> = newMappingImpl()
|
||||
|
||||
@@ -11,8 +11,8 @@ import org.jetbrains.kotlin.ir.backend.js.utils.MutableReference
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
|
||||
class JsMapping : DefaultMapping() {
|
||||
val esClassWhichNeedBoxParameters = mutableSetOf<IrClass>()
|
||||
val esClassToPossibilityForOptimization = mutableMapOf<IrClass, MutableReference<Boolean>>()
|
||||
val esClassWhichNeedBoxParameters = DefaultDelegateFactory.newDeclarationToValueMapping<IrClass, Boolean>()
|
||||
val esClassToPossibilityForOptimization = DefaultDelegateFactory.newDeclarationToValueMapping<IrClass, MutableReference<Boolean>>()
|
||||
|
||||
val outerThisFieldSymbols = DefaultDelegateFactory.newDeclarationToDeclarationMapping<IrClass, IrField>()
|
||||
val innerClassConstructors = DefaultDelegateFactory.newDeclarationToDeclarationMapping<IrConstructor, IrConstructor>()
|
||||
|
||||
+3
-3
@@ -83,7 +83,7 @@ class ExportModelToJsStatements(
|
||||
namespace != null ->
|
||||
listOf(jsAssignment(jsElementAccess(declaration.name, namespace), JsNameRef(name)).makeStmt())
|
||||
|
||||
esModules -> listOf(JsExport(name, alias = JsName(declaration.name, false)))
|
||||
esModules -> listOf(JsExport(name.makeRef(), alias = JsName(declaration.name, false)))
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
@@ -96,7 +96,7 @@ class ExportModelToJsStatements(
|
||||
when {
|
||||
namespace == null -> {
|
||||
val property = declaration.generateTopLevelGetters()
|
||||
listOf(JsVars(property), JsExport(property.name, JsName(declaration.name, false)))
|
||||
listOf(JsVars(property), JsExport(property.name.makeRef(), JsName(declaration.name, false)))
|
||||
}
|
||||
es6mode && declaration.isMember -> {
|
||||
val jsClass = parentClass?.getCorrespondingJsClass() ?: error("Expect to have parentClass at this point")
|
||||
@@ -168,7 +168,7 @@ class ExportModelToJsStatements(
|
||||
}
|
||||
val klassExport = when {
|
||||
namespace != null -> jsAssignment(newNameSpace, JsNameRef(name)).makeStmt()
|
||||
esModules -> JsExport(name, alias = JsName(declaration.name, false))
|
||||
esModules -> JsExport(name.makeRef(), alias = JsName(declaration.name, false))
|
||||
else -> null
|
||||
}
|
||||
|
||||
|
||||
+9
-1
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
import org.jetbrains.kotlin.library.impl.buffer
|
||||
import org.jetbrains.kotlin.protobuf.CodedInputStream
|
||||
import org.jetbrains.kotlin.protobuf.CodedOutputStream
|
||||
import org.jetbrains.kotlin.serialization.js.ModuleKind
|
||||
import java.security.MessageDigest
|
||||
|
||||
internal fun Hash128Bits.toProtoStream(out: CodedOutputStream) {
|
||||
@@ -164,6 +165,13 @@ internal fun CrossModuleReferences.crossModuleReferencesHashForIC() = HashCalcul
|
||||
val import = imports[tag]!!
|
||||
update(tag)
|
||||
update(import.exportedAs)
|
||||
update(import.moduleExporter.toString())
|
||||
|
||||
if (moduleKind == ModuleKind.ES) {
|
||||
update(import.moduleExporter.internalName.toString())
|
||||
update(import.moduleExporter.externalName)
|
||||
update(import.moduleExporter.relativeRequirePath ?: "")
|
||||
} else {
|
||||
update(import.moduleExporter.internalName.toString())
|
||||
}
|
||||
}
|
||||
}.finalize()
|
||||
|
||||
+4
-4
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.util.collectionUtils.filterIsInstanceAnd
|
||||
|
||||
class ES6ConstructorBoxParameterOptimizationLowering(private val context: JsIrBackendContext) : BodyLoweringPass {
|
||||
private val esClassWhichNeedBoxParameters = context.mapping.esClassWhichNeedBoxParameters
|
||||
private val IrClass.needsOfBoxParameter by context.mapping.esClassWhichNeedBoxParameters
|
||||
|
||||
override fun lower(irBody: IrBody, container: IrDeclaration) {
|
||||
if (!context.es6mode) return
|
||||
@@ -85,12 +85,12 @@ class ES6ConstructorBoxParameterOptimizationLowering(private val context: JsIrBa
|
||||
}
|
||||
|
||||
private fun IrClass.requiredToHaveBoxParameter(): Boolean {
|
||||
return esClassWhichNeedBoxParameters.contains(this)
|
||||
return needsOfBoxParameter == true
|
||||
}
|
||||
}
|
||||
|
||||
class ES6CollectConstructorsWhichNeedBoxParameters(private val context: JsIrBackendContext) : DeclarationTransformer {
|
||||
private val esClassWhichNeedBoxParameters = context.mapping.esClassWhichNeedBoxParameters
|
||||
private var IrClass.needsOfBoxParameter by context.mapping.esClassWhichNeedBoxParameters
|
||||
|
||||
override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
|
||||
if (!context.es6mode || declaration !is IrClass) return null
|
||||
@@ -134,7 +134,7 @@ class ES6CollectConstructorsWhichNeedBoxParameters(private val context: JsIrBack
|
||||
|
||||
private fun IrClass.addToClassListWhichNeedBoxParameter() {
|
||||
if (isExternal) return
|
||||
esClassWhichNeedBoxParameters.add(this)
|
||||
needsOfBoxParameter = true
|
||||
superClass?.addToClassListWhichNeedBoxParameter()
|
||||
}
|
||||
}
|
||||
+7
-7
@@ -177,8 +177,8 @@ class ES6PrimaryConstructorUsageOptimizationLowering(private val context: JsIrBa
|
||||
* Otherwise, we can generate a simple ES-class constructor in each class of the hierarchy
|
||||
*/
|
||||
class ES6CollectPrimaryConstructorsWhichCouldBeOptimizedLowering(private val context: JsIrBackendContext) : DeclarationTransformer {
|
||||
private val esClassWhichNeedBoxParameters = context.mapping.esClassWhichNeedBoxParameters
|
||||
private val esClassToPossibilityForOptimization = context.mapping.esClassToPossibilityForOptimization
|
||||
private val IrClass.needsOfBoxParameter by context.mapping.esClassWhichNeedBoxParameters
|
||||
private var IrClass.possibilityToOptimizeForEsClass by context.mapping.esClassToPossibilityForOptimization
|
||||
|
||||
override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
|
||||
if (
|
||||
@@ -186,7 +186,7 @@ class ES6CollectPrimaryConstructorsWhichCouldBeOptimizedLowering(private val con
|
||||
declaration is IrClass &&
|
||||
!declaration.isExternal &&
|
||||
!context.inlineClassesUtils.isClassInlineLike(declaration) &&
|
||||
!esClassToPossibilityForOptimization.contains(declaration)
|
||||
declaration.possibilityToOptimizeForEsClass == null
|
||||
) {
|
||||
declaration.checkIfCanBeOptimized()
|
||||
}
|
||||
@@ -199,7 +199,7 @@ class ES6CollectPrimaryConstructorsWhichCouldBeOptimizedLowering(private val con
|
||||
var nearestOptimizationDecision: MutableReference<Boolean>? = null
|
||||
|
||||
while (currentClass != null && !currentClass.isExternal) {
|
||||
val currentClassOptimizationDecision = esClassToPossibilityForOptimization[currentClass]
|
||||
val currentClassOptimizationDecision = currentClass.possibilityToOptimizeForEsClass
|
||||
|
||||
if (currentClassOptimizationDecision != null) {
|
||||
nearestOptimizationDecision = currentClassOptimizationDecision
|
||||
@@ -214,8 +214,8 @@ class ES6CollectPrimaryConstructorsWhichCouldBeOptimizedLowering(private val con
|
||||
}
|
||||
|
||||
currentClass = this
|
||||
while (currentClass != null && !currentClass.isExternal && !esClassToPossibilityForOptimization.contains(currentClass)) {
|
||||
esClassToPossibilityForOptimization[currentClass] = nearestOptimizationDecision
|
||||
while (currentClass != null && !currentClass.isExternal && currentClass.possibilityToOptimizeForEsClass == null) {
|
||||
currentClass.possibilityToOptimizeForEsClass = nearestOptimizationDecision
|
||||
|
||||
if (nearestOptimizationDecision.value && !currentClass.canBeOptimized()) {
|
||||
nearestOptimizationDecision.value = false
|
||||
@@ -249,7 +249,7 @@ class ES6CollectPrimaryConstructorsWhichCouldBeOptimizedLowering(private val con
|
||||
}
|
||||
|
||||
private fun IrClass.isSubclassOfExternalClassWithRequiredBoxParameter(): Boolean {
|
||||
return superClass?.isExternal == true && esClassWhichNeedBoxParameters.contains(this)
|
||||
return superClass?.isExternal == true && needsOfBoxParameter == true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-2
@@ -7,11 +7,19 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
||||
|
||||
import org.jetbrains.kotlin.ir.backend.js.export.TypeScriptFragment
|
||||
import org.jetbrains.kotlin.ir.backend.js.export.toTypeScript
|
||||
import org.jetbrains.kotlin.js.backend.ast.ESM_EXTENSION
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsProgram
|
||||
import org.jetbrains.kotlin.js.backend.ast.REGULAR_EXTENSION
|
||||
import org.jetbrains.kotlin.serialization.js.ModuleKind
|
||||
import java.io.File
|
||||
import java.nio.file.Files
|
||||
|
||||
val ModuleKind.extension: String
|
||||
get() = when (this) {
|
||||
ModuleKind.ES -> ESM_EXTENSION
|
||||
else -> REGULAR_EXTENSION
|
||||
}
|
||||
|
||||
abstract class CompilationOutputs {
|
||||
var dependencies: Collection<Pair<String, CompilationOutputs>> = emptyList()
|
||||
|
||||
@@ -35,10 +43,10 @@ abstract class CompilationOutputs {
|
||||
}
|
||||
|
||||
dependencies.forEach { (name, content) ->
|
||||
outputDir.resolve("$name.js").writeAsJsFile(content)
|
||||
outputDir.resolve("$name${moduleKind.extension}").writeAsJsFile(content)
|
||||
}
|
||||
|
||||
val outputJsFile = outputDir.resolve("$outputName.js")
|
||||
val outputJsFile = outputDir.resolve("$outputName${moduleKind.extension}")
|
||||
outputJsFile.writeAsJsFile(this)
|
||||
|
||||
if (genDTS) {
|
||||
|
||||
+64
-38
@@ -94,12 +94,14 @@ class CrossModuleDependenciesResolver(
|
||||
private val headers: List<JsIrModuleHeader>
|
||||
) {
|
||||
fun resolveCrossModuleDependencies(relativeRequirePath: Boolean): Map<JsIrModuleHeader, CrossModuleReferences> {
|
||||
val headerToBuilder = headers.associateWith { JsIrModuleCrossModuleReferecenceBuilder(moduleKind, it, relativeRequirePath) }
|
||||
val definitionModule = mutableMapOf<String, JsIrModuleCrossModuleReferecenceBuilder>()
|
||||
val headerToBuilder = headers.associateWith { JsIrModuleCrossModuleReferenceBuilder(moduleKind, it, relativeRequirePath) }
|
||||
val definitionModule = mutableMapOf<String, JsIrModuleCrossModuleReferenceBuilder>()
|
||||
|
||||
val mainModuleHeader = headers.last()
|
||||
val otherModuleHeaders = headers.dropLast(1)
|
||||
headerToBuilder[mainModuleHeader]!!.transitiveJsExportFrom = otherModuleHeaders
|
||||
if (moduleKind != ModuleKind.ES) {
|
||||
val mainModuleHeader = headers.last()
|
||||
val otherModuleHeaders = headers.dropLast(1)
|
||||
headerToBuilder[mainModuleHeader]!!.transitiveJsExportFrom = otherModuleHeaders
|
||||
}
|
||||
|
||||
for (header in headers) {
|
||||
val builder = headerToBuilder[header]!!
|
||||
@@ -130,9 +132,9 @@ class CrossModuleDependenciesResolver(
|
||||
}
|
||||
}
|
||||
|
||||
private class CrossModuleRef(val module: JsIrModuleCrossModuleReferecenceBuilder, val tag: String)
|
||||
private class CrossModuleRef(val module: JsIrModuleCrossModuleReferenceBuilder, val tag: String)
|
||||
|
||||
private class JsIrModuleCrossModuleReferecenceBuilder(
|
||||
private class JsIrModuleCrossModuleReferenceBuilder(
|
||||
val moduleKind: ModuleKind,
|
||||
val header: JsIrModuleHeader,
|
||||
val relativeRequirePath: Boolean
|
||||
@@ -150,20 +152,15 @@ private class JsIrModuleCrossModuleReferecenceBuilder(
|
||||
|
||||
fun buildCrossModuleRefs(): CrossModuleReferences {
|
||||
buildExportNames()
|
||||
val isImportOptional = moduleKind == ModuleKind.ES
|
||||
val importedModules = mutableMapOf<JsIrModuleHeader, JsImportedModule>()
|
||||
|
||||
fun import(moduleHeader: JsIrModuleHeader): JsName {
|
||||
return importedModules.getOrPut(moduleHeader) {
|
||||
val jsModuleName = JsName(moduleHeader.moduleName, false)
|
||||
val relativeRequirePath = relativeRequirePath(moduleHeader)
|
||||
|
||||
JsImportedModule(
|
||||
moduleHeader.externalModuleName,
|
||||
jsModuleName,
|
||||
null,
|
||||
relativeRequirePath
|
||||
)
|
||||
}.internalName
|
||||
fun import(moduleHeader: JsIrModuleHeader): JsImportedModule {
|
||||
return if (isImportOptional) {
|
||||
moduleHeader.toJsImportedModule()
|
||||
} else {
|
||||
importedModules.getOrPut(moduleHeader) { moduleHeader.toJsImportedModule() }
|
||||
}
|
||||
}
|
||||
|
||||
val resultImports = imports.associate { crossModuleRef ->
|
||||
@@ -173,13 +170,13 @@ private class JsIrModuleCrossModuleReferecenceBuilder(
|
||||
"Cross module dependency resolution failed due to signature '$tag' redefinition"
|
||||
}
|
||||
val exportedAs = crossModuleRef.module.exportNames[tag]!!
|
||||
val moduleName = import(crossModuleRef.module.header)
|
||||
val importedModule = import(crossModuleRef.module.header)
|
||||
|
||||
tag to CrossModuleImport(exportedAs, moduleName)
|
||||
tag to CrossModuleImport(exportedAs, importedModule)
|
||||
}
|
||||
|
||||
val transitiveExport = transitiveJsExportFrom.mapNotNull {
|
||||
if (!it.hasJsExports) null else CrossModuleTransitiveExport(import(it), it.externalModuleName)
|
||||
if (!it.hasJsExports) null else CrossModuleTransitiveExport(import(it).internalName, it.externalModuleName)
|
||||
}
|
||||
return CrossModuleReferences(
|
||||
moduleKind,
|
||||
@@ -190,12 +187,22 @@ private class JsIrModuleCrossModuleReferecenceBuilder(
|
||||
)
|
||||
}
|
||||
|
||||
private fun JsIrModuleHeader.toJsImportedModule(): JsImportedModule {
|
||||
val jsModuleName = JsName(moduleName, false)
|
||||
val relativeRequirePath = relativeRequirePath(this)
|
||||
|
||||
return JsImportedModule(
|
||||
externalModuleName,
|
||||
jsModuleName,
|
||||
null,
|
||||
relativeRequirePath
|
||||
)
|
||||
}
|
||||
|
||||
private fun relativeRequirePath(moduleHeader: JsIrModuleHeader): String? {
|
||||
if (!this.relativeRequirePath) return null
|
||||
|
||||
val parentMain = File(header.externalModuleName).parentFile
|
||||
|
||||
if (parentMain == null) return "./${moduleHeader.externalModuleName}"
|
||||
val parentMain = File(header.externalModuleName).parentFile ?: return "./${moduleHeader.externalModuleName}"
|
||||
|
||||
val relativePath = File(moduleHeader.externalModuleName)
|
||||
.toRelativeString(parentMain)
|
||||
@@ -206,10 +213,12 @@ private class JsIrModuleCrossModuleReferecenceBuilder(
|
||||
}
|
||||
}
|
||||
|
||||
class CrossModuleImport(val exportedAs: String, val moduleExporter: JsName)
|
||||
class CrossModuleImport(val exportedAs: String, val moduleExporter: JsImportedModule)
|
||||
|
||||
class CrossModuleTransitiveExport(val internalName: JsName, val externalName: String)
|
||||
|
||||
fun CrossModuleTransitiveExport.getRequireEsmName() = "$externalName$ESM_EXTENSION"
|
||||
|
||||
class CrossModuleReferences(
|
||||
val moduleKind: ModuleKind,
|
||||
val importedModules: List<JsImportedModule>, // additional Kotlin imported modules
|
||||
@@ -218,28 +227,45 @@ class CrossModuleReferences(
|
||||
val imports: Map<String, CrossModuleImport>, // tag -> import statement
|
||||
) {
|
||||
// built from imports
|
||||
var jsImports = emptyMap<String, JsVars.JsVar>() // tag -> import statement
|
||||
var jsImports = emptyMap<String, JsStatement>() // tag -> import statement
|
||||
private set
|
||||
|
||||
fun initJsImportsForModule(module: JsIrModule) {
|
||||
val tagToName = module.fragments.flatMap { it.nameBindings.entries }.associate { it.key to it.value }
|
||||
jsImports = imports.entries.associate {
|
||||
val importedAs = tagToName[it.key] ?: error("Internal error: cannot find imported name for signature ${it.key}")
|
||||
val exportRef = JsNameRef(
|
||||
it.value.exportedAs,
|
||||
it.value.moduleExporter.let {
|
||||
if (moduleKind == ModuleKind.ES) {
|
||||
it.makeRef()
|
||||
} else {
|
||||
ReservedJsNames.makeCrossModuleNameRef(it)
|
||||
}
|
||||
}
|
||||
)
|
||||
it.key to JsVars.JsVar(importedAs, exportRef)
|
||||
it.key to it.value.generateCrossModuleImportStatement(importedAs)
|
||||
}
|
||||
}
|
||||
|
||||
private fun CrossModuleImport.generateCrossModuleImportStatement(importedAs: JsName): JsStatement {
|
||||
return when (moduleKind) {
|
||||
ModuleKind.ES -> generateJsImportStatement(importedAs)
|
||||
else -> generateImportVariableDeclaration(importedAs)
|
||||
}
|
||||
}
|
||||
|
||||
private fun CrossModuleImport.generateImportVariableDeclaration(importedAs: JsName): JsStatement {
|
||||
val exportRef = JsNameRef(exportedAs, ReservedJsNames.makeCrossModuleNameRef(moduleExporter.internalName))
|
||||
return JsVars(JsVars.JsVar(importedAs, exportRef))
|
||||
}
|
||||
|
||||
private fun CrossModuleImport.generateJsImportStatement(importedAs: JsName): JsStatement {
|
||||
return JsImport(
|
||||
moduleExporter.getRequireName(true),
|
||||
JsImport.Element(JsName(exportedAs, false), importedAs.makeRef())
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun Empty(moduleKind: ModuleKind) = CrossModuleReferences(moduleKind, listOf(), emptyList(), emptyMap(), emptyMap())
|
||||
}
|
||||
}
|
||||
|
||||
fun JsStatement.renameImportedSymbolInternalName(newName: JsName): JsStatement {
|
||||
return when (this) {
|
||||
is JsImport -> JsImport(module, JsImport.Element((target as JsImport.Target.Elements).elements.single().name, newName.makeRef()))
|
||||
is JsVars -> JsVars(JsVars.JsVar(newName, vars.single().initExpression))
|
||||
else -> error("Unexpected cross-module import statement ${this::class.qualifiedName}")
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -58,10 +58,10 @@ class Merger(
|
||||
}
|
||||
}
|
||||
|
||||
for ((tag, jsVar) in crossModuleReferences.jsImports) {
|
||||
for ((tag, crossModuleJsImport) in crossModuleReferences.jsImports) {
|
||||
val importName = nameMap[tag] ?: error("Missing name for declaration '$tag'")
|
||||
|
||||
importStatements.putIfAbsent(tag, JsVars(JsVars.JsVar(importName, jsVar.initExpression)))
|
||||
importStatements.putIfAbsent(tag, crossModuleJsImport.renameImportedSymbolInternalName(importName))
|
||||
}
|
||||
|
||||
if (crossModuleReferences.exports.isNotEmpty()) {
|
||||
@@ -70,7 +70,7 @@ class Merger(
|
||||
if (isEsModules) {
|
||||
val exportedElements = crossModuleReferences.exports.entries.map { (tag, hash) ->
|
||||
val internalName = nameMap[tag] ?: error("Missing name for declaration '$tag'")
|
||||
JsExport.Element(internalName, JsName(hash, false))
|
||||
JsExport.Element(internalName.makeRef(), JsName(hash, false))
|
||||
}
|
||||
|
||||
additionalExports += JsExport(JsExport.Subject.Elements(exportedElements))
|
||||
@@ -143,7 +143,7 @@ class Merger(
|
||||
val exportedElements = currentModuleExportStatements.takeIf { it.isNotEmpty() }
|
||||
?.asSequence()
|
||||
?.flatMap { (it.subject as JsExport.Subject.Elements).elements }
|
||||
?.distinctBy { (it.alias ?: it.name).ident }
|
||||
?.distinctBy { it.alias?.ident ?: it.name.ident }
|
||||
?.map { if (it.name.ident == it.alias?.ident) JsExport.Element(it.name, null) else it }
|
||||
?.toList()
|
||||
|
||||
@@ -176,7 +176,7 @@ class Merger(
|
||||
private fun transitiveJsExport(): List<JsStatement> {
|
||||
return if (isEsModules) {
|
||||
crossModuleReferences.transitiveJsExportFrom.map {
|
||||
JsExport(JsExport.Subject.All, it.externalName)
|
||||
JsExport(JsExport.Subject.All, it.getRequireEsmName())
|
||||
}
|
||||
} else {
|
||||
val internalModuleName = ReservedJsNames.makeInternalModuleName()
|
||||
|
||||
+16
-6
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.js.common.isValidES5Identifier
|
||||
import org.jetbrains.kotlin.serialization.js.ModuleKind
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.partitionIsInstance
|
||||
|
||||
object ModuleWrapperTranslation {
|
||||
object Namer {
|
||||
@@ -105,7 +106,7 @@ object ModuleWrapperTranslation {
|
||||
val scope = program.scope
|
||||
val defineName = scope.declareName("define")
|
||||
val invocationArgs = listOf(
|
||||
JsArrayLiteral(listOf(JsStringLiteral("exports")) + importedModules.map { JsStringLiteral(it.requireName) }),
|
||||
JsArrayLiteral(listOf(JsStringLiteral("exports")) + importedModules.map { JsStringLiteral(it.getRequireName()) }),
|
||||
function
|
||||
)
|
||||
|
||||
@@ -122,23 +123,32 @@ object ModuleWrapperTranslation {
|
||||
val moduleName = scope.declareName("module")
|
||||
val requireName = scope.declareName("require")
|
||||
|
||||
val invocationArgs = importedModules.map { JsInvocation(requireName.makeRef(), JsStringLiteral(it.requireName)) }
|
||||
val invocationArgs = importedModules.map { JsInvocation(requireName.makeRef(), JsStringLiteral(it.getRequireName())) }
|
||||
val invocation = JsInvocation(function, listOf(JsNameRef("exports", moduleName.makeRef())) + invocationArgs)
|
||||
return listOf(invocation.makeStmt())
|
||||
}
|
||||
|
||||
private fun wrapEsModule(function: JsFunction, importedModules: List<JsImportedModule>): List<JsStatement> {
|
||||
val (alreadyPresentedImportStatements, restStatements) = function.body.statements.partitionIsInstance<JsStatement, JsImport>()
|
||||
|
||||
val importStatements = importedModules.zip(function.parameters.drop(1)).map {
|
||||
JsImport(
|
||||
it.first.externalName,
|
||||
it.first.getRequireName(true),
|
||||
if (it.first.plainReference == null) {
|
||||
JsImport.Target.All(alias = it.second.name)
|
||||
JsImport.Target.All(alias = it.second.name.makeRef())
|
||||
} else {
|
||||
JsImport.Target.Default(name = it.second.name)
|
||||
JsImport.Target.Default(name = it.second.name.makeRef())
|
||||
}
|
||||
)
|
||||
}
|
||||
return importStatements + function.body.statements.dropLast(1)
|
||||
|
||||
val alreadyPresentedImportStatementsWithoutDuplicates = alreadyPresentedImportStatements
|
||||
.groupBy { it.module }
|
||||
.map { (module, import) ->
|
||||
JsImport(module, *import.flatMap { it.elements }.toTypedArray())
|
||||
}
|
||||
|
||||
return importStatements + alreadyPresentedImportStatementsWithoutDuplicates + restStatements.dropLast(1)
|
||||
}
|
||||
|
||||
|
||||
|
||||
+15
@@ -116,6 +116,21 @@ private fun JsNode.computeScopes(): Scope {
|
||||
super.visitNameRef(nameRef)
|
||||
}
|
||||
|
||||
override fun visitImport(import: JsImport) {
|
||||
when (val target = import.target) {
|
||||
is JsImport.Target.All -> target.alias.name?.let { currentScope.declaredNames += it }
|
||||
is JsImport.Target.Default -> target.name.name?.let { currentScope.declaredNames += it }
|
||||
is JsImport.Target.Elements -> target.elements.forEach { element ->
|
||||
if (element.alias != null) {
|
||||
element.alias?.name?.let { currentScope.declaredNames += it }
|
||||
} else {
|
||||
currentScope.declaredNames += element.name
|
||||
}
|
||||
}
|
||||
}
|
||||
super.visitImport(import)
|
||||
}
|
||||
|
||||
override fun visitBreak(x: JsBreak) {}
|
||||
|
||||
override fun visitContinue(x: JsContinue) {}
|
||||
|
||||
Reference in New Issue
Block a user