[JS IR] move fragment generation closer to the beginning
This commit is contained in:
committed by
teamcityserver
parent
b1b263615c
commit
7e7c84fcfb
+62
-29
@@ -72,7 +72,7 @@ class IrModuleToJsTransformer(
|
|||||||
namer.merge(module.files, additionalPackages)
|
namer.merge(module.files, additionalPackages)
|
||||||
}
|
}
|
||||||
|
|
||||||
val jsCode = if (fullJs) generateWrappedModuleBody(modules, exportData, namer) else null
|
val jsCode = if (fullJs) generateWrappedModuleBody(modules, generateProgramFragments(modules, exportData, namer), namer) else null
|
||||||
|
|
||||||
val dceJsCode = if (dceJs) {
|
val dceJsCode = if (dceJs) {
|
||||||
eliminateDeadDeclarations(modules, backendContext, removeUnusedAssociatedObjects)
|
eliminateDeadDeclarations(modules, backendContext, removeUnusedAssociatedObjects)
|
||||||
@@ -80,15 +80,51 @@ class IrModuleToJsTransformer(
|
|||||||
// TODO: is this mode relevant for scripting? If yes, refactor so that the external name tables are used here when needed.
|
// 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)
|
val namer = NameTables(emptyList(), context = backendContext)
|
||||||
namer.merge(modules.flatMap { it.files }, additionalPackages)
|
namer.merge(modules.flatMap { it.files }, additionalPackages)
|
||||||
generateWrappedModuleBody(modules, exportData, namer)
|
generateWrappedModuleBody(modules, generateProgramFragments(modules, exportData, namer), namer)
|
||||||
} else null
|
} else null
|
||||||
|
|
||||||
return CompilerResult(jsCode, dceJsCode, dts)
|
return CompilerResult(jsCode, dceJsCode, dts)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateWrappedModuleBody(
|
private fun generateProgramFragments(
|
||||||
modules: Iterable<IrModuleFragment>,
|
modules: Iterable<IrModuleFragment>,
|
||||||
exportData: Map<IrModuleFragment, Map<IrFile, List<ExportedDeclaration>>>,
|
exportData: Map<IrModuleFragment, Map<IrFile, List<ExportedDeclaration>>>,
|
||||||
|
namer: NameTables,
|
||||||
|
): Map<IrFile, JsIrProgramFragment> {
|
||||||
|
|
||||||
|
val nameGenerator = IrNamerImpl(newNameTables = namer, backendContext)
|
||||||
|
|
||||||
|
val fragments = mutableMapOf<IrFile, JsIrProgramFragment>()
|
||||||
|
modules.forEach { m ->
|
||||||
|
m.files.forEach { f ->
|
||||||
|
val fragment = JsIrProgramFragment(f.fqName.asString())
|
||||||
|
|
||||||
|
val exports = exportData[m]!![f]!! // TODO
|
||||||
|
|
||||||
|
val internalModuleName = JsName("_")
|
||||||
|
val globalNames = NameTable<String>(namer.globalNames)
|
||||||
|
val exportStatements =
|
||||||
|
ExportModelToJsStatements(nameGenerator, { globalNames.declareFreshName(it, it) }).generateModuleExport(
|
||||||
|
ExportedModule(mainModuleName, moduleKind, exports),
|
||||||
|
internalModuleName,
|
||||||
|
)
|
||||||
|
|
||||||
|
fragment.exports.statements += exportStatements
|
||||||
|
|
||||||
|
if (exports.isNotEmpty()) {
|
||||||
|
fragment.dts = exports.toTypeScript(moduleKind)
|
||||||
|
}
|
||||||
|
|
||||||
|
fragments[f] = fragment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fragments
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateWrappedModuleBody(
|
||||||
|
modules: Iterable<IrModuleFragment>,
|
||||||
|
fragments: Map<IrFile, JsIrProgramFragment>,
|
||||||
namer: NameTables
|
namer: NameTables
|
||||||
): CompilationOutputs {
|
): CompilationOutputs {
|
||||||
if (multiModule) {
|
if (multiModule) {
|
||||||
@@ -104,7 +140,7 @@ class IrModuleToJsTransformer(
|
|||||||
mainModuleName,
|
mainModuleName,
|
||||||
listOf(main),
|
listOf(main),
|
||||||
others,
|
others,
|
||||||
exportData,
|
fragments,
|
||||||
namer,
|
namer,
|
||||||
refInfo,
|
refInfo,
|
||||||
generateMainCall = true
|
generateMainCall = true
|
||||||
@@ -117,7 +153,7 @@ class IrModuleToJsTransformer(
|
|||||||
moduleName,
|
moduleName,
|
||||||
listOf(module),
|
listOf(module),
|
||||||
others.drop(index + 1),
|
others.drop(index + 1),
|
||||||
exportData,
|
fragments,
|
||||||
namer,
|
namer,
|
||||||
refInfo,
|
refInfo,
|
||||||
generateMainCall = false
|
generateMainCall = false
|
||||||
@@ -130,7 +166,7 @@ class IrModuleToJsTransformer(
|
|||||||
mainModuleName,
|
mainModuleName,
|
||||||
modules,
|
modules,
|
||||||
emptyList(),
|
emptyList(),
|
||||||
exportData,
|
fragments,
|
||||||
namer,
|
namer,
|
||||||
EmptyCrossModuleReferenceInfo
|
EmptyCrossModuleReferenceInfo
|
||||||
)
|
)
|
||||||
@@ -141,7 +177,7 @@ class IrModuleToJsTransformer(
|
|||||||
moduleName: String,
|
moduleName: String,
|
||||||
modules: Iterable<IrModuleFragment>,
|
modules: Iterable<IrModuleFragment>,
|
||||||
dependencies: Iterable<IrModuleFragment>,
|
dependencies: Iterable<IrModuleFragment>,
|
||||||
exportData: Map<IrModuleFragment, Map<IrFile, List<ExportedDeclaration>>>,
|
fragments: Map<IrFile, JsIrProgramFragment>,
|
||||||
namer: NameTables,
|
namer: NameTables,
|
||||||
refInfo: CrossModuleReferenceInfo,
|
refInfo: CrossModuleReferenceInfo,
|
||||||
generateMainCall: Boolean = true
|
generateMainCall: Boolean = true
|
||||||
@@ -163,17 +199,9 @@ class IrModuleToJsTransformer(
|
|||||||
declareFreshGlobal = { JsName(sanitizeName(it)) } // TODO: Declare fresh name
|
declareFreshGlobal = { JsName(sanitizeName(it)) } // TODO: Declare fresh name
|
||||||
)
|
)
|
||||||
|
|
||||||
val (moduleBody, callToMain) = generateModuleBody(modules, staticContext)
|
val (moduleBody, callToMain, exportStatements) = generateModuleBody(modules, staticContext, fragments)
|
||||||
|
|
||||||
val internalModuleName = JsName("_")
|
val internalModuleName = JsName("_")
|
||||||
val globalNames = NameTable<String>(namer.globalNames)
|
|
||||||
|
|
||||||
val exportStatements = exportData.entries.filter { (m, _) -> m in modules }.flatMap { (_, f) -> f.values.flatMap {
|
|
||||||
ExportModelToJsStatements(nameGenerator, { globalNames.declareFreshName(it, it) }).generateModuleExport(
|
|
||||||
ExportedModule(moduleName, moduleKind, it),
|
|
||||||
internalModuleName,
|
|
||||||
)
|
|
||||||
} }
|
|
||||||
|
|
||||||
val (crossModuleImports, importedKotlinModules) = generateCrossModuleImports(
|
val (crossModuleImports, importedKotlinModules) = generateCrossModuleImports(
|
||||||
nameGenerator,
|
nameGenerator,
|
||||||
@@ -304,23 +332,26 @@ class IrModuleToJsTransformer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class ModuleBody(val statements: List<JsStatement>, val mainFunction: JsStatement?)
|
private data class ModuleBody(val statements: List<JsStatement>, val mainFunction: JsStatement?, val exportStatements: List<JsStatement>)
|
||||||
|
|
||||||
private fun generateModuleBody(modules: Iterable<IrModuleFragment>, staticContext: JsStaticContext): ModuleBody {
|
private fun generateModuleBody(
|
||||||
val fragments = modules.map { it.files.map { generateProgramFragment(it, staticContext) } }
|
modules: Iterable<IrModuleFragment>,
|
||||||
|
staticContext: JsStaticContext,
|
||||||
|
fragments: Map<IrFile, JsIrProgramFragment>
|
||||||
|
): ModuleBody {
|
||||||
|
val thisModuleFragments = modules.map { it.files.map { fragments[it]!!.fillProgramFragment(it, staticContext) } }
|
||||||
|
|
||||||
return merge(fragments, staticContext)
|
return merge(thisModuleFragments, staticContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val generateFilePaths = backendContext.configuration.getBoolean(JSConfigurationKeys.GENERATE_COMMENTS_WITH_FILE_PATH)
|
private val generateFilePaths = backendContext.configuration.getBoolean(JSConfigurationKeys.GENERATE_COMMENTS_WITH_FILE_PATH)
|
||||||
private val pathPrefixMap = backendContext.configuration.getMap(JSConfigurationKeys.FILE_PATHS_PREFIX_MAP)
|
private val pathPrefixMap = backendContext.configuration.getMap(JSConfigurationKeys.FILE_PATHS_PREFIX_MAP)
|
||||||
|
|
||||||
private fun generateProgramFragment(file: IrFile, staticContext: JsStaticContext): JsIrProgramFragment {
|
private fun JsIrProgramFragment.fillProgramFragment(file: IrFile, staticContext: JsStaticContext): JsIrProgramFragment {
|
||||||
require(staticContext.classModels.isEmpty())
|
require(staticContext.classModels.isEmpty())
|
||||||
require(staticContext.initializerBlock.statements.isEmpty())
|
require(staticContext.initializerBlock.statements.isEmpty())
|
||||||
|
|
||||||
val result = JsIrProgramFragment(file.fqName.asString())
|
val statements = this.declarations.statements
|
||||||
val statements = result.declarations.statements
|
|
||||||
|
|
||||||
val fileStatements = file.accept(IrFileToJsTransformer(), staticContext).statements
|
val fileStatements = file.accept(IrFileToJsTransformer(), staticContext).statements
|
||||||
if (fileStatements.isNotEmpty()) {
|
if (fileStatements.isNotEmpty()) {
|
||||||
@@ -348,26 +379,26 @@ class IrModuleToJsTransformer(
|
|||||||
statements.endRegion()
|
statements.endRegion()
|
||||||
}
|
}
|
||||||
|
|
||||||
result.classes += staticContext.classModels
|
this.classes += staticContext.classModels
|
||||||
result.initializers.statements += staticContext.initializerBlock.statements
|
this.initializers.statements += staticContext.initializerBlock.statements
|
||||||
|
|
||||||
if (mainArguments != null) {
|
if (mainArguments != null) {
|
||||||
JsMainFunctionDetector(backendContext).getMainFunctionOrNull(file)?.let {
|
JsMainFunctionDetector(backendContext).getMainFunctionOrNull(file)?.let {
|
||||||
val jsName = staticContext.getNameForStaticFunction(it)
|
val jsName = staticContext.getNameForStaticFunction(it)
|
||||||
val generateArgv = it.valueParameters.firstOrNull()?.isStringArrayParameter() ?: false
|
val generateArgv = it.valueParameters.firstOrNull()?.isStringArrayParameter() ?: false
|
||||||
val generateContinuation = it.isLoweredSuspendFunction(backendContext)
|
val generateContinuation = it.isLoweredSuspendFunction(backendContext)
|
||||||
result.mainFunction = JsInvocation(jsName.makeRef(), generateMainArguments(generateArgv, generateContinuation, staticContext)).makeStmt()
|
this.mainFunction = JsInvocation(jsName.makeRef(), generateMainArguments(generateArgv, generateContinuation, staticContext)).makeStmt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
backendContext.testFunsPerFile[file]?.let {
|
backendContext.testFunsPerFile[file]?.let {
|
||||||
result.testFunInvocation = JsInvocation(staticContext.getNameForStaticFunction(it).makeRef()).makeStmt()
|
this.testFunInvocation = JsInvocation(staticContext.getNameForStaticFunction(it).makeRef()).makeStmt()
|
||||||
}
|
}
|
||||||
|
|
||||||
staticContext.classModels.clear()
|
staticContext.classModels.clear()
|
||||||
staticContext.initializerBlock.statements.clear()
|
staticContext.initializerBlock.statements.clear()
|
||||||
|
|
||||||
return result
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun merge(fragments: List<List<JsIrProgramFragment>>, staticContext: JsStaticContext): ModuleBody {
|
private fun merge(fragments: List<List<JsIrProgramFragment>>, staticContext: JsStaticContext): ModuleBody {
|
||||||
@@ -420,7 +451,9 @@ class IrModuleToJsTransformer(
|
|||||||
|
|
||||||
val callToMain = lastModuleFragments.sortedBy { it.packageFqn }.firstNotNullOfOrNull { it.mainFunction }
|
val callToMain = lastModuleFragments.sortedBy { it.packageFqn }.firstNotNullOfOrNull { it.mainFunction }
|
||||||
|
|
||||||
return ModuleBody(statements, callToMain)
|
val exportStatements = fragments.flatMap { it.flatMap { it.exports.statements } }
|
||||||
|
|
||||||
|
return ModuleBody(statements, callToMain, exportStatements)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateMainArguments(
|
private fun generateMainArguments(
|
||||||
|
|||||||
+2
@@ -11,6 +11,8 @@ import org.jetbrains.kotlin.js.backend.ast.JsStatement
|
|||||||
|
|
||||||
class JsIrProgramFragment(val packageFqn: String) {
|
class JsIrProgramFragment(val packageFqn: String) {
|
||||||
val declarations = JsGlobalBlock()
|
val declarations = JsGlobalBlock()
|
||||||
|
val exports = JsGlobalBlock()
|
||||||
|
var dts: String? = null
|
||||||
val classes = mutableMapOf<IrClassSymbol, JsIrClassModel>()
|
val classes = mutableMapOf<IrClassSymbol, JsIrClassModel>()
|
||||||
val initializers = JsGlobalBlock()
|
val initializers = JsGlobalBlock()
|
||||||
var mainFunction: JsStatement? = null
|
var mainFunction: JsStatement? = null
|
||||||
|
|||||||
Reference in New Issue
Block a user