[JS IR IC] Do not read non modified JS into memory
Optimizaion: instead of reading all non modified JS files from the cache into the memory at once, the patch allows copying non-modified JS files from disk one by one during the compilation output writing routine.
This commit is contained in:
committed by
Space Team
parent
dd268d67ff
commit
75931fb9c8
@@ -77,6 +77,7 @@ import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerIr
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.JsCodeGenerator
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.TranslationMode
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.CompilationOutputsBuilt
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImplForJsIC
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
@@ -155,7 +156,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
||||
return transformer.makeJsCodeGenerator(ir.allModules, mode)
|
||||
}
|
||||
|
||||
fun compileAndTransformIrNew(): CompilationOutputs {
|
||||
fun compileAndTransformIrNew(): CompilationOutputsBuilt {
|
||||
return makeJsCodeGenerator().generateJsCode(relativeRequirePath = true, outJsProgram = false)
|
||||
}
|
||||
}
|
||||
@@ -317,7 +318,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
||||
)
|
||||
|
||||
val (outputs, rebuiltModules) = jsExecutableProducer.buildExecutable(arguments.irPerModule, outJsProgram = false)
|
||||
outputs.write(outputDir, outputName, arguments.generateDts, moduleName, moduleKind)
|
||||
outputs.writeAll(outputDir, outputName, arguments.generateDts, moduleName, moduleKind)
|
||||
|
||||
messageCollector.report(INFO, "Executable production duration (IC): ${System.currentTimeMillis() - beforeIc2Js}ms")
|
||||
for ((event, duration) in jsExecutableProducer.getStopwatchLaps()) {
|
||||
@@ -393,7 +394,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
||||
|
||||
messageCollector.report(INFO, "Executable production duration: ${System.currentTimeMillis() - start}ms")
|
||||
|
||||
outputs.write(outputDir, outputName, arguments.generateDts, moduleName, moduleKind)
|
||||
outputs.writeAll(outputDir, outputName, arguments.generateDts, moduleName, moduleKind)
|
||||
} catch (e: CompilationException) {
|
||||
messageCollector.report(
|
||||
ERROR,
|
||||
@@ -704,28 +705,6 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
||||
return icCaches
|
||||
}
|
||||
|
||||
private fun CompilationOutputs.write(outputDir: File, outputName: String, genDTS: Boolean, moduleName: String, moduleKind: ModuleKind) {
|
||||
val outputFile = outputDir.resolve("$outputName.js")
|
||||
outputFile.parentFile.mkdirs()
|
||||
outputFile.write(this)
|
||||
dependencies.forEach { (name, content) ->
|
||||
outputDir.resolve("$name.js").let {
|
||||
it.parentFile.mkdirs()
|
||||
it.write(content)
|
||||
}
|
||||
}
|
||||
|
||||
if (genDTS) {
|
||||
val dtsFile = outputDir.resolve("$outputName.d.ts")
|
||||
dtsFile.writeText(getFullTsDefinition(moduleName, moduleKind))
|
||||
}
|
||||
}
|
||||
|
||||
private fun File.write(outputs: CompilationOutputs) {
|
||||
writeText(outputs.jsCode)
|
||||
outputs.writeSourceMapIfPresent(this)
|
||||
}
|
||||
|
||||
override fun setupPlatformSpecificArgumentsAndServices(
|
||||
configuration: CompilerConfiguration,
|
||||
arguments: K2JSCompilerArguments,
|
||||
|
||||
@@ -11,46 +11,24 @@ import org.jetbrains.kotlin.backend.common.serialization.linkerissues.checkNoUnb
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity
|
||||
import org.jetbrains.kotlin.ir.backend.js.export.TypeScriptFragment
|
||||
import org.jetbrains.kotlin.ir.backend.js.export.toTypeScript
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.collectNativeImplementations
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.generateJsTests
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.moveBodilessDeclarationsToSeparatePlace
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.CompilationOutputs
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.TranslationMode
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFactory
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsProgram
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
import org.jetbrains.kotlin.js.config.RuntimeDiagnostic
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.serialization.js.ModuleKind
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
|
||||
import java.io.File
|
||||
|
||||
class CompilerResult(
|
||||
val outputs: Map<TranslationMode, CompilationOutputs>,
|
||||
)
|
||||
|
||||
class CompilationOutputs(
|
||||
val jsCode: String,
|
||||
val tsDefinitions: TypeScriptFragment? = null,
|
||||
val jsProgram: JsProgram? = null,
|
||||
val sourceMap: String? = null,
|
||||
val dependencies: Iterable<Pair<String, CompilationOutputs>> = emptyList()
|
||||
) {
|
||||
fun addDependencies(depends: Iterable<Pair<String, CompilationOutputs>>): CompilationOutputs {
|
||||
return CompilationOutputs(jsCode, tsDefinitions, jsProgram, sourceMap, depends)
|
||||
}
|
||||
|
||||
fun getFullTsDefinition(name: String, moduleKind: ModuleKind): String {
|
||||
val allTsDefinitions = dependencies.mapNotNull { it.second.tsDefinitions } + listOfNotNull(tsDefinitions)
|
||||
return allTsDefinitions.toTypeScript(name, moduleKind)
|
||||
}
|
||||
}
|
||||
|
||||
class LoweredIr(
|
||||
val context: JsIrBackendContext,
|
||||
val mainModule: IrModuleFragment,
|
||||
@@ -163,11 +141,3 @@ fun compileIr(
|
||||
|
||||
return LoweredIr(context, moduleFragment, allModules, moduleToName)
|
||||
}
|
||||
|
||||
fun CompilationOutputs.writeSourceMapIfPresent(outputJsFile: File) {
|
||||
sourceMap?.let {
|
||||
val mapFile = outputJsFile.resolveSibling("${outputJsFile.name}.map")
|
||||
outputJsFile.appendText("\n//# sourceMappingURL=${mapFile.name}\n")
|
||||
mapFile.writeText(it)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-4
@@ -5,7 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.backend.js.ic
|
||||
|
||||
import org.jetbrains.kotlin.ir.backend.js.CompilationOutputs
|
||||
import org.jetbrains.kotlin.ir.backend.js.SourceMapsInfo
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.*
|
||||
import org.jetbrains.kotlin.serialization.js.ModuleKind
|
||||
@@ -96,11 +95,10 @@ class JsExecutableProducer(
|
||||
val mainModule = cachedMainModule.compileModule(mainModuleName, true)
|
||||
|
||||
val cachedOtherModules = cachedProgram.dropLast(1)
|
||||
val dependencies = cachedOtherModules.map {
|
||||
mainModule.dependencies = cachedOtherModules.map {
|
||||
it.jsIrHeader.externalModuleName to it.compileModule(it.jsIrHeader.externalModuleName, false)
|
||||
}
|
||||
stopwatch.stop()
|
||||
val compilationOut = mainModule.addDependencies(dependencies)
|
||||
return BuildResult(compilationOut, rebuildModules)
|
||||
return BuildResult(mainModule, rebuildModules)
|
||||
}
|
||||
}
|
||||
|
||||
+12
-13
@@ -5,10 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.backend.js.ic
|
||||
|
||||
import org.jetbrains.kotlin.ir.backend.js.CompilationOutputs
|
||||
import org.jetbrains.kotlin.ir.backend.js.export.TypeScriptFragment
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.CrossModuleReferences
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.JsIrModuleHeader
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.*
|
||||
import java.io.File
|
||||
|
||||
class JsMultiModuleCache(private val moduleArtifacts: List<ModuleArtifact>) {
|
||||
@@ -99,17 +96,19 @@ class JsMultiModuleCache(private val moduleArtifacts: List<ModuleArtifact>) {
|
||||
}
|
||||
|
||||
fun fetchCompiledJsCode(artifact: ModuleArtifact) = artifact.artifactsDir?.let { cacheDir ->
|
||||
val jsCode = File(cacheDir, CACHED_MODULE_JS).ifExists { readText() }
|
||||
val sourceMap = File(cacheDir, CACHED_MODULE_JS_MAP).ifExists { readText() }
|
||||
val tsDefinitions = File(cacheDir, CACHED_MODULE_D_TS).ifExists { TypeScriptFragment(readText()) }
|
||||
jsCode?.let { CompilationOutputs(it, tsDefinitions, null, sourceMap) }
|
||||
val jsCodeFilePath = File(cacheDir, CACHED_MODULE_JS).ifExists { absolutePath }
|
||||
val sourceMapFilePath = File(cacheDir, CACHED_MODULE_JS_MAP).ifExists { absolutePath }
|
||||
val tsDefinitionsFilePath = File(cacheDir, CACHED_MODULE_D_TS).ifExists { absolutePath }
|
||||
jsCodeFilePath?.let { CompilationOutputsCached(it, sourceMapFilePath, tsDefinitionsFilePath) }
|
||||
}
|
||||
|
||||
fun commitCompiledJsCode(artifact: ModuleArtifact, compilationOutputs: CompilationOutputs) = artifact.artifactsDir?.let { cacheDir ->
|
||||
File(cacheDir, CACHED_MODULE_JS).writeIfNotNull(compilationOutputs.jsCode)
|
||||
File(cacheDir, CACHED_MODULE_JS_MAP).writeIfNotNull(compilationOutputs.sourceMap)
|
||||
File(cacheDir, CACHED_MODULE_D_TS).writeIfNotNull(compilationOutputs.tsDefinitions?.raw)
|
||||
}
|
||||
fun commitCompiledJsCode(artifact: ModuleArtifact, compilationOutputs: CompilationOutputsBuilt) =
|
||||
artifact.artifactsDir?.let { cacheDir ->
|
||||
val jsCodeFile = File(cacheDir, CACHED_MODULE_JS)
|
||||
val jsMapFile = File(cacheDir, CACHED_MODULE_JS_MAP)
|
||||
compilationOutputs.writeJsCode(jsCodeFile, jsMapFile)
|
||||
File(cacheDir, CACHED_MODULE_D_TS).writeIfNotNull(compilationOutputs.tsDefinitions?.raw)
|
||||
}
|
||||
|
||||
fun loadProgramHeadersFromCache(): List<CachedModuleInfo> {
|
||||
return moduleArtifacts.map { artifact ->
|
||||
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
||||
|
||||
import org.jetbrains.kotlin.ir.backend.js.export.TypeScriptFragment
|
||||
import org.jetbrains.kotlin.ir.backend.js.export.toTypeScript
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsProgram
|
||||
import org.jetbrains.kotlin.serialization.js.ModuleKind
|
||||
import java.io.File
|
||||
|
||||
abstract class CompilationOutputs {
|
||||
var dependencies: Collection<Pair<String, CompilationOutputs>> = emptyList()
|
||||
|
||||
abstract val tsDefinitions: TypeScriptFragment?
|
||||
|
||||
abstract val jsProgram: JsProgram?
|
||||
|
||||
abstract fun writeJsCode(outputJsFile: File, outputJsMapFile: File)
|
||||
|
||||
fun writeAll(outputDir: File, outputName: String, genDTS: Boolean, moduleName: String, moduleKind: ModuleKind): List<String> {
|
||||
val writtenJsFiles = ArrayList<String>(dependencies.size + 1)
|
||||
|
||||
val outputJsFile = outputDir.resolve("$outputName.js")
|
||||
|
||||
outputJsFile.parentFile.mkdirs()
|
||||
writeJsCode(outputJsFile, outputJsFile.mapForJsFile)
|
||||
|
||||
dependencies.forEach { (name, content) ->
|
||||
outputDir.resolve("$name.js").let { depJsFile ->
|
||||
depJsFile.parentFile.mkdirs()
|
||||
content.writeJsCode(depJsFile, depJsFile.mapForJsFile)
|
||||
writtenJsFiles += depJsFile.absolutePath
|
||||
}
|
||||
}
|
||||
|
||||
writtenJsFiles += outputJsFile.absolutePath
|
||||
|
||||
if (genDTS) {
|
||||
outputJsFile.dtsForJsFile.writeText(getFullTsDefinition(moduleName, moduleKind))
|
||||
}
|
||||
|
||||
return writtenJsFiles
|
||||
}
|
||||
|
||||
fun getFullTsDefinition(moduleName: String, moduleKind: ModuleKind): String {
|
||||
val allTsDefinitions = dependencies.mapNotNull { it.second.tsDefinitions } + listOfNotNull(tsDefinitions)
|
||||
return allTsDefinitions.toTypeScript(moduleName, moduleKind)
|
||||
}
|
||||
|
||||
private val File.mapForJsFile
|
||||
get() = resolveSibling("$name.map")
|
||||
|
||||
private val File.dtsForJsFile
|
||||
get() = resolveSibling("$nameWithoutExtension.d.ts")
|
||||
}
|
||||
|
||||
class CompilationOutputsBuilt(
|
||||
private val rawJsCode: String,
|
||||
private val sourceMap: String?,
|
||||
override val tsDefinitions: TypeScriptFragment?,
|
||||
override val jsProgram: JsProgram?,
|
||||
) : CompilationOutputs() {
|
||||
override fun writeJsCode(outputJsFile: File, outputJsMapFile: File) {
|
||||
var jsCodeWithSourceMap = rawJsCode
|
||||
|
||||
sourceMap?.let {
|
||||
outputJsMapFile.writeText(it)
|
||||
jsCodeWithSourceMap = "$jsCodeWithSourceMap\n//# sourceMappingURL=${outputJsMapFile.name}\n"
|
||||
}
|
||||
outputJsFile.writeText(jsCodeWithSourceMap)
|
||||
}
|
||||
}
|
||||
|
||||
class CompilationOutputsCached(
|
||||
private val jsCodeFilePath: String,
|
||||
private val sourceMapFilePath: String?,
|
||||
private val tsDefinitionsFilePath: String?
|
||||
) : CompilationOutputs() {
|
||||
override val tsDefinitions: TypeScriptFragment?
|
||||
get() = tsDefinitionsFilePath?.let { TypeScriptFragment(File(it).readText()) }
|
||||
|
||||
override val jsProgram: JsProgram?
|
||||
get() = null
|
||||
|
||||
override fun writeJsCode(outputJsFile: File, outputJsMapFile: File) {
|
||||
File(jsCodeFilePath).copyTo(outputJsFile, true)
|
||||
|
||||
sourceMapFilePath?.let {
|
||||
File(it).copyTo(outputJsMapFile, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-8
@@ -81,7 +81,7 @@ class JsCodeGenerator(
|
||||
private val moduleKind: ModuleKind,
|
||||
private val sourceMapsInfo: SourceMapsInfo?
|
||||
) {
|
||||
fun generateJsCode(relativeRequirePath: Boolean, outJsProgram: Boolean): CompilationOutputs {
|
||||
fun generateJsCode(relativeRequirePath: Boolean, outJsProgram: Boolean): CompilationOutputsBuilt {
|
||||
return generateWrappedModuleBody(
|
||||
multiModule,
|
||||
mainModuleName,
|
||||
@@ -380,7 +380,7 @@ private fun generateWrappedModuleBody(
|
||||
sourceMapsInfo: SourceMapsInfo?,
|
||||
relativeRequirePath: Boolean,
|
||||
outJsProgram: Boolean
|
||||
): CompilationOutputs {
|
||||
): CompilationOutputsBuilt {
|
||||
if (multiModule) {
|
||||
// mutable container allows explicitly remove elements from itself,
|
||||
// so we are able to help GC to free heavy JsIrModule objects
|
||||
@@ -398,7 +398,7 @@ private fun generateWrappedModuleBody(
|
||||
)
|
||||
}
|
||||
|
||||
val dependencies = buildList(moduleToRef.size) {
|
||||
mainModule.dependencies = buildList(moduleToRef.size) {
|
||||
while (moduleToRef.isNotEmpty()) {
|
||||
moduleToRef.removeFirst().let { (module, moduleRef) ->
|
||||
val moduleName = module.externalModuleName
|
||||
@@ -416,7 +416,7 @@ private fun generateWrappedModuleBody(
|
||||
}
|
||||
}
|
||||
|
||||
return mainModule.addDependencies(dependencies)
|
||||
return mainModule
|
||||
} else {
|
||||
return generateSingleWrappedModuleBody(
|
||||
mainModuleName,
|
||||
@@ -437,7 +437,7 @@ fun generateSingleWrappedModuleBody(
|
||||
generateCallToMain: Boolean,
|
||||
crossModuleReferences: CrossModuleReferences = CrossModuleReferences.Empty(moduleKind),
|
||||
outJsProgram: Boolean = true
|
||||
): CompilationOutputs {
|
||||
): CompilationOutputsBuilt {
|
||||
val program = Merger(
|
||||
moduleName,
|
||||
moduleKind,
|
||||
@@ -476,10 +476,10 @@ fun generateSingleWrappedModuleBody(
|
||||
|
||||
program.accept(JsToStringGenerationVisitor(jsCode, sourceMapBuilderConsumer))
|
||||
|
||||
return CompilationOutputs(
|
||||
return CompilationOutputsBuilt(
|
||||
jsCode.toString(),
|
||||
sourceMapBuilder?.build(),
|
||||
fragments.mapNotNull { it.dts }.ifNotEmpty { joinTypeScriptFragments() },
|
||||
program.takeIf { outJsProgram },
|
||||
sourceMapBuilder?.build()
|
||||
program.takeIf { outJsProgram }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.ir.backend.js.*
|
||||
import org.jetbrains.kotlin.ir.backend.js.ic.*
|
||||
import org.jetbrains.kotlin.ir.backend.js.SourceMapsInfo
|
||||
import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.CompilationOutputs
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.safeModuleName
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImplForJsIC
|
||||
@@ -225,16 +226,6 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
||||
writeText(ClassicJsBackendFacade.wrapWithModuleEmulationMarkers(jsCode, JS_MODULE_KIND, moduleName))
|
||||
}
|
||||
|
||||
private fun writeJsFile(name: String, text: String): String {
|
||||
val moduleFileName = "./$name.js"
|
||||
val file = File(jsDir, moduleFileName)
|
||||
if (file.exists()) {
|
||||
file.delete()
|
||||
}
|
||||
file.writeAsJsModule(text, moduleFileName)
|
||||
return file.canonicalPath
|
||||
}
|
||||
|
||||
private fun prepareExternalJsFiles(): MutableList<String> {
|
||||
jsDir.invalidateDir()
|
||||
return testDir.filesInDir.mapNotNullTo(mutableListOf(MODULE_EMULATION_FILE)) { file ->
|
||||
@@ -249,12 +240,15 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
||||
|
||||
private fun verifyJsCode(stepId: Int, mainModuleName: String, jsOutput: CompilationOutputs) {
|
||||
val files = prepareExternalJsFiles()
|
||||
jsOutput.dependencies.mapTo(files) { writeJsFile(it.first, it.second.jsCode) }
|
||||
files += writeJsFile(mainModuleName, jsOutput.jsCode)
|
||||
val compiledJsFiles = jsOutput.writeAll(jsDir, mainModuleName, true, mainModuleName, JS_MODULE_KIND)
|
||||
for (jsCodeFile in compiledJsFiles) {
|
||||
val jsFile = File(jsCodeFile)
|
||||
jsFile.writeAsJsModule(jsFile.readText(), "./${jsFile.name}")
|
||||
}
|
||||
|
||||
try {
|
||||
V8IrJsTestChecker.checkWithTestFunctionArgs(
|
||||
files = files,
|
||||
files = files + compiledJsFiles,
|
||||
testModuleName = "./$mainModuleName.js",
|
||||
testPackageName = null,
|
||||
testFunctionName = BOX_FUNCTION_NAME,
|
||||
@@ -269,11 +263,16 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun verifyDTS(stepId: Int, testInfo: List<TestStepInfo>, jsOutput: CompilationOutputs) {
|
||||
private fun verifyDTS(stepId: Int, testInfo: List<TestStepInfo>) {
|
||||
for (info in testInfo) {
|
||||
val expectedDTS = info.expectedDTS ?: continue
|
||||
val output = jsOutput.dependencies.find { it.first == info.moduleName }?.second ?: jsOutput
|
||||
val gotDTS = output.getFullTsDefinition(info.moduleName, JS_MODULE_KIND)
|
||||
|
||||
val dtsFile = jsDir.resolve("${File(info.modulePath).nameWithoutExtension}.d.ts")
|
||||
JUnit4Assertions.assertTrue(dtsFile.exists()) {
|
||||
"Cannot find d.ts (${dtsFile.absolutePath}) file for module ${info.moduleName} at step $stepId"
|
||||
}
|
||||
|
||||
val gotDTS = dtsFile.readText()
|
||||
JUnit4Assertions.assertEquals(expectedDTS, gotDTS) {
|
||||
"Mismatched d.ts for module ${info.moduleName} at step $stepId"
|
||||
}
|
||||
@@ -320,7 +319,7 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
||||
val (jsOutput, rebuiltModules) = jsExecutableProducer.buildExecutable(multiModule = true, outJsProgram = true)
|
||||
verifyJsExecutableProducerBuildModules(projStep.id, rebuiltModules, projStep.dirtyJS)
|
||||
verifyJsCode(projStep.id, mainModuleName, jsOutput)
|
||||
verifyDTS(projStep.id, testInfo, jsOutput)
|
||||
verifyDTS(projStep.id, testInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.ir.backend.js.ic.JsExecutableProducer
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerDesc
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer
|
||||
import org.jetbrains.kotlin.ir.backend.js.SourceMapsInfo
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.CompilationOutputs
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.TranslationMode
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImplForJsIC
|
||||
@@ -36,6 +37,7 @@ import org.jetbrains.kotlin.test.frontend.classic.moduleDescriptorProvider
|
||||
import org.jetbrains.kotlin.test.model.*
|
||||
import org.jetbrains.kotlin.test.services.*
|
||||
import org.jetbrains.kotlin.test.services.configuration.JsEnvironmentConfigurator
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.ifTrue
|
||||
import org.jetbrains.kotlin.utils.fileUtils.withReplacedExtensionOrNull
|
||||
import java.io.File
|
||||
|
||||
@@ -256,17 +258,28 @@ class JsIrBackendFacade(
|
||||
return this
|
||||
}
|
||||
|
||||
fun File.fixJsFile(newJsTarget: File, moduleId: String, moduleKind: ModuleKind) {
|
||||
val newJsCode = ClassicJsBackendFacade.wrapWithModuleEmulationMarkers(readText(), moduleKind, moduleId)
|
||||
|
||||
val oldJsMap = File("$absolutePath.map")
|
||||
val jsCodeMap = (moduleKind == ModuleKind.PLAIN && oldJsMap.exists()).ifTrue { oldJsMap.readText() }
|
||||
|
||||
this.delete()
|
||||
oldJsMap.delete()
|
||||
|
||||
newJsTarget.write(newJsCode)
|
||||
jsCodeMap?.let { File("${newJsTarget.absolutePath}.map").write(it) }
|
||||
}
|
||||
|
||||
private fun CompilationOutputs.writeTo(outputFile: File, moduleId: String, moduleKind: ModuleKind) {
|
||||
val wrappedCode = ClassicJsBackendFacade.wrapWithModuleEmulationMarkers(jsCode, moduleId = moduleId, moduleKind = moduleKind)
|
||||
outputFile.write(wrappedCode)
|
||||
val allJsFiles = writeAll(outputFile.parentFile, outputFile.nameWithoutExtension, false, moduleId, moduleKind)
|
||||
|
||||
if (moduleKind == ModuleKind.PLAIN) {
|
||||
writeSourceMapIfPresent(outputFile)
|
||||
}
|
||||
val mainModuleFile = File(allJsFiles.last())
|
||||
mainModuleFile.fixJsFile(outputFile, moduleId, moduleKind)
|
||||
|
||||
dependencies.forEach { (moduleId, outputs) ->
|
||||
val moduleWrappedCode = ClassicJsBackendFacade.wrapWithModuleEmulationMarkers(outputs.jsCode, moduleKind, moduleId)
|
||||
outputFile.augmentWithModuleName(moduleId).write(moduleWrappedCode)
|
||||
dependencies.map { it.first }.zip(allJsFiles.dropLast(1)).forEach { (depModuleId, builtJsFilePath) ->
|
||||
val newFile = outputFile.augmentWithModuleName(depModuleId)
|
||||
File(builtJsFilePath).fixJsFile(newFile, depModuleId, moduleKind)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.js.test.handlers
|
||||
|
||||
import org.jetbrains.kotlin.ir.backend.js.CompilationOutputs
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.CompilationOutputs
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.TranslationMode
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.safeModuleName
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsProgram
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.ir.backend.js.*
|
||||
import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity
|
||||
import org.jetbrains.kotlin.ir.backend.js.ic.CacheUpdater
|
||||
import org.jetbrains.kotlin.ir.backend.js.ic.JsExecutableProducer
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.CompilationOutputs
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.TranslationMode
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
||||
@@ -168,19 +169,10 @@ abstract class AbstractJsKLibABITestCase : KtUsefulTestCase() {
|
||||
buildBinaryNoIC(configuration, mainModuleKlibFile, allDependencies)
|
||||
|
||||
val binariesDir = File(buildDir, BIN_DIR_NAME).also { it.mkdirs() }
|
||||
val binaries = ArrayList<File>(allDependencies.regularDependencies.size)
|
||||
|
||||
for ((name, code) in compilationOutputs.dependencies) {
|
||||
val depBinary = binariesDir.binJsFile(name)
|
||||
depBinary.parentFile?.let { if (!it.exists()) it.mkdirs() }
|
||||
depBinary.writeText(code.jsCode)
|
||||
binaries.add(depBinary)
|
||||
val binaries = compilationOutputs.writeAll(binariesDir, MAIN_MODULE_NAME, false, MAIN_MODULE_NAME, ModuleKind.PLAIN).map {
|
||||
File(it)
|
||||
}
|
||||
|
||||
val mainBinary = binariesDir.binJsFile(MAIN_MODULE_NAME)
|
||||
mainBinary.writeText(compilationOutputs.jsCode)
|
||||
binaries.add(mainBinary)
|
||||
|
||||
executeAndCheckBinaries(MAIN_MODULE_NAME, binaries)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user