[JS TESTS] Drop old basic tests
This commit is contained in:
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.test.Directives
|
||||
import org.jetbrains.kotlin.test.KotlinBaseTest
|
||||
import org.jetbrains.kotlin.test.KotlinTestWithEnvironment
|
||||
import org.jetbrains.kotlin.test.TestFiles
|
||||
import org.jetbrains.kotlin.test.services.ModuleStructureExtractor
|
||||
import org.jetbrains.kotlin.test.util.KtTestUtil
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
import java.io.ByteArrayOutputStream
|
||||
@@ -140,7 +141,7 @@ abstract class AbstractJsLineNumberTest : KotlinTestWithEnvironment() {
|
||||
|
||||
private inner class TestFileFactoryImpl : TestFiles.TestFileFactory<TestModule, TestFile>, Closeable {
|
||||
private val tmpDir = KtTestUtil.tmpDir("js-tests")
|
||||
private val defaultModule = TestModule(BasicBoxTest.TEST_MODULE, emptyList(), emptyList())
|
||||
private val defaultModule = TestModule(ModuleStructureExtractor.DEFAULT_MODULE_NAME, emptyList(), emptyList())
|
||||
|
||||
override fun createFile(module: TestModule?, fileName: String, text: String, directives: Directives): TestFile? {
|
||||
val currentModule = module ?: defaultModule
|
||||
@@ -177,7 +178,7 @@ abstract class AbstractJsLineNumberTest : KotlinTestWithEnvironment() {
|
||||
companion object {
|
||||
private val DIR_NAME = "lineNumbers"
|
||||
private val LINES_PATTERN = Regex("^ *// *LINES: *(.*)$", RegexOption.MULTILINE)
|
||||
private val BASE_PATH = "${BasicBoxTest.TEST_DATA_DIR_PATH}/$DIR_NAME"
|
||||
private val OUT_PATH = "${BasicBoxTest.TEST_DATA_DIR_PATH}/out/$DIR_NAME"
|
||||
private val BASE_PATH = "${BasicWasmBoxTest.TEST_DATA_DIR_PATH}/$DIR_NAME"
|
||||
private val OUT_PATH = "${BasicWasmBoxTest.TEST_DATA_DIR_PATH}/out/$DIR_NAME"
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,672 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.js.test
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import org.jetbrains.kotlin.backend.common.phaser.AnyNamedPhase
|
||||
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
|
||||
import org.jetbrains.kotlin.backend.common.phaser.toPhaseMap
|
||||
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.ir.backend.js.*
|
||||
import org.jetbrains.kotlin.ir.backend.js.codegen.CompilerOutputSink
|
||||
import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity
|
||||
import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity.*
|
||||
import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationOptions
|
||||
import org.jetbrains.kotlin.ir.backend.js.codegen.generateEsModules
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer
|
||||
import org.jetbrains.kotlin.ir.backend.js.ic.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.persistent.PersistentIrFactory
|
||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||
import org.jetbrains.kotlin.js.config.ErrorTolerancePolicy
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
import org.jetbrains.kotlin.js.config.JsConfig
|
||||
import org.jetbrains.kotlin.js.config.RuntimeDiagnostic
|
||||
import org.jetbrains.kotlin.js.facade.MainCallParameters
|
||||
import org.jetbrains.kotlin.js.facade.TranslationUnit
|
||||
import org.jetbrains.kotlin.js.testNew.handlers.JsAstHandler
|
||||
import org.jetbrains.kotlin.konan.properties.propertyList
|
||||
import org.jetbrains.kotlin.library.KLIB_PROPERTY_DEPENDS
|
||||
import org.jetbrains.kotlin.library.KotlinAbiVersion
|
||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.parsing.parseBoolean
|
||||
import org.jetbrains.kotlin.test.TargetBackend
|
||||
import org.jetbrains.kotlin.util.DummyLogger
|
||||
import org.jetbrains.kotlin.utils.fileUtils.withReplacedExtensionOrNull
|
||||
import org.junit.Assert
|
||||
import java.io.File
|
||||
import java.lang.Boolean.getBoolean
|
||||
|
||||
private val fullRuntimeKlib: String = System.getProperty("kotlin.js.full.stdlib.path")
|
||||
private val defaultRuntimeKlib = System.getProperty("kotlin.js.reduced.stdlib.path")
|
||||
private val kotlinTestKLib = System.getProperty("kotlin.js.kotlin.test.path")
|
||||
|
||||
// TODO Cache on FS (requires bootstrap)
|
||||
private val predefinedKlibHasIcCache = mutableMapOf<String, TestModuleCache?>(
|
||||
File(fullRuntimeKlib).absolutePath to null,
|
||||
File(kotlinTestKLib).absolutePath to null,
|
||||
File(defaultRuntimeKlib).absolutePath to null
|
||||
)
|
||||
|
||||
class TestModuleCache(val moduleName: String, val files: MutableMap<String, FileCache>) {
|
||||
|
||||
constructor(moduleName: String) : this(moduleName, mutableMapOf())
|
||||
|
||||
fun cacheProvider(): PersistentCacheProvider {
|
||||
return object : PersistentCacheProvider {
|
||||
override fun fileFingerPrint(path: String): Hash {
|
||||
return 0L
|
||||
}
|
||||
|
||||
override fun serializedParts(path: String): SerializedIcDataForFile {
|
||||
error("Is not supported")
|
||||
}
|
||||
|
||||
override fun inlineGraphForFile(path: String, sigResolver: (Int) -> IdSignature): Collection<Pair<IdSignature, TransHash>> {
|
||||
error("Is not supported")
|
||||
}
|
||||
|
||||
override fun inlineHashes(path: String, sigResolver: (Int) -> IdSignature): Map<IdSignature, TransHash> {
|
||||
error("Is not supported")
|
||||
}
|
||||
|
||||
override fun allInlineHashes(sigResolver: (String, Int) -> IdSignature): Map<IdSignature, TransHash> {
|
||||
error("Is not supported")
|
||||
}
|
||||
|
||||
override fun binaryAst(path: String): ByteArray? {
|
||||
return files[path]?.ast ?: ByteArray(0)
|
||||
}
|
||||
|
||||
override fun dts(path: String): ByteArray? {
|
||||
return files[path]?.dts
|
||||
}
|
||||
|
||||
override fun sourceMap(path: String): ByteArray? {
|
||||
return files[path]?.sourceMap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun cacheConsumer(): PersistentCacheConsumer {
|
||||
return object : PersistentCacheConsumer {
|
||||
override fun commitInlineFunctions(
|
||||
path: String,
|
||||
hashes: Collection<Pair<IdSignature, TransHash>>,
|
||||
sigResolver: (IdSignature) -> Int
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
override fun commitFileFingerPrint(path: String, fingerprint: Hash) {
|
||||
|
||||
}
|
||||
|
||||
override fun commitInlineGraph(
|
||||
path: String,
|
||||
hashes: Collection<Pair<IdSignature, TransHash>>,
|
||||
sigResolver: (IdSignature) -> Int
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
override fun commitICCacheData(path: String, icData: SerializedIcDataForFile) {
|
||||
|
||||
}
|
||||
|
||||
override fun commitBinaryAst(path: String, astData: ByteArray) {
|
||||
val storage = files.getOrPut(path) { FileCache(path, null, null, null) }
|
||||
storage.ast = astData
|
||||
}
|
||||
|
||||
override fun commitBinaryDts(path: String, dstData: ByteArray) {
|
||||
val storage = files.getOrPut(path) { FileCache(path, null, null, null) }
|
||||
storage.dts = dstData
|
||||
}
|
||||
|
||||
override fun commitSourceMap(path: String, mapData: ByteArray) {
|
||||
val storage = files.getOrPut(path) { FileCache(path, null, null, null) }
|
||||
storage.sourceMap = mapData
|
||||
}
|
||||
|
||||
override fun invalidateForFile(path: String) {
|
||||
files.remove(path)
|
||||
}
|
||||
|
||||
override fun commitLibraryPath(libraryPath: String) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun createModuleCache(): ModuleCache = ModuleCache(moduleName, files)
|
||||
}
|
||||
|
||||
abstract class BasicIrBoxTest(
|
||||
pathToTestDir: String,
|
||||
testGroupOutputDirPrefix: String,
|
||||
generateSourceMap: Boolean = false,
|
||||
generateNodeJsRunner: Boolean = false,
|
||||
targetBackend: TargetBackend = TargetBackend.JS_IR
|
||||
) : BasicBoxTest(
|
||||
pathToTestDir,
|
||||
testGroupOutputDirPrefix,
|
||||
typedArraysEnabled = true,
|
||||
generateSourceMap = generateSourceMap,
|
||||
generateNodeJsRunner = generateNodeJsRunner,
|
||||
targetBackend = targetBackend
|
||||
) {
|
||||
open val generateDts = false
|
||||
|
||||
override val skipMinification = true
|
||||
|
||||
private fun getBoolean(s: String, default: Boolean) = System.getProperty(s)?.let { parseBoolean(it) } ?: default
|
||||
|
||||
private val runIcMode: Boolean = getBoolean("kotlin.js.ir.icMode")
|
||||
|
||||
private val lowerPerModule: Boolean = runIcMode || getBoolean("kotlin.js.ir.lowerPerModule")
|
||||
|
||||
private val klibMainModule: Boolean = getBoolean("kotlin.js.ir.klibMainModule")
|
||||
|
||||
override val skipRegularMode: Boolean = getBoolean("kotlin.js.ir.skipRegularMode")
|
||||
|
||||
override val runIrDce: Boolean = getBoolean("kotlin.js.ir.dce", true)
|
||||
|
||||
val perModule: Boolean = getBoolean("kotlin.js.ir.perModule")
|
||||
|
||||
// TODO Design incremental compilation for IR and add test support
|
||||
override val incrementalCompilationChecksEnabled = true
|
||||
|
||||
private val compilationCache = mutableMapOf<String, String>()
|
||||
|
||||
private val cachedDependencies = mutableMapOf<String, Collection<String>>()
|
||||
|
||||
override fun doTest(filePath: String, expectedResult: String, mainCallParameters: MainCallParameters) {
|
||||
compilationCache.clear()
|
||||
cachedDependencies.clear()
|
||||
super.doTest(filePath, expectedResult, mainCallParameters)
|
||||
}
|
||||
|
||||
override val testChecker get() = if (runTestInNashorn) NashornIrJsTestChecker else V8IrJsTestChecker
|
||||
|
||||
override fun translateFiles(
|
||||
units: List<TranslationUnit>,
|
||||
outputFile: File,
|
||||
dceOutputFile: File,
|
||||
config: JsConfig,
|
||||
outputPrefixFile: File?,
|
||||
outputPostfixFile: File?,
|
||||
mainCallParameters: MainCallParameters,
|
||||
incrementalData: IncrementalData,
|
||||
remap: Boolean,
|
||||
testPackage: String?,
|
||||
testFunction: String,
|
||||
needsFullIrRuntime: Boolean,
|
||||
isMainModule: Boolean,
|
||||
skipDceDriven: Boolean,
|
||||
esModules: Boolean,
|
||||
granularity: JsGenerationGranularity,
|
||||
propertyLazyInitialization: Boolean,
|
||||
safeExternalBoolean: Boolean,
|
||||
safeExternalBooleanDiagnostic: RuntimeDiagnostic?,
|
||||
skipMangleVerification: Boolean,
|
||||
abiVersion: KotlinAbiVersion,
|
||||
incrementalCompilation: Boolean,
|
||||
recompile: Boolean,
|
||||
icCache: MutableMap<String, TestModuleCache>,
|
||||
customTestModule: String?,
|
||||
) {
|
||||
val filesToCompile = units.mapNotNull { (it as? TranslationUnit.SourceFile)?.file }
|
||||
|
||||
val runtimeKlibs = if (needsFullIrRuntime) listOf(fullRuntimeKlib, kotlinTestKLib) else listOf(defaultRuntimeKlib)
|
||||
|
||||
val transitiveLibraries = config.configuration[JSConfigurationKeys.TRANSITIVE_LIBRARIES]!!.map { File(it).name }
|
||||
val friendsLibraries = (config.configuration[JSConfigurationKeys.FRIEND_PATHS] ?: emptyList()).map { File(it).name }
|
||||
|
||||
val allKlibPaths = (runtimeKlibs + transitiveLibraries.map {
|
||||
compilationCache[it] ?: error("Can't find compiled module for dependency $it")
|
||||
}).map { File(it).absolutePath }.toMutableList()
|
||||
|
||||
val friendPaths = friendsLibraries.map { compilationCache[it] ?: error("Can't find compiled module for friend dep $it") }.map {
|
||||
File(it).canonicalPath
|
||||
}
|
||||
|
||||
val klibPath = outputFile.canonicalPath.replace("_v5.js", "")
|
||||
|
||||
val actualOutputFile = outputFile.canonicalPath.let {
|
||||
if (!isMainModule) klibPath else it
|
||||
}
|
||||
|
||||
if (incrementalCompilationChecksEnabled && incrementalCompilation) {
|
||||
runtimeKlibs.forEach { createIcCache(it, null, runtimeKlibs, config, icCache) }
|
||||
}
|
||||
|
||||
if (!recompile) { // In case of incremental recompilation we only rebuild caches, not klib itself
|
||||
val module = prepareAnalyzedSourceModule(
|
||||
config.project,
|
||||
filesToCompile,
|
||||
config.configuration,
|
||||
allKlibPaths,
|
||||
friendPaths,
|
||||
AnalyzerWithCompilerReport(config.configuration),
|
||||
)
|
||||
generateKLib(
|
||||
module,
|
||||
irFactory = IrFactoryImpl,
|
||||
outputKlibPath = klibPath,
|
||||
nopack = true,
|
||||
jsOutputName = null,
|
||||
abiVersion = abiVersion
|
||||
)
|
||||
}
|
||||
|
||||
val klibCannonPath = File(klibPath).canonicalPath
|
||||
|
||||
if (incrementalCompilation) {
|
||||
icCache[klibCannonPath] =
|
||||
createIcCache(klibCannonPath, filesToCompile.map { it.virtualFilePath }, allKlibPaths + klibCannonPath, config, icCache)
|
||||
}
|
||||
|
||||
compilationCache[outputFile.name.replace(".js", ".meta.js")] = actualOutputFile
|
||||
|
||||
if (isMainModule) {
|
||||
logger.logFile("Output JS", outputFile)
|
||||
val mainArguments = mainCallParameters.run { if (shouldBeGenerated()) arguments() else null }
|
||||
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val granularity = if (perModule) PER_MODULE else granularity
|
||||
|
||||
if (!skipRegularMode) {
|
||||
val dirtyFilesToRecompile = if (recompile) {
|
||||
units.map { (it as TranslationUnit.SourceFile).file.virtualFilePath }.toSet()
|
||||
} else null
|
||||
|
||||
if (incrementalCompilation) {
|
||||
val jsOutputFile = if (recompile) File(outputFile.parentFile, outputFile.nameWithoutExtension + "-recompiled.js")
|
||||
else outputFile
|
||||
val compiledModule = generateJsFromAst(klibPath, icCache.map { it.key to it.value.createModuleCache() }.toMap())
|
||||
generateOldModuleSystems(compiledModule, jsOutputFile, dceOutputFile, config, units, dirtyFilesToRecompile)
|
||||
} else {
|
||||
val ir = compileToLoweredIr(
|
||||
config,
|
||||
outputFile,
|
||||
klibPath,
|
||||
allKlibPaths + klibCannonPath,
|
||||
friendPaths,
|
||||
testPackage,
|
||||
testFunction,
|
||||
propertyLazyInitialization = propertyLazyInitialization,
|
||||
skipMangleVerification = skipMangleVerification,
|
||||
safeExternalBoolean = safeExternalBoolean,
|
||||
safeExternalBooleanDiagnostic = safeExternalBooleanDiagnostic,
|
||||
dceDriven = false,
|
||||
granularity,
|
||||
dirtyFilesToRecompile
|
||||
)
|
||||
if (esModules) {
|
||||
generateEsModules(ir, outputFile.esModulesSubDir, granularity, config, customTestModule, mainArguments)
|
||||
if (runIrDce) {
|
||||
eliminateDeadDeclarations(ir.allModules, ir.context)
|
||||
generateEsModules(ir, dceOutputFile.esModulesSubDir, granularity, config, customTestModule, mainArguments)
|
||||
}
|
||||
} else {
|
||||
generateOldModuleSystems(
|
||||
ir.oldIr2Js(granularity, runIrDce, mainArguments),
|
||||
outputFile,
|
||||
dceOutputFile,
|
||||
config,
|
||||
units,
|
||||
dirtyFilesToRecompile
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun compileToLoweredIr(
|
||||
config: JsConfig,
|
||||
outputFile: File,
|
||||
klibPath: String,
|
||||
dependencies: List<String>,
|
||||
friendPaths: List<String>,
|
||||
testPackage: String?,
|
||||
testFunction: String,
|
||||
propertyLazyInitialization: Boolean,
|
||||
skipMangleVerification: Boolean,
|
||||
safeExternalBoolean: Boolean,
|
||||
safeExternalBooleanDiagnostic: RuntimeDiagnostic?,
|
||||
dceDriven: Boolean,
|
||||
granularity: JsGenerationGranularity,
|
||||
dirtyFilesToRecompile: Set<String>? = null
|
||||
): LoweredIr {
|
||||
|
||||
val debugMode = getBoolean("kotlin.js.debugMode")
|
||||
|
||||
val phaseConfig = if (debugMode) {
|
||||
val allPhasesSet = jsPhases.toPhaseMap().values.toSet()
|
||||
val dumpOutputDir = File(outputFile.parent, outputFile.nameWithoutExtension + "-irdump")
|
||||
logger.logFile("Dumping phasesTo", dumpOutputDir)
|
||||
PhaseConfig(
|
||||
jsPhases,
|
||||
dumpToDirectory = dumpOutputDir.path,
|
||||
toDumpStateAfter = fromSysPropertyOrAll("kotlin.js.test.phasesToDumpAfter", allPhasesSet),
|
||||
toValidateStateAfter = fromSysPropertyOrAll("kotlin.js.test.phasesToValidateAfter", allPhasesSet),
|
||||
dumpOnlyFqName = null
|
||||
)
|
||||
} else {
|
||||
PhaseConfig(jsPhases)
|
||||
}
|
||||
|
||||
val module = ModulesStructure(
|
||||
config.project,
|
||||
MainModule.Klib(klibPath),
|
||||
config.configuration,
|
||||
dependencies,
|
||||
friendPaths,
|
||||
icUseGlobalSignatures = runIcMode,
|
||||
icUseStdlibCache = runIcMode,
|
||||
icCache = emptyMap()
|
||||
)
|
||||
|
||||
return compile(
|
||||
module,
|
||||
phaseConfig = phaseConfig,
|
||||
irFactory = IrFactoryImpl,
|
||||
exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, testFunction))),
|
||||
dceDriven = dceDriven,
|
||||
propertyLazyInitialization = propertyLazyInitialization,
|
||||
verifySignatures = !skipMangleVerification,
|
||||
lowerPerModule = lowerPerModule,
|
||||
safeExternalBoolean = safeExternalBoolean,
|
||||
safeExternalBooleanDiagnostic = safeExternalBooleanDiagnostic,
|
||||
granularity = granularity,
|
||||
filesToLower = dirtyFilesToRecompile
|
||||
)
|
||||
}
|
||||
|
||||
private fun LoweredIr.oldIr2Js(
|
||||
granularity: JsGenerationGranularity,
|
||||
runDce: Boolean,
|
||||
mainArguments: List<String>?,
|
||||
): CompilerResult {
|
||||
check(granularity != PER_FILE) { "Per file granularity is not supported for old module systems" }
|
||||
val transformer = IrModuleToJsTransformer(
|
||||
context,
|
||||
mainArguments,
|
||||
fullJs = true,
|
||||
dceJs = runDce,
|
||||
multiModule = granularity == PER_MODULE,
|
||||
relativeRequirePath = false
|
||||
)
|
||||
|
||||
return transformer.generateModule(allModules)
|
||||
}
|
||||
|
||||
private fun generateOldModuleSystems(
|
||||
compiledModule: CompilerResult,
|
||||
outputFile: File,
|
||||
outputDceFile: File,
|
||||
config: JsConfig,
|
||||
units: List<TranslationUnit>,
|
||||
dirtyFilesToRecompile: Set<String>? = null
|
||||
) {
|
||||
outputFile.deleteRecursively()
|
||||
|
||||
val compiledOutput = compiledModule.outputs!!
|
||||
val compiledDCEOutput = if (dirtyFilesToRecompile != null) null else compiledModule.outputsAfterDce
|
||||
|
||||
compiledOutput.writeTo(outputFile, config)
|
||||
|
||||
compiledDCEOutput?.writeTo(outputDceFile, config)
|
||||
|
||||
if (generateDts) {
|
||||
val dtsFile = outputFile.withReplacedExtensionOrNull("_v5.js", ".d.ts")!!
|
||||
logger.logFile("Output d.ts", dtsFile)
|
||||
dtsFile.write(compiledModule.tsDefinitions ?: error("No ts definitions"))
|
||||
}
|
||||
|
||||
compiledOutput.jsProgram?.let {
|
||||
JsAstHandler.processUnitsOfJsProgram(it, units, targetBackend = TargetBackend.JS_IR) { Assert.fail(it) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateTestFile(outputDir: File, config: JsConfig, customTestModule: String?) {
|
||||
val moduleName = config.configuration[CommonConfigurationKeys.MODULE_NAME]
|
||||
val esmTestFile = File(outputDir, "test.mjs")
|
||||
logger.logFile("ES module test file", esmTestFile)
|
||||
val defaultTestModule =
|
||||
"""
|
||||
import { box } from './${moduleName}/index.js';
|
||||
let res = box();
|
||||
if (res !== "OK") {
|
||||
throw "Wrong result: " + String(res);
|
||||
}
|
||||
""".trimIndent()
|
||||
|
||||
esmTestFile.writeText(customTestModule ?: defaultTestModule)
|
||||
}
|
||||
|
||||
private fun generateEsModules(
|
||||
ir: LoweredIr,
|
||||
outputDir: File,
|
||||
granularity: JsGenerationGranularity,
|
||||
config: JsConfig,
|
||||
customTestModule: String?,
|
||||
mainArguments: List<String>?
|
||||
) {
|
||||
val options = JsGenerationOptions(generatePackageJson = true, generateTypeScriptDefinitions = generateDts)
|
||||
outputDir.deleteRecursively()
|
||||
generateEsModules(ir, jsOutputSink(outputDir), mainArguments = mainArguments, granularity = granularity, options = options)
|
||||
generateTestFile(outputDir, config, customTestModule)
|
||||
}
|
||||
|
||||
override fun checkIncrementalCompilation(
|
||||
sourceDirs: List<String>,
|
||||
module: TestModule,
|
||||
kotlinFiles: List<TestFile>,
|
||||
dependencies: List<String>,
|
||||
allDependencies: List<String>,
|
||||
friends: List<String>,
|
||||
multiModule: Boolean,
|
||||
tmpDir: File,
|
||||
remap: Boolean,
|
||||
outputFile: File,
|
||||
outputPrefixFile: File?,
|
||||
outputPostfixFile: File?,
|
||||
mainCallParameters: MainCallParameters,
|
||||
incrementalData: IncrementalData,
|
||||
testPackage: String?,
|
||||
testFunction: String,
|
||||
needsFullIrRuntime: Boolean,
|
||||
expectActualLinker: Boolean,
|
||||
icCaches: MutableMap<String, TestModuleCache>
|
||||
) {
|
||||
val isMainModule = module.name == DEFAULT_MODULE || module.name == TEST_MODULE
|
||||
val cacheKey = outputFile.canonicalPath.replace("_v5.js", "")
|
||||
|
||||
val icCache = icCaches[cacheKey] ?: error("No IC data found for module ${module.name}")
|
||||
|
||||
val dirtyFiles = mutableListOf<String>()
|
||||
val oldBinaryAsts = mutableMapOf<String, ByteArray>()
|
||||
|
||||
val dataProvider = icCache.cacheProvider()
|
||||
val dataConsumer = icCache.cacheConsumer()
|
||||
|
||||
for (testFile in kotlinFiles) {
|
||||
if (testFile.recompile) {
|
||||
val fileName = testFile.fileName
|
||||
oldBinaryAsts[fileName] = dataProvider.binaryAst(fileName) ?: error("No AST found for $fileName")
|
||||
dataConsumer.invalidateForFile(fileName)
|
||||
dirtyFiles.add(fileName)
|
||||
}
|
||||
}
|
||||
|
||||
val recompiledOutputFile = File(outputFile.parentFile, outputFile.nameWithoutExtension + "-recompiled.js")
|
||||
val recompiledMinOutputFile = File(recompiledOutputFile.parentFile, recompiledOutputFile.nameWithoutExtension + "-min.js")
|
||||
val recompiledConfig = createConfig(
|
||||
sourceDirs,
|
||||
module,
|
||||
dependencies,
|
||||
allDependencies,
|
||||
friends,
|
||||
multiModule,
|
||||
tmpDir,
|
||||
null,
|
||||
expectActualLinker,
|
||||
ErrorTolerancePolicy.DEFAULT
|
||||
)
|
||||
|
||||
translateFiles(
|
||||
dirtyFiles.map { TranslationUnit.SourceFile(createPsiFile(it)) },
|
||||
outputFile,
|
||||
recompiledMinOutputFile,
|
||||
recompiledConfig,
|
||||
outputPrefixFile,
|
||||
outputPostfixFile,
|
||||
mainCallParameters,
|
||||
incrementalData,
|
||||
remap,
|
||||
testPackage,
|
||||
testFunction,
|
||||
needsFullIrRuntime,
|
||||
isMainModule,
|
||||
skipDceDriven = true,
|
||||
granularity = WHOLE_PROGRAM, // TODO??
|
||||
propertyLazyInitialization = true,
|
||||
safeExternalBoolean = false,
|
||||
safeExternalBooleanDiagnostic = null,
|
||||
skipMangleVerification = false,
|
||||
abiVersion = KotlinAbiVersion.CURRENT,
|
||||
incrementalCompilation = true,
|
||||
recompile = true,
|
||||
icCache = icCaches,
|
||||
|
||||
// TODO??
|
||||
customTestModule = null,
|
||||
esModules = false,
|
||||
)
|
||||
|
||||
// TODO: enable asserts when binary stability is achieved
|
||||
// val cacheProvider = icCache.cacheProvider()
|
||||
// val newBinaryAsts = dirtyFiles.associateWith { cacheProvider.binaryAst(it) }
|
||||
//
|
||||
// for (file in dirtyFiles) {
|
||||
// val oldBinaryAst = oldBinaryAsts[file]
|
||||
// val newBinaryAst = newBinaryAsts[file]
|
||||
//
|
||||
// assert(oldBinaryAst.contentEquals(newBinaryAst)) { "Binary AST changed after recompilation for file $file" }
|
||||
// }
|
||||
//
|
||||
// if (isMainModule) {
|
||||
// val originalOutput = FileUtil.loadFile(outputFile)
|
||||
// val recompiledOutput = FileUtil.loadFile(recompiledOutputFile)
|
||||
// assertEquals("Output file changed after recompilation", originalOutput, recompiledOutput)
|
||||
// }
|
||||
}
|
||||
|
||||
private fun jsOutputSink(perFileOutputDir: File): CompilerOutputSink {
|
||||
perFileOutputDir.deleteRecursively()
|
||||
perFileOutputDir.mkdirs()
|
||||
|
||||
return object : CompilerOutputSink {
|
||||
override fun write(module: String, path: String, content: String) {
|
||||
val file = File(File(perFileOutputDir, module), path)
|
||||
file.parentFile.mkdirs()
|
||||
file.writeText(content)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createIcCache(
|
||||
path: String,
|
||||
dirtyFiles: Collection<String>?,
|
||||
allKlibPaths: Collection<String>,
|
||||
config: JsConfig,
|
||||
icCache: MutableMap<String, TestModuleCache>
|
||||
): TestModuleCache {
|
||||
|
||||
val cannonicalPath = File(path).canonicalPath
|
||||
var moduleCache = predefinedKlibHasIcCache[cannonicalPath]
|
||||
|
||||
if (moduleCache == null) {
|
||||
moduleCache = icCache[cannonicalPath] ?: TestModuleCache(cannonicalPath)
|
||||
|
||||
val allResolvedDependencies = jsResolveLibraries(allKlibPaths, emptyList(), DummyLogger)
|
||||
|
||||
val libs = allResolvedDependencies.getFullList().associateBy { File(it.libraryFile.path).canonicalPath }
|
||||
|
||||
val nameToKotlinLibrary: Map<ModuleName, KotlinLibrary> = libs.values.associateBy { it.moduleName }
|
||||
|
||||
val dependencyGraph = libs.values.associateWith {
|
||||
it.manifestProperties.propertyList(KLIB_PROPERTY_DEPENDS, escapeInQuotes = true).map { depName ->
|
||||
nameToKotlinLibrary[depName] ?: error("No Library found for $depName")
|
||||
}
|
||||
}
|
||||
|
||||
val currentLib = libs[File(cannonicalPath).canonicalPath] ?: error("Expected library at $cannonicalPath")
|
||||
|
||||
rebuildCacheForDirtyFiles(currentLib, config.configuration, dependencyGraph, dirtyFiles, moduleCache.cacheConsumer(), IrFactoryImpl)
|
||||
|
||||
if (cannonicalPath in predefinedKlibHasIcCache) {
|
||||
predefinedKlibHasIcCache[cannonicalPath] = moduleCache
|
||||
}
|
||||
}
|
||||
|
||||
icCache[cannonicalPath] = moduleCache
|
||||
|
||||
return moduleCache
|
||||
}
|
||||
|
||||
private fun fromSysPropertyOrAll(key: String, all: Set<AnyNamedPhase>): Set<AnyNamedPhase> {
|
||||
val phases = System.getProperty(key)?.split(',')?.toSet() ?: emptySet()
|
||||
if (phases.isEmpty()) return all
|
||||
|
||||
return all.filter { it.name in phases }.toSet()
|
||||
}
|
||||
|
||||
private fun CompilationOutputs.writeTo(outputFile: File, config: JsConfig) {
|
||||
val wrappedCode =
|
||||
wrapWithModuleEmulationMarkers(jsCode, moduleId = config.moduleId, moduleKind = config.moduleKind)
|
||||
outputFile.write(wrappedCode)
|
||||
|
||||
val dependencyPaths = mutableListOf<String>()
|
||||
|
||||
dependencies.forEach { (moduleId, outputs) ->
|
||||
val moduleWrappedCode = wrapWithModuleEmulationMarkers(outputs.jsCode, config.moduleKind, moduleId)
|
||||
val dependencyPath = outputFile.absolutePath.replace("_v5.js", "-${moduleId}_v5.js")
|
||||
dependencyPaths += dependencyPath
|
||||
File(dependencyPath).write(moduleWrappedCode)
|
||||
}
|
||||
|
||||
cachedDependencies[outputFile.absolutePath] = dependencyPaths
|
||||
}
|
||||
|
||||
override fun runGeneratedCode(
|
||||
jsFiles: List<String>,
|
||||
testModuleName: String?,
|
||||
testPackage: String?,
|
||||
testFunction: String,
|
||||
expectedResult: String,
|
||||
withModuleSystem: Boolean
|
||||
) {
|
||||
// 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
|
||||
|
||||
val allFiles = jsFiles.flatMap { file -> cachedDependencies[File(file).absolutePath]?.let { deps -> deps + file } ?: listOf(file) }
|
||||
testChecker.check(allFiles, testModuleName, testPackage, testFunction, expectedResult, withModuleSystem)
|
||||
}
|
||||
}
|
||||
|
||||
private fun File.write(text: String) {
|
||||
parentFile.mkdirs()
|
||||
writeText(text)
|
||||
}
|
||||
|
||||
val File.esModulesSubDir: File
|
||||
get() = File(absolutePath + "_esm")
|
||||
@@ -6,6 +6,9 @@
|
||||
package org.jetbrains.kotlin.js.test
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.vfs.StandardFileSystems
|
||||
import com.intellij.openapi.vfs.VirtualFileManager
|
||||
import com.intellij.psi.PsiManager
|
||||
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
|
||||
import org.jetbrains.kotlin.backend.common.phaser.toPhaseMap
|
||||
import org.jetbrains.kotlin.backend.wasm.WasmCompilerResult
|
||||
@@ -26,6 +29,7 @@ import org.jetbrains.kotlin.js.facade.TranslationUnit
|
||||
import org.jetbrains.kotlin.js.test.engines.ExternalTool
|
||||
import org.jetbrains.kotlin.js.test.engines.SpiderMonkeyEngine
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||
import org.jetbrains.kotlin.resolve.CompilerEnvironment
|
||||
@@ -288,6 +292,19 @@ abstract class BasicWasmBoxTest(
|
||||
override fun createEnvironment() =
|
||||
KotlinCoreEnvironment.createForTests(testRootDisposable, CompilerConfiguration(), EnvironmentConfigFiles.JS_CONFIG_FILES)
|
||||
|
||||
private fun KotlinTestWithEnvironment.createPsiFile(fileName: String): KtFile {
|
||||
val psiManager = PsiManager.getInstance(project)
|
||||
val fileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL)
|
||||
|
||||
val file = fileSystem.findFileByPath(fileName) ?: error("File not found: $fileName")
|
||||
|
||||
return psiManager.findFile(file) as KtFile
|
||||
}
|
||||
|
||||
private fun KotlinTestWithEnvironment.createPsiFiles(fileNames: List<String>): List<KtFile> {
|
||||
return fileNames.map { this@createPsiFiles.createPsiFile(it) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TEST_DATA_DIR_PATH = "js/js.translator/testData/"
|
||||
const val TEST_MODULE = "main"
|
||||
|
||||
@@ -12,6 +12,8 @@ import org.jetbrains.kotlin.js.engine.ScriptEngineV8
|
||||
import org.jetbrains.kotlin.js.engine.loadFiles
|
||||
import org.junit.Assert
|
||||
|
||||
private const val DIST_DIR_JS_PATH = "dist/js/"
|
||||
|
||||
fun createScriptEngine(): ScriptEngine {
|
||||
return if (java.lang.Boolean.getBoolean("kotlin.js.useNashorn")) ScriptEngineNashorn() else ScriptEngineV8()
|
||||
}
|
||||
@@ -27,7 +29,7 @@ fun ScriptEngine.runTestFunction(
|
||||
withModuleSystem: Boolean
|
||||
): String {
|
||||
var script = when {
|
||||
withModuleSystem -> BasicBoxTest.KOTLIN_TEST_INTERNAL + ".require('" + testModuleName!! + "')"
|
||||
withModuleSystem -> "\$kotlin_test_internal\$.require('" + testModuleName!! + "')"
|
||||
testModuleName === null -> "this"
|
||||
else -> testModuleName
|
||||
}
|
||||
@@ -140,9 +142,9 @@ object NashornJsTestChecker : AbstractNashornJsTestChecker() {
|
||||
}
|
||||
|
||||
override val preloadedScripts = listOf(
|
||||
BasicBoxTest.TEST_DATA_DIR_PATH + "nashorn-polyfills.js",
|
||||
BasicBoxTest.DIST_DIR_JS_PATH + "kotlin.js",
|
||||
BasicBoxTest.DIST_DIR_JS_PATH + "kotlin-test.js"
|
||||
BasicWasmBoxTest.TEST_DATA_DIR_PATH + "nashorn-polyfills.js",
|
||||
DIST_DIR_JS_PATH + "kotlin.js",
|
||||
DIST_DIR_JS_PATH + "kotlin-test.js"
|
||||
)
|
||||
|
||||
override fun createScriptEngineForTest(): ScriptEngineNashorn {
|
||||
@@ -156,7 +158,7 @@ object NashornJsTestChecker : AbstractNashornJsTestChecker() {
|
||||
|
||||
object NashornIrJsTestChecker : AbstractNashornJsTestChecker() {
|
||||
override val preloadedScripts = listOf(
|
||||
BasicBoxTest.TEST_DATA_DIR_PATH + "nashorn-polyfills.js",
|
||||
BasicWasmBoxTest.TEST_DATA_DIR_PATH + "nashorn-polyfills.js",
|
||||
"libraries/stdlib/js-v1/src/js/polyfills.js"
|
||||
)
|
||||
}
|
||||
@@ -166,8 +168,8 @@ object V8JsTestChecker : AbstractJsTestChecker() {
|
||||
override fun initialValue() =
|
||||
ScriptEngineV8().apply {
|
||||
val preloadedScripts = listOf(
|
||||
BasicBoxTest.DIST_DIR_JS_PATH + "kotlin.js",
|
||||
BasicBoxTest.DIST_DIR_JS_PATH + "kotlin-test.js"
|
||||
DIST_DIR_JS_PATH + "kotlin.js",
|
||||
DIST_DIR_JS_PATH + "kotlin-test.js"
|
||||
)
|
||||
loadFiles(preloadedScripts)
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.js.inline.clean.renameLabels
|
||||
import org.jetbrains.kotlin.js.inline.clean.resolveTemporaryNames
|
||||
import org.jetbrains.kotlin.js.parser.parse
|
||||
import org.jetbrains.kotlin.js.test.BasicBoxTest
|
||||
import org.jetbrains.kotlin.js.test.BasicWasmBoxTest
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.fail
|
||||
import org.junit.Rule
|
||||
@@ -50,7 +50,7 @@ class NameResolutionTest {
|
||||
|
||||
private fun doTest() {
|
||||
val methodName = testName.methodName
|
||||
val baseName = "${BasicBoxTest.TEST_DATA_DIR_PATH}/js-name-resolution/"
|
||||
val baseName = "${BasicWasmBoxTest.TEST_DATA_DIR_PATH}/js-name-resolution/"
|
||||
val originalName = "$baseName/$methodName.original.js"
|
||||
val expectedName = "$baseName/$methodName.expected.js"
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.synthetic
|
||||
import org.jetbrains.kotlin.js.inline.clean.FunctionPostProcessor
|
||||
import org.jetbrains.kotlin.js.parser.parse
|
||||
import org.jetbrains.kotlin.js.test.BasicBoxTest
|
||||
import org.jetbrains.kotlin.js.test.BasicWasmBoxTest
|
||||
import org.jetbrains.kotlin.js.test.createScriptEngine
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
import org.jetbrains.kotlin.js.util.TextOutputImpl
|
||||
@@ -29,7 +29,7 @@ abstract class BasicOptimizerTest(private var basePath: String) {
|
||||
|
||||
protected fun box() {
|
||||
val methodName = testName.methodName
|
||||
val baseName = "${BasicBoxTest.TEST_DATA_DIR_PATH}/js-optimizer/$basePath"
|
||||
val baseName = "${BasicWasmBoxTest.TEST_DATA_DIR_PATH}/js-optimizer/$basePath"
|
||||
val unoptimizedName = "$baseName/$methodName.original.js"
|
||||
val optimizedName = "$baseName/$methodName.optimized.js"
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ import org.jetbrains.kotlin.ir.util.IrMessageLogger
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.js.config.ErrorTolerancePolicy
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
import org.jetbrains.kotlin.js.test.esModulesSubDir
|
||||
import org.jetbrains.kotlin.js.testNew.handlers.JsBoxRunner.Companion.TEST_FUNCTION
|
||||
import org.jetbrains.kotlin.js.testNew.utils.esModulesSubDir
|
||||
import org.jetbrains.kotlin.js.testNew.utils.extractTestPackage
|
||||
import org.jetbrains.kotlin.js.testNew.utils.jsIrIncrementalDataProvider
|
||||
import org.jetbrains.kotlin.library.uniqueName
|
||||
|
||||
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.js.backend.ast.JsNullLiteral
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsProgram
|
||||
import org.jetbrains.kotlin.js.backend.ast.RecursiveJsVisitor
|
||||
import org.jetbrains.kotlin.js.facade.TranslationResult
|
||||
import org.jetbrains.kotlin.js.facade.TranslationUnit
|
||||
import org.jetbrains.kotlin.js.test.utils.DirectiveTestUtils
|
||||
import org.jetbrains.kotlin.test.TargetBackend
|
||||
import org.jetbrains.kotlin.test.backend.handlers.JsBinaryArtifactHandler
|
||||
@@ -30,36 +29,26 @@ class JsAstHandler(testServices: TestServices) : JsBinaryArtifactHandler(testSer
|
||||
is BinaryArtifacts.Js.JsIrArtifact -> artifact.compilerResult.outputs?.jsProgram ?: return
|
||||
else -> return
|
||||
}
|
||||
processJsProgram(jsProgram, ktFiles, module.targetBackend!!) {
|
||||
testServices.assertions.fail { it }
|
||||
processJsProgram(jsProgram, ktFiles, module.targetBackend!!)
|
||||
}
|
||||
|
||||
private fun processJsProgram(program: JsProgram, psiFiles: List<String>, targetBackend: TargetBackend) {
|
||||
// TODO: For now the IR backend generates JS code that doesn't pass verification,
|
||||
// TODO: so we temporarily disabled AST verification.
|
||||
if (targetBackend == TargetBackend.JS) {
|
||||
psiFiles.forEach { DirectiveTestUtils.processDirectives(program, it, targetBackend) }
|
||||
program.verifyAst()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun processUnitsOfJsProgram(
|
||||
program: JsProgram, units: List<TranslationUnit>, targetBackend: TargetBackend, onFail: (String) -> Unit
|
||||
) {
|
||||
processJsProgram(program, units.filterIsInstance<TranslationUnit.SourceFile>().map { it.file.text }, targetBackend, onFail)
|
||||
}
|
||||
|
||||
fun processJsProgram(program: JsProgram, psiFiles: List<String>, targetBackend: TargetBackend, onFail: (String) -> Unit) {
|
||||
// TODO: For now the IR backend generates JS code that doesn't pass verification,
|
||||
// TODO: so we temporarily disabled AST verification.
|
||||
if (targetBackend == TargetBackend.JS) {
|
||||
psiFiles.forEach { DirectiveTestUtils.processDirectives(program, it, targetBackend) }
|
||||
program.verifyAst(onFail)
|
||||
}
|
||||
}
|
||||
|
||||
private fun JsProgram.verifyAst(onFail: (String) -> Unit) {
|
||||
accept(object : RecursiveJsVisitor() {
|
||||
override fun visitExpressionStatement(x: JsExpressionStatement) {
|
||||
when (x.expression) {
|
||||
is JsNullLiteral -> onFail("Expression statement contains `null` literal")
|
||||
else -> super.visitExpressionStatement(x)
|
||||
}
|
||||
private fun JsProgram.verifyAst() {
|
||||
accept(object : RecursiveJsVisitor() {
|
||||
override fun visitExpressionStatement(x: JsExpressionStatement) {
|
||||
when (x.expression) {
|
||||
is JsNullLiteral -> testServices.assertions.fail { "Expression statement contains `null` literal" }
|
||||
else -> super.visitExpressionStatement(x)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.js.testNew.handlers
|
||||
|
||||
import org.jetbrains.kotlin.js.test.esModulesSubDir
|
||||
import org.jetbrains.kotlin.js.test.v8tool
|
||||
import org.jetbrains.kotlin.js.test.engines.ExternalTool
|
||||
import org.jetbrains.kotlin.js.testNew.utils.*
|
||||
import org.jetbrains.kotlin.test.directives.JsEnvironmentConfigurationDirectives
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
@@ -15,6 +14,8 @@ import org.jetbrains.kotlin.test.services.defaultsProvider
|
||||
import org.jetbrains.kotlin.test.services.moduleStructure
|
||||
import java.io.File
|
||||
|
||||
private val v8tool by lazy { ExternalTool(System.getProperty("javascript.engine.path.V8")) }
|
||||
|
||||
class JsBoxRunner(testServices: TestServices) : AbstractJsArtifactsCollector(testServices) {
|
||||
override fun processAfterAllModules(someAssertionWasFailed: Boolean) {
|
||||
if (someAssertionWasFailed) return
|
||||
|
||||
@@ -22,6 +22,10 @@ import org.jetbrains.kotlin.test.services.moduleStructure
|
||||
import java.io.File
|
||||
|
||||
class JsMinifierRunner(testServices: TestServices) : AbstractJsArtifactsCollector(testServices) {
|
||||
private val distDirJsPath = "dist/js/"
|
||||
private val overwriteReachableNodesProperty = "kotlin.js.overwriteReachableNodes"
|
||||
private val overwriteReachableNodes = java.lang.Boolean.getBoolean(overwriteReachableNodesProperty)
|
||||
|
||||
override fun processAfterAllModules(someAssertionWasFailed: Boolean) {
|
||||
if (someAssertionWasFailed) return
|
||||
|
||||
@@ -56,104 +60,96 @@ class JsMinifierRunner(testServices: TestServices) : AbstractJsArtifactsCollecto
|
||||
testPackage = testPackage,
|
||||
testFunction = testFunction,
|
||||
withModuleSystem = withModuleSystem
|
||||
) { expect, actual -> assertions.assertEquals(expect, actual) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val DIST_DIR_JS_PATH = "dist/js/"
|
||||
|
||||
private const val overwriteReachableNodesProperty = "kotlin.js.overwriteReachableNodes"
|
||||
private val overwriteReachableNodes = java.lang.Boolean.getBoolean(overwriteReachableNodesProperty)
|
||||
|
||||
private fun minificationThresholdChecker(expectedReachableNodes: Int?, actualReachableNodes: Int, file: File) {
|
||||
val fileContent = file.readText()
|
||||
val replacement = "// ${JsEnvironmentConfigurationDirectives.EXPECTED_REACHABLE_NODES.name}: $actualReachableNodes"
|
||||
val enablingMessage = "To set expected reachable nodes use '$replacement'\n" +
|
||||
"To enable automatic overwriting reachable nodes use property '-Pfd.${overwriteReachableNodesProperty}=true'"
|
||||
if (expectedReachableNodes == null) {
|
||||
val baseMessage = "The number of expected reachable nodes was not set. Actual reachable nodes: $actualReachableNodes."
|
||||
return when {
|
||||
overwriteReachableNodes -> {
|
||||
file.writeText("$replacement\n$fileContent")
|
||||
throw AssertionError(baseMessage)
|
||||
}
|
||||
else -> println("$baseMessage\n$enablingMessage")
|
||||
private fun minificationThresholdChecker(expectedReachableNodes: Int?, actualReachableNodes: Int, file: File) {
|
||||
val fileContent = file.readText()
|
||||
val replacement = "// ${JsEnvironmentConfigurationDirectives.EXPECTED_REACHABLE_NODES.name}: $actualReachableNodes"
|
||||
val enablingMessage = "To set expected reachable nodes use '$replacement'\n" +
|
||||
"To enable automatic overwriting reachable nodes use property '-Pfd.${overwriteReachableNodesProperty}=true'"
|
||||
if (expectedReachableNodes == null) {
|
||||
val baseMessage = "The number of expected reachable nodes was not set. Actual reachable nodes: $actualReachableNodes."
|
||||
return when {
|
||||
overwriteReachableNodes -> {
|
||||
file.writeText("$replacement\n$fileContent")
|
||||
throw AssertionError(baseMessage)
|
||||
}
|
||||
}
|
||||
|
||||
val minThreshold = expectedReachableNodes * 9 / 10
|
||||
val maxThreshold = expectedReachableNodes * 11 / 10
|
||||
if (actualReachableNodes < minThreshold || actualReachableNodes > maxThreshold) {
|
||||
val message = "Number of reachable nodes ($actualReachableNodes) does not fit into expected range " +
|
||||
"[$minThreshold; $maxThreshold]"
|
||||
val additionalMessage: String =
|
||||
if (overwriteReachableNodes) {
|
||||
val oldValue = "// ${JsEnvironmentConfigurationDirectives.EXPECTED_REACHABLE_NODES.name}: $expectedReachableNodes"
|
||||
val newText = fileContent.replaceFirst(oldValue, replacement)
|
||||
file.writeText(newText)
|
||||
""
|
||||
} else {
|
||||
"\n$enablingMessage"
|
||||
}
|
||||
|
||||
throw AssertionError("$message$additionalMessage")
|
||||
else -> println("$baseMessage\n$enablingMessage")
|
||||
}
|
||||
}
|
||||
|
||||
fun minifyAndRun(
|
||||
file: File,
|
||||
expectedReachableNodes: Int?,
|
||||
workDir: File,
|
||||
allJsFiles: List<String>,
|
||||
generatedJsFiles: List<Pair<String, String>>,
|
||||
expectedResult: String,
|
||||
testModuleName: String?,
|
||||
testPackage: String?,
|
||||
testFunction: String,
|
||||
withModuleSystem: Boolean,
|
||||
assertEquals: (String, String) -> Unit
|
||||
) {
|
||||
val kotlinJsLib = DIST_DIR_JS_PATH + "kotlin.js"
|
||||
val kotlinTestJsLib = DIST_DIR_JS_PATH + "kotlin-test.js"
|
||||
val kotlinJsLibOutput = File(workDir, "kotlin.min.js").path
|
||||
val kotlinTestJsLibOutput = File(workDir, "kotlin-test.min.js").path
|
||||
val minThreshold = expectedReachableNodes * 9 / 10
|
||||
val maxThreshold = expectedReachableNodes * 11 / 10
|
||||
if (actualReachableNodes < minThreshold || actualReachableNodes > maxThreshold) {
|
||||
val message = "Number of reachable nodes ($actualReachableNodes) does not fit into expected range " +
|
||||
"[$minThreshold; $maxThreshold]"
|
||||
val additionalMessage: String =
|
||||
if (overwriteReachableNodes) {
|
||||
val oldValue = "// ${JsEnvironmentConfigurationDirectives.EXPECTED_REACHABLE_NODES.name}: $expectedReachableNodes"
|
||||
val newText = fileContent.replaceFirst(oldValue, replacement)
|
||||
file.writeText(newText)
|
||||
""
|
||||
} else {
|
||||
"\n$enablingMessage"
|
||||
}
|
||||
|
||||
val kotlinJsInputFile = InputFile(InputResource.file(kotlinJsLib), null, kotlinJsLibOutput, "kotlin")
|
||||
val kotlinTestJsInputFile = InputFile(InputResource.file(kotlinTestJsLib), null, kotlinTestJsLibOutput, "kotlin-test")
|
||||
|
||||
val filesToMinify = generatedJsFiles.associate { (fileName, moduleName) ->
|
||||
val inputFileName = File(fileName).nameWithoutExtension
|
||||
fileName to InputFile(InputResource.file(fileName), null, File(workDir, inputFileName + ".min.js").absolutePath, moduleName)
|
||||
}
|
||||
|
||||
val testFunctionFqn = testModuleName + (if (testPackage.isNullOrEmpty()) "" else ".$testPackage") + ".$testFunction"
|
||||
val additionalReachableNodes = setOf(
|
||||
testFunctionFqn, "kotlin.kotlin.io.BufferedOutput", "kotlin.kotlin.io.output.flush",
|
||||
"kotlin.kotlin.io.output.buffer", "kotlin-test.kotlin.test.overrideAsserter_wbnzx$",
|
||||
"kotlin-test.kotlin.test.DefaultAsserter"
|
||||
)
|
||||
val allFilesToMinify = filesToMinify.values + kotlinJsInputFile + kotlinTestJsInputFile
|
||||
val dceResult = DeadCodeElimination.run(allFilesToMinify, additionalReachableNodes, true) { _, _ -> }
|
||||
|
||||
val reachableNodes = dceResult.reachableNodes
|
||||
minificationThresholdChecker(expectedReachableNodes, reachableNodes.count { it.reachable }, file)
|
||||
|
||||
val runList = mutableListOf<String>()
|
||||
runList += kotlinJsLibOutput
|
||||
runList += kotlinTestJsLibOutput
|
||||
runList += "${JsEnvironmentConfigurator.TEST_DATA_DIR_PATH}/nashorn-polyfills.js"
|
||||
runList += allJsFiles.map { filesToMinify[it]?.outputPath ?: it }
|
||||
|
||||
val engineForMinifier = createScriptEngine()
|
||||
val result = engineForMinifier.runAndRestoreContext {
|
||||
loadFiles(runList)
|
||||
overrideAsserter()
|
||||
eval(SETUP_KOTLIN_OUTPUT)
|
||||
runTestFunction(testModuleName, testPackage, testFunction, withModuleSystem)
|
||||
}
|
||||
engineForMinifier.release()
|
||||
assertEquals(expectedResult, result)
|
||||
throw AssertionError("$message$additionalMessage")
|
||||
}
|
||||
}
|
||||
|
||||
fun minifyAndRun(
|
||||
file: File,
|
||||
expectedReachableNodes: Int?,
|
||||
workDir: File,
|
||||
allJsFiles: List<String>,
|
||||
generatedJsFiles: List<Pair<String, String>>,
|
||||
expectedResult: String,
|
||||
testModuleName: String?,
|
||||
testPackage: String?,
|
||||
testFunction: String,
|
||||
withModuleSystem: Boolean
|
||||
) {
|
||||
val kotlinJsLib = distDirJsPath + "kotlin.js"
|
||||
val kotlinTestJsLib = distDirJsPath + "kotlin-test.js"
|
||||
val kotlinJsLibOutput = File(workDir, "kotlin.min.js").path
|
||||
val kotlinTestJsLibOutput = File(workDir, "kotlin-test.min.js").path
|
||||
|
||||
val kotlinJsInputFile = InputFile(InputResource.file(kotlinJsLib), null, kotlinJsLibOutput, "kotlin")
|
||||
val kotlinTestJsInputFile = InputFile(InputResource.file(kotlinTestJsLib), null, kotlinTestJsLibOutput, "kotlin-test")
|
||||
|
||||
val filesToMinify = generatedJsFiles.associate { (fileName, moduleName) ->
|
||||
val inputFileName = File(fileName).nameWithoutExtension
|
||||
fileName to InputFile(InputResource.file(fileName), null, File(workDir, inputFileName + ".min.js").absolutePath, moduleName)
|
||||
}
|
||||
|
||||
val testFunctionFqn = testModuleName + (if (testPackage.isNullOrEmpty()) "" else ".$testPackage") + ".$testFunction"
|
||||
val additionalReachableNodes = setOf(
|
||||
testFunctionFqn, "kotlin.kotlin.io.BufferedOutput", "kotlin.kotlin.io.output.flush",
|
||||
"kotlin.kotlin.io.output.buffer", "kotlin-test.kotlin.test.overrideAsserter_wbnzx$",
|
||||
"kotlin-test.kotlin.test.DefaultAsserter"
|
||||
)
|
||||
val allFilesToMinify = filesToMinify.values + kotlinJsInputFile + kotlinTestJsInputFile
|
||||
val dceResult = DeadCodeElimination.run(allFilesToMinify, additionalReachableNodes, true) { _, _ -> }
|
||||
|
||||
val reachableNodes = dceResult.reachableNodes
|
||||
minificationThresholdChecker(expectedReachableNodes, reachableNodes.count { it.reachable }, file)
|
||||
|
||||
val runList = mutableListOf<String>()
|
||||
runList += kotlinJsLibOutput
|
||||
runList += kotlinTestJsLibOutput
|
||||
runList += "${JsEnvironmentConfigurator.TEST_DATA_DIR_PATH}/nashorn-polyfills.js"
|
||||
runList += allJsFiles.map { filesToMinify[it]?.outputPath ?: it }
|
||||
|
||||
val engineForMinifier = createScriptEngine()
|
||||
val result = engineForMinifier.runAndRestoreContext {
|
||||
loadFiles(runList)
|
||||
overrideAsserter()
|
||||
eval(SETUP_KOTLIN_OUTPUT)
|
||||
runTestFunction(testModuleName, testPackage, testFunction, withModuleSystem)
|
||||
}
|
||||
engineForMinifier.release()
|
||||
assertions.assertEquals(expectedResult, result)
|
||||
}
|
||||
}
|
||||
@@ -37,65 +37,61 @@ class JsSourceMapHandler(testServices: TestServices) : JsBinaryArtifactHandler(t
|
||||
val result = (info.unwrap() as? BinaryArtifacts.Js.OldJsArtifact)?.translationResult
|
||||
?: throw IllegalArgumentException("JsSourceMapHandler suppose to work only with old js backend")
|
||||
val remap = JsEnvironmentConfigurationDirectives.SKIP_SOURCEMAP_REMAPPING !in module.directives
|
||||
checkSourceMap(outputFile, (result as TranslationResult.Success).program, remap) { expected, actual ->
|
||||
testServices.assertions.assertEquals(expected, actual)
|
||||
checkSourceMap(outputFile, (result as TranslationResult.Success).program, remap)
|
||||
}
|
||||
|
||||
private fun checkSourceMap(outputFile: File, program: JsProgram, remap: Boolean) {
|
||||
val generatedProgram = JsProgram()
|
||||
generatedProgram.globalBlock.statements += program.globalBlock.statements.map { it.deepCopy() }
|
||||
generatedProgram.accept(object : RecursiveJsVisitor() {
|
||||
override fun visitObjectLiteral(x: JsObjectLiteral) {
|
||||
super.visitObjectLiteral(x)
|
||||
x.isMultiline = false
|
||||
}
|
||||
|
||||
override fun visitVars(x: JsVars) {
|
||||
x.isMultiline = false
|
||||
super.visitVars(x)
|
||||
}
|
||||
})
|
||||
removeLocationFromBlocks(generatedProgram)
|
||||
generatedProgram.accept(AmbiguousAstSourcePropagation())
|
||||
|
||||
val output = TextOutputImpl()
|
||||
val pathResolver = SourceFilePathResolver(mutableListOf(File(".")), null)
|
||||
val sourceMapBuilder = SourceMap3Builder(outputFile, output, "")
|
||||
generatedProgram.accept(
|
||||
JsToStringGenerationVisitor(
|
||||
output, SourceMapBuilderConsumer(File("."), sourceMapBuilder, pathResolver, false, false)
|
||||
)
|
||||
)
|
||||
val code = output.toString()
|
||||
val generatedSourceMap = sourceMapBuilder.build()
|
||||
|
||||
val codeWithLines = generatedProgram.toStringWithLineNumbers()
|
||||
|
||||
val parsedProgram = JsProgram()
|
||||
parsedProgram.globalBlock.statements += parse(code, ThrowExceptionOnErrorReporter, parsedProgram.scope, outputFile.path).orEmpty()
|
||||
removeLocationFromBlocks(parsedProgram)
|
||||
val sourceMapParseResult = SourceMapParser.parse(generatedSourceMap)
|
||||
val sourceMap = when (sourceMapParseResult) {
|
||||
is SourceMapSuccess -> sourceMapParseResult.value
|
||||
is SourceMapError -> error("Could not parse source map: ${sourceMapParseResult.message}")
|
||||
}
|
||||
|
||||
if (remap) {
|
||||
SourceMapLocationRemapper(sourceMap).remap(parsedProgram)
|
||||
val codeWithRemappedLines = parsedProgram.toStringWithLineNumbers()
|
||||
testServices.assertions.assertEquals(codeWithLines, codeWithRemappedLines)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun checkSourceMap(outputFile: File, program: JsProgram, remap: Boolean, assertEquals: (String, String) -> Unit) {
|
||||
val generatedProgram = JsProgram()
|
||||
generatedProgram.globalBlock.statements += program.globalBlock.statements.map { it.deepCopy() }
|
||||
generatedProgram.accept(object : RecursiveJsVisitor() {
|
||||
override fun visitObjectLiteral(x: JsObjectLiteral) {
|
||||
super.visitObjectLiteral(x)
|
||||
x.isMultiline = false
|
||||
}
|
||||
|
||||
override fun visitVars(x: JsVars) {
|
||||
x.isMultiline = false
|
||||
super.visitVars(x)
|
||||
}
|
||||
})
|
||||
removeLocationFromBlocks(generatedProgram)
|
||||
generatedProgram.accept(AmbiguousAstSourcePropagation())
|
||||
|
||||
val output = TextOutputImpl()
|
||||
val pathResolver = SourceFilePathResolver(mutableListOf(File(".")), null)
|
||||
val sourceMapBuilder = SourceMap3Builder(outputFile, output, "")
|
||||
generatedProgram.accept(
|
||||
JsToStringGenerationVisitor(
|
||||
output, SourceMapBuilderConsumer(File("."), sourceMapBuilder, pathResolver, false, false)
|
||||
)
|
||||
)
|
||||
val code = output.toString()
|
||||
val generatedSourceMap = sourceMapBuilder.build()
|
||||
|
||||
val codeWithLines = generatedProgram.toStringWithLineNumbers()
|
||||
|
||||
val parsedProgram = JsProgram()
|
||||
parsedProgram.globalBlock.statements += parse(code, ThrowExceptionOnErrorReporter, parsedProgram.scope, outputFile.path).orEmpty()
|
||||
removeLocationFromBlocks(parsedProgram)
|
||||
val sourceMapParseResult = SourceMapParser.parse(generatedSourceMap)
|
||||
val sourceMap = when (sourceMapParseResult) {
|
||||
is SourceMapSuccess -> sourceMapParseResult.value
|
||||
is SourceMapError -> error("Could not parse source map: ${sourceMapParseResult.message}")
|
||||
private fun removeLocationFromBlocks(program: JsProgram) {
|
||||
program.globalBlock.accept(object : RecursiveJsVisitor() {
|
||||
override fun visitBlock(x: JsBlock) {
|
||||
super.visitBlock(x)
|
||||
x.source = null
|
||||
}
|
||||
|
||||
if (remap) {
|
||||
SourceMapLocationRemapper(sourceMap).remap(parsedProgram)
|
||||
val codeWithRemappedLines = parsedProgram.toStringWithLineNumbers()
|
||||
assertEquals(codeWithLines, codeWithRemappedLines)
|
||||
}
|
||||
}
|
||||
|
||||
private fun removeLocationFromBlocks(program: JsProgram) {
|
||||
program.globalBlock.accept(object : RecursiveJsVisitor() {
|
||||
override fun visitBlock(x: JsBlock) {
|
||||
super.visitBlock(x)
|
||||
x.source = null
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+26
-28
@@ -44,35 +44,33 @@ class NodeJsGeneratorHandler(testServices: TestServices) : AbstractJsArtifactsCo
|
||||
FileUtil.writeToFile(File(nodeRunnerName), nodeRunnerText)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun generateNodeRunner(files: Collection<String>, dir: File, moduleName: String, ignored: Boolean, testPackage: String?): String {
|
||||
val filesToLoad = files.map {
|
||||
val relativePath = when {
|
||||
it.startsWith(dir.absolutePath) -> FileUtil.getRelativePath(dir, File(it))!!
|
||||
else -> it
|
||||
}
|
||||
"\"${relativePath.replace(File.separatorChar, '/')}\""
|
||||
private fun generateNodeRunner(files: Collection<String>, dir: File, moduleName: String, ignored: Boolean, testPackage: String?): String {
|
||||
val filesToLoad = files.map {
|
||||
val relativePath = when {
|
||||
it.startsWith(dir.absolutePath) -> FileUtil.getRelativePath(dir, File(it))!!
|
||||
else -> it
|
||||
}
|
||||
val fqn = testPackage?.let { ".$it" } ?: ""
|
||||
val loadAndRun = "load([${filesToLoad.joinToString(",")}], '$moduleName')$fqn.box()"
|
||||
|
||||
val sb = StringBuilder()
|
||||
sb.append("module.exports = function(load) {\n")
|
||||
if (ignored) {
|
||||
sb.append(" try {\n")
|
||||
sb.append(" var result = $loadAndRun;\n")
|
||||
sb.append(" if (result != 'OK') return 'OK';")
|
||||
sb.append(" return 'fail: expected test failure';\n")
|
||||
sb.append(" }\n")
|
||||
sb.append(" catch (e) {\n")
|
||||
sb.append(" return 'OK';\n")
|
||||
sb.append("}\n")
|
||||
} else {
|
||||
sb.append(" return $loadAndRun;\n")
|
||||
}
|
||||
sb.append("};\n")
|
||||
|
||||
return sb.toString()
|
||||
"\"${relativePath.replace(File.separatorChar, '/')}\""
|
||||
}
|
||||
val fqn = testPackage?.let { ".$it" } ?: ""
|
||||
val loadAndRun = "load([${filesToLoad.joinToString(",")}], '$moduleName')$fqn.box()"
|
||||
|
||||
val sb = StringBuilder()
|
||||
sb.append("module.exports = function(load) {\n")
|
||||
if (ignored) {
|
||||
sb.append(" try {\n")
|
||||
sb.append(" var result = $loadAndRun;\n")
|
||||
sb.append(" if (result != 'OK') return 'OK';")
|
||||
sb.append(" return 'fail: expected test failure';\n")
|
||||
sb.append(" }\n")
|
||||
sb.append(" catch (e) {\n")
|
||||
sb.append(" return 'OK';\n")
|
||||
sb.append("}\n")
|
||||
} else {
|
||||
sb.append(" return $loadAndRun;\n")
|
||||
}
|
||||
sb.append("};\n")
|
||||
|
||||
return sb.toString()
|
||||
}
|
||||
}
|
||||
+96
-4
@@ -6,12 +6,10 @@
|
||||
package org.jetbrains.kotlin.js.testNew.utils
|
||||
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.ir.backend.js.ic.ModuleCache
|
||||
import org.jetbrains.kotlin.ir.backend.js.ic.ModuleName
|
||||
import org.jetbrains.kotlin.ir.backend.js.ic.rebuildCacheForDirtyFiles
|
||||
import org.jetbrains.kotlin.ir.backend.js.ic.*
|
||||
import org.jetbrains.kotlin.ir.backend.js.moduleName
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
||||
import org.jetbrains.kotlin.js.test.TestModuleCache
|
||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||
import org.jetbrains.kotlin.konan.properties.propertyList
|
||||
import org.jetbrains.kotlin.library.KLIB_PROPERTY_DEPENDS
|
||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||
@@ -24,6 +22,100 @@ import org.jetbrains.kotlin.test.services.configuration.JsEnvironmentConfigurato
|
||||
import org.jetbrains.kotlin.test.services.jsLibraryProvider
|
||||
import java.io.File
|
||||
|
||||
class TestModuleCache(val moduleName: String, val files: MutableMap<String, FileCache>) {
|
||||
|
||||
constructor(moduleName: String) : this(moduleName, mutableMapOf())
|
||||
|
||||
fun cacheProvider(): PersistentCacheProvider {
|
||||
return object : PersistentCacheProvider {
|
||||
override fun fileFingerPrint(path: String): Hash {
|
||||
return 0L
|
||||
}
|
||||
|
||||
override fun serializedParts(path: String): SerializedIcDataForFile {
|
||||
error("Is not supported")
|
||||
}
|
||||
|
||||
override fun inlineGraphForFile(path: String, sigResolver: (Int) -> IdSignature): Collection<Pair<IdSignature, TransHash>> {
|
||||
error("Is not supported")
|
||||
}
|
||||
|
||||
override fun inlineHashes(path: String, sigResolver: (Int) -> IdSignature): Map<IdSignature, TransHash> {
|
||||
error("Is not supported")
|
||||
}
|
||||
|
||||
override fun allInlineHashes(sigResolver: (String, Int) -> IdSignature): Map<IdSignature, TransHash> {
|
||||
error("Is not supported")
|
||||
}
|
||||
|
||||
override fun binaryAst(path: String): ByteArray? {
|
||||
return files[path]?.ast ?: ByteArray(0)
|
||||
}
|
||||
|
||||
override fun dts(path: String): ByteArray? {
|
||||
return files[path]?.dts
|
||||
}
|
||||
|
||||
override fun sourceMap(path: String): ByteArray? {
|
||||
return files[path]?.sourceMap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun cacheConsumer(): PersistentCacheConsumer {
|
||||
return object : PersistentCacheConsumer {
|
||||
override fun commitInlineFunctions(
|
||||
path: String,
|
||||
hashes: Collection<Pair<IdSignature, TransHash>>,
|
||||
sigResolver: (IdSignature) -> Int
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
override fun commitFileFingerPrint(path: String, fingerprint: Hash) {
|
||||
|
||||
}
|
||||
|
||||
override fun commitInlineGraph(
|
||||
path: String,
|
||||
hashes: Collection<Pair<IdSignature, TransHash>>,
|
||||
sigResolver: (IdSignature) -> Int
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
override fun commitICCacheData(path: String, icData: SerializedIcDataForFile) {
|
||||
|
||||
}
|
||||
|
||||
override fun commitBinaryAst(path: String, astData: ByteArray) {
|
||||
val storage = files.getOrPut(path) { FileCache(path, null, null, null) }
|
||||
storage.ast = astData
|
||||
}
|
||||
|
||||
override fun commitBinaryDts(path: String, dstData: ByteArray) {
|
||||
val storage = files.getOrPut(path) { FileCache(path, null, null, null) }
|
||||
storage.dts = dstData
|
||||
}
|
||||
|
||||
override fun commitSourceMap(path: String, mapData: ByteArray) {
|
||||
val storage = files.getOrPut(path) { FileCache(path, null, null, null) }
|
||||
storage.sourceMap = mapData
|
||||
}
|
||||
|
||||
override fun invalidateForFile(path: String) {
|
||||
files.remove(path)
|
||||
}
|
||||
|
||||
override fun commitLibraryPath(libraryPath: String) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun createModuleCache(): ModuleCache = ModuleCache(moduleName, files)
|
||||
}
|
||||
|
||||
class JsIrIncrementalDataProvider(private val testServices: TestServices) : TestService {
|
||||
private val fullRuntimeKlib: String = System.getProperty("kotlin.js.full.stdlib.path")
|
||||
private val defaultRuntimeKlib = System.getProperty("kotlin.js.reduced.stdlib.path")
|
||||
|
||||
@@ -25,6 +25,9 @@ import java.io.File
|
||||
|
||||
private const val MODULE_EMULATION_FILE = "${JsEnvironmentConfigurator.TEST_DATA_DIR_PATH}/moduleEmulation.js"
|
||||
|
||||
val File.esModulesSubDir: File
|
||||
get() = File(absolutePath + "_esm")
|
||||
|
||||
private fun extractJsFiles(testServices: TestServices, modules: List<TestModule>): Pair<List<String>, List<String>> {
|
||||
val outputDir = JsEnvironmentConfigurator.getJsArtifactsOutputDir(testServices)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user