diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt index 9bc10560112..6a78b2854b6 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt @@ -10,7 +10,6 @@ import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.common.runOnFilePostfix import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.ir.backend.js.lower.* import org.jetbrains.kotlin.ir.backend.js.lower.inline.* import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer @@ -23,8 +22,6 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator -import org.jetbrains.kotlin.serialization.js.JsModuleDescriptor -import org.jetbrains.kotlin.serialization.js.ModuleKind data class Result(val moduleDescriptor: ModuleDescriptor, val generatedCode: String) @@ -35,12 +32,8 @@ fun compile( export: FqName? = null, dependencies: List = listOf() ): Result { - val moduleDescriptors = - dependencies - .filterIsInstance() - .map { JsModuleDescriptor("", ModuleKind.PLAIN, listOf(), it) } - - val analysisResult = TopDownAnalyzerFacadeForJS.analyzeFiles(files, project, configuration, moduleDescriptors, emptyList()) + val analysisResult = + TopDownAnalyzerFacadeForJS.analyzeFiles(files, project, configuration, dependencies.filterIsInstance(), emptyList()) ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTestWithJsStdLib.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTestWithJsStdLib.kt index a2899b35a83..8ea2f1d15ed 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTestWithJsStdLib.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTestWithJsStdLib.kt @@ -77,7 +77,7 @@ abstract class AbstractDiagnosticsTestWithJsStdLib : AbstractDiagnosticsTest() { } override fun getAdditionalDependencies(module: ModuleDescriptorImpl): List = - config.moduleDescriptors.map { it.data } + config.moduleDescriptors override fun shouldSkipJvmSignatureDiagnostics(groupedByModule: Map>): Boolean = true diff --git a/compiler/tests/org/jetbrains/kotlin/serialization/js/KotlinJavascriptSerializerTest.kt b/compiler/tests/org/jetbrains/kotlin/serialization/js/KotlinJavascriptSerializerTest.kt index fce2c0879a7..84694d7a997 100644 --- a/compiler/tests/org/jetbrains/kotlin/serialization/js/KotlinJavascriptSerializerTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/serialization/js/KotlinJavascriptSerializerTest.kt @@ -33,6 +33,7 @@ import org.jetbrains.kotlin.js.config.JsConfig import org.jetbrains.kotlin.js.resolve.JsPlatform import org.jetbrains.kotlin.jvm.compiler.LoadDescriptorUtil.TEST_PACKAGE_FQNAME import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration +import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil.readModuleAsProto import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.TestCaseWithTmpdir @@ -94,9 +95,10 @@ class KotlinJavascriptSerializerTest : TestCaseWithTmpdir() { val metadata = KotlinJavascriptMetadataUtils.loadMetadata(metaFile) assert(metadata.size == 1) - val provider = KotlinJavascriptSerializationUtil.readModule( - metadata.single().body, LockBasedStorageManager(), module, DeserializationConfiguration.Default, LookupTracker.DO_NOTHING - ).data.sure { "No package fragment provider was created" } + val (header, packageFragmentProtos) = readModuleAsProto(metadata.single().body) + val provider = createKotlinJavascriptPackageFragmentProvider( + LockBasedStorageManager(), module, header, packageFragmentProtos, DeserializationConfiguration.Default, LookupTracker.DO_NOTHING + ).sure { "No package fragment provider was created" } module.initialize(provider) module.setDependencies(module, module.builtIns.builtInsModule) diff --git a/idea/ide-common/src/org/jetbrains/kotlin/caches/resolve/JsAnalyzerFacade.kt b/idea/ide-common/src/org/jetbrains/kotlin/caches/resolve/JsAnalyzerFacade.kt index 6df4c82c39d..d6da1f963ea 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/caches/resolve/JsAnalyzerFacade.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/caches/resolve/JsAnalyzerFacade.kt @@ -32,8 +32,8 @@ import org.jetbrains.kotlin.resolve.TargetEnvironment import org.jetbrains.kotlin.resolve.TargetPlatform import org.jetbrains.kotlin.resolve.lazy.ResolveSession import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService -import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil +import org.jetbrains.kotlin.serialization.js.createKotlinJavascriptPackageFragmentProvider import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils object JsAnalyzerFacade : ResolverForModuleFactory() { @@ -72,11 +72,12 @@ object JsAnalyzerFacade : ResolverForModuleFactory() { val providers = moduleInfo.getLibraryRoots() .flatMap { KotlinJavascriptMetadataUtils.loadMetadata(it) } .filter { it.version.isCompatible() } - .mapNotNull { - KotlinJavascriptSerializationUtil.readModule( - it.body, moduleContext.storageManager, moduleDescriptor, container.get(), - LookupTracker.DO_NOTHING - ).data + .map { metadata -> + val (header, packageFragmentProtos) = KotlinJavascriptSerializationUtil.readModuleAsProto(metadata.body) + createKotlinJavascriptPackageFragmentProvider( + moduleContext.storageManager, moduleDescriptor, header, packageFragmentProtos, + container.get(), LookupTracker.DO_NOTHING + ) } if (providers.isNotEmpty()) { diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/analyze/TopDownAnalyzerFacadeForJS.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/analyze/TopDownAnalyzerFacadeForJS.kt index d8d95b248af..4ace02d8fa6 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/analyze/TopDownAnalyzerFacadeForJS.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/analyze/TopDownAnalyzerFacadeForJS.kt @@ -25,7 +25,6 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory -import org.jetbrains.kotlin.serialization.js.JsModuleDescriptor import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil import org.jetbrains.kotlin.serialization.js.ModuleKind import org.jetbrains.kotlin.serialization.js.PackagesWithHeaderMetadata @@ -56,8 +55,8 @@ object TopDownAnalyzerFacadeForJS { files: Collection, project: Project, configuration: CompilerConfiguration, - moduleDescriptors: List>, - friendModuleDescriptors: List> + moduleDescriptors: List, + friendModuleDescriptors: List ): JsAnalysisResult { val moduleName = configuration[CommonConfigurationKeys.MODULE_NAME]!! @@ -65,9 +64,9 @@ object TopDownAnalyzerFacadeForJS { context.module.setDependencies( listOf(context.module) + - moduleDescriptors.map { it.data } + + moduleDescriptors + listOf(JsPlatform.builtIns.builtInsModule), - friendModuleDescriptors.map { it.data }.toSet() + friendModuleDescriptors.toSet() ) val moduleKind = configuration.get(JSConfigurationKeys.MODULE_KIND, ModuleKind.PLAIN) diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/config/JsConfig.java b/js/js.frontend/src/org/jetbrains/kotlin/js/config/JsConfig.java index ed09cf64b39..d41294593a8 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/config/JsConfig.java +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/config/JsConfig.java @@ -33,10 +33,7 @@ import org.jetbrains.kotlin.incremental.components.LookupTracker; import org.jetbrains.kotlin.js.resolve.JsPlatform; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration; -import org.jetbrains.kotlin.serialization.js.JsModuleDescriptor; -import org.jetbrains.kotlin.serialization.js.KotlinJavaScriptLibraryParts; -import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil; -import org.jetbrains.kotlin.serialization.js.ModuleKind; +import org.jetbrains.kotlin.serialization.js.*; import org.jetbrains.kotlin.storage.LockBasedStorageManager; import org.jetbrains.kotlin.utils.JsMetadataVersion; import org.jetbrains.kotlin.utils.KotlinJavascriptMetadata; @@ -64,11 +61,8 @@ public class JsConfig { private final List metadata = new SmartList<>(); private final List friends = new SmartList<>(); - @Nullable - private List> moduleDescriptors = null; - - @Nullable - private List> friendModuleDescriptors = null; + private List moduleDescriptors; + private List friendModuleDescriptors; private boolean initialized = false; @@ -237,19 +231,16 @@ public class JsConfig { } @NotNull - public List> getModuleDescriptors() { + public List getModuleDescriptors() { init(); return moduleDescriptors; } @NotNull - private List> createModuleDescriptors() { - List> moduleDescriptors = new SmartList<>(); - List kotlinModuleDescriptors = new ArrayList<>(); + private List createModuleDescriptors() { + List moduleDescriptors = new SmartList<>(); for (KotlinJavascriptMetadata metadataEntry : metadata) { - JsModuleDescriptor descriptor = createModuleDescriptor(metadataEntry); - moduleDescriptors.add(descriptor); - kotlinModuleDescriptors.add(descriptor.getData()); + moduleDescriptors.add(createModuleDescriptor(metadataEntry)); } if (metadataCache != null) { @@ -259,50 +250,30 @@ public class JsConfig { Name.special("<" + cached.getName() + ">"), storageManager, JsPlatform.INSTANCE.getBuiltIns() ); - JsModuleDescriptor rawDescriptor = KotlinJavascriptSerializationUtil.readModuleFromProto( - cached, storageManager, moduleDescriptor, + PackageFragmentProvider provider = KotlinJavascriptPackageFragmentProviderKt.createKotlinJavascriptPackageFragmentProvider( + storageManager, moduleDescriptor, cached.getData().getHeader(), cached.getData().getBody(), new CompilerDeserializationConfiguration(languageVersionSettings), LookupTracker.DO_NOTHING.INSTANCE ); - PackageFragmentProvider provider = rawDescriptor.getData(); - moduleDescriptor.initialize(provider != null ? provider : PackageFragmentProvider.Empty.INSTANCE); - - JsModuleDescriptor jsModuleDescriptor = cached.copy(moduleDescriptor); - moduleDescriptors.add(jsModuleDescriptor); - kotlinModuleDescriptors.add(jsModuleDescriptor.getData()); + moduleDescriptor.initialize(provider); + moduleDescriptors.add(moduleDescriptor); } } - for (JsModuleDescriptor module : moduleDescriptors) { - // TODO: remove downcast - setDependencies(module.getData(), kotlinModuleDescriptors); + for (ModuleDescriptorImpl module : moduleDescriptors) { + setDependencies(module, moduleDescriptors); } - moduleDescriptors = Collections.unmodifiableList(moduleDescriptors); - - return moduleDescriptors; + return Collections.unmodifiableList(moduleDescriptors); } @NotNull - public List> getFriendModuleDescriptors() { + public List getFriendModuleDescriptors() { init(); return friendModuleDescriptors; } - @NotNull - private List> createFriendModuleDescriptors() { - List> friendModuleDescriptors = new SmartList<>(); - for (KotlinJavascriptMetadata metadataEntry : friends) { - JsModuleDescriptor descriptor = createModuleDescriptor(metadataEntry); - friendModuleDescriptors.add(descriptor); - } - - friendModuleDescriptors = Collections.unmodifiableList(friendModuleDescriptors); - - return friendModuleDescriptors; - } - public void init() { if (!initialized) { JsConfig.Reporter reporter = new Reporter() { @@ -320,13 +291,13 @@ public class JsConfig { } if (friendModuleDescriptors == null) { - friendModuleDescriptors = createFriendModuleDescriptors(); + friendModuleDescriptors = CollectionsKt.map(friends, this::createModuleDescriptor); } } - private final IdentityHashMap> factoryMap = new IdentityHashMap<>(); + private final IdentityHashMap factoryMap = new IdentityHashMap<>(); - private JsModuleDescriptor createModuleDescriptor(KotlinJavascriptMetadata metadata) { + private ModuleDescriptorImpl createModuleDescriptor(KotlinJavascriptMetadata metadata) { return factoryMap.computeIfAbsent(metadata, m -> { LanguageVersionSettings languageVersionSettings = CommonConfigurationKeysKt.getLanguageVersionSettings(configuration); assert m.getVersion().isCompatible() || @@ -338,16 +309,15 @@ public class JsConfig { ); LookupTracker lookupTracker = configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER, LookupTracker.DO_NOTHING.INSTANCE); - JsModuleDescriptor rawDescriptor = KotlinJavascriptSerializationUtil.readModule( - m.getBody(), storageManager, moduleDescriptor, + KotlinJavaScriptLibraryParts parts = KotlinJavascriptSerializationUtil.readModuleAsProto(m.getBody()); + PackageFragmentProvider provider = KotlinJavascriptPackageFragmentProviderKt.createKotlinJavascriptPackageFragmentProvider( + storageManager, moduleDescriptor, parts.getHeader(), parts.getBody(), new CompilerDeserializationConfiguration(languageVersionSettings), lookupTracker ); - PackageFragmentProvider provider = rawDescriptor.getData(); - moduleDescriptor.initialize(provider != null ? provider : PackageFragmentProvider.Empty.INSTANCE); - - return rawDescriptor.copy(moduleDescriptor); + moduleDescriptor.initialize(provider); + return moduleDescriptor; }); } diff --git a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/JsModuleDescriptor.kt b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/JsModuleDescriptor.kt index ee7cde33b8d..1919d700d5e 100644 --- a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/JsModuleDescriptor.kt +++ b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/JsModuleDescriptor.kt @@ -16,6 +16,9 @@ package org.jetbrains.kotlin.serialization.js -class JsModuleDescriptor(val name: String, val kind: ModuleKind, val imported: List, val data: T) { - fun copy(newData: S) = JsModuleDescriptor(name, kind, imported, newData) -} +class JsModuleDescriptor( + val name: String, + val kind: ModuleKind, + val imported: List, + val data: T +) diff --git a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/KotlinJavascriptSerializationUtil.kt b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/KotlinJavascriptSerializationUtil.kt index b39b036fcb5..fddce0577af 100644 --- a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/KotlinJavascriptSerializationUtil.kt +++ b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/KotlinJavascriptSerializationUtil.kt @@ -51,34 +51,6 @@ import java.util.zip.GZIPOutputStream object KotlinJavascriptSerializationUtil { const val CLASS_METADATA_FILE_EXTENSION: String = "kjsm" - @JvmStatic - fun readModule( - metadata: ByteArray, - storageManager: StorageManager, - module: ModuleDescriptor, - configuration: DeserializationConfiguration, - lookupTracker: LookupTracker - ): JsModuleDescriptor = - readModuleFromProto(readModuleAsProto(metadata, module.name.asString()), storageManager, module, configuration, lookupTracker) - - fun readModuleAsProto(metadata: ByteArray, name: String): JsModuleDescriptor = - metadata.deserializeToLibraryParts(name) - - @JvmStatic - fun readModuleFromProto( - jsModule: JsModuleDescriptor, - storageManager: StorageManager, module: ModuleDescriptor, - configuration: DeserializationConfiguration, - lookupTracker: LookupTracker - ): JsModuleDescriptor { - val (header, packageFragmentProtos) = jsModule.data - return jsModule.copy( - createKotlinJavascriptPackageFragmentProvider( - storageManager, module, header, packageFragmentProtos, configuration, lookupTracker - ) - ) - } - fun readDescriptors( metadata: PackagesWithHeaderMetadata, storageManager: StorageManager, @@ -334,27 +306,30 @@ object KotlinJavascriptSerializationUtil { } } - private fun ByteArray.deserializeToLibraryParts(name: String): JsModuleDescriptor { - val (header, content) = GZIPInputStream(ByteArrayInputStream(this)).use { stream -> + @JvmStatic + fun readModuleAsProto(metadata: ByteArray): KotlinJavaScriptLibraryParts { + val (header, content) = GZIPInputStream(ByteArrayInputStream(metadata)).use { stream -> JsProtoBuf.Header.parseDelimitedFrom(stream, JsSerializerProtocol.extensionRegistry) to JsProtoBuf.Library.parseFrom(stream, JsSerializerProtocol.extensionRegistry) } - return JsModuleDescriptor( - name = name, - data = KotlinJavaScriptLibraryParts(header, content.packageFragmentList), - kind = when (content.kind) { - null, JsProtoBuf.Library.Kind.PLAIN -> ModuleKind.PLAIN - JsProtoBuf.Library.Kind.AMD -> ModuleKind.AMD - JsProtoBuf.Library.Kind.COMMON_JS -> ModuleKind.COMMON_JS - JsProtoBuf.Library.Kind.UMD -> ModuleKind.UMD - }, - imported = content.importedModuleList - ) + val moduleKind = when (content.kind) { + null, JsProtoBuf.Library.Kind.PLAIN -> ModuleKind.PLAIN + JsProtoBuf.Library.Kind.AMD -> ModuleKind.AMD + JsProtoBuf.Library.Kind.COMMON_JS -> ModuleKind.COMMON_JS + JsProtoBuf.Library.Kind.UMD -> ModuleKind.UMD + } + + return KotlinJavaScriptLibraryParts(header, content.packageFragmentList, moduleKind, content.importedModuleList) } } -data class KotlinJavaScriptLibraryParts(val header: JsProtoBuf.Header, val body: List) +data class KotlinJavaScriptLibraryParts( + val header: JsProtoBuf.Header, + val body: List, + val kind: ModuleKind, + val importedModules: List +) internal fun DeclarationDescriptor.extractFileId(): Int? = when (this) { is DeserializedClassDescriptor -> classProto.getExtension(JsProtoBuf.classContainingFileId) diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicBoxTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicBoxTest.kt index 8f18fb074d6..9770ca94417 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicBoxTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicBoxTest.kt @@ -49,6 +49,7 @@ import org.jetbrains.kotlin.metadata.DebugProtoBuf import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.KtPsiFactory +import org.jetbrains.kotlin.serialization.js.JsModuleDescriptor import org.jetbrains.kotlin.serialization.js.JsSerializerProtocol import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil import org.jetbrains.kotlin.serialization.js.ModuleKind @@ -394,9 +395,11 @@ abstract class BasicBoxTest( val originalMetadata = FileUtil.loadFile(File(outputFile.parentFile, outputFile.nameWithoutExtension + ".meta.js")) val recompiledMetadata = removeRecompiledSuffix( FileUtil.loadFile(File(recompiledOutputFile.parentFile, recompiledOutputFile.nameWithoutExtension + ".meta.js"))) - assertEquals("Metadata file changed after recompilation", - metadataAsString(originalMetadata, module.name), - metadataAsString(recompiledMetadata, module.name)) + assertEquals( + "Metadata file changed after recompilation", + metadataAsString(originalMetadata), + metadataAsString(recompiledMetadata) + ) } } @@ -406,10 +409,10 @@ abstract class BasicBoxTest( return String(out.toByteArray(), Charset.forName("UTF-8")) } - private fun metadataAsString(metadata: String, moduleName: String): String { + private fun metadataAsString(metadata: String): String { val containers = mutableListOf() KotlinJavascriptMetadataUtils.parseMetadata(metadata, containers) - val metadataParts = KotlinJavascriptSerializationUtil.readModuleAsProto(containers.single().body, moduleName).data.body + val metadataParts = KotlinJavascriptSerializationUtil.readModuleAsProto(containers.single().body).body return metadataParts.joinToString("-----\n") { val binary = it.toByteArray() DebugProtoBuf.PackageFragment.parseFrom(binary, JsSerializerProtocol.extensionRegistry).toString() @@ -738,13 +741,12 @@ abstract class BasicBoxTest( KotlinCoreEnvironment.createForTests(testRootDisposable, CompilerConfiguration(), EnvironmentConfigFiles.JS_CONFIG_FILES) companion object { - val METADATA_CACHE = (JsConfig.JS_STDLIB.asSequence() + JsConfig.JS_KOTLIN_TEST) - .flatMap { - KotlinJavascriptMetadataUtils - .loadMetadata(it).asSequence() - .map { KotlinJavascriptSerializationUtil.readModuleAsProto(it.body, it.moduleName) } - } - .toList() + val METADATA_CACHE = (JsConfig.JS_STDLIB + JsConfig.JS_KOTLIN_TEST).flatMap { path -> + KotlinJavascriptMetadataUtils.loadMetadata(path).map { metadata -> + val parts = KotlinJavascriptSerializationUtil.readModuleAsProto(metadata.body) + JsModuleDescriptor(metadata.moduleName, parts.kind, parts.importedModules, parts) + } + } const val TEST_DATA_DIR_PATH = "js/js.translator/testData/" const val DIST_DIR_JS_PATH = "dist/js/"