[JS IR BE] Support compilation and tests against klib

This commit is contained in:
Roman Artemev
2019-02-19 22:16:36 +03:00
committed by romanart
parent b99377fd69
commit 079f2534c7
15 changed files with 290 additions and 410 deletions
@@ -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())
}
}
@@ -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
@@ -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") }
}
}
@@ -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)
@@ -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",
@@ -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)
}
@@ -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(
@@ -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())
}
}
@@ -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)
}
}