@@ -94,12 +94,14 @@ class CrossModuleDependenciesResolver(
94
94
private val headers : List <JsIrModuleHeader >
95
95
) {
96
96
fun resolveCrossModuleDependencies (relativeRequirePath : Boolean ): Map <JsIrModuleHeader , CrossModuleReferences > {
97
- val headerToBuilder = headers.associateWith { JsIrModuleCrossModuleReferecenceBuilder (moduleKind, it, relativeRequirePath) }
98
- val definitionModule = mutableMapOf<String , JsIrModuleCrossModuleReferecenceBuilder >()
97
+ val headerToBuilder = headers.associateWith { JsIrModuleCrossModuleReferenceBuilder (moduleKind, it, relativeRequirePath) }
98
+ val definitionModule = mutableMapOf<String , JsIrModuleCrossModuleReferenceBuilder >()
99
99
100
- val mainModuleHeader = headers.last()
101
- val otherModuleHeaders = headers.dropLast(1 )
102
- headerToBuilder[mainModuleHeader]!! .transitiveJsExportFrom = otherModuleHeaders
100
+ if (moduleKind != ModuleKind .ES ) {
101
+ val mainModuleHeader = headers.last()
102
+ val otherModuleHeaders = headers.dropLast(1 )
103
+ headerToBuilder[mainModuleHeader]!! .transitiveJsExportFrom = otherModuleHeaders
104
+ }
103
105
104
106
for (header in headers) {
105
107
val builder = headerToBuilder[header]!!
@@ -130,9 +132,9 @@ class CrossModuleDependenciesResolver(
130
132
}
131
133
}
132
134
133
- private class CrossModuleRef (val module : JsIrModuleCrossModuleReferecenceBuilder , val tag : String )
135
+ private class CrossModuleRef (val module : JsIrModuleCrossModuleReferenceBuilder , val tag : String )
134
136
135
- private class JsIrModuleCrossModuleReferecenceBuilder (
137
+ private class JsIrModuleCrossModuleReferenceBuilder (
136
138
val moduleKind : ModuleKind ,
137
139
val header : JsIrModuleHeader ,
138
140
val relativeRequirePath : Boolean
@@ -150,20 +152,15 @@ private class JsIrModuleCrossModuleReferecenceBuilder(
150
152
151
153
fun buildCrossModuleRefs (): CrossModuleReferences {
152
154
buildExportNames()
155
+ val isImportOptional = moduleKind == ModuleKind .ES
153
156
val importedModules = mutableMapOf<JsIrModuleHeader , JsImportedModule >()
154
157
155
- fun import (moduleHeader : JsIrModuleHeader ): JsName {
156
- return importedModules.getOrPut(moduleHeader) {
157
- val jsModuleName = JsName (moduleHeader.moduleName, false )
158
- val relativeRequirePath = relativeRequirePath(moduleHeader)
159
-
160
- JsImportedModule (
161
- moduleHeader.externalModuleName,
162
- jsModuleName,
163
- null ,
164
- relativeRequirePath
165
- )
166
- }.internalName
158
+ fun import (moduleHeader : JsIrModuleHeader ): JsImportedModule {
159
+ return if (isImportOptional) {
160
+ moduleHeader.toJsImportedModule()
161
+ } else {
162
+ importedModules.getOrPut(moduleHeader) { moduleHeader.toJsImportedModule() }
163
+ }
167
164
}
168
165
169
166
val resultImports = imports.associate { crossModuleRef ->
@@ -173,13 +170,13 @@ private class JsIrModuleCrossModuleReferecenceBuilder(
173
170
" Cross module dependency resolution failed due to signature '$tag ' redefinition"
174
171
}
175
172
val exportedAs = crossModuleRef.module.exportNames[tag]!!
176
- val moduleName = import(crossModuleRef.module.header)
173
+ val importedModule = import(crossModuleRef.module.header)
177
174
178
- tag to CrossModuleImport (exportedAs, moduleName )
175
+ tag to CrossModuleImport (exportedAs, importedModule )
179
176
}
180
177
181
178
val transitiveExport = transitiveJsExportFrom.mapNotNull {
182
- if (! it.hasJsExports) null else CrossModuleTransitiveExport (import(it), it.externalModuleName)
179
+ if (! it.hasJsExports) null else CrossModuleTransitiveExport (import(it).internalName , it.externalModuleName)
183
180
}
184
181
return CrossModuleReferences (
185
182
moduleKind,
@@ -190,12 +187,22 @@ private class JsIrModuleCrossModuleReferecenceBuilder(
190
187
)
191
188
}
192
189
190
+ private fun JsIrModuleHeader.toJsImportedModule (): JsImportedModule {
191
+ val jsModuleName = JsName (moduleName, false )
192
+ val relativeRequirePath = relativeRequirePath(this )
193
+
194
+ return JsImportedModule (
195
+ externalModuleName,
196
+ jsModuleName,
197
+ null ,
198
+ relativeRequirePath
199
+ )
200
+ }
201
+
193
202
private fun relativeRequirePath (moduleHeader : JsIrModuleHeader ): String? {
194
203
if (! this .relativeRequirePath) return null
195
204
196
- val parentMain = File (header.externalModuleName).parentFile
197
-
198
- if (parentMain == null ) return " ./${moduleHeader.externalModuleName} "
205
+ val parentMain = File (header.externalModuleName).parentFile ? : return " ./${moduleHeader.externalModuleName} "
199
206
200
207
val relativePath = File (moduleHeader.externalModuleName)
201
208
.toRelativeString(parentMain)
@@ -206,10 +213,12 @@ private class JsIrModuleCrossModuleReferecenceBuilder(
206
213
}
207
214
}
208
215
209
- class CrossModuleImport (val exportedAs : String , val moduleExporter : JsName )
216
+ class CrossModuleImport (val exportedAs : String , val moduleExporter : JsImportedModule )
210
217
211
218
class CrossModuleTransitiveExport (val internalName : JsName , val externalName : String )
212
219
220
+ fun CrossModuleTransitiveExport.getRequireEsmName () = " $externalName$ESM_EXTENSION "
221
+
213
222
class CrossModuleReferences (
214
223
val moduleKind : ModuleKind ,
215
224
val importedModules : List <JsImportedModule >, // additional Kotlin imported modules
@@ -218,28 +227,45 @@ class CrossModuleReferences(
218
227
val imports : Map <String , CrossModuleImport >, // tag -> import statement
219
228
) {
220
229
// built from imports
221
- var jsImports = emptyMap<String , JsVars . JsVar >() // tag -> import statement
230
+ var jsImports = emptyMap<String , JsStatement >() // tag -> import statement
222
231
private set
223
232
224
233
fun initJsImportsForModule (module : JsIrModule ) {
225
234
val tagToName = module.fragments.flatMap { it.nameBindings.entries }.associate { it.key to it.value }
226
235
jsImports = imports.entries.associate {
227
236
val importedAs = tagToName[it.key] ? : error(" Internal error: cannot find imported name for signature ${it.key} " )
228
- val exportRef = JsNameRef (
229
- it.value.exportedAs,
230
- it.value.moduleExporter.let {
231
- if (moduleKind == ModuleKind .ES ) {
232
- it.makeRef()
233
- } else {
234
- ReservedJsNames .makeCrossModuleNameRef(it)
235
- }
236
- }
237
- )
238
- it.key to JsVars .JsVar (importedAs, exportRef)
237
+ it.key to it.value.generateCrossModuleImportStatement(importedAs)
239
238
}
240
239
}
241
240
241
+ private fun CrossModuleImport.generateCrossModuleImportStatement (importedAs : JsName ): JsStatement {
242
+ return when (moduleKind) {
243
+ ModuleKind .ES -> generateJsImportStatement(importedAs)
244
+ else -> generateImportVariableDeclaration(importedAs)
245
+ }
246
+ }
247
+
248
+ private fun CrossModuleImport.generateImportVariableDeclaration (importedAs : JsName ): JsStatement {
249
+ val exportRef = JsNameRef (exportedAs, ReservedJsNames .makeCrossModuleNameRef(moduleExporter.internalName))
250
+ return JsVars (JsVars .JsVar (importedAs, exportRef))
251
+ }
252
+
253
+ private fun CrossModuleImport.generateJsImportStatement (importedAs : JsName ): JsStatement {
254
+ return JsImport (
255
+ moduleExporter.getRequireName(true ),
256
+ JsImport .Element (JsName (exportedAs, false ), importedAs.makeRef())
257
+ )
258
+ }
259
+
242
260
companion object {
243
261
fun Empty (moduleKind : ModuleKind ) = CrossModuleReferences (moduleKind, listOf (), emptyList(), emptyMap(), emptyMap())
244
262
}
245
263
}
264
+
265
+ fun JsStatement.renameImportedSymbolInternalName (newName : JsName ): JsStatement {
266
+ return when (this ) {
267
+ is JsImport -> JsImport (module, JsImport .Element ((target as JsImport .Target .Elements ).elements.single().name, newName.makeRef()))
268
+ is JsVars -> JsVars (JsVars .JsVar (newName, vars.single().initExpression))
269
+ else -> error(" Unexpected cross-module import statement ${this ::class .qualifiedName} " )
270
+ }
271
+ }
0 commit comments