Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.ir.backend.js.utils.toJsIdentifier
import org.jetbrains.kotlin.js.backend.ast.*
class JsIrProgramFragment(val packageFqn: String) {
val nameBindings = mutableMapOf()
val declarations = JsCompositeBlock()
val exports = JsCompositeBlock()
val importedModules = mutableListOf()
val imports = mutableMapOf()
var dts: String? = null
val classes = mutableMapOf()
val initializers = JsCompositeBlock()
var mainFunction: JsStatement? = null
var testFunInvocation: JsStatement? = null
var suiteFn: JsName? = null
val definitions = mutableSetOf()
val polyfills = JsCompositeBlock()
}
class JsIrModule(
val moduleName: String,
val externalModuleName: String,
val fragments: List
) {
fun makeModuleHeader(): JsIrModuleHeader {
val nameBindings = mutableMapOf()
val definitions = mutableSetOf()
var hasJsExports = false
for (fragment in fragments) {
hasJsExports = hasJsExports || !fragment.exports.isEmpty
for ((tag, name) in fragment.nameBindings.entries) {
nameBindings[tag] = name.toString()
}
definitions += fragment.definitions
}
return JsIrModuleHeader(moduleName, externalModuleName, definitions, nameBindings, hasJsExports, this)
}
}
class JsIrModuleHeader(
val moduleName: String,
val externalModuleName: String,
val definitions: Set,
val nameBindings: Map,
val hasJsExports: Boolean,
var associatedModule: JsIrModule?
) {
val externalNames: Set by lazy { nameBindings.keys - definitions }
}
class JsIrProgram(val modules: List) {
val mainModule = modules.last()
val otherModules = modules.dropLast(1)
fun crossModuleDependencies(relativeRequirePath: Boolean): Map {
val resolver = CrossModuleDependenciesResolver(modules.map { it.makeModuleHeader() })
val crossModuleReferences = resolver.resolveCrossModuleDependencies(relativeRequirePath)
return crossModuleReferences.entries.associate {
val module = it.key.associatedModule ?: error("Internal error: module ${it.key.moduleName} is not loaded")
it.value.initJsImportsForModule(module)
module to it.value
}
}
}
class CrossModuleDependenciesResolver(private val headers: List) {
fun resolveCrossModuleDependencies(relativeRequirePath: Boolean): Map {
val headerToBuilder = headers.associateWith { JsIrModuleCrossModuleReferecenceBuilder(it, relativeRequirePath) }
val definitionModule = mutableMapOf()
val mainModuleHeader = headers.last()
val otherModuleHeaders = headers.dropLast(1)
headerToBuilder[mainModuleHeader]!!.transitiveJsExportFrom = otherModuleHeaders
for (header in headers) {
val builder = headerToBuilder[header]!!
for (definition in header.definitions) {
require(definition !in definitionModule) { "Duplicate definition: $definition" }
definitionModule[definition] = builder
}
}
for (header in headers) {
val builder = headerToBuilder[header]!!
for (tag in header.externalNames) {
val fromModuleBuilder = definitionModule[tag] ?: continue // TODO error?
builder.imports += CrossModuleRef(fromModuleBuilder, tag)
fromModuleBuilder.exports += tag
}
}
return headers.associateWith { headerToBuilder[it]!!.buildCrossModuleRefs() }
}
}
private fun String.prettyTag() = takeWhile { c -> c != '|' }
private class CrossModuleRef(val module: JsIrModuleCrossModuleReferecenceBuilder, val tag: String)
private class JsIrModuleCrossModuleReferecenceBuilder(val header: JsIrModuleHeader, val relativeRequirePath: Boolean) {
val imports = mutableListOf()
val exports = mutableSetOf()
var transitiveJsExportFrom = emptyList()
private lateinit var exportNames: Map // tag -> index
private fun buildExportNames() {
var index = 0
exportNames = exports.sorted().associateWith { index++.toJsIdentifier() }
}
fun buildCrossModuleRefs(): CrossModuleReferences {
buildExportNames()
val importedModules = mutableMapOf()
fun import(moduleHeader: JsIrModuleHeader): JsName {
return importedModules.getOrPut(moduleHeader) {
val jsModuleName = JsName(moduleHeader.moduleName, false)
JsImportedModule(moduleHeader.externalModuleName, jsModuleName, null, relativeRequirePath)
}.internalName
}
val resultImports = imports.associate { crossModuleRef ->
val tag = crossModuleRef.tag
require(crossModuleRef.module::exportNames.isInitialized) {
// This situation appears in case of a dependent module redefine a symbol (function) from their dependency
"Cross module dependency resolution failed due to symbol '${tag.prettyTag()}' redefinition"
}
val exportedAs = crossModuleRef.module.exportNames[tag]!!
val moduleName = import(crossModuleRef.module.header)
tag to CrossModuleImport(exportedAs, moduleName)
}
val transitiveExport = transitiveJsExportFrom.mapNotNull {
if (it.hasJsExports) import(it) else null
}
return CrossModuleReferences(importedModules.values.toList(), transitiveExport, exportNames, resultImports)
}
}
class CrossModuleImport(val exportedAs: String, val moduleExporter: JsName)
class CrossModuleReferences(
val importedModules: List, // additional Kotlin imported modules
val transitiveJsExportFrom: List, // the list of modules which provide their js exports for transitive export
val exports: Map, // tag -> index
val imports: Map, // tag -> import statement
) {
// built from imports
var jsImports = emptyMap() // 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 symbol ${it.key.prettyTag()}")
val exportRef = JsNameRef(it.value.exportedAs, ReservedJsNames.makeCrossModuleNameRef(it.value.moduleExporter))
it.key to JsVars.JsVar(importedAs, exportRef)
}
}
companion object {
val Empty = CrossModuleReferences(listOf(), emptyList(), emptyMap(), emptyMap())
}
}