[JS IR BE] Support compilation and tests against klib
This commit is contained in:
+6
-11
@@ -15,8 +15,8 @@ import org.jetbrains.kotlin.backend.js.JsDeclarationFactory
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.SourceManager
|
||||
@@ -34,7 +34,6 @@ import org.jetbrains.kotlin.ir.types.impl.IrDynamicTypeImpl
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.ir.util.getPropertyDeclaration
|
||||
import org.jetbrains.kotlin.ir.util.kotlinPackageFqn
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsNode
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
@@ -43,13 +42,12 @@ import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.createDynamicType
|
||||
|
||||
class JsIrBackendContext(
|
||||
val module: ModuleDescriptor,
|
||||
val module: ModuleDescriptorImpl,
|
||||
override val irBuiltIns: IrBuiltIns,
|
||||
val symbolTable: SymbolTable,
|
||||
irModuleFragment: IrModuleFragment,
|
||||
override val configuration: CompilerConfiguration,
|
||||
val dependencies: List<CompiledModule>,
|
||||
val moduleType: ModuleType
|
||||
val compilationMode: CompilationMode
|
||||
) : CommonBackendContext {
|
||||
|
||||
override val builtIns = module.builtIns
|
||||
@@ -131,8 +129,9 @@ class JsIrBackendContext(
|
||||
private val operatorMap = referenceOperators()
|
||||
|
||||
// TODO: get rid of this
|
||||
val functions = (0..22).map { symbolTable.referenceClass(builtIns.getFunction(it)) }
|
||||
val suspendFunctions = (0..22).map { symbolTable.referenceClass(builtIns.getSuspendFunction(it)) }
|
||||
|
||||
fun functionN(n: Int) = symbolTable.lazyWrapper.referenceClass(builtIns.getFunction(n))
|
||||
fun suspendFunctionN(n: Int) = symbolTable.lazyWrapper.referenceClass(builtIns.getSuspendFunction(n))
|
||||
|
||||
private fun primitivesWithImplicitCompanionObject(): List<Name> {
|
||||
val numbers = PrimitiveType.NUMBER_TYPES
|
||||
@@ -144,10 +143,6 @@ class JsIrBackendContext(
|
||||
|
||||
val dynamicType = IrDynamicTypeImpl(createDynamicType(builtIns), emptyList(), Variance.INVARIANT)
|
||||
|
||||
val originalModuleIndex = ModuleIndex(irModuleFragment)
|
||||
|
||||
lateinit var moduleFragmentCopy: IrModuleFragment
|
||||
|
||||
fun getOperatorByName(name: Name, type: KotlinType) = operatorMap[name]?.get(type)
|
||||
|
||||
override val ir = object : Ir<CommonBackendContext>(this, irModuleFragment) {
|
||||
|
||||
@@ -99,13 +99,6 @@ private val lateinitLoweringPhase = makeJsModulePhase(
|
||||
description = "Insert checks for lateinit field references"
|
||||
)
|
||||
|
||||
private val moduleCopyingPhase = makeCustomJsModulePhase(
|
||||
{ context, module -> context.moduleFragmentCopy = module.deepCopyWithSymbols() },
|
||||
name = "ModuleCopying",
|
||||
description = "<Supposed to be removed> Copy current module to make it accessible from different one",
|
||||
prerequisite = setOf(lateinitLoweringPhase)
|
||||
)
|
||||
|
||||
private val functionInliningPhase = makeCustomJsModulePhase(
|
||||
{ context, module ->
|
||||
FunctionInlining(context).inline(module)
|
||||
@@ -114,7 +107,7 @@ private val functionInliningPhase = makeCustomJsModulePhase(
|
||||
},
|
||||
name = "FunctionInliningPhase",
|
||||
description = "Perform function inlining",
|
||||
prerequisite = setOf(moduleCopyingPhase, lateinitLoweringPhase, arrayInlineConstructorLoweringPhase, coroutineIntrinsicLoweringPhase)
|
||||
prerequisite = setOf(lateinitLoweringPhase, arrayInlineConstructorLoweringPhase, coroutineIntrinsicLoweringPhase)
|
||||
)
|
||||
|
||||
private val removeInlineFunctionsWithReifiedTypeParametersLoweringPhase = makeJsModulePhase(
|
||||
@@ -356,7 +349,6 @@ val jsPhases = namedIrModulePhase(
|
||||
coroutineIntrinsicLoweringPhase then
|
||||
arrayInlineConstructorLoweringPhase then
|
||||
lateinitLoweringPhase then
|
||||
moduleCopyingPhase then
|
||||
functionInliningPhase then
|
||||
removeInlineFunctionsWithReifiedTypeParametersLoweringPhase then
|
||||
throwableSuccessorsLoweringPhase then
|
||||
|
||||
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
@@ -34,52 +33,30 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
import java.io.File
|
||||
|
||||
enum class ModuleType {
|
||||
TEST_RUNTIME,
|
||||
SECONDARY,
|
||||
MAIN
|
||||
}
|
||||
|
||||
class CompiledModule(
|
||||
val moduleName: String,
|
||||
val generatedCode: String?,
|
||||
val moduleFragment: IrModuleFragment?,
|
||||
val moduleType: ModuleType,
|
||||
val dependencies: List<CompiledModule>
|
||||
) {
|
||||
val descriptor
|
||||
get() = moduleFragment!!.descriptor as ModuleDescriptorImpl
|
||||
}
|
||||
var moduleDescriptor: ModuleDescriptorImpl?,
|
||||
val klibPath: String,
|
||||
val dependencies: List<CompiledModule>,
|
||||
val isBuiltIn: Boolean
|
||||
)
|
||||
|
||||
enum class CompilationMode(val generateJS: Boolean) {
|
||||
KLIB(false),
|
||||
KLIB_WITH_JS(true),
|
||||
TEST_AGAINST_CACHE(true),
|
||||
TEST_AGAINST_KLIB(true),
|
||||
enum class CompilationMode(val generateJS: Boolean, val generateKlib: Boolean) {
|
||||
KLIB(false, true),
|
||||
KLIB_WITH_JS(true, true),
|
||||
JS_AGAINST_KLIB(true, false)
|
||||
}
|
||||
|
||||
private val runtimeKlibPath = "js/js.translator/testData/out/klibs/runtime/"
|
||||
|
||||
private val moduleHeaderFileName = "module.kji"
|
||||
private val declarationsDirName = "ir/"
|
||||
private val debugDataFileName = "debug.txt"
|
||||
private fun metadataFileName(moduleName: String) = "$moduleName.${JsKlibMetadataSerializationUtil.CLASS_METADATA_FILE_EXTENSION}"
|
||||
|
||||
private val JS_IR_RUNTIME_MODULE_NAME = "JS_IR_RUNTIME"
|
||||
|
||||
data class JsKlib(
|
||||
val moduleDescriptor: ModuleDescriptor,
|
||||
val moduleIr: IrModuleFragment,
|
||||
val symbolTable: SymbolTable,
|
||||
val irBuiltIns: IrBuiltIns
|
||||
)
|
||||
|
||||
|
||||
private val logggg = object : LoggingContext {
|
||||
override var inVerbosePhase: Boolean
|
||||
get() = TODO("not implemented")
|
||||
@@ -88,63 +65,40 @@ private val logggg = object : LoggingContext {
|
||||
override fun log(message: () -> String) {}
|
||||
}
|
||||
|
||||
private fun deserializeRuntimeMetadata(
|
||||
klibDirFile: File,
|
||||
moduleName: String,
|
||||
lookupTracker: LookupTracker,
|
||||
metadataVersion: JsKlibMetadataVersion,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
): ModuleDescriptor {
|
||||
val metadataFile = File(klibDirFile, metadataFileName(moduleName))
|
||||
val storageManager = LockBasedStorageManager("JsConfig")
|
||||
val serializer = JsKlibMetadataSerializationUtil
|
||||
val parts = serializer.readModuleAsProto(metadataFile.readBytes())
|
||||
val builtIns = object : KotlinBuiltIns(storageManager) {}//analysisResult.moduleDescriptor.builtIns
|
||||
val md = ModuleDescriptorImpl(Name.special("<$moduleName>"), storageManager, builtIns)
|
||||
builtIns.builtInsModule = md
|
||||
val packageProviders = listOf(
|
||||
functionInterfacePackageFragmentProvider(storageManager, md),
|
||||
createJsKlibMetadataPackageFragmentProvider(
|
||||
storageManager, md, parts.header, parts.body, metadataVersion,
|
||||
CompilerDeserializationConfiguration(languageVersionSettings),
|
||||
lookupTracker
|
||||
)
|
||||
)
|
||||
private fun metadataFileName(moduleName: String) = "$moduleName.${JsKlibMetadataSerializationUtil.CLASS_METADATA_FILE_EXTENSION}"
|
||||
|
||||
md.initialize(CompositePackageFragmentProvider(packageProviders))
|
||||
md.setDependencies(listOf(md))
|
||||
return md
|
||||
}
|
||||
|
||||
private fun deserializeRuntimeIr(
|
||||
moduleDescriptor: ModuleDescriptor,
|
||||
klibDirFile: File,
|
||||
deserializeDeclaration: Boolean,
|
||||
symbolTable: SymbolTable,
|
||||
irBuiltIns: IrBuiltIns
|
||||
): IrModuleFragment {
|
||||
val moduleFile = File(klibDirFile, moduleHeaderFileName)
|
||||
val deserializer = IrKlibProtoBufModuleDeserializer(
|
||||
moduleDescriptor,
|
||||
logggg,
|
||||
irBuiltIns,
|
||||
klibDirFile,
|
||||
symbolTable,
|
||||
null
|
||||
)
|
||||
return deserializer.deserializeIrModule(moduleDescriptor, moduleFile.readBytes(), deserializeDeclaration)
|
||||
}
|
||||
data class JsKlib(
|
||||
val moduleDescriptor: ModuleDescriptorImpl,
|
||||
val moduleIr: IrModuleFragment,
|
||||
val symbolTable: SymbolTable,
|
||||
val irBuiltIns: IrBuiltIns,
|
||||
val deserializer: IrKlibProtoBufModuleDeserializer
|
||||
)
|
||||
|
||||
private fun deserializerRuntimeKlib(
|
||||
|
||||
private fun deserializeModuleFromKlib(
|
||||
locationDir: String,
|
||||
moduleName: String,
|
||||
lookupTracker: LookupTracker,
|
||||
storageManager: LockBasedStorageManager,
|
||||
metadataVersion: JsKlibMetadataVersion,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
deserializeDeclaration: Boolean
|
||||
dependencies: List<CompiledModule>,
|
||||
builtinsModule: ModuleDescriptorImpl?
|
||||
): JsKlib {
|
||||
val klibDirFile = File(locationDir)
|
||||
val md = deserializeRuntimeMetadata(klibDirFile, moduleName, lookupTracker, metadataVersion, languageVersionSettings)
|
||||
val md = loadKlibMetadata(
|
||||
moduleName,
|
||||
locationDir,
|
||||
builtinsModule == null,
|
||||
lookupTracker,
|
||||
storageManager,
|
||||
metadataVersion,
|
||||
languageVersionSettings,
|
||||
builtinsModule,
|
||||
dependencies
|
||||
)
|
||||
|
||||
val st = SymbolTable()
|
||||
val typeTranslator = TypeTranslator(st, languageVersionSettings).also {
|
||||
@@ -153,9 +107,17 @@ private fun deserializerRuntimeKlib(
|
||||
|
||||
val irBuiltIns = IrBuiltIns(md.builtIns, typeTranslator, st)
|
||||
|
||||
val moduleFragment = deserializeRuntimeIr(md, klibDirFile, deserializeDeclaration, st, irBuiltIns)
|
||||
val moduleFile = File(klibDirFile, moduleHeaderFileName)
|
||||
val deserializer = IrKlibProtoBufModuleDeserializer(md, logggg, irBuiltIns, st, null)
|
||||
|
||||
return JsKlib(md, moduleFragment, st, irBuiltIns)
|
||||
dependencies.forEach {
|
||||
val dependencyKlibDir = File(it.klibPath, moduleHeaderFileName)
|
||||
deserializer.deserializeIrModule(it.moduleDescriptor!!, dependencyKlibDir.readBytes(), File(it.klibPath), false)
|
||||
}
|
||||
|
||||
val moduleFragment = deserializer.deserializeIrModule(md, moduleFile.readBytes(), klibDirFile, true)
|
||||
|
||||
return JsKlib(md, moduleFragment, st, irBuiltIns, deserializer)
|
||||
}
|
||||
|
||||
fun compile(
|
||||
@@ -163,247 +125,235 @@ fun compile(
|
||||
files: List<KtFile>,
|
||||
configuration: CompilerConfiguration,
|
||||
export: List<FqName> = emptyList(),
|
||||
compileMode: CompilationMode = CompilationMode.TEST_AGAINST_CACHE,
|
||||
compileMode: CompilationMode,
|
||||
dependencies: List<CompiledModule> = emptyList(),
|
||||
builtInsModule: CompiledModule? = null,
|
||||
moduleType: ModuleType
|
||||
klibPath: String
|
||||
): CompiledModule {
|
||||
return when (compileMode) {
|
||||
CompilationMode.KLIB, CompilationMode.KLIB_WITH_JS ->
|
||||
compileIntoKlib(files, project, configuration, dependencies, builtInsModule, moduleType, compileMode.generateJS)
|
||||
CompilationMode.TEST_AGAINST_CACHE ->
|
||||
compileIntoJsAgainstCachedDeps(files, project, configuration, dependencies, builtInsModule, moduleType)
|
||||
CompilationMode.TEST_AGAINST_KLIB -> compileIntoJsAgainstKlib(files, project, configuration, dependencies, moduleType)
|
||||
}
|
||||
}
|
||||
|
||||
private fun compileIntoJsAgainstKlib(
|
||||
files: List<KtFile>,
|
||||
project: Project,
|
||||
configuration: CompilerConfiguration,
|
||||
dependencies: List<CompiledModule>,
|
||||
moduleType: ModuleType
|
||||
): CompiledModule {
|
||||
val runtimeKlib = File(runtimeKlibPath)
|
||||
val metadataVersion = configuration.get(CommonConfigurationKeys.METADATA_VERSION) as? JsKlibMetadataVersion
|
||||
?: JsKlibMetadataVersion.INSTANCE
|
||||
val lookupTracker = configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER, LookupTracker.DO_NOTHING)
|
||||
val lookupTracker = LookupTracker.DO_NOTHING
|
||||
val languageSettings = configuration.languageVersionSettings
|
||||
|
||||
val runtimeModule = deserializeRuntimeMetadata(
|
||||
runtimeKlib,
|
||||
JS_IR_RUNTIME_MODULE_NAME,
|
||||
lookupTracker,
|
||||
metadataVersion,
|
||||
languageSettings
|
||||
)
|
||||
val storageManeger = LockBasedStorageManager("JsDepencencies")
|
||||
val dfsHandler: MetadataDFSHandler = DependencyMetadataLoader(lookupTracker, metadataVersion, languageSettings, storageManeger)
|
||||
val sortedDeps = DFS.dfs(dependencies, CompiledModule::dependencies, dfsHandler)
|
||||
val builtInModule = sortedDeps.firstOrNull()?.moduleDescriptor // null in case compiling builtInModule itself
|
||||
|
||||
val analysisResult =
|
||||
TopDownAnalyzerFacadeForJS.analyzeFiles(
|
||||
files,
|
||||
project,
|
||||
configuration,
|
||||
sortedDeps.mapNotNull { it.moduleDescriptor },
|
||||
emptyList(),
|
||||
emptyList(),
|
||||
thisIsBuiltInsModule = false,
|
||||
customBuiltInsModule = runtimeModule as ModuleDescriptorImpl
|
||||
thisIsBuiltInsModule = builtInModule == null,
|
||||
customBuiltInsModule = builtInModule
|
||||
)
|
||||
|
||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
|
||||
|
||||
TopDownAnalyzerFacadeForJS.checkForErrors(files, analysisResult.bindingContext)
|
||||
|
||||
val moduleDescriptor = analysisResult.moduleDescriptor as ModuleDescriptorImpl
|
||||
val symbolTable = SymbolTable()
|
||||
|
||||
val psi2IrTranslator = Psi2IrTranslator(languageSettings)
|
||||
val psi2IrContext = psi2IrTranslator.createGeneratorContext(analysisResult.moduleDescriptor, analysisResult.bindingContext, symbolTable)
|
||||
val moduleFile = File(runtimeKlib, moduleHeaderFileName)
|
||||
val deserializer = IrKlibProtoBufModuleDeserializer(
|
||||
runtimeModule,
|
||||
logggg,
|
||||
psi2IrContext.irBuiltIns,
|
||||
runtimeKlib,
|
||||
symbolTable,
|
||||
null
|
||||
)
|
||||
val runtimeModuleFragment = deserializer.deserializeIrModule(runtimeModule, moduleFile.readBytes(), false)
|
||||
val psi2IrContext = psi2IrTranslator.createGeneratorContext(moduleDescriptor, analysisResult.bindingContext, symbolTable)
|
||||
val irBuiltIns = psi2IrContext.irBuiltIns
|
||||
|
||||
val moduleFragment = psi2IrTranslator.generateModuleFragment(psi2IrContext, files, deserializer)
|
||||
var deserializer = IrKlibProtoBufModuleDeserializer(moduleDescriptor, logggg, irBuiltIns, symbolTable, null)
|
||||
|
||||
val context = JsIrBackendContext(
|
||||
analysisResult.moduleDescriptor,
|
||||
psi2IrContext.irBuiltIns,
|
||||
psi2IrContext.symbolTable,
|
||||
moduleFragment,
|
||||
configuration,
|
||||
dependencies,
|
||||
moduleType
|
||||
)
|
||||
|
||||
|
||||
|
||||
ExternalDependenciesGenerator(
|
||||
runtimeModuleFragment.descriptor,
|
||||
context.symbolTable,
|
||||
context.irBuiltIns,
|
||||
deserializer
|
||||
).generateUnboundSymbolsAsDependencies(runtimeModuleFragment)
|
||||
|
||||
val files = runtimeModuleFragment.files + moduleFragment.files
|
||||
|
||||
moduleFragment.files.clear()
|
||||
moduleFragment.files += files
|
||||
|
||||
moduleFragment.patchDeclarationParents()
|
||||
|
||||
jsPhases.invokeToplevel(context.phaseConfig, context, moduleFragment)
|
||||
|
||||
val jsProgram = moduleFragment.accept(IrModuleToJsTransformer(context), null)
|
||||
|
||||
return CompiledModule(project.name, jsProgram.toString(), null, moduleType, emptyList())
|
||||
}
|
||||
|
||||
private fun compileIntoJsAgainstCachedDeps(
|
||||
files: List<KtFile>,
|
||||
project: Project,
|
||||
configuration: CompilerConfiguration,
|
||||
dependencies: List<CompiledModule>,
|
||||
builtInsModule: CompiledModule?,
|
||||
moduleType: ModuleType
|
||||
): CompiledModule {
|
||||
val analysisResult =
|
||||
TopDownAnalyzerFacadeForJS.analyzeFiles(
|
||||
files,
|
||||
project,
|
||||
configuration,
|
||||
dependencies.map { it.descriptor },
|
||||
emptyList(),
|
||||
thisIsBuiltInsModule = builtInsModule == null,
|
||||
customBuiltInsModule = builtInsModule?.descriptor
|
||||
)
|
||||
|
||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
|
||||
|
||||
TopDownAnalyzerFacadeForJS.checkForErrors(files, analysisResult.bindingContext)
|
||||
|
||||
val irDependencies = dependencies.mapNotNull { it.moduleFragment }
|
||||
|
||||
val symbolTable = SymbolTable()
|
||||
irDependencies.forEach { symbolTable.loadModule(it) }
|
||||
|
||||
val psi2IrTranslator = Psi2IrTranslator(configuration.languageVersionSettings)
|
||||
val psi2IrContext = psi2IrTranslator.createGeneratorContext(analysisResult.moduleDescriptor, analysisResult.bindingContext, symbolTable)
|
||||
|
||||
val moduleFragment = psi2IrTranslator.generateModuleFragment(psi2IrContext, files)
|
||||
|
||||
// TODO: Split compilation into two steps: kt -> ir, ir -> js
|
||||
val moduleName = configuration[CommonConfigurationKeys.MODULE_NAME]!!
|
||||
when (moduleType) {
|
||||
ModuleType.MAIN -> {
|
||||
val moduleDependencies: List<CompiledModule> =
|
||||
DFS.topologicalOrder(dependencies, CompiledModule::dependencies)
|
||||
.filter { it.moduleType == ModuleType.SECONDARY }
|
||||
|
||||
val fileDependencies = moduleDependencies.flatMap { it.moduleFragment!!.files }
|
||||
|
||||
moduleFragment.files.addAll(0, fileDependencies)
|
||||
}
|
||||
|
||||
ModuleType.SECONDARY -> {
|
||||
return CompiledModule(moduleName, null, moduleFragment, moduleType, dependencies)
|
||||
}
|
||||
|
||||
ModuleType.TEST_RUNTIME -> {
|
||||
}
|
||||
val deserializedModuleFragments = sortedDeps.map {
|
||||
val moduleFile = File(it.klibPath, moduleHeaderFileName)
|
||||
deserializer.deserializeIrModule(it.moduleDescriptor!!, moduleFile.readBytes(), File(it.klibPath), false)
|
||||
}
|
||||
|
||||
val context = JsIrBackendContext(
|
||||
analysisResult.moduleDescriptor,
|
||||
psi2IrContext.irBuiltIns,
|
||||
psi2IrContext.symbolTable,
|
||||
moduleFragment,
|
||||
configuration,
|
||||
dependencies,
|
||||
moduleType
|
||||
)
|
||||
var moduleFragment = psi2IrTranslator.generateModuleFragment(psi2IrContext, files, deserializer)
|
||||
val moduleName = configuration.get(CommonConfigurationKeys.MODULE_NAME) as String
|
||||
|
||||
jsPhases.invokeToplevel(context.phaseConfig, context, moduleFragment)
|
||||
|
||||
val jsProgram = moduleFragment.accept(IrModuleToJsTransformer(context), null)
|
||||
|
||||
return CompiledModule(moduleName, jsProgram.toString(), context.moduleFragmentCopy, moduleType, dependencies)
|
||||
}
|
||||
|
||||
private fun compileIntoKlib(
|
||||
files: List<KtFile>,
|
||||
project: Project,
|
||||
configuration: CompilerConfiguration,
|
||||
dependencies: List<CompiledModule>,
|
||||
builtInsModule: CompiledModule?,
|
||||
moduleType: ModuleType,
|
||||
generateJsCode: Boolean
|
||||
): CompiledModule {
|
||||
val analysisResult =
|
||||
TopDownAnalyzerFacadeForJS.analyzeFiles(
|
||||
files,
|
||||
project,
|
||||
configuration,
|
||||
dependencies.map { it.descriptor },
|
||||
emptyList(),
|
||||
thisIsBuiltInsModule = builtInsModule == null,
|
||||
customBuiltInsModule = builtInsModule?.descriptor
|
||||
val context = if (compileMode.generateKlib) {
|
||||
deserializedModuleFragments.forEach {
|
||||
ExternalDependenciesGenerator(it.descriptor, symbolTable, irBuiltIns, null).generateUnboundSymbolsAsDependencies(it)
|
||||
}
|
||||
deserializedModuleFragments.forEach { it.patchDeclarationParents() }
|
||||
serializeModuleIntoKlib(
|
||||
moduleName,
|
||||
metadataVersion,
|
||||
languageSettings,
|
||||
symbolTable,
|
||||
psi2IrContext.bindingContext,
|
||||
klibPath,
|
||||
dependencies,
|
||||
moduleFragment
|
||||
)
|
||||
|
||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
|
||||
if (compileMode.generateJS) {
|
||||
deserializeModuleFromKlib(
|
||||
klibPath,
|
||||
moduleName,
|
||||
lookupTracker,
|
||||
LockBasedStorageManager("JsDeserialized"),
|
||||
metadataVersion,
|
||||
languageSettings,
|
||||
sortedDeps,
|
||||
builtInModule
|
||||
).let {
|
||||
deserializer = it.deserializer
|
||||
moduleFragment = it.moduleIr
|
||||
|
||||
TopDownAnalyzerFacadeForJS.checkForErrors(files, analysisResult.bindingContext)
|
||||
JsIrBackendContext(it.moduleDescriptor, it.irBuiltIns, it.symbolTable, it.moduleIr, configuration, compileMode).also {
|
||||
moduleFragment.replaceUnboundSymbols(it)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return CompiledModule(moduleName, null, null, klibPath, dependencies, builtInModule == null)
|
||||
}
|
||||
} else JsIrBackendContext(moduleDescriptor, irBuiltIns, symbolTable, moduleFragment, configuration, compileMode)
|
||||
|
||||
val irDependencies = dependencies.mapNotNull { it.moduleFragment }
|
||||
val jsProgram = if (compileMode.generateJS) {
|
||||
deserializedModuleFragments.forEach {
|
||||
ExternalDependenciesGenerator(
|
||||
it.descriptor,
|
||||
context.symbolTable,
|
||||
context.irBuiltIns,
|
||||
deserializer
|
||||
).generateUnboundSymbolsAsDependencies(it)
|
||||
}
|
||||
|
||||
val symbolTable = SymbolTable()
|
||||
val irFiles = deserializedModuleFragments.flatMap { it.files } + moduleFragment.files
|
||||
|
||||
val psi2IrTranslator = Psi2IrTranslator(configuration.languageVersionSettings)
|
||||
val psi2IrContext = psi2IrTranslator.createGeneratorContext(analysisResult.moduleDescriptor, analysisResult.bindingContext, symbolTable)
|
||||
moduleFragment.files.clear()
|
||||
moduleFragment.files += irFiles
|
||||
|
||||
val moduleFragment = psi2IrTranslator.generateModuleFragment(psi2IrContext, files)
|
||||
ExternalDependenciesGenerator(
|
||||
moduleDescriptor = context.module,
|
||||
symbolTable = context.symbolTable,
|
||||
irBuiltIns = context.irBuiltIns
|
||||
).generateUnboundSymbolsAsDependencies(moduleFragment)
|
||||
moduleFragment.patchDeclarationParents()
|
||||
|
||||
val declarationTable = DeclarationTable(moduleFragment.irBuiltins, DescriptorTable(), psi2IrContext.symbolTable)
|
||||
|
||||
jsPhases.invokeToplevel(context.phaseConfig, context, moduleFragment)
|
||||
|
||||
moduleFragment.accept(IrModuleToJsTransformer(context), null)
|
||||
} else null
|
||||
|
||||
return CompiledModule(moduleName, jsProgram?.toString(), null, klibPath, dependencies, builtInModule == null)
|
||||
|
||||
}
|
||||
|
||||
private fun loadKlibMetadata(
|
||||
moduleName: String,
|
||||
klibPath: String,
|
||||
isBuiltIn: Boolean,
|
||||
lookupTracker: LookupTracker,
|
||||
storageManager: LockBasedStorageManager,
|
||||
metadataVersion: JsKlibMetadataVersion,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
builtinsModule: ModuleDescriptorImpl?,
|
||||
dependencies: List<CompiledModule>
|
||||
): ModuleDescriptorImpl {
|
||||
assert(isBuiltIn == (builtinsModule === null))
|
||||
|
||||
val metadataFile = File(klibPath, metadataFileName(moduleName))
|
||||
|
||||
val serializer = JsKlibMetadataSerializationUtil
|
||||
val parts = serializer.readModuleAsProto(metadataFile.readBytes())
|
||||
val builtIns = builtinsModule?.builtIns ?: object : KotlinBuiltIns(storageManager) {}
|
||||
val md = ModuleDescriptorImpl(Name.special("<$moduleName>"), storageManager, builtIns)
|
||||
if (isBuiltIn) builtIns.builtInsModule = md
|
||||
val currentModuleFragmentProvider = createJsKlibMetadataPackageFragmentProvider(
|
||||
storageManager, md, parts.header, parts.body, metadataVersion,
|
||||
CompilerDeserializationConfiguration(languageVersionSettings),
|
||||
lookupTracker
|
||||
)
|
||||
|
||||
val packageFragmentProvider = if (isBuiltIn) {
|
||||
val functionFragmentProvider = functionInterfacePackageFragmentProvider(storageManager, md)
|
||||
CompositePackageFragmentProvider(listOf(functionFragmentProvider, currentModuleFragmentProvider))
|
||||
} else currentModuleFragmentProvider
|
||||
|
||||
md.initialize(packageFragmentProvider)
|
||||
md.setDependencies(listOf(md) + dependencies.mapNotNull { it.moduleDescriptor })
|
||||
|
||||
return md
|
||||
}
|
||||
|
||||
typealias MetadataDFSHandler = DFS.NodeHandler<CompiledModule, List<CompiledModule>>
|
||||
|
||||
private class DependencyMetadataLoader(
|
||||
private val lookupTracker: LookupTracker,
|
||||
private val metadataVersion: JsKlibMetadataVersion,
|
||||
private val languageVersionSettings: LanguageVersionSettings,
|
||||
private val storageManager: LockBasedStorageManager
|
||||
) : MetadataDFSHandler {
|
||||
private val sortedDependencies = mutableListOf<CompiledModule>()
|
||||
|
||||
private var runtimeModule: ModuleDescriptorImpl? = null
|
||||
|
||||
override fun beforeChildren(current: CompiledModule) = true
|
||||
|
||||
override fun afterChildren(current: CompiledModule) {
|
||||
val md = current.moduleDescriptor ?: loadKlibMetadata(
|
||||
current.moduleName,
|
||||
current.klibPath,
|
||||
current.isBuiltIn,
|
||||
lookupTracker,
|
||||
storageManager,
|
||||
metadataVersion,
|
||||
languageVersionSettings,
|
||||
runtimeModule,
|
||||
current.dependencies
|
||||
).also { current.moduleDescriptor = it }
|
||||
sortedDependencies += current
|
||||
if (current.isBuiltIn) runtimeModule = md
|
||||
}
|
||||
|
||||
override fun result() = sortedDependencies
|
||||
}
|
||||
|
||||
fun serializeModuleIntoKlib(
|
||||
moduleName: String,
|
||||
metadataVersion: JsKlibMetadataVersion,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
symbolTable: SymbolTable,
|
||||
bindingContext: BindingContext,
|
||||
klibPath: String,
|
||||
dependencies: List<CompiledModule>,
|
||||
moduleFragment: IrModuleFragment
|
||||
) {
|
||||
val declarationTable = DeclarationTable(moduleFragment.irBuiltins, DescriptorTable(), symbolTable)
|
||||
|
||||
val serializedIr = IrModuleSerializer(logggg, declarationTable/*, onlyForInlines = false*/).serializedIrModule(moduleFragment)
|
||||
val serializer = JsKlibMetadataSerializationUtil
|
||||
|
||||
val moduleName = configuration.get(CommonConfigurationKeys.MODULE_NAME) as String
|
||||
val metadataVersion = configuration.get(CommonConfigurationKeys.METADATA_VERSION) as? JsKlibMetadataVersion
|
||||
?: JsKlibMetadataVersion.INSTANCE
|
||||
val moduleDescription =
|
||||
JsKlibMetadataModuleDescriptor(moduleName, irDependencies.map { it.name.asString() }, moduleFragment.descriptor)
|
||||
JsKlibMetadataModuleDescriptor(moduleName, dependencies.map { it.moduleName }, moduleFragment.descriptor)
|
||||
val serializedData = serializer.serializeMetadata(
|
||||
psi2IrContext.bindingContext,
|
||||
bindingContext,
|
||||
moduleDescription,
|
||||
configuration.get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS)!!,
|
||||
languageVersionSettings,
|
||||
metadataVersion
|
||||
) { declarationDescriptor ->
|
||||
val index = declarationTable.descriptorTable.get(declarationDescriptor)
|
||||
index?.let { newDescriptorUniqId(it) }
|
||||
}
|
||||
|
||||
val stdKlibDir = File(runtimeKlibPath).also {
|
||||
val klibDir = File(klibPath).also {
|
||||
it.deleteRecursively()
|
||||
it.mkdirs()
|
||||
}
|
||||
|
||||
val moduleFile = File(stdKlibDir, moduleHeaderFileName)
|
||||
val moduleFile = File(klibDir, moduleHeaderFileName)
|
||||
moduleFile.writeBytes(serializedIr.module)
|
||||
|
||||
val irDeclarationDir = File(stdKlibDir, declarationsDirName).also { it.mkdir() }
|
||||
val irDeclarationDir = File(klibDir, declarationsDirName).also { it.mkdir() }
|
||||
|
||||
for ((id, data) in serializedIr.declarations) {
|
||||
val file = File(irDeclarationDir, id.declarationFileName)
|
||||
file.writeBytes(data)
|
||||
}
|
||||
|
||||
|
||||
val debugFile = File(stdKlibDir, debugDataFileName)
|
||||
val debugFile = File(klibDir, debugDataFileName)
|
||||
|
||||
for ((id, data) in serializedIr.debugIndex) {
|
||||
debugFile.appendText(id.toString())
|
||||
@@ -412,29 +362,7 @@ private fun compileIntoKlib(
|
||||
debugFile.appendText("\n")
|
||||
}
|
||||
|
||||
File(stdKlibDir, "${moduleDescription.name}.${JsKlibMetadataSerializationUtil.CLASS_METADATA_FILE_EXTENSION}").also {
|
||||
File(klibDir, "${moduleDescription.name}.${JsKlibMetadataSerializationUtil.CLASS_METADATA_FILE_EXTENSION}").also {
|
||||
it.writeBytes(serializedData.asByteArray())
|
||||
}
|
||||
|
||||
val jsProgram = if (generateJsCode) {
|
||||
val lookupTracker = configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER, LookupTracker.DO_NOTHING)
|
||||
val (md, deserializedModuleFragment, st, irBuiltIns) = deserializerRuntimeKlib(
|
||||
runtimeKlibPath,
|
||||
JS_IR_RUNTIME_MODULE_NAME,
|
||||
lookupTracker,
|
||||
metadataVersion,
|
||||
configuration.languageVersionSettings,
|
||||
true
|
||||
)
|
||||
|
||||
val context = JsIrBackendContext(md, irBuiltIns, st, deserializedModuleFragment, configuration, dependencies, moduleType)
|
||||
|
||||
deserializedModuleFragment.replaceUnboundSymbols(context)
|
||||
|
||||
jsPhases.invokeToplevel(context.phaseConfig, context, deserializedModuleFragment)
|
||||
|
||||
deserializedModuleFragment.accept(IrModuleToJsTransformer(context), null)
|
||||
} else null
|
||||
|
||||
return CompiledModule(moduleName, jsProgram?.toString(), null, moduleType, emptyList())
|
||||
}
|
||||
}
|
||||
+13
-14
@@ -29,7 +29,7 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.IrTypeProjection
|
||||
import org.jetbrains.kotlin.ir.types.toIrType
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.util.isInlined
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
@@ -211,10 +211,11 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
|
||||
val additionalDeclarations = generateFactoryBodyWithGuard(factoryFunction) {
|
||||
val statements = mutableListOf<IrStatement>(getterFunction)
|
||||
|
||||
val getterFunctionType = context.builtIns.getFunction(getterFunction.valueParameters.size + 1)
|
||||
val type = getterFunctionType.toIrType(symbolTable = context.symbolTable)
|
||||
val irGetReference = JsIrBuilder.buildFunctionReference(type, getterFunction.symbol)
|
||||
val irVar = JsIrBuilder.buildVar(type, factoryFunction, initializer = irGetReference)
|
||||
val getterFunctionTypeSymbol = context.functionN(getterFunction.valueParameters.size + 1)
|
||||
|
||||
val getterFunctionIrType = IrSimpleTypeImpl(getterFunctionTypeSymbol, false, emptyList(), emptyList())
|
||||
val irGetReference = JsIrBuilder.buildFunctionReference(getterFunctionIrType, getterFunction.symbol)
|
||||
val irVar = JsIrBuilder.buildVar(getterFunctionIrType, factoryFunction, initializer = irGetReference)
|
||||
|
||||
statements += irVar
|
||||
|
||||
@@ -226,11 +227,9 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
|
||||
|
||||
if (setterFunction != null) {
|
||||
statements += setterFunction
|
||||
val setterFunctionType = context.builtIns.getFunction(setterFunction.valueParameters.size + 1)
|
||||
val irSetReference = JsIrBuilder.buildFunctionReference(
|
||||
setterFunctionType.toIrType(symbolTable = context.symbolTable),
|
||||
setterFunction.symbol
|
||||
)
|
||||
val setterFunctionTypeSymbol = context.functionN(setterFunction.valueParameters.size + 1)
|
||||
val setterFunctionIrType = IrSimpleTypeImpl(setterFunctionTypeSymbol, false, emptyList(), emptyList())
|
||||
val irSetReference = JsIrBuilder.buildFunctionReference(setterFunctionIrType, setterFunction.symbol)
|
||||
statements += JsIrBuilder.buildCall(context.intrinsics.jsSetJSField.symbol).apply {
|
||||
putValueArgument(0, JsIrBuilder.buildGetValue(irVar.symbol))
|
||||
putValueArgument(1, setterConst)
|
||||
@@ -282,10 +281,10 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
|
||||
val additionalDeclarations = generateFactoryBodyWithGuard(factoryFunction) {
|
||||
val statements = mutableListOf<IrStatement>(closureFunction)
|
||||
|
||||
val getterFunctionType = context.builtIns.getFunction(closureFunction.valueParameters.size + 1)
|
||||
val type = getterFunctionType.toIrType(symbolTable = context.symbolTable)
|
||||
val irGetReference = JsIrBuilder.buildFunctionReference(type, closureFunction.symbol)
|
||||
val irVar = JsIrBuilder.buildVar(type, factoryFunction, initializer = irGetReference)
|
||||
val getterFunctionTypeSymbol = context.functionN(closureFunction.valueParameters.size + 1)
|
||||
val getterFunctionIrType = IrSimpleTypeImpl(getterFunctionTypeSymbol, false, emptyList(), emptyList())
|
||||
val irGetReference = JsIrBuilder.buildFunctionReference(getterFunctionIrType, closureFunction.symbol)
|
||||
val irVar = JsIrBuilder.buildVar(getterFunctionIrType, factoryFunction, initializer = irGetReference)
|
||||
val irVarSymbol = irVar.symbol
|
||||
|
||||
statements += irVar
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ class JsDefaultArgumentStubGenerator(override val context: JsIrBackendContext) :
|
||||
private fun resolveInvoke(paramCount: Int): IrSimpleFunction {
|
||||
assert(paramCount > 0)
|
||||
val fqn = FqName.fromSegments(listOf("kotlin", "Function$paramCount"))
|
||||
val functionKlass = context.run { symbolTable.lazyWrapper.referenceClass(getClass(fqn)) }.owner
|
||||
val functionKlass = context.functionN(paramCount).owner
|
||||
return functionKlass.declarations.filterIsInstance<IrSimpleFunction>().first { it.name == Name.identifier("invoke") }
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -307,12 +307,12 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo
|
||||
if (unboundFunctionParameters != null) {
|
||||
// Suspend lambda inherits SuspendFunction.
|
||||
val numberOfParameters = unboundFunctionParameters.size
|
||||
suspendFunctionClass = context.suspendFunctions[numberOfParameters].owner
|
||||
suspendFunctionClass = context.suspendFunctionN(numberOfParameters).owner
|
||||
val unboundParameterTypes = unboundFunctionParameters.map { it.type }
|
||||
suspendFunctionClassTypeArguments = unboundParameterTypes + irFunction.returnType
|
||||
superTypes += suspendFunctionClass.typeWith(suspendFunctionClassTypeArguments)
|
||||
|
||||
functionClass = context.functions[numberOfParameters + 1].owner
|
||||
functionClass = context.functionN(numberOfParameters + 1).owner
|
||||
val continuationType = continuationClassSymbol.typeWith(irFunction.returnType)
|
||||
functionClassTypeArguments = unboundParameterTypes + continuationType + context.irBuiltIns.anyNType
|
||||
superTypes += functionClass.typeWith(functionClassTypeArguments)
|
||||
|
||||
+7
-5
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.ir.backend.js.lower.inline
|
||||
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
|
||||
import org.jetbrains.kotlin.builtins.getFunctionalClassKind
|
||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
@@ -54,11 +55,12 @@ internal val FunctionDescriptor.isFunctionInvoke: Boolean
|
||||
|
||||
internal val IrFunction.isFunctionInvoke: Boolean
|
||||
get() {
|
||||
val dispatchReceiver = dispatchReceiverParameter ?: return false
|
||||
assert(!dispatchReceiver.type.isKFunction())
|
||||
|
||||
return dispatchReceiver.type.isFunctionTypeOrSubtype() &&
|
||||
/*this.isOperator &&*/ this.name == OperatorNameConventions.INVOKE
|
||||
// val dispatchReceiver = dispatchReceiverParameter ?: return false
|
||||
// assert(!dispatchReceiver.type.isKFunction())
|
||||
//
|
||||
// return dispatchReceiver.type.isFunctionTypeOrSubtype() &&
|
||||
// /*this.isOperator &&*/ this.name == OperatorNameConventions.INVOKE
|
||||
return descriptor is FunctionInvokeDescriptor
|
||||
}
|
||||
|
||||
// It is possible to declare "external inline fun",
|
||||
|
||||
+7
-5
@@ -30,7 +30,6 @@ class IrKlibProtoBufModuleDeserializer(
|
||||
currentModule: ModuleDescriptor,
|
||||
logger: LoggingContext,
|
||||
builtIns: IrBuiltIns,
|
||||
libraryDir: File,
|
||||
symbolTable: SymbolTable,
|
||||
val forwardModuleDescriptor: ModuleDescriptor?)
|
||||
: IrModuleDeserializer(logger, builtIns, symbolTable) {
|
||||
@@ -53,8 +52,10 @@ class IrKlibProtoBufModuleDeserializer(
|
||||
builtIns.builtIns.getBuiltInClassByFqName(it)
|
||||
})
|
||||
|
||||
val moduleRoot = libraryDir
|
||||
val irDirectory = File(libraryDir, "ir/")
|
||||
val descriptorToDirectoryMap = mutableMapOf<ModuleDescriptor, File>()
|
||||
|
||||
// val moduleRoot = libraryDir
|
||||
private fun irDirectory(m: ModuleDescriptor): File = descriptorToDirectoryMap[m]!!
|
||||
|
||||
|
||||
private val FUNCTION_INDEX_START: Long
|
||||
@@ -204,7 +205,7 @@ class IrKlibProtoBufModuleDeserializer(
|
||||
}
|
||||
|
||||
private fun loadTopLevelDeclarationProto(uniqIdKey: UniqIdKey): IrKlibProtoBuf.IrDeclaration {
|
||||
val file = File(irDirectory, uniqIdKey.uniqId.declarationFileName)
|
||||
val file = File(irDirectory(deserializedModuleDescriptor!!), uniqIdKey.uniqId.declarationFileName)
|
||||
return IrKlibProtoBuf.IrDeclaration.parseFrom(file.readBytes().codedInputStream, JsKlibMetadataSerializerProtocol.extensionRegistry)
|
||||
}
|
||||
|
||||
@@ -347,7 +348,8 @@ class IrKlibProtoBufModuleDeserializer(
|
||||
return module
|
||||
}
|
||||
|
||||
fun deserializeIrModule(moduleDescriptor: ModuleDescriptor, byteArray: ByteArray, deserializeAllDeclarations: Boolean = false): IrModuleFragment {
|
||||
fun deserializeIrModule(moduleDescriptor: ModuleDescriptor, byteArray: ByteArray, klibLocation: File, deserializeAllDeclarations: Boolean = false): IrModuleFragment {
|
||||
descriptorToDirectoryMap[moduleDescriptor] = File(klibLocation, "ir/")
|
||||
val proto = IrKlibProtoBuf.IrModule.parseFrom(byteArray.codedInputStream, JsKlibMetadataSerializerProtocol.extensionRegistry)
|
||||
return deserializeIrModule(proto, moduleDescriptor, deserializeAllDeclarations)
|
||||
}
|
||||
|
||||
+2
-6
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.ModuleType
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithVisibility
|
||||
@@ -187,11 +186,8 @@ class IrModuleToJsTransformer(private val backendContext: JsIrBackendContext) :
|
||||
}
|
||||
|
||||
override fun visitModuleFragment(declaration: IrModuleFragment, data: Nothing?): JsNode =
|
||||
when (backendContext.moduleType) {
|
||||
ModuleType.MAIN -> generateModule(declaration)
|
||||
ModuleType.SECONDARY -> JsEmpty
|
||||
ModuleType.TEST_RUNTIME -> generateModuleInGlobalScope(declaration)
|
||||
}
|
||||
if (backendContext.compilationMode.generateKlib) generateModuleInGlobalScope(declaration)
|
||||
else generateModule(declaration)
|
||||
|
||||
|
||||
private fun processClassModels(
|
||||
|
||||
+3
-6
@@ -114,14 +114,11 @@ class SimpleNameGenerator : NameGenerator {
|
||||
}
|
||||
|
||||
|
||||
if (declaration.name.isSpecial || declaration.visibility == Visibilities.LOCAL) {
|
||||
if (declaration.descriptor !is DeserializedClassDescriptor) {
|
||||
// TODO: temporary workaround for Unit instance
|
||||
nameDeclarator = context.staticContext.rootScope::declareFreshName
|
||||
}
|
||||
nameDeclarator = context.staticContext.rootScope::declareFreshName
|
||||
if (declaration.kind == ClassKind.OBJECT || declaration.name.isSpecial || declaration.visibility == Visibilities.LOCAL) {
|
||||
val parent = declaration.parent
|
||||
when (parent) {
|
||||
is IrDeclarationWithName -> nameBuilder.append(getNameForDeclaration(parent, context))
|
||||
is IrDeclaration -> nameBuilder.append(getNameForDeclaration(parent, context))
|
||||
is IrPackageFragment -> nameBuilder.append(parent.fqName.asString())
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -61,11 +61,13 @@ class ExternalDependenciesGenerator(
|
||||
|
||||
deserializer?.declareForwardDeclarations()
|
||||
|
||||
// assert(symbolTable.unboundClasses.isEmpty())
|
||||
if (deserializer != null) return
|
||||
|
||||
assert(symbolTable.unboundClasses.isEmpty())
|
||||
assert(symbolTable.unboundConstructors.isEmpty())
|
||||
assert(symbolTable.unboundEnumEntries.isEmpty())
|
||||
assert(symbolTable.unboundFields.isEmpty())
|
||||
// assert(symbolTable.unboundSimpleFunctions.isEmpty())
|
||||
assert(symbolTable.unboundSimpleFunctions.isEmpty())
|
||||
assert(symbolTable.unboundTypeParameters.isEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,10 +56,11 @@ object TopDownAnalyzerFacadeForJS {
|
||||
"Can't simultaneously use custom built-ins module and set current module as built-ins"
|
||||
}
|
||||
val projectContext = ProjectContext(project)
|
||||
val builtIns = if (thisIsBuiltInsModule || customBuiltInsModule != null) {
|
||||
object : KotlinBuiltIns(projectContext.storageManager) {}
|
||||
} else {
|
||||
JsPlatform.builtIns
|
||||
|
||||
val builtIns = when {
|
||||
thisIsBuiltInsModule -> object : KotlinBuiltIns(projectContext.storageManager) {}
|
||||
customBuiltInsModule != null -> customBuiltInsModule.builtIns
|
||||
else -> JsPlatform.builtIns
|
||||
}
|
||||
|
||||
val moduleName = configuration[CommonConfigurationKeys.MODULE_NAME]!!
|
||||
@@ -72,10 +73,6 @@ object TopDownAnalyzerFacadeForJS {
|
||||
|
||||
val additionalPackages = mutableListOf<PackageFragmentProvider>()
|
||||
|
||||
if (customBuiltInsModule != null) {
|
||||
builtIns.builtInsModule = customBuiltInsModule
|
||||
}
|
||||
|
||||
if (thisIsBuiltInsModule) {
|
||||
builtIns.builtInsModule = context.module
|
||||
additionalPackages += functionInterfacePackageFragmentProvider(context.storageManager, context.module)
|
||||
|
||||
@@ -13,13 +13,11 @@ import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import org.jetbrains.kotlin.ir.backend.js.CompilationMode
|
||||
import org.jetbrains.kotlin.ir.backend.js.ModuleType
|
||||
import org.jetbrains.kotlin.ir.backend.js.compile
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
import org.jetbrains.kotlin.js.test.JsIrTestRuntime
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.serialization.js.ModuleKind
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import java.io.File
|
||||
|
||||
fun buildConfiguration(environment: KotlinCoreEnvironment): CompilerConfiguration {
|
||||
@@ -42,9 +40,8 @@ fun buildConfiguration(environment: KotlinCoreEnvironment): CompilerConfiguratio
|
||||
return runtimeConfiguration
|
||||
}
|
||||
|
||||
private val stdKlibFile = File("js/js.translator/testData/out/klibs/stdlib.klib")
|
||||
|
||||
private val resultJs = "js/js.translator/testData/out/klibs/result.js"
|
||||
private val runtimeKlibPath = "js/js.translator/testData/out/klibs/runtime/"
|
||||
|
||||
fun main() {
|
||||
|
||||
@@ -66,11 +63,8 @@ fun main() {
|
||||
emptyList(),
|
||||
CompilationMode.KLIB_WITH_JS,
|
||||
emptyList(),
|
||||
null,
|
||||
ModuleType.TEST_RUNTIME
|
||||
runtimeKlibPath
|
||||
)
|
||||
|
||||
File(resultJs).writeText(result.generatedCode!!)
|
||||
|
||||
// TODO("Write library into $stdKlibFile")
|
||||
result.generatedCode?.let { File(resultJs).writeText(it) }
|
||||
}
|
||||
@@ -5,11 +5,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.js.test
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import org.jetbrains.kotlin.ir.backend.js.CompilationMode
|
||||
import org.jetbrains.kotlin.ir.backend.js.ModuleType
|
||||
import org.jetbrains.kotlin.ir.backend.js.CompiledModule
|
||||
import org.jetbrains.kotlin.ir.backend.js.compile
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
@@ -17,12 +14,17 @@ import org.jetbrains.kotlin.js.config.JsConfig
|
||||
import org.jetbrains.kotlin.js.facade.MainCallParameters
|
||||
import org.jetbrains.kotlin.js.facade.TranslationUnit
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import org.jetbrains.kotlin.test.TargetBackend
|
||||
import java.io.File
|
||||
|
||||
private var runtimeResults = mutableMapOf<JsIrTestRuntime, CompiledModule>()
|
||||
|
||||
private val runtimeKlibPath = "js/js.translator/testData/out/klibs/runtime/"
|
||||
|
||||
private val JS_IR_RUNTIME_MODULE_NAME = "JS_IR_RUNTIME"
|
||||
|
||||
private val runtimeKlib = CompiledModule(JS_IR_RUNTIME_MODULE_NAME, null, null, runtimeKlibPath, emptyList(), true)
|
||||
|
||||
abstract class BasicIrBoxTest(
|
||||
pathToTestDir: String,
|
||||
testGroupOutputDirPrefix: String,
|
||||
@@ -80,31 +82,8 @@ abstract class BasicIrBoxTest(
|
||||
)
|
||||
)
|
||||
|
||||
val runtimeConfiguration = config.configuration.copy()
|
||||
|
||||
// TODO: is it right in general? Maybe sometimes we need to compile with newer versions or with additional language features.
|
||||
runtimeConfiguration.languageVersionSettings = LanguageVersionSettingsImpl(
|
||||
LanguageVersion.LATEST_STABLE, ApiVersion.LATEST_STABLE,
|
||||
specificFeatures = mapOf(
|
||||
LanguageFeature.AllowContractsForCustomFunctions to LanguageFeature.State.ENABLED,
|
||||
LanguageFeature.MultiPlatformProjects to LanguageFeature.State.ENABLED
|
||||
),
|
||||
analysisFlags = mapOf(
|
||||
AnalysisFlags.useExperimental to listOf("kotlin.contracts.ExperimentalContracts", "kotlin.Experimental"),
|
||||
AnalysisFlags.allowResultReturnType to true
|
||||
)
|
||||
)
|
||||
|
||||
val runtimeFile = File(runtime.path)
|
||||
val runtimeResult = runtimeResults.getOrPut(runtime) {
|
||||
runtimeConfiguration.put(CommonConfigurationKeys.MODULE_NAME, "JS_IR_RUNTIME")
|
||||
val result = compile(config.project, runtime.sources.map(::createPsiFile), runtimeConfiguration, moduleType = ModuleType.TEST_RUNTIME)
|
||||
runtimeFile.write(result.generatedCode!!)
|
||||
result
|
||||
}
|
||||
|
||||
val dependencyNames = config.configuration[JSConfigurationKeys.LIBRARIES]!!.map { File(it).name }
|
||||
val dependencies = listOf(runtimeResult) + dependencyNames.mapNotNull {
|
||||
val dependencies = listOf(runtimeKlib) + dependencyNames.mapNotNull {
|
||||
compilationCache[it]
|
||||
}
|
||||
|
||||
@@ -113,25 +92,26 @@ abstract class BasicIrBoxTest(
|
||||
// config.configuration.put(CommonConfigurationKeys.PHASES_TO_DUMP_STATE_AFTER, setOf("MultipleCatchesLowering"))
|
||||
// config.configuration.put(CommonConfigurationKeys.PHASES_TO_VALIDATE, setOf("ALL"))
|
||||
|
||||
val actualOutputFile = outputFile.absolutePath.let {
|
||||
if (!isMainModule) it.replace("_v5.js", "/") else it
|
||||
}
|
||||
|
||||
val result = compile(
|
||||
config.project,
|
||||
filesToCompile,
|
||||
config.configuration,
|
||||
listOf(FqName((testPackage?.let { "$it." } ?: "") + testFunction)),
|
||||
CompilationMode.TEST_AGAINST_CACHE,//CompilationMode.TEST_AGAINST_KLIB,
|
||||
if (isMainModule) CompilationMode.JS_AGAINST_KLIB else CompilationMode.KLIB,
|
||||
dependencies,
|
||||
runtimeResult,
|
||||
moduleType = if (isMainModule) ModuleType.MAIN else ModuleType.SECONDARY
|
||||
klibPath = actualOutputFile
|
||||
)
|
||||
|
||||
compilationCache[outputFile.name.replace(".js", ".meta.js")] = result
|
||||
|
||||
val generatedCode = result.generatedCode
|
||||
if (generatedCode != null) {
|
||||
// Prefix to help node.js runner find runtime
|
||||
val runtimePrefix = "// RUNTIME: [\"${runtimeFile.path}\"]\n"
|
||||
val wrappedCode = wrapWithModuleEmulationMarkers(generatedCode, moduleId = config.moduleId, moduleKind = config.moduleKind)
|
||||
outputFile.write(runtimePrefix + wrappedCode)
|
||||
outputFile.write(wrappedCode)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +126,8 @@ abstract class BasicIrBoxTest(
|
||||
) {
|
||||
// TODO: should we do anything special for module systems?
|
||||
// TODO: return list of js from translateFiles and provide then to this function with other js files
|
||||
nashornIrJsTestCheckers[runtime]!!.check(jsFiles, testModuleName, null, testFunction, expectedResult, withModuleSystem)
|
||||
|
||||
NashornIrJsTestChecker().check(jsFiles, testModuleName, null, testFunction, expectedResult, withModuleSystem)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -147,20 +147,15 @@ object NashornJsTestChecker : AbstractNashornJsTestChecker() {
|
||||
}
|
||||
}
|
||||
|
||||
class NashornIrJsTestChecker(private val runtime: JsIrTestRuntime) : AbstractNashornJsTestChecker() {
|
||||
class NashornIrJsTestChecker : AbstractNashornJsTestChecker() {
|
||||
override fun createScriptEngineForTest(): ScriptEngine {
|
||||
val engine = createScriptEngine()
|
||||
|
||||
listOf(
|
||||
listOfNotNull(
|
||||
BasicBoxTest.TEST_DATA_DIR_PATH + "nashorn-polyfills.js",
|
||||
"libraries/stdlib/js/src/js/polyfills.js",
|
||||
runtime.path
|
||||
"libraries/stdlib/js/src/js/polyfills.js"
|
||||
).forEach(engine::loadFile)
|
||||
|
||||
return engine
|
||||
}
|
||||
}
|
||||
|
||||
val nashornIrJsTestCheckers = JsIrTestRuntime.values().associate {
|
||||
it to NashornIrJsTestChecker(it)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user