[K/JS] Support eager initialization for per-file granularity
This commit is contained in:
+4
@@ -221,6 +221,10 @@ internal fun CrossModuleReferences.crossModuleReferencesHashForIC() = HashCalcul
|
|||||||
update(exports[tag]!!)
|
update(exports[tag]!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateForEach(importsWithEffect.sortedBy { it.moduleExporter.externalName }) { import ->
|
||||||
|
update(import.moduleExporter.externalName)
|
||||||
|
}
|
||||||
|
|
||||||
updateForEach(imports.keys.sorted()) { tag ->
|
updateForEach(imports.keys.sorted()) { tag ->
|
||||||
val import = imports[tag]!!
|
val import = imports[tag]!!
|
||||||
update(tag)
|
update(tag)
|
||||||
|
|||||||
+48
-12
@@ -78,7 +78,11 @@ class JsPerFileCache(private val moduleArtifacts: List<ModuleArtifact>) : JsMult
|
|||||||
private fun JsIrProgramFragment.getExportFragmentExternalName(moduleArtifact: ModuleArtifact) =
|
private fun JsIrProgramFragment.getExportFragmentExternalName(moduleArtifact: ModuleArtifact) =
|
||||||
moduleFragmentToExternalName.getExternalNameForExporterFile(name, packageFqn, moduleArtifact.moduleExternalName)
|
moduleFragmentToExternalName.getExternalNameForExporterFile(name, packageFqn, moduleArtifact.moduleExternalName)
|
||||||
|
|
||||||
private fun JsIrProgramFragment.asIrModuleHeader(moduleName: String, reexportedIn: String? = null): JsIrModuleHeader {
|
private fun JsIrProgramFragment.asIrModuleHeader(
|
||||||
|
moduleName: String,
|
||||||
|
reexportedIn: String? = null,
|
||||||
|
importWithEffectIn: String? = null,
|
||||||
|
): JsIrModuleHeader {
|
||||||
return JsIrModuleHeader(
|
return JsIrModuleHeader(
|
||||||
moduleName = moduleName,
|
moduleName = moduleName,
|
||||||
externalModuleName = moduleName,
|
externalModuleName = moduleName,
|
||||||
@@ -86,14 +90,25 @@ class JsPerFileCache(private val moduleArtifacts: List<ModuleArtifact>) : JsMult
|
|||||||
nameBindings = nameBindings.mapValues { v -> v.value.toString() },
|
nameBindings = nameBindings.mapValues { v -> v.value.toString() },
|
||||||
optionalCrossModuleImports = optionalCrossModuleImports,
|
optionalCrossModuleImports = optionalCrossModuleImports,
|
||||||
reexportedInModuleWithName = reexportedIn,
|
reexportedInModuleWithName = reexportedIn,
|
||||||
|
importedWithEffectInModuleWithName = importWithEffectIn,
|
||||||
associatedModule = null
|
associatedModule = null
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun SrcFileArtifact.loadJsIrModuleHeaders(moduleArtifact: ModuleArtifact) = with(loadJsIrFragments()) {
|
private fun SrcFileArtifact.loadJsIrModuleHeaders(moduleArtifact: ModuleArtifact) = with(loadJsIrFragments()) {
|
||||||
LoadedJsIrModuleHeaders(
|
LoadedJsIrModuleHeaders(
|
||||||
mainFragment.run { asIrModuleHeader(getMainFragmentExternalName(moduleArtifact)) },
|
mainFragment.run {
|
||||||
exportFragment?.run { asIrModuleHeader(mainFragment.getExportFragmentExternalName(moduleArtifact), moduleArtifact.moduleExternalName) },
|
asIrModuleHeader(
|
||||||
|
getMainFragmentExternalName(moduleArtifact),
|
||||||
|
importWithEffectIn = runIf(hasEffect) { moduleArtifact.moduleExternalName }
|
||||||
|
)
|
||||||
|
},
|
||||||
|
exportFragment?.run {
|
||||||
|
asIrModuleHeader(
|
||||||
|
mainFragment.getExportFragmentExternalName(moduleArtifact),
|
||||||
|
reexportedIn = moduleArtifact.moduleExternalName
|
||||||
|
)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,6 +123,8 @@ class JsPerFileCache(private val moduleArtifacts: List<ModuleArtifact>) : JsMult
|
|||||||
reexportedIn = cachedFileInfo.moduleArtifact.moduleExternalName
|
reexportedIn = cachedFileInfo.moduleArtifact.moduleExternalName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val importWithEffectIn = ifTrue { readString() }
|
||||||
val (definitions, nameBindings, optionalCrossModuleImports) = fetchJsIrModuleHeaderNames()
|
val (definitions, nameBindings, optionalCrossModuleImports) = fetchJsIrModuleHeaderNames()
|
||||||
|
|
||||||
it.jsIrHeader = JsIrModuleHeader(
|
it.jsIrHeader = JsIrModuleHeader(
|
||||||
@@ -117,6 +134,7 @@ class JsPerFileCache(private val moduleArtifacts: List<ModuleArtifact>) : JsMult
|
|||||||
nameBindings = nameBindings,
|
nameBindings = nameBindings,
|
||||||
optionalCrossModuleImports = optionalCrossModuleImports,
|
optionalCrossModuleImports = optionalCrossModuleImports,
|
||||||
reexportedInModuleWithName = reexportedIn,
|
reexportedInModuleWithName = reexportedIn,
|
||||||
|
importedWithEffectInModuleWithName = importWithEffectIn,
|
||||||
associatedModule = null,
|
associatedModule = null,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -149,12 +167,13 @@ class JsPerFileCache(private val moduleArtifacts: List<ModuleArtifact>) : JsMult
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun CodedOutputStream.commitSingleFileInfo(cachedFileInfo: CachedFileInfo.SerializableCachedFileInfo) {
|
private fun CodedOutputStream.commitSingleFileInfo(cachedFileInfo: CachedFileInfo) {
|
||||||
writeStringNoTag(cachedFileInfo.jsIrHeader.externalModuleName)
|
writeStringNoTag(cachedFileInfo.jsIrHeader.externalModuleName)
|
||||||
cachedFileInfo.crossFileReferencesHash.toProtoStream(this)
|
cachedFileInfo.crossFileReferencesHash.toProtoStream(this)
|
||||||
if (cachedFileInfo is CachedFileInfo.ExportFileCachedInfo) {
|
if (cachedFileInfo is CachedFileInfo.ExportFileCachedInfo) {
|
||||||
ifNotNull(cachedFileInfo.tsDeclarationsHash, ::writeInt64NoTag)
|
ifNotNull(cachedFileInfo.tsDeclarationsHash, ::writeInt64NoTag)
|
||||||
}
|
}
|
||||||
|
ifNotNull(cachedFileInfo.jsIrHeader.importedWithEffectInModuleWithName) { writeStringNoTag(it) }
|
||||||
commitJsIrModuleHeaderNames(cachedFileInfo.jsIrHeader)
|
commitJsIrModuleHeaderNames(cachedFileInfo.jsIrHeader)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,18 +186,16 @@ class JsPerFileCache(private val moduleArtifacts: List<ModuleArtifact>) : JsMult
|
|||||||
}
|
}
|
||||||
is CachedFileInfo.ModuleProxyFileCachedInfo -> {
|
is CachedFileInfo.ModuleProxyFileCachedInfo -> {
|
||||||
moduleHeaderArtifact?.useCodedOutput {
|
moduleHeaderArtifact?.useCodedOutput {
|
||||||
writeStringNoTag(jsIrHeader.externalModuleName)
|
commitSingleFileInfo(this@commitFileInfo)
|
||||||
crossFileReferencesHash.toProtoStream(this)
|
|
||||||
commitJsIrModuleHeaderNames(jsIrHeader)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is CachedFileInfo.ExportFileCachedInfo -> {}
|
is CachedFileInfo.ExportFileCachedInfo -> {}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ModuleArtifact.generateModuleProxyFileCachedInfo(): CachedFileInfo {
|
private fun ModuleArtifact.generateModuleProxyFileCachedInfo(importedWithEffectInModuleWithName: String? = null): CachedFileInfo {
|
||||||
return CachedFileInfo.ModuleProxyFileCachedInfo(
|
return CachedFileInfo.ModuleProxyFileCachedInfo(
|
||||||
this,
|
this,
|
||||||
generateProxyIrModuleWith(moduleExternalName, moduleExternalName).makeModuleHeader()
|
generateProxyIrModuleWith(moduleExternalName, moduleExternalName, importedWithEffectInModuleWithName).makeModuleHeader()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,7 +247,11 @@ class JsPerFileCache(private val moduleArtifacts: List<ModuleArtifact>) : JsMult
|
|||||||
|
|
||||||
override fun loadJsIrModule(cacheInfo: CachedFileInfo): JsIrModule {
|
override fun loadJsIrModule(cacheInfo: CachedFileInfo): JsIrModule {
|
||||||
if (cacheInfo !is CachedFileInfo.SerializableCachedFileInfo) {
|
if (cacheInfo !is CachedFileInfo.SerializableCachedFileInfo) {
|
||||||
return generateProxyIrModuleWith(cacheInfo.jsIrHeader.externalModuleName, cacheInfo.jsIrHeader.externalModuleName)
|
return generateProxyIrModuleWith(
|
||||||
|
cacheInfo.jsIrHeader.externalModuleName,
|
||||||
|
cacheInfo.jsIrHeader.externalModuleName,
|
||||||
|
cacheInfo.jsIrHeader.importedWithEffectInModuleWithName
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val fragments = cacheInfo.fileArtifact.loadJsIrFragments()
|
val fragments = cacheInfo.fileArtifact.loadJsIrFragments()
|
||||||
@@ -244,8 +265,11 @@ class JsPerFileCache(private val moduleArtifacts: List<ModuleArtifact>) : JsMult
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun loadProgramHeadersFromCache(): List<CachedFileInfo> {
|
override fun loadProgramHeadersFromCache(): List<CachedFileInfo> {
|
||||||
|
var someModuleHasEffect = false
|
||||||
|
val mainModuleArtifact = moduleArtifacts.last()
|
||||||
return moduleArtifacts
|
return moduleArtifacts
|
||||||
.flatMap { moduleArtifact ->
|
.flatMap { moduleArtifact ->
|
||||||
|
var hasModuleLevelEffect = false
|
||||||
var hasFileWithJsExportedDeclaration = false
|
var hasFileWithJsExportedDeclaration = false
|
||||||
moduleArtifact.fileArtifacts
|
moduleArtifact.fileArtifacts
|
||||||
.flatMap { srcFileArtifact ->
|
.flatMap { srcFileArtifact ->
|
||||||
@@ -257,11 +281,21 @@ class JsPerFileCache(private val moduleArtifacts: List<ModuleArtifact>) : JsMult
|
|||||||
if (!hasFileWithJsExportedDeclaration && cachedFileInfo.hasExportFile()) {
|
if (!hasFileWithJsExportedDeclaration && cachedFileInfo.hasExportFile()) {
|
||||||
hasFileWithJsExportedDeclaration = true
|
hasFileWithJsExportedDeclaration = true
|
||||||
}
|
}
|
||||||
|
if (!hasModuleLevelEffect && cachedFileInfo.hasModuleLevelEffect()) {
|
||||||
|
someModuleHasEffect = true
|
||||||
|
hasModuleLevelEffect = true
|
||||||
|
}
|
||||||
|
|
||||||
cachedFileInfo
|
cachedFileInfo
|
||||||
}
|
}
|
||||||
.butIf(hasFileWithJsExportedDeclaration) {
|
.butIf(hasFileWithJsExportedDeclaration || hasModuleLevelEffect || (someModuleHasEffect && moduleArtifact === mainModuleArtifact)) { list ->
|
||||||
it.plus(moduleArtifact.fetchModuleProxyFileInfo() ?: moduleArtifact.generateModuleProxyFileCachedInfo())
|
val importWithEffectIn = mainModuleArtifact.moduleExternalName.takeIf {
|
||||||
|
hasModuleLevelEffect && moduleArtifact !== mainModuleArtifact
|
||||||
|
}
|
||||||
|
val fetchedProxyFileInfo = moduleArtifact.fetchModuleProxyFileInfo()?.takeIf {
|
||||||
|
it.jsIrHeader.importedWithEffectInModuleWithName == importWithEffectIn
|
||||||
|
}
|
||||||
|
list.plus(fetchedProxyFileInfo ?: moduleArtifact.generateModuleProxyFileCachedInfo(importWithEffectIn))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onEach { headerToCachedInfo[it.jsIrHeader] = it }
|
.onEach { headerToCachedInfo[it.jsIrHeader] = it }
|
||||||
@@ -288,4 +322,6 @@ class JsPerFileCache(private val moduleArtifacts: List<ModuleArtifact>) : JsMult
|
|||||||
private data class LoadedJsIrModuleHeaders(val mainHeader: JsIrModuleHeader, val exportHeader: JsIrModuleHeader?)
|
private data class LoadedJsIrModuleHeaders(val mainHeader: JsIrModuleHeader, val exportHeader: JsIrModuleHeader?)
|
||||||
|
|
||||||
private fun List<JsPerFileCache.CachedFileInfo>.hasExportFile(): Boolean = size > 1
|
private fun List<JsPerFileCache.CachedFileInfo>.hasExportFile(): Boolean = size > 1
|
||||||
|
private fun List<JsPerFileCache.CachedFileInfo>.hasModuleLevelEffect(): Boolean =
|
||||||
|
last().jsIrHeader.importedWithEffectInModuleWithName != null
|
||||||
}
|
}
|
||||||
@@ -27,6 +27,7 @@ class JsPerModuleCache(private val moduleArtifacts: List<ModuleArtifact>) : JsMu
|
|||||||
private fun ModuleArtifact.fetchModuleInfo() = File(artifactsDir, JS_MODULE_HEADER).useCodedInputIfExists {
|
private fun ModuleArtifact.fetchModuleInfo() = File(artifactsDir, JS_MODULE_HEADER).useCodedInputIfExists {
|
||||||
val crossModuleReferencesHash = ICHash.fromProtoStream(this)
|
val crossModuleReferencesHash = ICHash.fromProtoStream(this)
|
||||||
val reexportedInModuleWithName = ifTrue { readString() }
|
val reexportedInModuleWithName = ifTrue { readString() }
|
||||||
|
val importedWithEffectInModuleWithName = ifTrue { readString() }
|
||||||
val (definitions, nameBindings, optionalCrossModuleImports) = fetchJsIrModuleHeaderNames()
|
val (definitions, nameBindings, optionalCrossModuleImports) = fetchJsIrModuleHeaderNames()
|
||||||
|
|
||||||
CachedModuleInfo(
|
CachedModuleInfo(
|
||||||
@@ -38,6 +39,7 @@ class JsPerModuleCache(private val moduleArtifacts: List<ModuleArtifact>) : JsMu
|
|||||||
nameBindings = nameBindings,
|
nameBindings = nameBindings,
|
||||||
optionalCrossModuleImports = optionalCrossModuleImports,
|
optionalCrossModuleImports = optionalCrossModuleImports,
|
||||||
reexportedInModuleWithName = reexportedInModuleWithName,
|
reexportedInModuleWithName = reexportedInModuleWithName,
|
||||||
|
importedWithEffectInModuleWithName = importedWithEffectInModuleWithName,
|
||||||
associatedModule = null
|
associatedModule = null
|
||||||
),
|
),
|
||||||
crossModuleReferencesHash = crossModuleReferencesHash
|
crossModuleReferencesHash = crossModuleReferencesHash
|
||||||
@@ -48,6 +50,7 @@ class JsPerModuleCache(private val moduleArtifacts: List<ModuleArtifact>) : JsMu
|
|||||||
File(cacheDir, JS_MODULE_HEADER).useCodedOutput {
|
File(cacheDir, JS_MODULE_HEADER).useCodedOutput {
|
||||||
crossModuleReferencesHash.toProtoStream(this)
|
crossModuleReferencesHash.toProtoStream(this)
|
||||||
ifNotNull(jsIrHeader.reexportedInModuleWithName) { writeStringNoTag(it) }
|
ifNotNull(jsIrHeader.reexportedInModuleWithName) { writeStringNoTag(it) }
|
||||||
|
ifNotNull(jsIrHeader.importedWithEffectInModuleWithName) { writeStringNoTag(it) }
|
||||||
commitJsIrModuleHeaderNames(jsIrHeader)
|
commitJsIrModuleHeaderNames(jsIrHeader)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-1
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
|||||||
import org.jetbrains.kotlin.ir.backend.js.lower.JsCodeOutliningLowering
|
import org.jetbrains.kotlin.ir.backend.js.lower.JsCodeOutliningLowering
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
|
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.util.hasAnnotation
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
|
|
||||||
@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
|
@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
|
||||||
@@ -41,8 +42,13 @@ class IrDeclarationToJsTransformer : BaseIrElementToJsNodeTransformer<JsStatemen
|
|||||||
if (declaration.isExternal) return JsEmpty
|
if (declaration.isExternal) return JsEmpty
|
||||||
|
|
||||||
if (declaration.initializer != null) {
|
if (declaration.initializer != null) {
|
||||||
|
val eagerInitializationAnnotation = context.staticContext.backendContext.propertyLazyInitialization.eagerInitialization
|
||||||
val initializer = declaration.initializer!!.accept(IrElementToJsExpressionTransformer(), context)
|
val initializer = declaration.initializer!!.accept(IrElementToJsExpressionTransformer(), context)
|
||||||
context.staticContext.initializerBlock.statements += jsAssignment(fieldName.makeRef(), initializer).makeStmt()
|
val initializerBlock = when {
|
||||||
|
declaration.correspondingPropertySymbol?.owner?.hasAnnotation(eagerInitializationAnnotation) == true -> context.staticContext.eagerInitializerBlock
|
||||||
|
else -> context.staticContext.initializerBlock
|
||||||
|
}
|
||||||
|
initializerBlock.statements += jsAssignment(fieldName.makeRef(), initializer).makeStmt()
|
||||||
}
|
}
|
||||||
|
|
||||||
return JsVars(JsVars.JsVar(fieldName))
|
return JsVars(JsVars.JsVar(fieldName))
|
||||||
|
|||||||
+21
-7
@@ -47,10 +47,11 @@ val String.safeModuleName: String
|
|||||||
val IrModuleFragment.safeName: String
|
val IrModuleFragment.safeName: String
|
||||||
get() = name.asString().safeModuleName
|
get() = name.asString().safeModuleName
|
||||||
|
|
||||||
fun generateProxyIrModuleWith(safeName: String, externalName: String) = JsIrModule(
|
fun generateProxyIrModuleWith(safeName: String, externalName: String, importedWithEffectInModuleWithName: String? = null) = JsIrModule(
|
||||||
safeName,
|
safeName,
|
||||||
externalName,
|
externalName,
|
||||||
listOf(JsIrProgramFragment(safeName, "<proxy-file>"))
|
listOf(JsIrProgramFragment(safeName, "<proxy-file>")),
|
||||||
|
importedWithEffectInModuleWithName = importedWithEffectInModuleWithName
|
||||||
)
|
)
|
||||||
|
|
||||||
enum class JsGenerationGranularity {
|
enum class JsGenerationGranularity {
|
||||||
@@ -264,15 +265,25 @@ class IrModuleToJsTransformer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun generateJsIrProgramPerFile(exportData: List<IrAndExportedDeclarations>, mode: TranslationMode): JsIrProgram {
|
private fun generateJsIrProgramPerFile(exportData: List<IrAndExportedDeclarations>, mode: TranslationMode): JsIrProgram {
|
||||||
|
val mainModule = exportData.last()
|
||||||
|
var someModuleHasEffect = false
|
||||||
|
|
||||||
val modulesPerFile = buildList {
|
val modulesPerFile = buildList {
|
||||||
for (module in exportData) {
|
for (module in exportData) {
|
||||||
|
var hasModuleLevelEffect = false
|
||||||
var hasFileWithJsExportedDeclaration = false
|
var hasFileWithJsExportedDeclaration = false
|
||||||
|
|
||||||
for (fileExports in module.files) {
|
for (fileExports in module.files) {
|
||||||
if (fileExports.file.couldBeSkipped()) continue
|
if (fileExports.file.couldBeSkipped()) continue
|
||||||
val programFragments = generateProgramFragment(fileExports, mode)
|
val programFragments = generateProgramFragment(fileExports, mode)
|
||||||
|
|
||||||
add(fileExports.toJsIrModule(programFragments.mainFragment))
|
fileExports.toJsIrModule(module, programFragments.mainFragment).let {
|
||||||
|
add(it)
|
||||||
|
if (it.importedWithEffectInModuleWithName != null) {
|
||||||
|
someModuleHasEffect = true
|
||||||
|
hasModuleLevelEffect = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
programFragments.exportFragment?.let {
|
programFragments.exportFragment?.let {
|
||||||
add(fileExports.toJsIrModuleForExport(module, it))
|
add(fileExports.toJsIrModuleForExport(module, it))
|
||||||
@@ -280,8 +291,8 @@ class IrModuleToJsTransformer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasFileWithJsExportedDeclaration) {
|
if (hasFileWithJsExportedDeclaration || hasModuleLevelEffect || (module === mainModule && someModuleHasEffect)) {
|
||||||
add(module.toJsIrProxyModule())
|
add(module.toJsIrProxyModule(mainModule.fragment.safeName.takeIf { module !== mainModule && hasModuleLevelEffect }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -289,11 +300,12 @@ class IrModuleToJsTransformer(
|
|||||||
return JsIrProgram(modulesPerFile)
|
return JsIrProgram(modulesPerFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrFileExports.toJsIrModule(programFragment: JsIrProgramFragment): JsIrModule {
|
private fun IrFileExports.toJsIrModule(module: IrAndExportedDeclarations, programFragment: JsIrProgramFragment): JsIrModule {
|
||||||
return JsIrModule(
|
return JsIrModule(
|
||||||
moduleFragmentToNameMapper.getSafeNameFor(file),
|
moduleFragmentToNameMapper.getSafeNameFor(file),
|
||||||
moduleFragmentToNameMapper.getExternalNameFor(file),
|
moduleFragmentToNameMapper.getExternalNameFor(file),
|
||||||
listOf(programFragment),
|
listOf(programFragment),
|
||||||
|
importedWithEffectInModuleWithName = runIf(programFragment.hasEffect) { module.fragment.safeName }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,10 +318,11 @@ class IrModuleToJsTransformer(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrAndExportedDeclarations.toJsIrProxyModule(): JsIrModule {
|
private fun IrAndExportedDeclarations.toJsIrProxyModule(importedWithEffectInModuleWithName: String? = null): JsIrModule {
|
||||||
return generateProxyIrModuleWith(
|
return generateProxyIrModuleWith(
|
||||||
fragment.safeName,
|
fragment.safeName,
|
||||||
moduleFragmentToNameMapper.getExternalNameFor(fragment),
|
moduleFragmentToNameMapper.getExternalNameFor(fragment),
|
||||||
|
importedWithEffectInModuleWithName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -391,6 +404,7 @@ class IrModuleToJsTransformer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
result.initializers.statements += staticContext.initializerBlock.statements
|
result.initializers.statements += staticContext.initializerBlock.statements
|
||||||
|
result.eagerInitializers.statements += staticContext.eagerInitializerBlock.statements
|
||||||
|
|
||||||
if (mainArguments != null) {
|
if (mainArguments != null) {
|
||||||
JsMainFunctionDetector(backendContext).getMainFunctionOrNull(fileExports.file)?.let {
|
JsMainFunctionDetector(backendContext).getMainFunctionOrNull(fileExports.file)?.let {
|
||||||
|
|||||||
+29
-2
@@ -22,6 +22,7 @@ class JsIrProgramFragment(val name: String, val packageFqn: String) {
|
|||||||
var dts: TypeScriptFragment? = null
|
var dts: TypeScriptFragment? = null
|
||||||
val classes = mutableMapOf<JsName, JsIrIcClassModel>()
|
val classes = mutableMapOf<JsName, JsIrIcClassModel>()
|
||||||
val initializers = JsCompositeBlock()
|
val initializers = JsCompositeBlock()
|
||||||
|
val eagerInitializers = JsCompositeBlock()
|
||||||
var mainFunction: JsStatement? = null
|
var mainFunction: JsStatement? = null
|
||||||
var testFunInvocation: JsStatement? = null
|
var testFunInvocation: JsStatement? = null
|
||||||
var suiteFn: JsName? = null
|
var suiteFn: JsName? = null
|
||||||
@@ -34,6 +35,7 @@ class JsIrModule(
|
|||||||
val externalModuleName: String,
|
val externalModuleName: String,
|
||||||
val fragments: List<JsIrProgramFragment>,
|
val fragments: List<JsIrProgramFragment>,
|
||||||
val reexportedInModuleWithName: String? = null,
|
val reexportedInModuleWithName: String? = null,
|
||||||
|
val importedWithEffectInModuleWithName: String? = null,
|
||||||
) {
|
) {
|
||||||
fun makeModuleHeader(): JsIrModuleHeader {
|
fun makeModuleHeader(): JsIrModuleHeader {
|
||||||
val nameBindings = mutableMapOf<String, String>()
|
val nameBindings = mutableMapOf<String, String>()
|
||||||
@@ -55,6 +57,7 @@ class JsIrModule(
|
|||||||
nameBindings = nameBindings,
|
nameBindings = nameBindings,
|
||||||
optionalCrossModuleImports = optionalCrossModuleImports,
|
optionalCrossModuleImports = optionalCrossModuleImports,
|
||||||
reexportedInModuleWithName = reexportedInModuleWithName.takeIf { hasDeclarationsToReexport },
|
reexportedInModuleWithName = reexportedInModuleWithName.takeIf { hasDeclarationsToReexport },
|
||||||
|
importedWithEffectInModuleWithName = importedWithEffectInModuleWithName,
|
||||||
associatedModule = this
|
associatedModule = this
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -67,6 +70,7 @@ class JsIrModuleHeader(
|
|||||||
val nameBindings: Map<String, String>,
|
val nameBindings: Map<String, String>,
|
||||||
val optionalCrossModuleImports: Set<String>,
|
val optionalCrossModuleImports: Set<String>,
|
||||||
val reexportedInModuleWithName: String? = null,
|
val reexportedInModuleWithName: String? = null,
|
||||||
|
val importedWithEffectInModuleWithName: String? = null,
|
||||||
var associatedModule: JsIrModule?,
|
var associatedModule: JsIrModule?,
|
||||||
) {
|
) {
|
||||||
val externalNames: Set<String> by lazy(LazyThreadSafetyMode.NONE) { nameBindings.keys - definitions }
|
val externalNames: Set<String> by lazy(LazyThreadSafetyMode.NONE) { nameBindings.keys - definitions }
|
||||||
@@ -94,12 +98,14 @@ class JsIrProgram(private var modules: List<JsIrModule>) {
|
|||||||
class CrossModuleDependenciesResolver(private val moduleKind: ModuleKind, private val headers: List<JsIrModuleHeader>) {
|
class CrossModuleDependenciesResolver(private val moduleKind: ModuleKind, private val headers: List<JsIrModuleHeader>) {
|
||||||
fun resolveCrossModuleDependencies(relativeRequirePath: Boolean): Map<JsIrModuleHeader, CrossModuleReferences> {
|
fun resolveCrossModuleDependencies(relativeRequirePath: Boolean): Map<JsIrModuleHeader, CrossModuleReferences> {
|
||||||
val reexportModuleToHeader = headers.groupBy { it.reexportedInModuleWithName }
|
val reexportModuleToHeader = headers.groupBy { it.reexportedInModuleWithName }
|
||||||
|
val importedInModuleWithEffect = headers.groupBy { it.importedWithEffectInModuleWithName }
|
||||||
val headerToBuilder = headers.associateWith {
|
val headerToBuilder = headers.associateWith {
|
||||||
JsIrModuleCrossModuleReferenceBuilder(
|
JsIrModuleCrossModuleReferenceBuilder(
|
||||||
moduleKind,
|
moduleKind,
|
||||||
it,
|
it,
|
||||||
relativeRequirePath,
|
relativeRequirePath,
|
||||||
reexportModuleToHeader[it.moduleName] ?: emptyList(),
|
reexportModuleToHeader[it.moduleName] ?: emptyList(),
|
||||||
|
importedInModuleWithEffect[it.moduleName] ?: emptyList(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val definitionModule = mutableMapOf<String, JsIrModuleCrossModuleReferenceBuilder>()
|
val definitionModule = mutableMapOf<String, JsIrModuleCrossModuleReferenceBuilder>()
|
||||||
@@ -143,6 +149,7 @@ private class JsIrModuleCrossModuleReferenceBuilder(
|
|||||||
val header: JsIrModuleHeader,
|
val header: JsIrModuleHeader,
|
||||||
val relativeRequirePath: Boolean,
|
val relativeRequirePath: Boolean,
|
||||||
val transitiveExportFrom: List<JsIrModuleHeader>,
|
val transitiveExportFrom: List<JsIrModuleHeader>,
|
||||||
|
val importWithEffectFrom: List<JsIrModuleHeader>,
|
||||||
) {
|
) {
|
||||||
val imports = mutableListOf<CrossModuleRef>()
|
val imports = mutableListOf<CrossModuleRef>()
|
||||||
val exports = mutableSetOf<String>()
|
val exports = mutableSetOf<String>()
|
||||||
@@ -186,10 +193,14 @@ private class JsIrModuleCrossModuleReferenceBuilder(
|
|||||||
CrossModuleTransitiveExport(import(it).internalName, relativeRequirePath(it) ?: it.externalModuleName)
|
CrossModuleTransitiveExport(import(it).internalName, relativeRequirePath(it) ?: it.externalModuleName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val importsWithEffect = importWithEffectFrom.map { CrossModuleImportWithEffect(import(it)) }
|
||||||
|
|
||||||
return CrossModuleReferences(
|
return CrossModuleReferences(
|
||||||
moduleKind,
|
moduleKind,
|
||||||
importedModules.values.toList(),
|
importedModules.values.toList(),
|
||||||
transitiveExport,
|
transitiveExport,
|
||||||
|
importsWithEffect,
|
||||||
exportNames,
|
exportNames,
|
||||||
resultImports
|
resultImports
|
||||||
)
|
)
|
||||||
@@ -220,8 +231,9 @@ private class JsIrModuleCrossModuleReferenceBuilder(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CrossModuleImport(val exportedAs: String, val moduleExporter: JsImportedModule)
|
|
||||||
|
|
||||||
|
class CrossModuleImport(val exportedAs: String, val moduleExporter: JsImportedModule)
|
||||||
|
class CrossModuleImportWithEffect(val moduleExporter: JsImportedModule)
|
||||||
class CrossModuleTransitiveExport(val internalName: JsName, val externalName: String)
|
class CrossModuleTransitiveExport(val internalName: JsName, val externalName: String)
|
||||||
|
|
||||||
fun CrossModuleTransitiveExport.getRequireEsmName() = "$externalName$ESM_EXTENSION"
|
fun CrossModuleTransitiveExport.getRequireEsmName() = "$externalName$ESM_EXTENSION"
|
||||||
@@ -230,6 +242,7 @@ class CrossModuleReferences(
|
|||||||
val moduleKind: ModuleKind,
|
val moduleKind: ModuleKind,
|
||||||
val importedModules: List<JsImportedModule>, // additional Kotlin imported modules
|
val importedModules: List<JsImportedModule>, // additional Kotlin imported modules
|
||||||
val transitiveExportFrom: List<CrossModuleTransitiveExport>, // the list of modules which provide their exports for transitive export
|
val transitiveExportFrom: List<CrossModuleTransitiveExport>, // the list of modules which provide their exports for transitive export
|
||||||
|
val importsWithEffect: List<CrossModuleImportWithEffect>, // the list of modules which provide their effects for import
|
||||||
val exports: Map<String, String>, // tag -> index
|
val exports: Map<String, String>, // tag -> index
|
||||||
val imports: Map<String, CrossModuleImport>, // tag -> import statement
|
val imports: Map<String, CrossModuleImport>, // tag -> import statement
|
||||||
) {
|
) {
|
||||||
@@ -237,6 +250,8 @@ class CrossModuleReferences(
|
|||||||
var jsImports = emptyMap<String, JsStatement>() // tag -> import statement
|
var jsImports = emptyMap<String, JsStatement>() // tag -> import statement
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
val jsImportsWithEffect: List<JsStatement> = importsWithEffect.map { it.generateCrossModuleImportStatement() }
|
||||||
|
|
||||||
fun initJsImportsForModule(module: JsIrModule) {
|
fun initJsImportsForModule(module: JsIrModule) {
|
||||||
val tagToName = module.fragments.flatMap { it.nameBindings.entries }.associate { it.key to it.value }
|
val tagToName = module.fragments.flatMap { it.nameBindings.entries }.associate { it.key to it.value }
|
||||||
jsImports = imports.entries.associate {
|
jsImports = imports.entries.associate {
|
||||||
@@ -252,6 +267,17 @@ class CrossModuleReferences(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun CrossModuleImportWithEffect.generateCrossModuleImportStatement(): JsStatement {
|
||||||
|
return when (moduleKind) {
|
||||||
|
ModuleKind.ES -> generateJsImportStatement()
|
||||||
|
else -> error("Should not appear in non ES-modules compilations")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun CrossModuleImportWithEffect.generateJsImportStatement(): JsStatement {
|
||||||
|
return JsImport(moduleExporter.getRequireName(true), JsImport.Target.Effect)
|
||||||
|
}
|
||||||
|
|
||||||
private fun CrossModuleImport.generateImportVariableDeclaration(importedAs: JsName): JsStatement {
|
private fun CrossModuleImport.generateImportVariableDeclaration(importedAs: JsName): JsStatement {
|
||||||
val exportRef = JsNameRef(exportedAs, ReservedJsNames.makeCrossModuleNameRef(moduleExporter.internalName))
|
val exportRef = JsNameRef(exportedAs, ReservedJsNames.makeCrossModuleNameRef(moduleExporter.internalName))
|
||||||
return JsVars(JsVars.JsVar(importedAs, exportRef))
|
return JsVars(JsVars.JsVar(importedAs, exportRef))
|
||||||
@@ -265,7 +291,7 @@ class CrossModuleReferences(
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun Empty(moduleKind: ModuleKind) = CrossModuleReferences(moduleKind, listOf(), emptyList(), emptyMap(), emptyMap())
|
fun Empty(moduleKind: ModuleKind) = CrossModuleReferences(moduleKind, listOf(), emptyList(), emptyList(), emptyMap(), emptyMap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,3 +305,4 @@ fun JsStatement.renameImportedSymbolInternalName(newName: JsName): JsStatement {
|
|||||||
|
|
||||||
val List<JsIrProgramFragment>.mainFragment: JsIrProgramFragment get() = first()
|
val List<JsIrProgramFragment>.mainFragment: JsIrProgramFragment get() = first()
|
||||||
val List<JsIrProgramFragment>.exportFragment: JsIrProgramFragment? get() = getOrNull(1)
|
val List<JsIrProgramFragment>.exportFragment: JsIrProgramFragment? get() = getOrNull(1)
|
||||||
|
val JsIrProgramFragment.hasEffect: Boolean get() = eagerInitializers.statements.isNotEmpty()
|
||||||
+7
-2
@@ -22,6 +22,7 @@ class Merger(
|
|||||||
|
|
||||||
private val isEsModules = moduleKind == ModuleKind.ES
|
private val isEsModules = moduleKind == ModuleKind.ES
|
||||||
private val importStatements = mutableMapOf<String, JsStatement>()
|
private val importStatements = mutableMapOf<String, JsStatement>()
|
||||||
|
private val importStatementsWithEffect = mutableListOf<JsStatement>()
|
||||||
private val importedModulesMap = mutableMapOf<JsImportedModuleKey, JsImportedModule>()
|
private val importedModulesMap = mutableMapOf<JsImportedModuleKey, JsImportedModule>()
|
||||||
|
|
||||||
private val additionalExports = mutableListOf<JsStatement>()
|
private val additionalExports = mutableListOf<JsStatement>()
|
||||||
@@ -57,6 +58,7 @@ class Merger(
|
|||||||
}
|
}
|
||||||
|
|
||||||
rename(f.initializers)
|
rename(f.initializers)
|
||||||
|
rename(f.eagerInitializers)
|
||||||
f.mainFunction?.let { rename(it) }
|
f.mainFunction?.let { rename(it) }
|
||||||
f.testFunInvocation?.let { rename(it) }
|
f.testFunInvocation?.let { rename(it) }
|
||||||
f.suiteFn?.let { f.suiteFn = rename(it) }
|
f.suiteFn?.let { f.suiteFn = rename(it) }
|
||||||
@@ -68,6 +70,8 @@ class Merger(
|
|||||||
importStatements.putIfAbsent(tag, crossModuleJsImport.renameImportedSymbolInternalName(importName))
|
importStatements.putIfAbsent(tag, crossModuleJsImport.renameImportedSymbolInternalName(importName))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
importStatementsWithEffect.addAll(crossModuleReferences.jsImportsWithEffect)
|
||||||
|
|
||||||
if (crossModuleReferences.exports.isNotEmpty()) {
|
if (crossModuleReferences.exports.isNotEmpty()) {
|
||||||
val internalModuleName = ReservedJsNames.makeInternalModuleName()
|
val internalModuleName = ReservedJsNames.makeInternalModuleName()
|
||||||
|
|
||||||
@@ -213,7 +217,7 @@ class Merger(
|
|||||||
fragments.forEach {
|
fragments.forEach {
|
||||||
moduleBody += it.declarations.statements
|
moduleBody += it.declarations.statements
|
||||||
classModels += it.classes
|
classModels += it.classes
|
||||||
initializerBlock.statements += it.initializers.statements
|
initializerBlock.statements += it.initializers.statements + it.eagerInitializers.statements
|
||||||
polyfillDeclarationBlock.statements += it.polyfills.statements
|
polyfillDeclarationBlock.statements += it.polyfills.statements
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,7 +252,7 @@ class Merger(
|
|||||||
val exportStatements = declareAndCallJsExporter() + additionalExports + transitiveJsExport()
|
val exportStatements = declareAndCallJsExporter() + additionalExports + transitiveJsExport()
|
||||||
|
|
||||||
val importedJsModules = this.importedModulesMap.values.toList() + this.crossModuleReferences.importedModules
|
val importedJsModules = this.importedModulesMap.values.toList() + this.crossModuleReferences.importedModules
|
||||||
val importStatements = this.importStatements.values.toList()
|
val importStatements = this.importStatements.values.toList() + this.importStatementsWithEffect.toList()
|
||||||
|
|
||||||
val program = JsProgram()
|
val program = JsProgram()
|
||||||
|
|
||||||
@@ -342,6 +346,7 @@ class Merger(
|
|||||||
is JsImport -> JsImport(
|
is JsImport -> JsImport(
|
||||||
module,
|
module,
|
||||||
when (target) {
|
when (target) {
|
||||||
|
is JsImport.Target.Effect -> JsImport.Target.Effect
|
||||||
is JsImport.Target.All -> JsImport.Target.All(alias = name.makeRef())
|
is JsImport.Target.All -> JsImport.Target.All(alias = name.makeRef())
|
||||||
is JsImport.Target.Default -> JsImport.Target.Default(name = name.makeRef())
|
is JsImport.Target.Default -> JsImport.Target.Default(name = name.makeRef())
|
||||||
is JsImport.Target.Elements -> JsImport.Target.Elements(
|
is JsImport.Target.Elements -> JsImport.Target.Elements(
|
||||||
|
|||||||
+1
@@ -119,6 +119,7 @@ private fun JsNode.computeScopes(): Scope {
|
|||||||
|
|
||||||
override fun visitImport(import: JsImport) {
|
override fun visitImport(import: JsImport) {
|
||||||
when (val target = import.target) {
|
when (val target = import.target) {
|
||||||
|
is JsImport.Target.Effect -> {}
|
||||||
is JsImport.Target.All -> target.alias.name?.let { currentScope.declaredNames += it }
|
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.Default -> target.name.name?.let { currentScope.declaredNames += it }
|
||||||
is JsImport.Target.Elements -> target.elements.forEach {
|
is JsImport.Target.Elements -> target.elements.forEach {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ class JsStaticContext(
|
|||||||
val classModels = mutableMapOf<IrClassSymbol, JsIrClassModel>()
|
val classModels = mutableMapOf<IrClassSymbol, JsIrClassModel>()
|
||||||
|
|
||||||
val initializerBlock = JsCompositeBlock()
|
val initializerBlock = JsCompositeBlock()
|
||||||
|
val eagerInitializerBlock = JsCompositeBlock()
|
||||||
|
|
||||||
val isPerFile: Boolean get() = mode.granularity === JsGenerationGranularity.PER_FILE
|
val isPerFile: Boolean get() = mode.granularity === JsGenerationGranularity.PER_FILE
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -37,6 +37,7 @@ object ImportType {
|
|||||||
const val ALL = 0
|
const val ALL = 0
|
||||||
const val ITEMS = 1
|
const val ITEMS = 1
|
||||||
const val DEFAULT = 2
|
const val DEFAULT = 2
|
||||||
|
const val EFFECT = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
object ExportType {
|
object ExportType {
|
||||||
|
|||||||
+2
@@ -94,6 +94,7 @@ private class JsIrAstDeserializer(private val source: ByteArray) {
|
|||||||
|
|
||||||
readRepeated { declarations.statements += readStatement() }
|
readRepeated { declarations.statements += readStatement() }
|
||||||
readRepeated { initializers.statements += readStatement() }
|
readRepeated { initializers.statements += readStatement() }
|
||||||
|
readRepeated { eagerInitializers.statements += readStatement() }
|
||||||
readRepeated { exports.statements += readStatement() }
|
readRepeated { exports.statements += readStatement() }
|
||||||
readRepeated { polyfills.statements += readStatement() }
|
readRepeated { polyfills.statements += readStatement() }
|
||||||
|
|
||||||
@@ -238,6 +239,7 @@ private class JsIrAstDeserializer(private val source: ByteArray) {
|
|||||||
JsImport(
|
JsImport(
|
||||||
readString(),
|
readString(),
|
||||||
when (val type = readByte().toInt()) {
|
when (val type = readByte().toInt()) {
|
||||||
|
ImportType.EFFECT -> JsImport.Target.Effect
|
||||||
ImportType.ALL -> JsImport.Target.All(nameTable[readInt()].makeRef())
|
ImportType.ALL -> JsImport.Target.All(nameTable[readInt()].makeRef())
|
||||||
ImportType.DEFAULT -> JsImport.Target.Default(nameTable[readInt()].makeRef())
|
ImportType.DEFAULT -> JsImport.Target.Default(nameTable[readInt()].makeRef())
|
||||||
ImportType.ITEMS -> JsImport.Target.Elements(readList {
|
ImportType.ITEMS -> JsImport.Target.Elements(readList {
|
||||||
|
|||||||
+4
@@ -132,6 +132,7 @@ private class JsIrAstSerializer {
|
|||||||
|
|
||||||
writeCompositeBlock(fragment.declarations)
|
writeCompositeBlock(fragment.declarations)
|
||||||
writeCompositeBlock(fragment.initializers)
|
writeCompositeBlock(fragment.initializers)
|
||||||
|
writeCompositeBlock(fragment.eagerInitializers)
|
||||||
writeCompositeBlock(fragment.exports)
|
writeCompositeBlock(fragment.exports)
|
||||||
writeCompositeBlock(fragment.polyfills)
|
writeCompositeBlock(fragment.polyfills)
|
||||||
|
|
||||||
@@ -328,6 +329,9 @@ private class JsIrAstSerializer {
|
|||||||
writeString(import.module)
|
writeString(import.module)
|
||||||
|
|
||||||
when (val target = import.target) {
|
when (val target = import.target) {
|
||||||
|
is JsImport.Target.Effect -> {
|
||||||
|
writeByte(ImportType.EFFECT)
|
||||||
|
}
|
||||||
is JsImport.Target.All -> {
|
is JsImport.Target.All -> {
|
||||||
writeByte(ImportType.ALL)
|
writeByte(ImportType.ALL)
|
||||||
writeInt(internalizeName(target.alias.name!!))
|
writeInt(internalizeName(target.alias.name!!))
|
||||||
|
|||||||
@@ -1404,7 +1404,10 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
|||||||
p.print("}");
|
p.print("}");
|
||||||
}
|
}
|
||||||
|
|
||||||
p.print(" from ");
|
if (!(target == JsImport.Target.Effect.INSTANCE)) {
|
||||||
|
p.print(" from ");
|
||||||
|
}
|
||||||
|
|
||||||
p.print(javaScriptString(jsImport.getModule()));
|
p.print(javaScriptString(jsImport.getModule()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ class JsImport(
|
|||||||
get() = (target as Target.Elements).elements
|
get() = (target as Target.Elements).elements
|
||||||
|
|
||||||
sealed class Target {
|
sealed class Target {
|
||||||
|
object Effect : Target()
|
||||||
class Elements(val elements: MutableList<Element>) : Target()
|
class Elements(val elements: MutableList<Element>) : Target()
|
||||||
class Default(val name: JsNameRef) : Target() {
|
class Default(val name: JsNameRef) : Target() {
|
||||||
constructor(name: String) : this(JsNameRef(name))
|
constructor(name: String) : this(JsNameRef(name))
|
||||||
@@ -36,6 +37,7 @@ class JsImport(
|
|||||||
|
|
||||||
override fun acceptChildren(visitor: JsVisitor) {
|
override fun acceptChildren(visitor: JsVisitor) {
|
||||||
when (target) {
|
when (target) {
|
||||||
|
is Target.Effect -> {}
|
||||||
is Target.All -> visitor.accept(target.alias)
|
is Target.All -> visitor.accept(target.alias)
|
||||||
is Target.Default -> visitor.accept(target.name)
|
is Target.Default -> visitor.accept(target.name)
|
||||||
is Target.Elements -> target.elements.forEach {
|
is Target.Elements -> target.elements.forEach {
|
||||||
|
|||||||
+18
@@ -2041,6 +2041,24 @@ public class FirJsBoxTestGenerated extends AbstractFirJsBoxTest {
|
|||||||
runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/constructor.kt");
|
runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/constructor.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("eagerInitializationGlobal1.kt")
|
||||||
|
public void testEagerInitializationGlobal1() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/eagerInitializationGlobal1.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("eagerInitializationGlobal2.kt")
|
||||||
|
public void testEagerInitializationGlobal2() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/eagerInitializationGlobal2.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("eagerInitializationGlobal3.kt")
|
||||||
|
public void testEagerInitializationGlobal3() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/eagerInitializationGlobal3.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("inheritance.kt")
|
@TestMetadata("inheritance.kt")
|
||||||
public void testInheritance() throws Exception {
|
public void testInheritance() throws Exception {
|
||||||
|
|||||||
+18
@@ -2147,6 +2147,24 @@ public class FirJsES6BoxTestGenerated extends AbstractFirJsES6BoxTest {
|
|||||||
runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/constructor.kt");
|
runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/constructor.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("eagerInitializationGlobal1.kt")
|
||||||
|
public void testEagerInitializationGlobal1() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/eagerInitializationGlobal1.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("eagerInitializationGlobal2.kt")
|
||||||
|
public void testEagerInitializationGlobal2() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/eagerInitializationGlobal2.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("eagerInitializationGlobal3.kt")
|
||||||
|
public void testEagerInitializationGlobal3() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/eagerInitializationGlobal3.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("inheritance.kt")
|
@TestMetadata("inheritance.kt")
|
||||||
public void testInheritance() throws Exception {
|
public void testInheritance() throws Exception {
|
||||||
|
|||||||
+18
@@ -2147,6 +2147,24 @@ public class IrBoxJsES6TestGenerated extends AbstractIrBoxJsES6Test {
|
|||||||
runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/constructor.kt");
|
runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/constructor.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("eagerInitializationGlobal1.kt")
|
||||||
|
public void testEagerInitializationGlobal1() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/eagerInitializationGlobal1.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("eagerInitializationGlobal2.kt")
|
||||||
|
public void testEagerInitializationGlobal2() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/eagerInitializationGlobal2.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("eagerInitializationGlobal3.kt")
|
||||||
|
public void testEagerInitializationGlobal3() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/eagerInitializationGlobal3.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("inheritance.kt")
|
@TestMetadata("inheritance.kt")
|
||||||
public void testInheritance() throws Exception {
|
public void testInheritance() throws Exception {
|
||||||
|
|||||||
+18
@@ -2041,6 +2041,24 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
|||||||
runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/constructor.kt");
|
runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/constructor.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("eagerInitializationGlobal1.kt")
|
||||||
|
public void testEagerInitializationGlobal1() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/eagerInitializationGlobal1.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("eagerInitializationGlobal2.kt")
|
||||||
|
public void testEagerInitializationGlobal2() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/eagerInitializationGlobal2.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("eagerInitializationGlobal3.kt")
|
||||||
|
public void testEagerInitializationGlobal3() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/eagerInitializationGlobal3.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("inheritance.kt")
|
@TestMetadata("inheritance.kt")
|
||||||
public void testInheritance() throws Exception {
|
public void testInheritance() throws Exception {
|
||||||
|
|||||||
Vendored
+28
@@ -0,0 +1,28 @@
|
|||||||
|
// TARGET_BACKEND: JS_IR
|
||||||
|
// IGNORE_BACKEND: WASM
|
||||||
|
// ES_MODULES
|
||||||
|
// PROPERTY_LAZY_INITIALIZATION
|
||||||
|
|
||||||
|
// FILE: lib.kt
|
||||||
|
var z1 = false
|
||||||
|
var z2 = false
|
||||||
|
|
||||||
|
// FILE: lib2.kt
|
||||||
|
|
||||||
|
@OptIn(kotlin.ExperimentalStdlibApi::class)
|
||||||
|
@EagerInitialization
|
||||||
|
val x = foo()
|
||||||
|
|
||||||
|
private fun foo(): Int {
|
||||||
|
z1 = true
|
||||||
|
return 42
|
||||||
|
}
|
||||||
|
|
||||||
|
// Will be initialized since [x]'s initializer calls a function from the file.
|
||||||
|
val y = run { z2 = true; 117 }
|
||||||
|
|
||||||
|
// FILE: main.kt
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return return if (z1 && z2) "OK" else "fail"
|
||||||
|
}
|
||||||
Vendored
+23
@@ -0,0 +1,23 @@
|
|||||||
|
// TARGET_BACKEND: JS_IR
|
||||||
|
// IGNORE_BACKEND: WASM
|
||||||
|
// ES_MODULES
|
||||||
|
// PROPERTY_LAZY_INITIALIZATION
|
||||||
|
|
||||||
|
// FILE: lib.kt
|
||||||
|
var z1 = false
|
||||||
|
var z2 = false
|
||||||
|
|
||||||
|
// FILE: lib2.kt
|
||||||
|
|
||||||
|
@OptIn(kotlin.ExperimentalStdlibApi::class)
|
||||||
|
@EagerInitialization
|
||||||
|
val x = run { z1 = true; 42 }
|
||||||
|
|
||||||
|
// Won't be initialized (cause no function from the file will be called during [x] initialization).
|
||||||
|
val y = run { z2 = true; 117 }
|
||||||
|
|
||||||
|
// FILE: main.kt
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return if (z1 && !z2) "OK" else "fail"
|
||||||
|
}
|
||||||
Vendored
+19
@@ -0,0 +1,19 @@
|
|||||||
|
// TARGET_BACKEND: JS_IR
|
||||||
|
// IGNORE_BACKEND: WASM
|
||||||
|
// ES_MODULES
|
||||||
|
// PROPERTY_LAZY_INITIALIZATION
|
||||||
|
|
||||||
|
// FILE: lib.kt
|
||||||
|
var z1 = false
|
||||||
|
|
||||||
|
// FILE: lib2.kt
|
||||||
|
|
||||||
|
@OptIn(kotlin.ExperimentalStdlibApi::class)
|
||||||
|
@EagerInitialization
|
||||||
|
val x = run { z1 = !z1; 42 }
|
||||||
|
|
||||||
|
val y = run { 73 }
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return if (z1) "OK" else "fail"
|
||||||
|
}
|
||||||
+11
-3
@@ -1,10 +1,18 @@
|
|||||||
IGNORE_PER_FILE: true
|
|
||||||
|
|
||||||
MODULES: lib1, main
|
MODULES: lib1, main
|
||||||
|
|
||||||
STEP 0:
|
STEP 0:
|
||||||
libs: lib1, main
|
libs: lib1, main
|
||||||
dirty js modules: lib1, main
|
dirty js modules: lib1, main
|
||||||
STEP 1..3:
|
dirty js files: lib1/l1, lib1/l2, main/m, main/m.export, main
|
||||||
|
STEP 1:
|
||||||
libs: lib1, main
|
libs: lib1, main
|
||||||
dirty js modules: lib1
|
dirty js modules: lib1
|
||||||
|
dirty js files: lib1/l2, lib1, main
|
||||||
|
STEP 2:
|
||||||
|
libs: lib1, main
|
||||||
|
dirty js modules: lib1
|
||||||
|
dirty js files: lib1/l2
|
||||||
|
STEP 3:
|
||||||
|
libs: lib1, main
|
||||||
|
dirty js modules: lib1
|
||||||
|
dirty js files: lib1/l2, main
|
||||||
|
|||||||
Reference in New Issue
Block a user