[JS IR] Pass forward -Xir-property-lazy-initialization option
Pass forward -Xir-property-lazy-initialization option for the incremental cache. ^KT-50175 Fixed
This commit is contained in:
committed by
Space
parent
2f853175c7
commit
59173baf5a
@@ -153,6 +153,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
|||||||
val sourcesFiles = environmentForJS.getSourceFiles()
|
val sourcesFiles = environmentForJS.getSourceFiles()
|
||||||
|
|
||||||
configurationJs.put(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE, arguments.allowKotlinPackage)
|
configurationJs.put(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE, arguments.allowKotlinPackage)
|
||||||
|
configurationJs.put(JSConfigurationKeys.PROPERTY_LAZY_INITIALIZATION, arguments.irPropertyLazyInitialization)
|
||||||
|
|
||||||
if (!checkKotlinPackageUsage(environmentForJS.configuration, sourcesFiles)) return ExitCode.COMPILATION_ERROR
|
if (!checkKotlinPackageUsage(environmentForJS.configuration, sourcesFiles)) return ExitCode.COMPILATION_ERROR
|
||||||
|
|
||||||
@@ -388,7 +389,6 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
|||||||
arguments.irDceRuntimeDiagnostic,
|
arguments.irDceRuntimeDiagnostic,
|
||||||
messageCollector
|
messageCollector
|
||||||
),
|
),
|
||||||
propertyLazyInitialization = arguments.irPropertyLazyInitialization,
|
|
||||||
baseClassIntoMetadata = arguments.irBaseClassInMetadata,
|
baseClassIntoMetadata = arguments.irBaseClassInMetadata,
|
||||||
safeExternalBoolean = arguments.irSafeExternalBoolean,
|
safeExternalBoolean = arguments.irSafeExternalBoolean,
|
||||||
safeExternalBooleanDiagnostic = RuntimeDiagnostic.resolve(
|
safeExternalBooleanDiagnostic = RuntimeDiagnostic.resolve(
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ class JsIrBackendContext(
|
|||||||
override val scriptMode: Boolean = false,
|
override val scriptMode: Boolean = false,
|
||||||
override val es6mode: Boolean = false,
|
override val es6mode: Boolean = false,
|
||||||
val dceRuntimeDiagnostic: RuntimeDiagnostic? = null,
|
val dceRuntimeDiagnostic: RuntimeDiagnostic? = null,
|
||||||
propertyLazyInitialization: Boolean = false,
|
|
||||||
val baseClassIntoMetadata: Boolean = false,
|
val baseClassIntoMetadata: Boolean = false,
|
||||||
val safeExternalBoolean: Boolean = false,
|
val safeExternalBoolean: Boolean = false,
|
||||||
val safeExternalBooleanDiagnostic: RuntimeDiagnostic? = null,
|
val safeExternalBooleanDiagnostic: RuntimeDiagnostic? = null,
|
||||||
@@ -141,7 +140,7 @@ class JsIrBackendContext(
|
|||||||
override val reflectionSymbols: ReflectionSymbols get() = intrinsics.reflectionSymbols
|
override val reflectionSymbols: ReflectionSymbols get() = intrinsics.reflectionSymbols
|
||||||
|
|
||||||
override val propertyLazyInitialization: PropertyLazyInitialization = PropertyLazyInitialization(
|
override val propertyLazyInitialization: PropertyLazyInitialization = PropertyLazyInitialization(
|
||||||
enabled = propertyLazyInitialization,
|
enabled = configuration.getBoolean(JSConfigurationKeys.PROPERTY_LAZY_INITIALIZATION),
|
||||||
eagerInitialization = symbolTable.referenceClass(getJsInternalClass("EagerInitialization"))
|
eagerInitialization = symbolTable.referenceClass(getJsInternalClass("EagerInitialization"))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ fun compile(
|
|||||||
exportedDeclarations: Set<FqName> = emptySet(),
|
exportedDeclarations: Set<FqName> = emptySet(),
|
||||||
dceRuntimeDiagnostic: RuntimeDiagnostic? = null,
|
dceRuntimeDiagnostic: RuntimeDiagnostic? = null,
|
||||||
es6mode: Boolean = false,
|
es6mode: Boolean = false,
|
||||||
propertyLazyInitialization: Boolean,
|
|
||||||
verifySignatures: Boolean = true,
|
verifySignatures: Boolean = true,
|
||||||
baseClassIntoMetadata: Boolean = false,
|
baseClassIntoMetadata: Boolean = false,
|
||||||
safeExternalBoolean: Boolean = false,
|
safeExternalBoolean: Boolean = false,
|
||||||
@@ -76,7 +75,6 @@ fun compile(
|
|||||||
exportedDeclarations,
|
exportedDeclarations,
|
||||||
dceRuntimeDiagnostic,
|
dceRuntimeDiagnostic,
|
||||||
es6mode,
|
es6mode,
|
||||||
propertyLazyInitialization,
|
|
||||||
baseClassIntoMetadata,
|
baseClassIntoMetadata,
|
||||||
safeExternalBoolean,
|
safeExternalBoolean,
|
||||||
safeExternalBooleanDiagnostic,
|
safeExternalBooleanDiagnostic,
|
||||||
@@ -97,7 +95,6 @@ fun compileIr(
|
|||||||
exportedDeclarations: Set<FqName>,
|
exportedDeclarations: Set<FqName>,
|
||||||
dceRuntimeDiagnostic: RuntimeDiagnostic?,
|
dceRuntimeDiagnostic: RuntimeDiagnostic?,
|
||||||
es6mode: Boolean,
|
es6mode: Boolean,
|
||||||
propertyLazyInitialization: Boolean,
|
|
||||||
baseClassIntoMetadata: Boolean,
|
baseClassIntoMetadata: Boolean,
|
||||||
safeExternalBoolean: Boolean,
|
safeExternalBoolean: Boolean,
|
||||||
safeExternalBooleanDiagnostic: RuntimeDiagnostic?,
|
safeExternalBooleanDiagnostic: RuntimeDiagnostic?,
|
||||||
@@ -123,7 +120,6 @@ fun compileIr(
|
|||||||
configuration,
|
configuration,
|
||||||
es6mode = es6mode,
|
es6mode = es6mode,
|
||||||
dceRuntimeDiagnostic = dceRuntimeDiagnostic,
|
dceRuntimeDiagnostic = dceRuntimeDiagnostic,
|
||||||
propertyLazyInitialization = propertyLazyInitialization,
|
|
||||||
baseClassIntoMetadata = baseClassIntoMetadata,
|
baseClassIntoMetadata = baseClassIntoMetadata,
|
||||||
safeExternalBoolean = safeExternalBoolean,
|
safeExternalBoolean = safeExternalBoolean,
|
||||||
safeExternalBooleanDiagnostic = safeExternalBooleanDiagnostic,
|
safeExternalBooleanDiagnostic = safeExternalBooleanDiagnostic,
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ fun compileWithIC(
|
|||||||
es6mode: Boolean = false,
|
es6mode: Boolean = false,
|
||||||
multiModule: Boolean = false,
|
multiModule: Boolean = false,
|
||||||
relativeRequirePath: Boolean = false,
|
relativeRequirePath: Boolean = false,
|
||||||
propertyLazyInitialization: Boolean = false,
|
|
||||||
verifySignatures: Boolean = true,
|
verifySignatures: Boolean = true,
|
||||||
baseClassIntoMetadata: Boolean = false,
|
baseClassIntoMetadata: Boolean = false,
|
||||||
lowerPerModule: Boolean = false,
|
lowerPerModule: Boolean = false,
|
||||||
@@ -67,7 +66,6 @@ fun compileWithIC(
|
|||||||
configuration,
|
configuration,
|
||||||
es6mode = es6mode,
|
es6mode = es6mode,
|
||||||
dceRuntimeDiagnostic = dceRuntimeDiagnostic,
|
dceRuntimeDiagnostic = dceRuntimeDiagnostic,
|
||||||
propertyLazyInitialization = propertyLazyInitialization,
|
|
||||||
baseClassIntoMetadata = baseClassIntoMetadata,
|
baseClassIntoMetadata = baseClassIntoMetadata,
|
||||||
safeExternalBoolean = safeExternalBoolean,
|
safeExternalBoolean = safeExternalBoolean,
|
||||||
safeExternalBooleanDiagnostic = safeExternalBooleanDiagnostic,
|
safeExternalBooleanDiagnostic = safeExternalBooleanDiagnostic,
|
||||||
|
|||||||
@@ -9,12 +9,13 @@ import java.io.File
|
|||||||
import java.io.PrintWriter
|
import java.io.PrintWriter
|
||||||
|
|
||||||
// TODO md5 hash
|
// TODO md5 hash
|
||||||
data class CacheInfo(val path: String, val libPath: String, var flatHash: ULong, var transHash: ULong) {
|
data class CacheInfo(val path: String, val libPath: String, var flatHash: ULong, var transHash: ULong, var configHash: ULong) {
|
||||||
fun save() {
|
fun save() {
|
||||||
PrintWriter(File(File(path), "info")).use {
|
PrintWriter(File(File(path), "info")).use {
|
||||||
it.println(libPath)
|
it.println(libPath)
|
||||||
it.println(flatHash.toString(16))
|
it.println(flatHash.toString(16))
|
||||||
it.println(transHash.toString(16))
|
it.println(transHash.toString(16))
|
||||||
|
it.println(configHash.toString(16))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,9 +25,11 @@ data class CacheInfo(val path: String, val libPath: String, var flatHash: ULong,
|
|||||||
|
|
||||||
if (!info.exists()) return null
|
if (!info.exists()) return null
|
||||||
|
|
||||||
val (libPath, flatHash, transHash) = info.readLines()
|
val (libPath, flatHash, transHash, configHash) = info.readLines()
|
||||||
|
|
||||||
return CacheInfo(path, libPath, flatHash.toULong(16), transHash.toULong(16))
|
// safe cast for the backward compatibility with the cache from the previous compiler versions
|
||||||
|
val configHashULong = configHash.toULongOrNull(16) ?: 0UL
|
||||||
|
return CacheInfo(path, libPath, flatHash.toULong(16), transHash.toULong(16), configHashULong)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,8 @@ private fun invalidateCacheForModule(
|
|||||||
cacheProvider: PersistentCacheProvider,
|
cacheProvider: PersistentCacheProvider,
|
||||||
cacheConsumer: PersistentCacheConsumer,
|
cacheConsumer: PersistentCacheConsumer,
|
||||||
signatureResolver: (String, Int) -> IdSignature,
|
signatureResolver: (String, Int) -> IdSignature,
|
||||||
fileFingerPrints: MutableMap<String, Hash>
|
fileFingerPrints: MutableMap<String, Hash>,
|
||||||
|
configUpdated: Boolean
|
||||||
): Pair<Set<String>, Collection<String>> {
|
): Pair<Set<String>, Collection<String>> {
|
||||||
|
|
||||||
val dirtyFiles = mutableSetOf<String>()
|
val dirtyFiles = mutableSetOf<String>()
|
||||||
@@ -64,7 +65,7 @@ private fun invalidateCacheForModule(
|
|||||||
// 2. calculate new fingerprints
|
// 2. calculate new fingerprints
|
||||||
val fileNewFingerprint = library.fingerprint(index)
|
val fileNewFingerprint = library.fingerprint(index)
|
||||||
|
|
||||||
if (fileOldFingerprint != fileNewFingerprint) {
|
if (fileOldFingerprint != fileNewFingerprint || configUpdated) {
|
||||||
fileFingerPrints[file] = fileNewFingerprint
|
fileFingerPrints[file] = fileNewFingerprint
|
||||||
cachedInlineHashesForFile.remove(file)
|
cachedInlineHashesForFile.remove(file)
|
||||||
|
|
||||||
@@ -203,9 +204,25 @@ private fun buildCacheForModule(
|
|||||||
|
|
||||||
// TODO: actual way of building a cache could change in future
|
// TODO: actual way of building a cache could change in future
|
||||||
|
|
||||||
cacheExecutor.execute(irModule, dependencies, deserializer, configuration, dirtyFiles, deletedFiles, cacheConsumer, emptySet(), mainArguments)
|
cacheExecutor.execute(
|
||||||
|
irModule,
|
||||||
|
dependencies,
|
||||||
|
deserializer,
|
||||||
|
configuration,
|
||||||
|
dirtyFiles,
|
||||||
|
deletedFiles,
|
||||||
|
cacheConsumer,
|
||||||
|
emptySet(),
|
||||||
|
mainArguments
|
||||||
|
)
|
||||||
|
|
||||||
cacheConsumer.commitLibraryInfo(libraryInfo.libPath.toCanonicalPath(), libraryInfo.flatHash, libraryInfo.transHash, irModule.name.asString())
|
cacheConsumer.commitLibraryInfo(
|
||||||
|
libraryInfo.libPath.toCanonicalPath(),
|
||||||
|
libraryInfo.flatHash,
|
||||||
|
libraryInfo.transHash,
|
||||||
|
libraryInfo.configHash,
|
||||||
|
irModule.name.asString()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadModules(
|
private fun loadModules(
|
||||||
@@ -315,24 +332,11 @@ fun interface CacheExecutor {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun File.md5(): ULong {
|
private fun calcMD5(feeder: (MessageDigest) -> Unit): ULong {
|
||||||
val md5 = MessageDigest.getInstance("MD5")
|
val md5 = MessageDigest.getInstance("MD5")
|
||||||
|
feeder(md5)
|
||||||
fun File.process(prefix: String = "") {
|
|
||||||
if (isDirectory) {
|
|
||||||
this.listFiles()!!.sortedBy { it.name }.forEach {
|
|
||||||
md5.update((prefix + it.name).toByteArray())
|
|
||||||
it.process(prefix + it.name + "/")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
md5.update(readBytes())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.process()
|
|
||||||
|
|
||||||
val d = md5.digest()
|
val d = md5.digest()
|
||||||
|
|
||||||
return ((d[0].toULong() and 0xFFUL)
|
return ((d[0].toULong() and 0xFFUL)
|
||||||
or ((d[1].toULong() and 0xFFUL) shl 8)
|
or ((d[1].toULong() and 0xFFUL) shl 8)
|
||||||
or ((d[2].toULong() and 0xFFUL) shl 16)
|
or ((d[2].toULong() and 0xFFUL) shl 16)
|
||||||
@@ -344,6 +348,30 @@ private fun File.md5(): ULong {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun File.md5(): ULong {
|
||||||
|
fun File.process(md5: MessageDigest, prefix: String = "") {
|
||||||
|
if (isDirectory) {
|
||||||
|
this.listFiles()!!.sortedBy { it.name }.forEach {
|
||||||
|
md5.update((prefix + it.name).toByteArray())
|
||||||
|
it.process(md5, prefix + it.name + "/")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
md5.update(readBytes())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return calcMD5 { this.process(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun CompilerConfiguration.calcMD5(): ULong {
|
||||||
|
val importantBooleanSettingKeys = listOf(JSConfigurationKeys.PROPERTY_LAZY_INITIALIZATION)
|
||||||
|
return calcMD5 {
|
||||||
|
for (key in importantBooleanSettingKeys) {
|
||||||
|
it.update(key.toString().toByteArray())
|
||||||
|
it.update(getBoolean(key).toString().toByteArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun checkLibrariesHash(
|
private fun checkLibrariesHash(
|
||||||
libraries: Map<ModulePath, KotlinLibrary>,
|
libraries: Map<ModulePath, KotlinLibrary>,
|
||||||
dependencyGraph: Map<KotlinLibrary, List<KotlinLibrary>>,
|
dependencyGraph: Map<KotlinLibrary, List<KotlinLibrary>>,
|
||||||
@@ -391,8 +419,9 @@ fun actualizeCacheForModule(
|
|||||||
mainArguments: List<String>?,
|
mainArguments: List<String>?,
|
||||||
executor: CacheExecutor
|
executor: CacheExecutor
|
||||||
): CacheUpdateStatus {
|
): CacheUpdateStatus {
|
||||||
|
val configMD5 = compilerConfiguration.calcMD5()
|
||||||
val modulePath = moduleName.toCanonicalPath()
|
val modulePath = moduleName.toCanonicalPath()
|
||||||
val cacheInfo = CacheInfo.load(cachePath) ?: CacheInfo(cachePath, modulePath, 0UL, 0UL)
|
val cacheInfo = CacheInfo.load(cachePath) ?: CacheInfo(cachePath, modulePath, 0UL, 0UL, configMD5)
|
||||||
val icCacheMap: Map<ModulePath, CacheInfo> = loadCacheInfo(icCachePaths).also {
|
val icCacheMap: Map<ModulePath, CacheInfo> = loadCacheInfo(icCachePaths).also {
|
||||||
it[modulePath] = cacheInfo
|
it[modulePath] = cacheInfo
|
||||||
}
|
}
|
||||||
@@ -405,7 +434,9 @@ fun actualizeCacheForModule(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkLibrariesHash(libraries, dependencyGraph, icCacheMap, modulePath)) {
|
val configUpdated = configMD5 != cacheInfo.configHash
|
||||||
|
cacheInfo.configHash = configMD5
|
||||||
|
if (checkLibrariesHash(libraries, dependencyGraph, icCacheMap, modulePath) && !configUpdated) {
|
||||||
return CacheUpdateStatus.FAST_PATH // up-to-date
|
return CacheUpdateStatus.FAST_PATH // up-to-date
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -425,7 +456,8 @@ fun actualizeCacheForModule(
|
|||||||
persistentCacheConsumer,
|
persistentCacheConsumer,
|
||||||
irFactory,
|
irFactory,
|
||||||
mainArguments,
|
mainArguments,
|
||||||
executor
|
executor,
|
||||||
|
configUpdated
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,7 +471,8 @@ private fun actualizeCacheForModule(
|
|||||||
persistentCacheConsumer: PersistentCacheConsumer,
|
persistentCacheConsumer: PersistentCacheConsumer,
|
||||||
irFactory: IrFactory,
|
irFactory: IrFactory,
|
||||||
mainArguments: List<String>?,
|
mainArguments: List<String>?,
|
||||||
cacheExecutor: CacheExecutor
|
cacheExecutor: CacheExecutor,
|
||||||
|
configUpdated: Boolean
|
||||||
): CacheUpdateStatus {
|
): CacheUpdateStatus {
|
||||||
// 1. Invalidate
|
// 1. Invalidate
|
||||||
val dependencies = dependencyGraph[library]!!
|
val dependencies = dependencyGraph[library]!!
|
||||||
@@ -486,7 +519,8 @@ private fun actualizeCacheForModule(
|
|||||||
currentLibraryCacheProvider,
|
currentLibraryCacheProvider,
|
||||||
persistentCacheConsumer,
|
persistentCacheConsumer,
|
||||||
signatureResolver,
|
signatureResolver,
|
||||||
fileFingerPrints
|
fileFingerPrints,
|
||||||
|
configUpdated
|
||||||
)
|
)
|
||||||
|
|
||||||
if (dirtySet.isEmpty()) return CacheUpdateStatus.NO_DIRTY_FILES // up-to-date
|
if (dirtySet.isEmpty()) return CacheUpdateStatus.NO_DIRTY_FILES // up-to-date
|
||||||
@@ -582,7 +616,7 @@ fun rebuildCacheForDirtyFiles(
|
|||||||
|
|
||||||
val currentIrModule = irModules.find { it.second == library }?.first!!
|
val currentIrModule = irModules.find { it.second == library }?.first!!
|
||||||
|
|
||||||
cacheConsumer.commitLibraryInfo(library.libraryFile.path.toCanonicalPath(), 0UL, 0UL, currentIrModule.name.asString())
|
cacheConsumer.commitLibraryInfo(library.libraryFile.path.toCanonicalPath(), 0UL, 0UL, 0UL, currentIrModule.name.asString())
|
||||||
|
|
||||||
buildCacheForModuleFiles(
|
buildCacheForModuleFiles(
|
||||||
currentIrModule,
|
currentIrModule,
|
||||||
|
|||||||
+4
-3
@@ -203,7 +203,7 @@ interface PersistentCacheConsumer {
|
|||||||
fun commitSourceMap(path: String, mapData: ByteArray)
|
fun commitSourceMap(path: String, mapData: ByteArray)
|
||||||
fun invalidateForFile(path: String)
|
fun invalidateForFile(path: String)
|
||||||
|
|
||||||
fun commitLibraryInfo(libraryPath: String, flatHash: ULong, transHash: ULong, moduleName: String)
|
fun commitLibraryInfo(libraryPath: String, flatHash: ULong, transHash: ULong, configHash: ULong, moduleName: String)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val EMPTY = object : PersistentCacheConsumer {
|
val EMPTY = object : PersistentCacheConsumer {
|
||||||
@@ -231,7 +231,7 @@ interface PersistentCacheConsumer {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun commitLibraryInfo(libraryPath: String, flatHash: ULong, transHash: ULong, moduleName: String) {
|
override fun commitLibraryInfo(libraryPath: String, flatHash: ULong, transHash: ULong, configHash: ULong, moduleName: String) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,7 +324,7 @@ class PersistentCacheConsumerImpl(private val cachePath: String) : PersistentCac
|
|||||||
commitByteArrayToCacheFile(path, fileSourceMap, mapData)
|
commitByteArrayToCacheFile(path, fileSourceMap, mapData)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun commitLibraryInfo(libraryPath: String, flatHash: ULong, transHash: ULong, moduleName: String) {
|
override fun commitLibraryInfo(libraryPath: String, flatHash: ULong, transHash: ULong, configHash: ULong, moduleName: String) {
|
||||||
val infoFile = File(File(cachePath), "info")
|
val infoFile = File(File(cachePath), "info")
|
||||||
if (infoFile.exists()) {
|
if (infoFile.exists()) {
|
||||||
infoFile.delete()
|
infoFile.delete()
|
||||||
@@ -335,6 +335,7 @@ class PersistentCacheConsumerImpl(private val cachePath: String) : PersistentCac
|
|||||||
it.println(libraryPath)
|
it.println(libraryPath)
|
||||||
it.println(flatHash.toString(16))
|
it.println(flatHash.toString(16))
|
||||||
it.println(transHash.toString(16))
|
it.println(transHash.toString(16))
|
||||||
|
it.println(configHash.toString(16))
|
||||||
it.println(moduleName)
|
it.println(moduleName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
|||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.config.CompilerConfigurationKey
|
import org.jetbrains.kotlin.config.CompilerConfigurationKey
|
||||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||||
|
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||||
import org.jetbrains.kotlin.platform.isCommon
|
import org.jetbrains.kotlin.platform.isCommon
|
||||||
import org.jetbrains.kotlin.platform.js.isJs
|
import org.jetbrains.kotlin.platform.js.isJs
|
||||||
import org.jetbrains.kotlin.platform.jvm.isJvm
|
import org.jetbrains.kotlin.platform.jvm.isJvm
|
||||||
@@ -26,6 +27,7 @@ import org.jetbrains.kotlin.platform.konan.isNative
|
|||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.test.ApplicationEnvironmentDisposer
|
import org.jetbrains.kotlin.test.ApplicationEnvironmentDisposer
|
||||||
import org.jetbrains.kotlin.test.TestInfrastructureInternals
|
import org.jetbrains.kotlin.test.TestInfrastructureInternals
|
||||||
|
import org.jetbrains.kotlin.test.directives.JsEnvironmentConfigurationDirectives
|
||||||
import org.jetbrains.kotlin.test.model.FrontendKinds
|
import org.jetbrains.kotlin.test.model.FrontendKinds
|
||||||
import org.jetbrains.kotlin.test.model.TestFile
|
import org.jetbrains.kotlin.test.model.TestFile
|
||||||
import org.jetbrains.kotlin.test.model.TestModule
|
import org.jetbrains.kotlin.test.model.TestModule
|
||||||
@@ -98,6 +100,9 @@ open class CompilerConfigurationProviderImpl(
|
|||||||
fun createCompilerConfiguration(module: TestModule): CompilerConfiguration {
|
fun createCompilerConfiguration(module: TestModule): CompilerConfiguration {
|
||||||
val configuration = CompilerConfiguration()
|
val configuration = CompilerConfiguration()
|
||||||
configuration[CommonConfigurationKeys.MODULE_NAME] = module.name
|
configuration[CommonConfigurationKeys.MODULE_NAME] = module.name
|
||||||
|
if (JsEnvironmentConfigurationDirectives.PROPERTY_LAZY_INITIALIZATION in module.directives) {
|
||||||
|
configuration.put(JSConfigurationKeys.PROPERTY_LAZY_INITIALIZATION, true)
|
||||||
|
}
|
||||||
|
|
||||||
if (module.frontendKind == FrontendKinds.FIR) {
|
if (module.frontendKind == FrontendKinds.FIR) {
|
||||||
configuration[CommonConfigurationKeys.USE_FIR] = true
|
configuration[CommonConfigurationKeys.USE_FIR] = true
|
||||||
|
|||||||
@@ -96,4 +96,7 @@ public class JSConfigurationKeys {
|
|||||||
|
|
||||||
public static final CompilerConfigurationKey<Boolean> PARTIAL_LINKAGE =
|
public static final CompilerConfigurationKey<Boolean> PARTIAL_LINKAGE =
|
||||||
CompilerConfigurationKey.create("allows some symbols in klibs be missed");
|
CompilerConfigurationKey.create("allows some symbols in klibs be missed");
|
||||||
|
|
||||||
|
public static final CompilerConfigurationKey<Boolean> PROPERTY_LAZY_INITIALIZATION =
|
||||||
|
CompilerConfigurationKey.create("perform lazy initialization for properties");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ abstract class AbstractJsKLibABITestCase : AbstractKlibABITestCase() {
|
|||||||
override fun compileBinaryAndRun(project: Project, configuration: CompilerConfiguration, libraries: Collection<String>, mainModulePath: String, buildDir: File) {
|
override fun compileBinaryAndRun(project: Project, configuration: CompilerConfiguration, libraries: Collection<String>, mainModulePath: String, buildDir: File) {
|
||||||
configuration.put(JSConfigurationKeys.PARTIAL_LINKAGE, true)
|
configuration.put(JSConfigurationKeys.PARTIAL_LINKAGE, true)
|
||||||
configuration.put(JSConfigurationKeys.MODULE_KIND, ModuleKind.PLAIN)
|
configuration.put(JSConfigurationKeys.MODULE_KIND, ModuleKind.PLAIN)
|
||||||
|
configuration.put(JSConfigurationKeys.PROPERTY_LAZY_INITIALIZATION, true)
|
||||||
configuration.put(CommonConfigurationKeys.MODULE_NAME, MAIN_MODULE_NAME)
|
configuration.put(CommonConfigurationKeys.MODULE_NAME, MAIN_MODULE_NAME)
|
||||||
val kLib = MainModule.Klib(mainModulePath)
|
val kLib = MainModule.Klib(mainModulePath)
|
||||||
val moduleStructure = ModulesStructure(project, kLib, configuration, libraries, emptyList())
|
val moduleStructure = ModulesStructure(project, kLib, configuration, libraries, emptyList())
|
||||||
@@ -38,7 +39,6 @@ abstract class AbstractJsKLibABITestCase : AbstractKlibABITestCase() {
|
|||||||
PhaseConfig(jsPhases),
|
PhaseConfig(jsPhases),
|
||||||
IrFactoryImplForJsIC(WholeWorldStageController()),
|
IrFactoryImplForJsIC(WholeWorldStageController()),
|
||||||
exportedDeclarations = setOf(FqName("box")),
|
exportedDeclarations = setOf(FqName("box")),
|
||||||
propertyLazyInitialization = true,
|
|
||||||
granularity = JsGenerationGranularity.PER_MODULE,
|
granularity = JsGenerationGranularity.PER_MODULE,
|
||||||
icCompatibleIr2Js = true
|
icCompatibleIr2Js = true
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ class JsIrBackendFacade(
|
|||||||
|
|
||||||
override fun transform(module: TestModule, inputArtifact: BinaryArtifacts.KLib): BinaryArtifacts.Js? {
|
override fun transform(module: TestModule, inputArtifact: BinaryArtifacts.KLib): BinaryArtifacts.Js? {
|
||||||
val configuration = testServices.compilerConfigurationProvider.getCompilerConfiguration(module)
|
val configuration = testServices.compilerConfigurationProvider.getCompilerConfiguration(module)
|
||||||
|
|
||||||
val isMainModule = JsEnvironmentConfigurator.isMainModule(module, testServices)
|
val isMainModule = JsEnvironmentConfigurator.isMainModule(module, testServices)
|
||||||
if (!isMainModule) return null
|
if (!isMainModule) return null
|
||||||
|
|
||||||
@@ -133,7 +134,6 @@ class JsIrBackendFacade(
|
|||||||
exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, TEST_FUNCTION))),
|
exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, TEST_FUNCTION))),
|
||||||
dceRuntimeDiagnostic = null,
|
dceRuntimeDiagnostic = null,
|
||||||
es6mode = false,
|
es6mode = false,
|
||||||
propertyLazyInitialization = JsEnvironmentConfigurationDirectives.PROPERTY_LAZY_INITIALIZATION in module.directives,
|
|
||||||
baseClassIntoMetadata = false,
|
baseClassIntoMetadata = false,
|
||||||
safeExternalBoolean = JsEnvironmentConfigurationDirectives.SAFE_EXTERNAL_BOOLEAN in module.directives,
|
safeExternalBoolean = JsEnvironmentConfigurationDirectives.SAFE_EXTERNAL_BOOLEAN in module.directives,
|
||||||
safeExternalBooleanDiagnostic = module.directives[JsEnvironmentConfigurationDirectives.SAFE_EXTERNAL_BOOLEAN_DIAGNOSTIC].singleOrNull(),
|
safeExternalBooleanDiagnostic = module.directives[JsEnvironmentConfigurationDirectives.SAFE_EXTERNAL_BOOLEAN_DIAGNOSTIC].singleOrNull(),
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ class TestModuleCache(val files: MutableMap<String, FileCache>) {
|
|||||||
files.remove(path)
|
files.remove(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun commitLibraryInfo(libraryPath: String, flatHash: ULong, transHash: ULong, moduleName: String) {
|
override fun commitLibraryInfo(libraryPath: String, flatHash: ULong, transHash: ULong, configHash: ULong, moduleName: String) {
|
||||||
storedModuleName = moduleName
|
storedModuleName = moduleName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+45
@@ -124,6 +124,51 @@ class Kotlin2JsIrGradlePluginIT : AbstractKotlin2JsGradlePluginIT(true) {
|
|||||||
build("assemble")
|
build("assemble")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DisplayName("Check IR incremental cache invalidation by compiler args")
|
||||||
|
@GradleTest
|
||||||
|
fun testJsIrIncrementalCacheInvalidationByArgs(gradleVersion: GradleVersion) {
|
||||||
|
project("kotlin2JsIrICProject", gradleVersion) {
|
||||||
|
val buildConfig = buildGradleKts.readText()
|
||||||
|
|
||||||
|
fun setLazyInitializationArg(value: Boolean) {
|
||||||
|
buildGradleKts.writeText(buildConfig)
|
||||||
|
buildGradleKts.appendText(
|
||||||
|
"""
|
||||||
|
|
|
||||||
|
|tasks.named<org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrLink>("compileDevelopmentExecutableKotlinJs") {
|
||||||
|
| kotlinOptions {
|
||||||
|
| freeCompilerArgs += "-Xir-property-lazy-initialization=$value"
|
||||||
|
| }
|
||||||
|
|}
|
||||||
|
""".trimMargin()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun String.testScriptOutLines() = this.lines().mapNotNull {
|
||||||
|
val trimmed = it.removePrefix(">>> TEST OUT: ")
|
||||||
|
if (trimmed == it) null else trimmed
|
||||||
|
}
|
||||||
|
|
||||||
|
// -Xir-property-lazy-initialization default is true
|
||||||
|
build("nodeRun") {
|
||||||
|
assertTasksExecuted(":compileDevelopmentExecutableKotlinJs")
|
||||||
|
assertEquals(listOf("Hello, Gradle."), output.testScriptOutLines())
|
||||||
|
}
|
||||||
|
|
||||||
|
setLazyInitializationArg(false)
|
||||||
|
build("nodeRun") {
|
||||||
|
assertTasksExecuted(":compileDevelopmentExecutableKotlinJs")
|
||||||
|
assertEquals(listOf("TOP LEVEL!", "Hello, Gradle."), output.testScriptOutLines())
|
||||||
|
}
|
||||||
|
|
||||||
|
setLazyInitializationArg(true)
|
||||||
|
build("nodeRun") {
|
||||||
|
assertTasksExecuted(":compileDevelopmentExecutableKotlinJs")
|
||||||
|
assertEquals(listOf("Hello, Gradle."), output.testScriptOutLines())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsGradlePluginTests
|
@JsGradlePluginTests
|
||||||
|
|||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("js")
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "com.example"
|
||||||
|
version = "1.0"
|
||||||
|
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
mavenLocal()
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
js(IR) {
|
||||||
|
binaries.executable()
|
||||||
|
nodejs {}
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
kotlin.code.style=official
|
||||||
|
kotlin.incremental.js.ir=true
|
||||||
|
kotlin.incremental.js.klib=true
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
fun main() {
|
||||||
|
println(greeting("Gradle"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun greeting(name: String) = ">>> TEST OUT: Hello, $name."
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
@JsExport
|
||||||
|
val topLevelForLazy = { println(">>> TEST OUT: TOP LEVEL!"); 0 }()
|
||||||
Reference in New Issue
Block a user