diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt index 36c475f1faf..47679c3cb92 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt @@ -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, - 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 { 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(this, irModuleFragment) { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt index 2e5ef112e05..8ffeacd85be 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt @@ -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 = " 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 diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt index ad8aa540865..cf93f10b8fb 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt @@ -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 -) { - val descriptor - get() = moduleFragment!!.descriptor as ModuleDescriptorImpl -} + var moduleDescriptor: ModuleDescriptorImpl?, + val klibPath: String, + val dependencies: List, + 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, + 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, configuration: CompilerConfiguration, export: List = emptyList(), - compileMode: CompilationMode = CompilationMode.TEST_AGAINST_CACHE, + compileMode: CompilationMode, dependencies: List = 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, - project: Project, - configuration: CompilerConfiguration, - dependencies: List, - 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, - project: Project, - configuration: CompilerConfiguration, - dependencies: List, - 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 = - 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, - project: Project, - configuration: CompilerConfiguration, - dependencies: List, - 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 +): 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> + +private class DependencyMetadataLoader( + private val lookupTracker: LookupTracker, + private val metadataVersion: JsKlibMetadataVersion, + private val languageVersionSettings: LanguageVersionSettings, + private val storageManager: LockBasedStorageManager +) : MetadataDFSHandler { + private val sortedDependencies = mutableListOf() + + 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, + 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()) -} +} \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/CallableReferenceLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/CallableReferenceLowering.kt index 000d7dcdd40..7e018854fdd 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/CallableReferenceLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/CallableReferenceLowering.kt @@ -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(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(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 diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsDefaultArgumentStubGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsDefaultArgumentStubGenerator.kt index ccebb59edee..d5b20762070 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsDefaultArgumentStubGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsDefaultArgumentStubGenerator.kt @@ -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().first { it.name == Name.identifier("invoke") } } } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/SuspendFunctionsLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/SuspendFunctionsLowering.kt index b867a457087..988189abf36 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/SuspendFunctionsLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/SuspendFunctionsLowering.kt @@ -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) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/LegacyDescriptorUtils.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/LegacyDescriptorUtils.kt index 0ce0b33c3bb..c61837fb07e 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/LegacyDescriptorUtils.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/LegacyDescriptorUtils.kt @@ -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", diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/IrKlibProtoBufModuleDeserializer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/IrKlibProtoBufModuleDeserializer.kt index b73c044acbf..8cbcfbcf5ae 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/IrKlibProtoBufModuleDeserializer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/IrKlibProtoBufModuleDeserializer.kt @@ -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() + +// 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) } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt index 89cec83f11f..229918a3c7f 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt @@ -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( diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/SimpleNameGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/SimpleNameGenerator.kt index 568f7b9242e..f18e0a9a2c7 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/SimpleNameGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/SimpleNameGenerator.kt @@ -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()) } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt index 4b4fc39be40..20e86150c7a 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt @@ -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()) } } diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/analyze/TopDownAnalyzerFacadeForJS.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/analyze/TopDownAnalyzerFacadeForJS.kt index ea704c79459..0d958e7703c 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/analyze/TopDownAnalyzerFacadeForJS.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/analyze/TopDownAnalyzerFacadeForJS.kt @@ -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() - if (customBuiltInsModule != null) { - builtIns.builtInsModule = customBuiltInsModule - } - if (thisIsBuiltInsModule) { builtIns.builtInsModule = context.module additionalPackages += functionInterfacePackageFragmentProvider(context.storageManager, context.module) diff --git a/js/js.tests/test/org/jetbrains/kotlin/generators/tests/GenerateIrRuntime.kt b/js/js.tests/test/org/jetbrains/kotlin/generators/tests/GenerateIrRuntime.kt index a6e62a868e7..1e2a58764d3 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/generators/tests/GenerateIrRuntime.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/generators/tests/GenerateIrRuntime.kt @@ -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) } } \ No newline at end of file diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt index 6f9b8b589c1..e621f99d08d 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt @@ -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() +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) } } diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/JsTestChecker.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/JsTestChecker.kt index 92185a5db6d..884e1e7d16e 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/JsTestChecker.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/JsTestChecker.kt @@ -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) -} +} \ No newline at end of file