Refactor deserialization initialization in built-ins and JS

BuiltinsPackageFragment was only designed to work with a single instance alive.
Because of this, it was creating deserialization subsystem upon initialization.
This was not working perfectly in JS where it was used, because multiple
storage managers, class caches and other components were created for each
package, leading to different concurrency errors and performance hits. Also in
the near future another package fragment will be needed to represent the
built-in package "kotlin.reflect"
This commit is contained in:
Alexander Udalov
2015-04-17 21:19:19 +03:00
parent 19ddb4b510
commit 3d928a0842
10 changed files with 183 additions and 102 deletions
@@ -16,8 +16,8 @@
package org.jetbrains.kotlin.serialization.builtins package org.jetbrains.kotlin.serialization.builtins
import org.jetbrains.kotlin.builtins.BuiltinsPackageFragment
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.createBuiltInPackageFragmentProvider
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
import org.jetbrains.kotlin.jvm.compiler.LoadDescriptorUtil.TEST_PACKAGE_FQNAME import org.jetbrains.kotlin.jvm.compiler.LoadDescriptorUtil.TEST_PACKAGE_FQNAME
import org.jetbrains.kotlin.serialization.deserialization.FlexibleTypeCapabilitiesDeserializer import org.jetbrains.kotlin.serialization.deserialization.FlexibleTypeCapabilitiesDeserializer
@@ -40,19 +40,21 @@ public class BuiltInsSerializerTest : TestCaseWithTmpdir() {
val module = JetTestUtils.createEmptyModule("<module>") val module = JetTestUtils.createEmptyModule("<module>")
val packageFragment = val packageFragmentProvider = createBuiltInPackageFragmentProvider(
BuiltinsPackageFragment(TEST_PACKAGE_FQNAME, LockBasedStorageManager(), module, FlexibleTypeCapabilitiesDeserializer.ThrowException) { LockBasedStorageManager(), module, setOf(TEST_PACKAGE_FQNAME),
val file = File(tmpdir, it) FlexibleTypeCapabilitiesDeserializer.ThrowException
if (file.exists()) FileInputStream(file) else null ) {
} val file = File(tmpdir, it)
if (file.exists()) FileInputStream(file) else null
}
module.initialize(packageFragment.provider) module.initialize(packageFragmentProvider)
module.addDependencyOnModule(module) module.addDependencyOnModule(module)
module.addDependencyOnModule(KotlinBuiltIns.getInstance().getBuiltInsModule()) module.addDependencyOnModule(KotlinBuiltIns.getInstance().getBuiltInsModule())
module.seal() module.seal()
RecursiveDescriptorComparator.validateAndCompareDescriptorWithFile( RecursiveDescriptorComparator.validateAndCompareDescriptorWithFile(
module.getPackage(TEST_PACKAGE_FQNAME), module.getPackage(TEST_PACKAGE_FQNAME)!!,
RecursiveDescriptorComparator.DONT_INCLUDE_METHODS_OF_OBJECT, RecursiveDescriptorComparator.DONT_INCLUDE_METHODS_OF_OBJECT,
File(source.replace(".kt", ".txt")) File(source.replace(".kt", ".txt"))
) )
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.addKotlinSourceRoots import org.jetbrains.kotlin.config.addKotlinSourceRoots
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS
import org.jetbrains.kotlin.js.config.LibrarySourcesConfig import org.jetbrains.kotlin.js.config.LibrarySourcesConfig
@@ -35,6 +34,7 @@ import org.jetbrains.kotlin.test.JetTestUtils
import org.jetbrains.kotlin.test.TestCaseWithTmpdir import org.jetbrains.kotlin.test.TestCaseWithTmpdir
import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
import org.jetbrains.kotlin.utils.sure
import java.io.File import java.io.File
public class KotlinJavascriptSerializerTest : TestCaseWithTmpdir() { public class KotlinJavascriptSerializerTest : TestCaseWithTmpdir() {
@@ -81,7 +81,8 @@ public class KotlinJavascriptSerializerTest : TestCaseWithTmpdir() {
val metadata = KotlinJavascriptMetadataUtils.loadMetadata(metaFile) val metadata = KotlinJavascriptMetadataUtils.loadMetadata(metaFile)
assert(metadata.size() == 1) assert(metadata.size() == 1)
val provider = CompositePackageFragmentProvider(KotlinJavascriptSerializationUtil.getPackageFragmentProviders(module, metadata[0].body)) val provider = KotlinJavascriptSerializationUtil.createPackageFragmentProvider(module, metadata[0].body)
.sure { "No package fragment provider was created" }
module.initialize(provider) module.initialize(provider)
module.addDependencyOnModule(module) module.addDependencyOnModule(module)
@@ -0,0 +1,49 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.builtins
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.serialization.ClassData
import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder
import java.io.InputStream
public class BuiltInsClassDataFinder(
private val packageFragmentProvider: PackageFragmentProvider,
private val loadResource: (path: String) -> InputStream?
) : ClassDataFinder {
override fun findClassData(classId: ClassId): ClassData? {
val packageFragment = packageFragmentProvider.getPackageFragments(classId.getPackageFqName()).singleOrNull() ?: return null
val stream = loadResource(BuiltInsSerializationUtil.getClassMetadataPath(classId)) ?: return null
val classProto = ProtoBuf.Class.parseFrom(stream, BuiltInsSerializationUtil.EXTENSION_REGISTRY)
val nameResolver =
(packageFragment as? BuiltinsPackageFragment ?: error("Not a built-in package fragment: $packageFragment")).nameResolver
val expectedShortName = classId.getShortClassName()
val actualShortName = nameResolver.getClassId(classProto.getFqName()).getShortClassName()
if (!actualShortName.isSpecial() && actualShortName != expectedShortName) {
// Workaround for case-insensitive file systems,
// otherwise we'd find "Collection" for "collection" etc
return null
}
return ClassData(nameResolver, classProto)
}
}
@@ -16,14 +16,23 @@
package org.jetbrains.kotlin.builtins package org.jetbrains.kotlin.builtins
import org.jetbrains.kotlin.name.* import com.google.protobuf.ExtensionRegistryLite
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf
import kotlin.platform.platformStatic import kotlin.platform.platformStatic
public object BuiltInsSerializationUtil { public object BuiltInsSerializationUtil {
public val EXTENSION_REGISTRY: ExtensionRegistryLite
init {
EXTENSION_REGISTRY = ExtensionRegistryLite.newInstance()
BuiltInsProtoBuf.registerAllExtensions(EXTENSION_REGISTRY)
}
private val CLASS_METADATA_FILE_EXTENSION = "kotlin_class" private val CLASS_METADATA_FILE_EXTENSION = "kotlin_class"
private val PACKAGE_FILE_NAME = ".kotlin_package" private val PACKAGE_FILE_NAME = ".kotlin_package"
private val STRING_TABLE_FILE_NAME = ".kotlin_string_table" private val STRING_TABLE_FILE_NAME = ".kotlin_string_table"
private val CLASS_NAMES_FILE_NAME = ".kotlin_class_names"
platformStatic public fun getClassMetadataPath(classId: ClassId): String { platformStatic public fun getClassMetadataPath(classId: ClassId): String {
return packageFqNameToPath(classId.getPackageFqName()) + "/" + classId.getRelativeClassName().asString() + return packageFqNameToPath(classId.getPackageFqName()) + "/" + classId.getRelativeClassName().asString() +
@@ -36,9 +45,6 @@ public object BuiltInsSerializationUtil {
platformStatic public fun getStringTableFilePath(fqName: FqName): String = platformStatic public fun getStringTableFilePath(fqName: FqName): String =
packageFqNameToPath(fqName) + "/" + STRING_TABLE_FILE_NAME packageFqNameToPath(fqName) + "/" + STRING_TABLE_FILE_NAME
platformStatic public fun getClassNamesFilePath(fqName: FqName): String =
packageFqNameToPath(fqName) + "/" + CLASS_NAMES_FILE_NAME
private fun packageFqNameToPath(fqName: FqName): String = private fun packageFqNameToPath(fqName: FqName): String =
fqName.asString().replace('.', '/') fqName.asString().replace('.', '/')
} }
@@ -16,86 +16,45 @@
package org.jetbrains.kotlin.builtins package org.jetbrains.kotlin.builtins
import com.google.protobuf.ExtensionRegistryLite
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
import org.jetbrains.kotlin.descriptors.PackageFragmentProviderImpl
import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.serialization.ClassData
import org.jetbrains.kotlin.serialization.ProtoBuf import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf import org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.* import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
import java.io.InputStream import java.io.InputStream
import javax.inject.Inject
import kotlin.properties.Delegates
public class BuiltinsPackageFragment( public class BuiltinsPackageFragment(
fqName: FqName, fqName: FqName,
storageManager: StorageManager, storageManager: StorageManager,
module: ModuleDescriptor, module: ModuleDescriptor,
flexibleTypeCapabilitiesDeserializer: FlexibleTypeCapabilitiesDeserializer,
private val loadResource: (path: String) -> InputStream? private val loadResource: (path: String) -> InputStream?
) : PackageFragmentDescriptorImpl(module, fqName) { ) : PackageFragmentDescriptorImpl(module, fqName) {
private val extensionRegistry: ExtensionRegistryLite val nameResolver = NameResolver.read(loadResourceSure(BuiltInsSerializationUtil.getStringTableFilePath(fqName)))
init { private var components: DeserializationComponents by Delegates.notNull()
extensionRegistry = ExtensionRegistryLite.newInstance()
BuiltInsProtoBuf.registerAllExtensions(extensionRegistry) Inject
extensionRegistry public fun setDeserializationComponents(components: DeserializationComponents) {
this.components = components
} }
private val nameResolver = NameResolver.read( private val memberScope = storageManager.createLazyValue {
getStream(BuiltInsSerializationUtil.getStringTableFilePath(fqName)) val stream = loadResourceSure(BuiltInsSerializationUtil.getPackageFilePath(fqName))
) val proto = ProtoBuf.Package.parseFrom(stream, BuiltInsSerializationUtil.EXTENSION_REGISTRY)
DeserializedPackageMemberScope(this, proto, nameResolver, components, classNames = {
public val provider: PackageFragmentProvider = PackageFragmentProviderImpl(listOf(this)) proto.getExtension(BuiltInsProtoBuf.className)?.map { id -> nameResolver.getName(id) } ?: listOf()
})
private val members: DeserializedPackageMemberScope = run {
val proto = loadPackage()
val localClassResolver = LocalClassResolverImpl()
val components = DeserializationComponents(
storageManager, module, BuiltInsClassDataFinder(),
BuiltInsAnnotationAndConstantLoader(getContainingDeclaration()),
provider, localClassResolver,
flexibleTypeCapabilitiesDeserializer
)
localClassResolver.setDeserializationComponents(components)
DeserializedPackageMemberScope(this, proto, nameResolver, components, { readClassNames(proto) })
} }
private fun loadPackage(): ProtoBuf.Package { override fun getMemberScope() = memberScope()
val stream = getStream(BuiltInsSerializationUtil.getPackageFilePath(fqName))
return ProtoBuf.Package.parseFrom(stream, extensionRegistry)
}
private fun readClassNames(proto: ProtoBuf.Package): List<Name> { private fun loadResourceSure(path: String): InputStream =
return proto.getExtension(BuiltInsProtoBuf.className)?.map { id -> nameResolver.getName(id) } ?: listOf()
}
override fun getMemberScope() = members
private fun getStream(path: String): InputStream =
loadResource(path) ?: throw IllegalStateException("Resource not found in classpath: $path") loadResource(path) ?: throw IllegalStateException("Resource not found in classpath: $path")
private inner class BuiltInsClassDataFinder : ClassDataFinder {
override fun findClassData(classId: ClassId): ClassData? {
val stream = loadResource(BuiltInsSerializationUtil.getClassMetadataPath(classId)) ?: return null
val classProto = ProtoBuf.Class.parseFrom(stream, extensionRegistry)
val expectedShortName = classId.getShortClassName()
val actualShortName = nameResolver.getClassId(classProto.getFqName()).getShortClassName()
if (!actualShortName.isSpecial() && actualShortName != expectedShortName) {
// Workaround for case-insensitive file systems,
// otherwise we'd find "Collection" for "collection" etc
return null
}
return ClassData(nameResolver, classProto)
}
}
} }
@@ -40,6 +40,7 @@ import org.jetbrains.kotlin.types.checker.JetTypeChecker;
import java.io.InputStream; import java.io.InputStream;
import java.util.*; import java.util.*;
import static kotlin.KotlinPackage.single;
import static org.jetbrains.kotlin.builtins.PrimitiveType.*; import static org.jetbrains.kotlin.builtins.PrimitiveType.*;
public class KotlinBuiltIns { public class KotlinBuiltIns {
@@ -109,22 +110,25 @@ public class KotlinBuiltIns {
private KotlinBuiltIns() { private KotlinBuiltIns() {
builtInsModule = new ModuleDescriptorImpl( builtInsModule = new ModuleDescriptorImpl(
Name.special("<built-ins lazy module>"), Collections.<ImportPath>emptyList(), PlatformToKotlinClassMap.EMPTY Name.special("<built-ins module>"), Collections.<ImportPath>emptyList(), PlatformToKotlinClassMap.EMPTY
); );
builtinsPackageFragment = new BuiltinsPackageFragment(
BUILT_INS_PACKAGE_FQ_NAME, new LockBasedStorageManager(), builtInsModule, PackageFragmentProvider packageFragmentProvider = BuiltinsPackage.createBuiltInPackageFragmentProvider(
FlexibleTypeCapabilitiesDeserializer.ThrowException.INSTANCE$, new LockBasedStorageManager(), builtInsModule, Collections.singleton(BUILT_INS_PACKAGE_FQ_NAME),
new Function1<String, InputStream>() { FlexibleTypeCapabilitiesDeserializer.ThrowException.INSTANCE$, new Function1<String, InputStream>() {
@Override @Override
public InputStream invoke(String path) { public InputStream invoke(String path) {
return KotlinBuiltIns.class.getClassLoader().getResourceAsStream(path); return KotlinBuiltIns.class.getClassLoader().getResourceAsStream(path);
} }
} }
); );
builtInsModule.initialize(builtinsPackageFragment.getProvider());
builtInsModule.initialize(packageFragmentProvider);
builtInsModule.addDependencyOnModule(builtInsModule); builtInsModule.addDependencyOnModule(builtInsModule);
builtInsModule.seal(); builtInsModule.seal();
builtinsPackageFragment = (BuiltinsPackageFragment) single(packageFragmentProvider.getPackageFragments(BUILT_INS_PACKAGE_FQ_NAME));
primitiveTypeToNullableJetType = new EnumMap<PrimitiveType, JetType>(PrimitiveType.class); primitiveTypeToNullableJetType = new EnumMap<PrimitiveType, JetType>(PrimitiveType.class);
primitiveTypeToArrayJetType = new EnumMap<PrimitiveType, JetType>(PrimitiveType.class); primitiveTypeToArrayJetType = new EnumMap<PrimitiveType, JetType>(PrimitiveType.class);
primitiveJetTypeToJetArrayType = new HashMap<JetType, JetType>(); primitiveJetTypeToJetArrayType = new HashMap<JetType, JetType>();
@@ -0,0 +1,60 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.builtins
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
import org.jetbrains.kotlin.descriptors.PackageFragmentProviderImpl
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents
import org.jetbrains.kotlin.serialization.deserialization.FlexibleTypeCapabilitiesDeserializer
import org.jetbrains.kotlin.serialization.deserialization.LocalClassResolverImpl
import org.jetbrains.kotlin.storage.StorageManager
import java.io.InputStream
public fun createBuiltInPackageFragmentProvider(
storageManager: StorageManager,
module: ModuleDescriptor,
packageFqNames: Set<FqName>,
flexibleTypeCapabilitiesDeserializer: FlexibleTypeCapabilitiesDeserializer,
loadResource: (String) -> InputStream?
): PackageFragmentProvider {
val packageFragments = packageFqNames.map { fqName ->
BuiltinsPackageFragment(fqName, storageManager, module, loadResource)
}
val provider = PackageFragmentProviderImpl(packageFragments)
val localClassResolver = LocalClassResolverImpl()
val components = DeserializationComponents(
storageManager,
module,
BuiltInsClassDataFinder(provider, loadResource),
BuiltInsAnnotationAndConstantLoader(module),
provider,
localClassResolver,
flexibleTypeCapabilitiesDeserializer
)
localClassResolver.setDeserializationComponents(components)
for (packageFragment in packageFragments) {
packageFragment.setDeserializationComponents(components)
}
return provider
}
@@ -66,7 +66,8 @@ public object JsAnalyzerFacade : AnalyzerFacade<JsResolverForModule, PlatformAna
if (!JsHeaderLibraryDetectionUtil.isJsHeaderLibraryWithSources(files.toList())) { if (!JsHeaderLibraryDetectionUtil.isJsHeaderLibraryWithSources(files.toList())) {
val providers = moduleInfo.library.getFiles(OrderRootType.CLASSES) val providers = moduleInfo.library.getFiles(OrderRootType.CLASSES)
.flatMap { KotlinJavascriptMetadataUtils.loadMetadata(PathUtil.getLocalPath(it)!!) } .flatMap { KotlinJavascriptMetadataUtils.loadMetadata(PathUtil.getLocalPath(it)!!) }
.flatMap { KotlinJavascriptSerializationUtil.getPackageFragmentProviders(moduleDescriptor, it.body) } .map { KotlinJavascriptSerializationUtil.createPackageFragmentProvider(moduleDescriptor, it.body) }
.filterNotNull()
if (providers.isNotEmpty()) { if (providers.isNotEmpty()) {
packageFragmentProvider = CompositePackageFragmentProvider(listOf(packageFragmentProvider) + providers) packageFragmentProvider = CompositePackageFragmentProvider(listOf(packageFragmentProvider) + providers)
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil;
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadata; import org.jetbrains.kotlin.utils.KotlinJavascriptMetadata;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
@@ -107,7 +108,7 @@ public abstract class Config {
return moduleId; return moduleId;
} }
public abstract boolean checkLibFilesAndReportErrors(@NotNull Function1<String, Unit> report); public abstract boolean checkLibFilesAndReportErrors(@NotNull Function1<String, Unit> report);
protected abstract void init(@NotNull List<JetFile> sourceFilesInLibraries, @NotNull List<KotlinJavascriptMetadata> metadata); protected abstract void init(@NotNull List<JetFile> sourceFilesInLibraries, @NotNull List<KotlinJavascriptMetadata> metadata);
@@ -117,10 +118,10 @@ public abstract class Config {
if (moduleDescriptors != null) return moduleDescriptors; if (moduleDescriptors != null) return moduleDescriptors;
moduleDescriptors = new SmartList<ModuleDescriptorImpl>(); moduleDescriptors = new SmartList<ModuleDescriptorImpl>();
for(KotlinJavascriptMetadata metadataEntry : metadata) { for (KotlinJavascriptMetadata metadataEntry : metadata) {
moduleDescriptors.add(createModuleDescriptor(metadataEntry)); moduleDescriptors.add(createModuleDescriptor(metadataEntry));
} }
for(ModuleDescriptorImpl module : moduleDescriptors) { for (ModuleDescriptorImpl module : moduleDescriptors) {
setDependencies(module, moduleDescriptors); setDependencies(module, moduleDescriptors);
module.seal(); module.seal();
} }
@@ -149,18 +150,19 @@ public abstract class Config {
private static ModuleDescriptorImpl createModuleDescriptor(KotlinJavascriptMetadata metadata) { private static ModuleDescriptorImpl createModuleDescriptor(KotlinJavascriptMetadata metadata) {
ModuleDescriptorImpl moduleDescriptor = TopDownAnalyzerFacadeForJS.createJsModule("<" + metadata.getModuleName() + ">"); ModuleDescriptorImpl moduleDescriptor = TopDownAnalyzerFacadeForJS.createJsModule("<" + metadata.getModuleName() + ">");
List<PackageFragmentProvider> providers = KotlinJavascriptSerializationUtil PackageFragmentProvider provider =
.getPackageFragmentProviders(moduleDescriptor, metadata.getBody()); KotlinJavascriptSerializationUtil.createPackageFragmentProvider(moduleDescriptor, metadata.getBody());
CompositePackageFragmentProvider compositePackageFragmentProvider = new CompositePackageFragmentProvider(providers);
moduleDescriptor.initialize(compositePackageFragmentProvider); moduleDescriptor.initialize(
provider != null ? provider : new CompositePackageFragmentProvider(Collections.<PackageFragmentProvider>emptyList())
);
moduleDescriptor.addDependencyOnModule(KotlinBuiltIns.getInstance().getBuiltInsModule()); moduleDescriptor.addDependencyOnModule(KotlinBuiltIns.getInstance().getBuiltInsModule());
return moduleDescriptor; return moduleDescriptor;
} }
private static void setDependencies(ModuleDescriptorImpl module, List<ModuleDescriptorImpl> modules) { private static void setDependencies(ModuleDescriptorImpl module, List<ModuleDescriptorImpl> modules) {
for(ModuleDescriptorImpl moduleItem : modules) { for (ModuleDescriptorImpl moduleItem : modules) {
module.addDependencyOnModule(moduleItem); module.addDependencyOnModule(moduleItem);
} }
} }
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.serialization.js
import com.google.protobuf.ByteString import com.google.protobuf.ByteString
import org.jetbrains.kotlin.builtins.BuiltInsSerializationUtil import org.jetbrains.kotlin.builtins.BuiltInsSerializationUtil
import org.jetbrains.kotlin.builtins.BuiltinsPackageFragment import org.jetbrains.kotlin.builtins.createBuiltInPackageFragmentProvider
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
@@ -44,29 +44,26 @@ public object KotlinJavascriptSerializationUtil {
private val PACKAGE_FILE_SUFFIX = "/.kotlin_package" private val PACKAGE_FILE_SUFFIX = "/.kotlin_package"
platformStatic platformStatic
public fun getPackageFragmentProviders(moduleDescriptor: ModuleDescriptor, metadata: ByteArray): List<PackageFragmentProvider> { public fun createPackageFragmentProvider(moduleDescriptor: ModuleDescriptor, metadata: ByteArray): PackageFragmentProvider? {
val gzipInputStream = GZIPInputStream(ByteArrayInputStream(metadata)) val gzipInputStream = GZIPInputStream(ByteArrayInputStream(metadata))
val content = JsProtoBuf.Library.parseFrom(gzipInputStream) val content = JsProtoBuf.Library.parseFrom(gzipInputStream)
gzipInputStream.close() gzipInputStream.close()
val contentMap: MutableMap<String, ByteArray> = hashMapOf() val contentMap: MutableMap<String, ByteArray> = hashMapOf()
for(index in 0..content.getEntryCount()-1) { for (index in content.getEntryCount().indices) {
val entry = content.getEntry(index) val entry = content.getEntry(index)
contentMap[entry.getPath()] = entry.getContent().toByteArray() contentMap[entry.getPath()] = entry.getContent().toByteArray()
} }
val packages = getPackages(contentMap) val packageFqNames = getPackages(contentMap).map { FqName(it) }.toSet()
if (packageFqNames.isEmpty()) return null
val load = { path: String -> if (!contentMap.containsKey(path)) null else ByteArrayInputStream(contentMap.get(path)) } return createBuiltInPackageFragmentProvider(
LockBasedStorageManager(), moduleDescriptor, packageFqNames, FlexibleTypeCapabilitiesDeserializer.Dynamic
val providers = arrayListOf<PackageFragmentProvider>() ) {
for (packageName in packages) { path ->
val fqName = FqName(packageName) if (!contentMap.containsKey(path)) null else ByteArrayInputStream(contentMap.get(path))
val packageFragment = BuiltinsPackageFragment(fqName, LockBasedStorageManager(), moduleDescriptor, FlexibleTypeCapabilitiesDeserializer.Dynamic, load)
providers.add(packageFragment.provider)
} }
return providers
} }
public fun contentMapToByteArray(contentMap: Map<String, ByteArray>): ByteArray { public fun contentMapToByteArray(contentMap: Map<String, ByteArray>): ByteArray {