[JS IR] Invalidate all klib dependencies after removing it
Without the invalidation, broken JS code (with broken cross-module references) may appear. ^KT-54911 Fixed
This commit is contained in:
committed by
Space Team
parent
ca19d71a00
commit
693258ae91
@@ -42,12 +42,12 @@ import java.util.EnumSet
|
||||
|
||||
abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
||||
companion object {
|
||||
private val TEST_DATA_DIR_PATH = System.getProperty("kotlin.js.test.root.out.dir") ?: error("'kotlin.js.test.root.out.dir' is not set")
|
||||
private const val BOX_FUNCTION_NAME = "box"
|
||||
|
||||
private const val STDLIB_MODULE_NAME = "kotlin-kotlin-stdlib-js-ir"
|
||||
private val OUT_DIR_PATH = System.getProperty("kotlin.js.test.root.out.dir") ?: error("'kotlin.js.test.root.out.dir' is not set")
|
||||
private val STDLIB_KLIB = File(System.getProperty("kotlin.js.stdlib.klib.path") ?: error("Please set stdlib path")).canonicalPath
|
||||
|
||||
private const val BOX_FUNCTION_NAME = "box"
|
||||
private const val STDLIB_MODULE_NAME = "kotlin-kotlin-stdlib-js-ir"
|
||||
|
||||
private val KT_FILE_IGNORE_PATTERN = Regex("^.*\\..+\\.kt$")
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
||||
val expectedFileStats: Map<String, Set<String>>
|
||||
)
|
||||
|
||||
private fun setupTestStep(projStep: ProjectInfo.ProjectBuildStep, module: String): TestStepInfo {
|
||||
private fun setupTestStep(projStep: ProjectInfo.ProjectBuildStep, module: String, buildKlib: Boolean): TestStepInfo {
|
||||
val projStepId = projStep.id
|
||||
val moduleTestDir = File(testDir, module)
|
||||
val moduleSourceDir = File(sourceDir, module)
|
||||
@@ -136,17 +136,20 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
||||
modification.execute(moduleTestDir, moduleSourceDir) { deletedFiles.add(it.name) }
|
||||
}
|
||||
|
||||
val dependencies = moduleStep.dependencies.mapTo(mutableListOf(File(STDLIB_KLIB))) {
|
||||
resolveModuleArtifact(it.moduleName, buildDir)
|
||||
val expectedFileStats = moduleStep.expectedFileStats.toMutableMap()
|
||||
if (deletedFiles.isNotEmpty()) {
|
||||
val removedFiles = expectedFileStats[DirtyFileState.REMOVED_FILE.str] ?: emptySet()
|
||||
expectedFileStats[DirtyFileState.REMOVED_FILE.str] = removedFiles + deletedFiles
|
||||
}
|
||||
val outputKlibFile = resolveModuleArtifact(module, buildDir)
|
||||
val configuration = createConfiguration(module, projStep.language)
|
||||
buildArtifact(configuration, module, moduleSourceDir, dependencies, outputKlibFile)
|
||||
|
||||
val expectedFileStats = if (deletedFiles.isEmpty()) {
|
||||
moduleStep.expectedFileStats
|
||||
} else {
|
||||
moduleStep.expectedFileStats + (DirtyFileState.REMOVED_FILE.str to deletedFiles)
|
||||
val outputKlibFile = resolveModuleArtifact(module, buildDir)
|
||||
|
||||
if (buildKlib) {
|
||||
val dependencies = moduleStep.dependencies.mapTo(mutableListOf(File(STDLIB_KLIB))) {
|
||||
resolveModuleArtifact(it.moduleName, buildDir)
|
||||
}
|
||||
val configuration = createConfiguration(module, projStep.language)
|
||||
buildArtifact(configuration, module, moduleSourceDir, dependencies, outputKlibFile)
|
||||
}
|
||||
return TestStepInfo(
|
||||
module.safeModuleName,
|
||||
@@ -155,9 +158,7 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
||||
)
|
||||
}
|
||||
|
||||
private fun verifyCacheUpdateStats(
|
||||
stepId: Int, stats: KotlinSourceFileMap<EnumSet<DirtyFileState>>, testInfo: List<TestStepInfo>
|
||||
) {
|
||||
private fun verifyCacheUpdateStats(stepId: Int, stats: KotlinSourceFileMap<EnumSet<DirtyFileState>>, testInfo: List<TestStepInfo>) {
|
||||
val gotStats = stats.filter { it.key.path != STDLIB_KLIB }
|
||||
|
||||
val checkedLibs = mutableSetOf<KotlinLibraryFile>()
|
||||
@@ -170,7 +171,9 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
||||
val got = mutableMapOf<String, MutableSet<String>>()
|
||||
for ((srcFile, dirtyStats) in updateStatus) {
|
||||
for (dirtyStat in dirtyStats) {
|
||||
got.getOrPut(dirtyStat.str) { mutableSetOf() }.add(File(srcFile.path).name)
|
||||
if (dirtyStat != DirtyFileState.NON_MODIFIED_IR) {
|
||||
got.getOrPut(dirtyStat.str) { mutableSetOf() }.add(File(srcFile.path).name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,7 +226,7 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
||||
|
||||
fun execute() {
|
||||
for (projStep in projectInfo.steps) {
|
||||
val testInfo = projStep.order.map { setupTestStep(projStep, it) }
|
||||
val testInfo = projStep.order.map { setupTestStep(projStep, it, true) }
|
||||
|
||||
val configuration = createConfiguration(projStep.order.last(), projStep.language)
|
||||
val cacheUpdater = CacheUpdater(
|
||||
@@ -238,8 +241,10 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
||||
}
|
||||
)
|
||||
|
||||
val removedModulesInfo = (projectInfo.modules - projStep.order.toSet()).map { setupTestStep(projStep, it, false) }
|
||||
|
||||
val icCaches = cacheUpdater.actualizeCaches()
|
||||
verifyCacheUpdateStats(projStep.id, cacheUpdater.getDirtyFileLastStats(), testInfo)
|
||||
verifyCacheUpdateStats(projStep.id, cacheUpdater.getDirtyFileLastStats(), testInfo + removedModulesInfo)
|
||||
|
||||
val mainModuleName = icCaches.last().moduleExternalName
|
||||
val jsExecutableProducer = JsExecutableProducer(
|
||||
@@ -342,7 +347,7 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
||||
}
|
||||
|
||||
private fun testWorkingDir(testName: String): File {
|
||||
val dir = File(File(File(TEST_DATA_DIR_PATH), "incrementalOut/invalidation"), testName)
|
||||
val dir = File(File(File(OUT_DIR_PATH), "incrementalOut/invalidation"), testName)
|
||||
|
||||
dir.invalidateDir()
|
||||
|
||||
|
||||
+10
@@ -275,11 +275,21 @@ public class InvalidationTestGenerated extends AbstractInvalidationTest {
|
||||
runTest("js/js.translator/testData/incremental/invalidation/renameFile/");
|
||||
}
|
||||
|
||||
@TestMetadata("renameModule")
|
||||
public void testRenameModule() throws Exception {
|
||||
runTest("js/js.translator/testData/incremental/invalidation/renameModule/");
|
||||
}
|
||||
|
||||
@TestMetadata("simple")
|
||||
public void testSimple() throws Exception {
|
||||
runTest("js/js.translator/testData/incremental/invalidation/simple/");
|
||||
}
|
||||
|
||||
@TestMetadata("splitJoinModule")
|
||||
public void testSplitJoinModule() throws Exception {
|
||||
runTest("js/js.translator/testData/incremental/invalidation/splitJoinModule/");
|
||||
}
|
||||
|
||||
@TestMetadata("suspendFunctions")
|
||||
public void testSuspendFunctions() throws Exception {
|
||||
runTest("js/js.translator/testData/incremental/invalidation/suspendFunctions/");
|
||||
|
||||
Vendored
+2
@@ -5,7 +5,9 @@ STEP 1:
|
||||
STEP 2:
|
||||
updated exports: l1a.kt
|
||||
STEP 3:
|
||||
removed inverse depends: l1b.kt, l1a.kt
|
||||
STEP 4:
|
||||
modifications:
|
||||
U : l1a.4.kt -> l1a.kt
|
||||
modified ir: l1a.kt
|
||||
updated exports: l1b.kt
|
||||
|
||||
Vendored
+1
-5
@@ -1,8 +1,4 @@
|
||||
STEP 0:
|
||||
modifications:
|
||||
U : proxy.0.kt -> proxy.kt
|
||||
added file: proxy.kt
|
||||
STEP 1..7:
|
||||
STEP 0..7:
|
||||
STEP 8:
|
||||
dependencies: lib1
|
||||
modifications:
|
||||
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
fun unused_foo_proxy(s: String) = 77
|
||||
+1
@@ -0,0 +1 @@
|
||||
fun foo() = 1
|
||||
+1
@@ -0,0 +1 @@
|
||||
inline fun foo() = 2
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
STEP 0:
|
||||
STEP 1:
|
||||
modifications:
|
||||
U : l1.1.kt -> l1.kt
|
||||
added file: l1.kt
|
||||
STEP 2:
|
||||
modifications:
|
||||
U : l1.2.kt -> l1.kt
|
||||
modified ir: l1.kt
|
||||
STEP 3:
|
||||
removed file: l1.kt
|
||||
STEP 4..5:
|
||||
@@ -0,0 +1 @@
|
||||
fun foo() = 0
|
||||
@@ -0,0 +1 @@
|
||||
fun foo() = 3
|
||||
@@ -0,0 +1 @@
|
||||
inline fun foo() = 4
|
||||
@@ -0,0 +1 @@
|
||||
inline fun foo() = 5
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
STEP 0:
|
||||
modifications:
|
||||
U : l1.0.kt -> l1.kt
|
||||
added file: l1.kt
|
||||
STEP 1:
|
||||
removed file: l1.kt
|
||||
STEP 2:
|
||||
STEP 3:
|
||||
modifications:
|
||||
U : l1.3.kt -> l1.kt
|
||||
added file: l1.kt
|
||||
STEP 4:
|
||||
modifications:
|
||||
U : l1.4.kt -> l1.kt
|
||||
modified ir: l1.kt
|
||||
STEP 5:
|
||||
modifications:
|
||||
U : l1.5.kt -> l1.kt
|
||||
modified ir: l1.kt
|
||||
@@ -0,0 +1,7 @@
|
||||
fun box(stepId: Int): String {
|
||||
val x = foo()
|
||||
if (x != stepId) {
|
||||
return "Fail: $x != $stepId"
|
||||
}
|
||||
return "OK"
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
STEP 0:
|
||||
dependencies: lib1
|
||||
added file: m.kt
|
||||
STEP 1:
|
||||
dependencies: lib1-new
|
||||
removed direct depends: m.kt
|
||||
STEP 2:
|
||||
dependencies: lib1-new
|
||||
updated imports: m.kt
|
||||
STEP 3:
|
||||
dependencies: lib1
|
||||
removed direct depends: m.kt
|
||||
STEP 4..5:
|
||||
dependencies: lib1
|
||||
updated imports: m.kt
|
||||
@@ -0,0 +1,11 @@
|
||||
MODULES: lib1, lib1-new, main
|
||||
|
||||
STEP 0:
|
||||
libs: lib1, main
|
||||
dirty js: lib1, main
|
||||
STEP 1..2:
|
||||
libs: lib1-new, main
|
||||
dirty js: lib1-new, main
|
||||
STEP 3..5:
|
||||
libs: lib1, main
|
||||
dirty js: lib1, main
|
||||
+1
@@ -0,0 +1 @@
|
||||
fun fooA() = 1
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
STEP 0:
|
||||
STEP 1:
|
||||
modifications:
|
||||
U : l1a.1.kt -> l1a.kt
|
||||
added file: l1a.kt
|
||||
STEP 2..3:
|
||||
STEP 4:
|
||||
modifications:
|
||||
D : l1a.kt
|
||||
STEP 5:
|
||||
+1
@@ -0,0 +1 @@
|
||||
fun fooB() = 2
|
||||
+1
@@ -0,0 +1 @@
|
||||
inline fun fooB() = 3
|
||||
+1
@@ -0,0 +1 @@
|
||||
inline fun fooB() = 4
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
STEP 0:
|
||||
STEP 1:
|
||||
modifications:
|
||||
U : l1b.1.kt -> l1b.kt
|
||||
added file: l1b.kt
|
||||
STEP 2:
|
||||
modifications:
|
||||
U : l1b.2.kt -> l1b.kt
|
||||
modified ir: l1b.kt
|
||||
STEP 2:
|
||||
modifications:
|
||||
U : l1b.3.kt -> l1b.kt
|
||||
modified ir: l1b.kt
|
||||
STEP 4:
|
||||
modifications:
|
||||
D : l1b.kt
|
||||
STEP 5:
|
||||
+1
@@ -0,0 +1 @@
|
||||
fun fooC() = 4
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
STEP 0:
|
||||
STEP 1:
|
||||
modifications:
|
||||
U : l1c.1.kt -> l1c.kt
|
||||
added file: l1c.kt
|
||||
STEP 2..3:
|
||||
STEP 4:
|
||||
modifications:
|
||||
D : l1c.kt
|
||||
STEP 5:
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
fun fooA() = 3
|
||||
|
||||
fun fooB() = 3
|
||||
|
||||
fun fooC() = 4
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
fun fooA() = 3
|
||||
|
||||
fun fooB() = 4
|
||||
|
||||
fun fooC() = 4
|
||||
+1
@@ -0,0 +1 @@
|
||||
fun fooA() = 1
|
||||
+1
@@ -0,0 +1 @@
|
||||
fun fooB() = 2
|
||||
+1
@@ -0,0 +1 @@
|
||||
fun fooC() = 3
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
STEP 0:
|
||||
modifications:
|
||||
U : l1a.0.kt -> l1a.kt
|
||||
U : l1b.0.kt -> l1b.kt
|
||||
U : l1c.0.kt -> l1c.kt
|
||||
added file: l1a.kt, l1b.kt, l1c.kt
|
||||
STEP 1:
|
||||
modifications:
|
||||
D : l1a.kt
|
||||
D : l1b.kt
|
||||
D : l1c.kt
|
||||
STEP 2..3:
|
||||
STEP 4:
|
||||
modifications:
|
||||
U : l1.4.kt -> l1.kt
|
||||
added file: l1.kt
|
||||
STEP 5:
|
||||
modifications:
|
||||
U : l1.5.kt -> l1.kt
|
||||
modified ir: l1.kt
|
||||
+1
@@ -0,0 +1 @@
|
||||
fun qux() = fooA() + fooB() + fooC() - 6
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
STEP 0:
|
||||
dependencies: lib1
|
||||
modifications:
|
||||
U : l2.0.kt -> l2.kt
|
||||
added file: l2.kt
|
||||
STEP 1:
|
||||
dependencies: lib1-a, lib1-b, lib1-c
|
||||
removed direct depends: l2.kt
|
||||
STEP 2..3:
|
||||
dependencies: lib1-a, lib1-b, lib1-c
|
||||
updated imports: l2.kt
|
||||
STEP 4:
|
||||
dependencies: lib1
|
||||
removed direct depends: l2.kt
|
||||
STEP 5:
|
||||
dependencies: lib1
|
||||
@@ -0,0 +1,7 @@
|
||||
fun box(stepId: Int): String {
|
||||
val x = qux()
|
||||
if (x != stepId) {
|
||||
return "Fail: $x != $stepId"
|
||||
}
|
||||
return "OK"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
STEP 0:
|
||||
dependencies: lib1, lib2
|
||||
added file: m.kt
|
||||
STEP 1..3:
|
||||
dependencies: lib1-a, lib1-b, lib1-c, lib2
|
||||
STEP 4..5:
|
||||
dependencies: lib1, lib2
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
MODULES: lib1, lib1-a, lib1-b, lib1-c, lib2, main
|
||||
|
||||
STEP 0:
|
||||
libs: lib1, lib2, main
|
||||
dirty js: lib1, lib2, main
|
||||
STEP 1:
|
||||
libs: lib1-a, lib1-b, lib1-c, lib2, main
|
||||
dirty js: lib1-a, lib1-b, lib1-c, lib2
|
||||
STEP 2..3:
|
||||
libs: lib1-a, lib1-b, lib1-c, lib2, main
|
||||
dirty js: lib1-b, lib2
|
||||
STEP 4:
|
||||
libs: lib1, lib2, main
|
||||
dirty js: lib1, lib2
|
||||
STEP 5:
|
||||
libs: lib1, lib2, main
|
||||
dirty js: lib1
|
||||
Reference in New Issue
Block a user