[JS IR] Take into account file annotations for calculating symbol hashes
^KT-55367 Fixed
This commit is contained in:
committed by
Space Team
parent
4136189114
commit
48daf0befe
@@ -255,7 +255,7 @@ class CacheUpdater(
|
|||||||
symbolCanBeExported = true
|
symbolCanBeExported = true
|
||||||
}
|
}
|
||||||
if (symbolCanBeExported) {
|
if (symbolCanBeExported) {
|
||||||
idSignatureToFile[signature] = IdSignatureSource(libFile, KotlinSourceFile(fileDeserializer.file), symbol)
|
idSignatureToFile[signature] = IdSignatureSource(libFile, fileDeserializer.file, symbol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,12 +276,12 @@ class CacheUpdater(
|
|||||||
) {
|
) {
|
||||||
val allImportedSignatures = addParentSignatures(maybeImportedSignatures, idSignatureToFile, libFile, srcFile)
|
val allImportedSignatures = addParentSignatures(maybeImportedSignatures, idSignatureToFile, libFile, srcFile)
|
||||||
for (importedSignature in allImportedSignatures) {
|
for (importedSignature in allImportedSignatures) {
|
||||||
val (dependencyLib, dependencyFile) = idSignatureToFile[importedSignature] ?: continue
|
val dependency = idSignatureToFile[importedSignature] ?: continue
|
||||||
signatureHashCalculator[importedSignature]?.also { signatureHash ->
|
signatureHashCalculator[importedSignature]?.also { signatureHash ->
|
||||||
addDirectDependency(dependencyLib, dependencyFile, importedSignature, signatureHash)
|
addDirectDependency(dependency.lib, dependency.src, importedSignature, signatureHash)
|
||||||
} ?: notFoundIcError("signature $importedSignature hash", dependencyLib, dependencyFile)
|
} ?: notFoundIcError("signature $importedSignature hash", dependency.lib, dependency.src)
|
||||||
|
|
||||||
updatedMetadata[dependencyLib, dependencyFile]?.also { dependencyMetadata ->
|
updatedMetadata[dependency.lib, dependency.src]?.also { dependencyMetadata ->
|
||||||
dependencyMetadata.addInverseDependency(libFile, srcFile, importedSignature)
|
dependencyMetadata.addInverseDependency(libFile, srcFile, importedSignature)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-5
@@ -59,6 +59,10 @@ private class HashCalculatorForIC {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateAnnotationContainer(annotationContainer: IrAnnotationContainer) {
|
||||||
|
updateForEach(annotationContainer.annotations, ::update)
|
||||||
|
}
|
||||||
|
|
||||||
inline fun <T> updateForEach(collection: Collection<T>, f: (T) -> Unit) {
|
inline fun <T> updateForEach(collection: Collection<T>, f: (T) -> Unit) {
|
||||||
update(collection.size)
|
update(collection.size)
|
||||||
collection.forEach { f(it) }
|
collection.forEach { f(it) }
|
||||||
@@ -112,6 +116,10 @@ internal fun IrSimpleFunction.irSimpleFunctionHashForIC() = HashCalculatorForIC(
|
|||||||
it.update(this)
|
it.update(this)
|
||||||
}.finalize()
|
}.finalize()
|
||||||
|
|
||||||
|
internal fun IrAnnotationContainer.irAnnotationContainerHashForIC() = HashCalculatorForIC().also {
|
||||||
|
it.updateAnnotationContainer(this)
|
||||||
|
}.finalize()
|
||||||
|
|
||||||
internal fun IrSymbol.irSymbolHashForIC() = HashCalculatorForIC().also {
|
internal fun IrSymbol.irSymbolHashForIC() = HashCalculatorForIC().also {
|
||||||
it.update(toString())
|
it.update(toString())
|
||||||
// symbol rendering prints very little information about type parameters
|
// symbol rendering prints very little information about type parameters
|
||||||
@@ -128,11 +136,7 @@ internal fun IrSymbol.irSymbolHashForIC() = HashCalculatorForIC().also {
|
|||||||
it.update(functionParam.defaultValue?.let { 1 } ?: 0)
|
it.update(functionParam.defaultValue?.let { 1 } ?: 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(owner as? IrAnnotationContainer)?.let { annotationContainer ->
|
(owner as? IrAnnotationContainer)?.let(it::updateAnnotationContainer)
|
||||||
it.updateForEach(annotationContainer.annotations) { annotation ->
|
|
||||||
it.update(annotation)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.finalize()
|
}.finalize()
|
||||||
|
|
||||||
internal fun String.stringHashForIC() = HashCalculatorForIC().also { it.update(this) }.finalize()
|
internal fun String.stringHashForIC() = HashCalculatorForIC().also { it.update(this) }.finalize()
|
||||||
|
|||||||
+15
-2
@@ -25,27 +25,39 @@ internal class IdSignatureHashCalculator {
|
|||||||
private val inlineFunctionCallGraph = hashMapOf<IrFunction, Set<IrFunction>>()
|
private val inlineFunctionCallGraph = hashMapOf<IrFunction, Set<IrFunction>>()
|
||||||
private val processingFunctions = hashSetOf<IrFunction>()
|
private val processingFunctions = hashSetOf<IrFunction>()
|
||||||
private val functionTransitiveHashes = hashMapOf<IrFunction, ICHash>()
|
private val functionTransitiveHashes = hashMapOf<IrFunction, ICHash>()
|
||||||
|
private val fileAnnotationHashes = hashMapOf<IrFile, ICHash>()
|
||||||
|
|
||||||
private val allIdSignatureHashes = hashMapOf<IdSignature, ICHash>()
|
private val allIdSignatureHashes = hashMapOf<IdSignature, ICHash>()
|
||||||
|
|
||||||
|
private val IrFile.annotationsHash: ICHash
|
||||||
|
get() = fileAnnotationHashes.getOrPut(this, ::irAnnotationContainerHashForIC)
|
||||||
|
|
||||||
private inner class FlatHashCalculator : IrElementVisitorVoid {
|
private inner class FlatHashCalculator : IrElementVisitorVoid {
|
||||||
|
private var fileAnnotationsHash = ICHash()
|
||||||
|
|
||||||
override fun visitElement(element: IrElement) {
|
override fun visitElement(element: IrElement) {
|
||||||
element.acceptChildrenVoid(this)
|
element.acceptChildrenVoid(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitFile(declaration: IrFile, data: Nothing?) {
|
||||||
|
fileAnnotationsHash = declaration.annotationsHash
|
||||||
|
declaration.acceptChildrenVoid(this)
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitSimpleFunction(declaration: IrSimpleFunction) {
|
override fun visitSimpleFunction(declaration: IrSimpleFunction) {
|
||||||
if (declaration.isInline) {
|
if (declaration.isInline) {
|
||||||
if (declaration in flatHashes) {
|
if (declaration in flatHashes) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
flatHashes[declaration] = if (declaration.isFakeOverride) {
|
val inlineFunctionFlatHash = if (declaration.isFakeOverride) {
|
||||||
declaration.resolveFakeOverride()?.irSimpleFunctionHashForIC()
|
declaration.resolveFakeOverride()?.irSimpleFunctionHashForIC()
|
||||||
?: icError("can not resolve fake override for ${declaration.render()}")
|
?: icError("can not resolve fake override for ${declaration.render()}")
|
||||||
} else {
|
} else {
|
||||||
declaration.irSimpleFunctionHashForIC()
|
declaration.irSimpleFunctionHashForIC()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flatHashes[declaration] = fileAnnotationsHash.combineWith(inlineFunctionFlatHash)
|
||||||
}
|
}
|
||||||
// go deeper since local inline special declarations (like a reference adaptor) may appear
|
// go deeper since local inline special declarations (like a reference adaptor) may appear
|
||||||
declaration.acceptChildrenVoid(this)
|
declaration.acceptChildrenVoid(this)
|
||||||
@@ -120,7 +132,8 @@ internal class IdSignatureHashCalculator {
|
|||||||
fun addAllSignatureSymbols(idSignatureToFile: Map<IdSignature, IdSignatureSource>) {
|
fun addAllSignatureSymbols(idSignatureToFile: Map<IdSignature, IdSignatureSource>) {
|
||||||
for ((signature, signatureSrc) in idSignatureToFile) {
|
for ((signature, signatureSrc) in idSignatureToFile) {
|
||||||
if (signature !in allIdSignatureHashes) {
|
if (signature !in allIdSignatureHashes) {
|
||||||
allIdSignatureHashes[signature] = signatureSrc.symbol.irSymbolHashForIC()
|
val fileAnnotationsHash = signatureSrc.srcIrFile.annotationsHash
|
||||||
|
allIdSignatureHashes[signature] = fileAnnotationsHash.combineWith(signatureSrc.symbol.irSymbolHashForIC())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-1
@@ -11,7 +11,14 @@ import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
|||||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||||
import org.jetbrains.kotlin.ir.util.resolveFakeOverride
|
import org.jetbrains.kotlin.ir.util.resolveFakeOverride
|
||||||
|
|
||||||
internal data class IdSignatureSource(val lib: KotlinLibraryFile, val src: KotlinSourceFile, val symbol: IrSymbol)
|
internal class IdSignatureSource(
|
||||||
|
val lib: KotlinLibraryFile,
|
||||||
|
val srcIrFile: IrFile,
|
||||||
|
val symbol: IrSymbol
|
||||||
|
) {
|
||||||
|
val src: KotlinSourceFile
|
||||||
|
get() = KotlinSourceFile(srcIrFile)
|
||||||
|
}
|
||||||
|
|
||||||
internal fun addParentSignatures(
|
internal fun addParentSignatures(
|
||||||
signatures: Collection<IdSignature>,
|
signatures: Collection<IdSignature>,
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
|||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImplForJsIC
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImplForJsIC
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||||
|
import org.jetbrains.kotlin.js.test.converters.ClassicJsBackendFacade
|
||||||
|
import org.jetbrains.kotlin.js.test.utils.MODULE_EMULATION_FILE
|
||||||
import org.jetbrains.kotlin.js.testOld.V8IrJsTestChecker
|
import org.jetbrains.kotlin.js.testOld.V8IrJsTestChecker
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
@@ -49,9 +51,9 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
|||||||
private const val BOX_FUNCTION_NAME = "box"
|
private const val BOX_FUNCTION_NAME = "box"
|
||||||
private const val STDLIB_MODULE_NAME = "kotlin-kotlin-stdlib-js-ir"
|
private const val STDLIB_MODULE_NAME = "kotlin-kotlin-stdlib-js-ir"
|
||||||
|
|
||||||
private val KT_FILE_IGNORE_PATTERN = Regex("^.*\\..+\\.kt$")
|
private val TEST_FILE_IGNORE_PATTERN = Regex("^.*\\..+\\.\\w\\w$")
|
||||||
|
|
||||||
private val JS_MODULE_KIND = ModuleKind.PLAIN
|
private val JS_MODULE_KIND = ModuleKind.COMMON_JS
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createEnvironment(): KotlinCoreEnvironment {
|
override fun createEnvironment(): KotlinCoreEnvironment {
|
||||||
@@ -66,6 +68,9 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
|||||||
return ModuleInfoParser(infoFile).parse(moduleName)
|
return ModuleInfoParser(infoFile).parse(moduleName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val File.filesInDir
|
||||||
|
get() = listFiles() ?: error("cannot retrieve the file list for $absolutePath directory")
|
||||||
|
|
||||||
protected fun doTest(testPath: String) {
|
protected fun doTest(testPath: String) {
|
||||||
val testDirectory = File(testPath)
|
val testDirectory = File(testPath)
|
||||||
val testName = testDirectory.name
|
val testName = testDirectory.name
|
||||||
@@ -84,10 +89,11 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
|||||||
val workingDir = testWorkingDir(projectInfo.name)
|
val workingDir = testWorkingDir(projectInfo.name)
|
||||||
val sourceDir = File(workingDir, "sources").also { it.invalidateDir() }
|
val sourceDir = File(workingDir, "sources").also { it.invalidateDir() }
|
||||||
val buildDir = File(workingDir, "build").also { it.invalidateDir() }
|
val buildDir = File(workingDir, "build").also { it.invalidateDir() }
|
||||||
|
val jsDir = File(workingDir, "js").also { it.invalidateDir() }
|
||||||
|
|
||||||
initializeWorkingDir(projectInfo, testDirectory, sourceDir, buildDir)
|
initializeWorkingDir(projectInfo, testDirectory, sourceDir, buildDir)
|
||||||
|
|
||||||
ProjectStepsExecutor(projectInfo, modulesInfos, testDirectory, sourceDir, buildDir).execute()
|
ProjectStepsExecutor(projectInfo, modulesInfos, testDirectory, sourceDir, buildDir, jsDir).execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveModuleArtifact(moduleName: String, buildDir: File): File {
|
private fun resolveModuleArtifact(moduleName: String, buildDir: File): File {
|
||||||
@@ -121,7 +127,8 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
|||||||
private val moduleInfos: Map<String, ModuleInfo>,
|
private val moduleInfos: Map<String, ModuleInfo>,
|
||||||
private val testDir: File,
|
private val testDir: File,
|
||||||
private val sourceDir: File,
|
private val sourceDir: File,
|
||||||
private val buildDir: File
|
private val buildDir: File,
|
||||||
|
private val jsDir: File
|
||||||
) {
|
) {
|
||||||
private inner class TestStepInfo(
|
private inner class TestStepInfo(
|
||||||
val moduleName: String,
|
val moduleName: String,
|
||||||
@@ -214,26 +221,46 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun writeJsFile(name: String, text: String): String {
|
private fun File.writeAsJsModule(jsCode: String, moduleName: String) {
|
||||||
val file = File(buildDir, "$name.js")
|
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()) {
|
if (file.exists()) {
|
||||||
file.delete()
|
file.delete()
|
||||||
}
|
}
|
||||||
file.writeText(text)
|
file.writeAsJsModule(text, moduleFileName)
|
||||||
return file.canonicalPath
|
return file.canonicalPath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun prepareExternalJsFiles(): MutableList<String> {
|
||||||
|
jsDir.invalidateDir()
|
||||||
|
return testDir.filesInDir.mapNotNullTo(mutableListOf(MODULE_EMULATION_FILE)) { file ->
|
||||||
|
file.takeIf { it.name.isAllowedJsFile() }?.readText()?.let { jsCode ->
|
||||||
|
val externalModule = jsDir.resolve(file.name)
|
||||||
|
externalModule.writeAsJsModule(jsCode, file.nameWithoutExtension)
|
||||||
|
externalModule.canonicalPath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun verifyJsCode(stepId: Int, mainModuleName: String, jsOutput: CompilationOutputs) {
|
private fun verifyJsCode(stepId: Int, mainModuleName: String, jsOutput: CompilationOutputs) {
|
||||||
val files = jsOutput.dependencies.map { writeJsFile(it.first, it.second.jsCode) } + writeJsFile(mainModuleName, jsOutput.jsCode)
|
val files = prepareExternalJsFiles()
|
||||||
|
jsOutput.dependencies.mapTo(files) { writeJsFile(it.first, it.second.jsCode) }
|
||||||
|
files += writeJsFile(mainModuleName, jsOutput.jsCode)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
V8IrJsTestChecker.checkWithTestFunctionArgs(
|
V8IrJsTestChecker.checkWithTestFunctionArgs(
|
||||||
files = files,
|
files = files,
|
||||||
testModuleName = mainModuleName,
|
testModuleName = "./$mainModuleName.js",
|
||||||
testPackageName = null,
|
testPackageName = null,
|
||||||
testFunctionName = BOX_FUNCTION_NAME,
|
testFunctionName = BOX_FUNCTION_NAME,
|
||||||
testFunctionArgs = "$stepId",
|
testFunctionArgs = "$stepId",
|
||||||
expectedResult = "OK",
|
expectedResult = "OK",
|
||||||
withModuleSystem = false
|
withModuleSystem = true
|
||||||
)
|
)
|
||||||
} catch (e: ComparisonFailure) {
|
} catch (e: ComparisonFailure) {
|
||||||
throw ComparisonFailure("Mismatched box out at step $stepId", e.expected, e.actual)
|
throw ComparisonFailure("Mismatched box out at step $stepId", e.expected, e.actual)
|
||||||
@@ -298,7 +325,9 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun String.isAllowedKtFile() = endsWith(".kt") && !KT_FILE_IGNORE_PATTERN.matches(this)
|
private fun String.isAllowedKtFile() = endsWith(".kt") && !TEST_FILE_IGNORE_PATTERN.matches(this)
|
||||||
|
|
||||||
|
private fun String.isAllowedJsFile() = endsWith(".js") && !TEST_FILE_IGNORE_PATTERN.matches(this)
|
||||||
|
|
||||||
private fun File.filteredKtFiles(): Collection<File> {
|
private fun File.filteredKtFiles(): Collection<File> {
|
||||||
assert(isDirectory && exists())
|
assert(isDirectory && exists())
|
||||||
@@ -377,11 +406,10 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
|||||||
File(buildDir, module).invalidateDir()
|
File(buildDir, module).invalidateDir()
|
||||||
val testModuleDir = File(testDir, module)
|
val testModuleDir = File(testDir, module)
|
||||||
|
|
||||||
testModuleDir.listFiles { _, fileName -> fileName.isAllowedKtFile() }!!.forEach { file ->
|
testModuleDir.filesInDir.forEach { file ->
|
||||||
assert(!file.isDirectory)
|
if (file.name.isAllowedKtFile()) {
|
||||||
val fileName = file.name
|
file.copyTo(moduleSourceDir.resolve(file.name))
|
||||||
val workingFile = File(moduleSourceDir, fileName)
|
}
|
||||||
file.copyTo(workingFile)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ import org.jetbrains.kotlin.test.services.configuration.JsEnvironmentConfigurato
|
|||||||
import org.jetbrains.kotlin.util.collectionUtils.filterIsInstanceAnd
|
import org.jetbrains.kotlin.util.collectionUtils.filterIsInstanceAnd
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
private const val MODULE_EMULATION_FILE = "${JsEnvironmentConfigurator.TEST_DATA_DIR_PATH}/moduleEmulation.js"
|
const val MODULE_EMULATION_FILE = "${JsEnvironmentConfigurator.TEST_DATA_DIR_PATH}/moduleEmulation.js"
|
||||||
|
|
||||||
fun TestModule.getNameFor(filePath: String, testServices: TestServices): String {
|
fun TestModule.getNameFor(filePath: String, testServices: TestServices): String {
|
||||||
return JsEnvironmentConfigurator.getJsArtifactSimpleName(testServices, name) + "-js-" + filePath
|
return JsEnvironmentConfigurator.getJsArtifactSimpleName(testServices, name) + "-js-" + filePath
|
||||||
|
|||||||
+5
@@ -250,6 +250,11 @@ public class InvalidationTestGenerated extends AbstractInvalidationTest {
|
|||||||
runTest("js/js.translator/testData/incremental/invalidation/moveAndModifyInlineFunction/");
|
runTest("js/js.translator/testData/incremental/invalidation/moveAndModifyInlineFunction/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("moveExternalDeclarationsBetweenJsModules")
|
||||||
|
public void testMoveExternalDeclarationsBetweenJsModules() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/incremental/invalidation/moveExternalDeclarationsBetweenJsModules/");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("moveFilesBetweenModules")
|
@TestMetadata("moveFilesBetweenModules")
|
||||||
public void testMoveFilesBetweenModules() throws Exception {
|
public void testMoveFilesBetweenModules() throws Exception {
|
||||||
runTest("js/js.translator/testData/incremental/invalidation/moveFilesBetweenModules/");
|
runTest("js/js.translator/testData/incremental/invalidation/moveFilesBetweenModules/");
|
||||||
|
|||||||
+1
@@ -3,3 +3,4 @@ STEP 0:
|
|||||||
added file: m.kt
|
added file: m.kt
|
||||||
STEP 1:
|
STEP 1:
|
||||||
dependencies: lib1
|
dependencies: lib1
|
||||||
|
updated imports: m.kt
|
||||||
|
|||||||
+1
-4
@@ -1,8 +1,5 @@
|
|||||||
MODULES: lib1, main
|
MODULES: lib1, main
|
||||||
|
|
||||||
STEP 0:
|
STEP 0..1:
|
||||||
libs: lib1, main
|
libs: lib1, main
|
||||||
dirty js: lib1, main
|
dirty js: lib1, main
|
||||||
STEP 1:
|
|
||||||
libs: lib1, main
|
|
||||||
dirty js: lib1
|
|
||||||
|
|||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
(function (_) {
|
||||||
|
'use strict';
|
||||||
|
function externalDemoFunction() { return 3; }
|
||||||
|
|
||||||
|
_.externalDemoFunction = externalDemoFunction;
|
||||||
|
|
||||||
|
return _
|
||||||
|
}(module.exports));
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
(function (_) {
|
||||||
|
'use strict';
|
||||||
|
function externalDemoFunction() { return 0; }
|
||||||
|
|
||||||
|
_.externalDemoFunction = externalDemoFunction;
|
||||||
|
|
||||||
|
return _
|
||||||
|
}(module.exports));
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
(function (_) {
|
||||||
|
'use strict';
|
||||||
|
function externalDemoFunction() { return 2; }
|
||||||
|
|
||||||
|
_.externalDemoFunction = externalDemoFunction;
|
||||||
|
|
||||||
|
return _
|
||||||
|
}(module.exports));
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
(function (_) {
|
||||||
|
'use strict';
|
||||||
|
function externalDemoFunction() { return 1; }
|
||||||
|
|
||||||
|
_.externalDemoFunction = externalDemoFunction;
|
||||||
|
|
||||||
|
return _
|
||||||
|
}(module.exports));
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
(function (_) {
|
||||||
|
'use strict';
|
||||||
|
function externalDemoFunction() { return 5; }
|
||||||
|
|
||||||
|
_.externalDemoFunction = externalDemoFunction;
|
||||||
|
|
||||||
|
return _
|
||||||
|
}(module.exports));
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
(function (_) {
|
||||||
|
'use strict';
|
||||||
|
function externalDemoFunction() { return 4; }
|
||||||
|
|
||||||
|
_.externalDemoFunction = externalDemoFunction;
|
||||||
|
|
||||||
|
return _
|
||||||
|
}(module.exports));
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
@file:JsModule("js-module-a")
|
||||||
|
|
||||||
|
external fun externalDemoFunction(): Int
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
@file:JsModule("js-module-a")
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
@file:JsModule("js-module-a-new")
|
||||||
|
|
||||||
|
external fun externalDemoFunction(): Int
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
@file:JsModule("js-module-b")
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
@file:JsModule("js-module-b")
|
||||||
|
|
||||||
|
external fun externalDemoFunction(): Int
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
@file:JsModule("js-module-b-new")
|
||||||
|
|
||||||
|
external fun externalDemoFunction(): Int
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
fun demoFunction() = externalDemoFunction()
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
fun demoFunction() = -1
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
STEP 0:
|
||||||
|
modifications:
|
||||||
|
U : JsModuleA.0.kt -> JsModuleA.kt
|
||||||
|
U : JsModuleB.0.kt -> JsModuleB.kt
|
||||||
|
U : demo.0.kt -> demo.kt
|
||||||
|
added file: JsModuleA.kt, JsModuleB.kt, demo.kt
|
||||||
|
STEP 1:
|
||||||
|
modifications:
|
||||||
|
U : JsModuleA.1.kt -> JsModuleA.kt
|
||||||
|
U : JsModuleB.1.kt -> JsModuleB.kt
|
||||||
|
modified ir: JsModuleA.kt, JsModuleB.kt
|
||||||
|
updated imports: demo.kt
|
||||||
|
STEP 2:
|
||||||
|
modifications:
|
||||||
|
U : JsModuleB.2.kt -> JsModuleB.kt
|
||||||
|
modified ir: JsModuleB.kt
|
||||||
|
updated imports: demo.kt
|
||||||
|
STEP 3:
|
||||||
|
modifications:
|
||||||
|
U : demo.3.kt -> demo.kt
|
||||||
|
modified ir: demo.kt
|
||||||
|
STEP 4:
|
||||||
|
modifications:
|
||||||
|
U : JsModuleA.4.kt -> JsModuleA.kt
|
||||||
|
U : JsModuleB.0.kt -> JsModuleB.kt
|
||||||
|
modified ir: JsModuleA.kt, JsModuleB.kt
|
||||||
|
STEP 5:
|
||||||
|
modifications:
|
||||||
|
U : JsModuleA.1.kt -> JsModuleA.kt
|
||||||
|
modified ir: JsModuleA.kt
|
||||||
|
updated exports: JsModuleA.kt
|
||||||
|
STEP 6:
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
@file:JsModule("js-module-c")
|
||||||
|
|
||||||
|
external fun externalDemoFunction(): Int
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
@file:JsModule("js-module-c-new")
|
||||||
|
|
||||||
|
external fun externalDemoFunction(): Int
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
STEP 0:
|
||||||
|
dependencies: lib1
|
||||||
|
modifications:
|
||||||
|
U : test.0.kt -> test.kt
|
||||||
|
added file: test.kt
|
||||||
|
STEP 1..2:
|
||||||
|
dependencies: lib1
|
||||||
|
STEP 3:
|
||||||
|
dependencies: lib1
|
||||||
|
modifications:
|
||||||
|
U : test.3.kt -> test.kt
|
||||||
|
modified ir: test.kt
|
||||||
|
STEP 4:
|
||||||
|
dependencies: lib1
|
||||||
|
updated imports: test.kt
|
||||||
|
STEP 5:
|
||||||
|
dependencies: lib1
|
||||||
|
modifications:
|
||||||
|
U : JsModuleC.5.kt -> JsModuleC.kt
|
||||||
|
added file: JsModuleC.kt
|
||||||
|
updated exports: JsModuleC.kt
|
||||||
|
updated imports: test.kt
|
||||||
|
STEP 6:
|
||||||
|
dependencies: lib1
|
||||||
|
modifications:
|
||||||
|
U : JsModuleC.6.kt -> JsModuleC.kt
|
||||||
|
modified ir: JsModuleC.kt
|
||||||
|
updated imports: test.kt
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
fun testFunction() = demoFunction()
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
fun testFunction() = externalDemoFunction() + 1
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
fun box(stepId: Int): String {
|
||||||
|
val x = testFunction()
|
||||||
|
if (x != stepId) {
|
||||||
|
return "Fail: $x != $stepId"
|
||||||
|
}
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
STEP 0:
|
||||||
|
dependencies: lib1, lib2
|
||||||
|
added file: m.kt
|
||||||
|
STEP 1..6:
|
||||||
|
dependencies: lib1, lib2
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
MODULES: lib1, lib2, main
|
||||||
|
|
||||||
|
STEP 0:
|
||||||
|
libs: lib1, lib2, main
|
||||||
|
dirty js: lib1, lib2, main
|
||||||
|
STEP 1..2:
|
||||||
|
libs: lib1, lib2, main
|
||||||
|
dirty js: lib1
|
||||||
|
STEP 3..5:
|
||||||
|
libs: lib1, lib2, main
|
||||||
|
dirty js: lib1, lib2
|
||||||
|
STEP 6:
|
||||||
|
libs: lib1, lib2, main
|
||||||
|
dirty js: lib2
|
||||||
+2
-4
@@ -1,4 +1,2 @@
|
|||||||
declare namespace kotlin_main {
|
type Nullable<T> = T | null | undefined
|
||||||
type Nullable<T> = T | null | undefined
|
export declare function box(stepId: number): string;
|
||||||
function box(stepId: number): string;
|
|
||||||
}
|
|
||||||
+3
-5
@@ -1,5 +1,3 @@
|
|||||||
declare namespace kotlin_main {
|
type Nullable<T> = T | null | undefined
|
||||||
type Nullable<T> = T | null | undefined
|
export declare function foo(): number;
|
||||||
function foo(): number;
|
export declare function box(stepId: number): string;
|
||||||
function box(stepId: number): string;
|
|
||||||
}
|
|
||||||
+3
-5
@@ -1,5 +1,3 @@
|
|||||||
declare namespace kotlin_main {
|
type Nullable<T> = T | null | undefined
|
||||||
type Nullable<T> = T | null | undefined
|
export declare function bar(): number;
|
||||||
function bar(): number;
|
export declare function box(stepId: number): string;
|
||||||
function box(stepId: number): string;
|
|
||||||
}
|
|
||||||
+7
-9
@@ -1,10 +1,8 @@
|
|||||||
declare namespace kotlin_main {
|
type Nullable<T> = T | null | undefined
|
||||||
type Nullable<T> = T | null | undefined
|
export declare function bar(): number;
|
||||||
function bar(): number;
|
export declare class MyClass {
|
||||||
class MyClass {
|
constructor(stepId: number);
|
||||||
constructor(stepId: number);
|
get stepId(): number;
|
||||||
get stepId(): number;
|
qux(): number;
|
||||||
qux(): number;
|
|
||||||
}
|
|
||||||
function box(stepId: number): string;
|
|
||||||
}
|
}
|
||||||
|
export declare function box(stepId: number): string;
|
||||||
+6
-8
@@ -1,9 +1,7 @@
|
|||||||
declare namespace kotlin_main {
|
type Nullable<T> = T | null | undefined
|
||||||
type Nullable<T> = T | null | undefined
|
export declare class MyClass {
|
||||||
class MyClass {
|
constructor(stepId: number);
|
||||||
constructor(stepId: number);
|
get stepId(): number;
|
||||||
get stepId(): number;
|
qux(): number;
|
||||||
qux(): number;
|
|
||||||
}
|
|
||||||
function box(stepId: number): string;
|
|
||||||
}
|
}
|
||||||
|
export declare function box(stepId: number): string;
|
||||||
+6
-8
@@ -1,9 +1,7 @@
|
|||||||
declare namespace kotlin_main {
|
type Nullable<T> = T | null | undefined
|
||||||
type Nullable<T> = T | null | undefined
|
export declare class MyClass {
|
||||||
class MyClass {
|
constructor(stepId: number);
|
||||||
constructor(stepId: number);
|
get stepId(): number;
|
||||||
get stepId(): number;
|
baz(): number;
|
||||||
baz(): number;
|
|
||||||
}
|
|
||||||
function box(stepId: number): string;
|
|
||||||
}
|
}
|
||||||
|
export declare function box(stepId: number): string;
|
||||||
+6
-8
@@ -1,9 +1,7 @@
|
|||||||
declare namespace kotlin_main {
|
type Nullable<T> = T | null | undefined
|
||||||
type Nullable<T> = T | null | undefined
|
export declare class MyClass {
|
||||||
class MyClass {
|
constructor(stepId: number);
|
||||||
constructor(stepId: number);
|
get stepId(): number;
|
||||||
get stepId(): number;
|
bar(): number;
|
||||||
bar(): number;
|
|
||||||
}
|
|
||||||
function box(stepId: number): string;
|
|
||||||
}
|
}
|
||||||
|
export declare function box(stepId: number): string;
|
||||||
Reference in New Issue
Block a user