Support inlining internal functions to friend modules in JS BE
There's one exception: if an inline internal function calls private function, this will fail at run time.
This commit is contained in:
@@ -18,10 +18,11 @@ package org.jetbrains.kotlin.js.descriptorUtils
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
import org.jetbrains.kotlin.js.config.JsConfig
|
||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
@@ -52,3 +53,14 @@ fun ClassDescriptor.hasPrimaryConstructor(): Boolean = unsubstitutedPrimaryConst
|
||||
|
||||
val DeclarationDescriptor.isCoroutineLambda: Boolean
|
||||
get() = this is AnonymousFunctionDescriptor && isSuspend
|
||||
|
||||
|
||||
fun DeclarationDescriptor.shouldBeExported(config: JsConfig): Boolean =
|
||||
this !is DeclarationDescriptorWithVisibility || effectiveVisibility(visibility, true).shouldBeExported(config) ||
|
||||
AnnotationsUtils.getJsNameAnnotation(this) != null
|
||||
|
||||
private fun EffectiveVisibility.shouldBeExported(config: JsConfig): Boolean {
|
||||
if (publicApi) return true
|
||||
if (config.configuration.getBoolean(JSConfigurationKeys.FRIEND_PATHS_DISABLED)) return false
|
||||
return toVisibility() == Visibilities.INTERNAL
|
||||
}
|
||||
@@ -4754,6 +4754,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("internalFriend.kt")
|
||||
public void testInternalFriend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/inlineMultiModule/internalFriend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("internalNameClash.kt")
|
||||
public void testInternalNameClash() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/inlineMultiModule/internalNameClash.kt");
|
||||
|
||||
+2
-9
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.descriptors.annotations.isEffectivelyInlineOnly
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.exportedTag
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.staticRef
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
import org.jetbrains.kotlin.js.descriptorUtils.shouldBeExported
|
||||
import org.jetbrains.kotlin.js.translate.utils.*
|
||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.isLibraryObject
|
||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.isNativeObject
|
||||
@@ -147,13 +147,6 @@ internal class DeclarationExporter(val context: StaticContext) {
|
||||
it.exportedTag = context.getTag(declaration)
|
||||
}
|
||||
|
||||
private fun EffectiveVisibility.publicOrInternal(): Boolean {
|
||||
if (publicApi) return true
|
||||
if (context.config.configuration.getBoolean(JSConfigurationKeys.FRIEND_PATHS_DISABLED)) return false
|
||||
return toVisibility() == Visibilities.INTERNAL
|
||||
}
|
||||
|
||||
private fun MemberDescriptor.shouldBeExported(force: Boolean) =
|
||||
force || effectiveVisibility(checkPublishedApi = true).publicOrInternal() || AnnotationsUtils.getJsNameAnnotation(this) != null
|
||||
private fun MemberDescriptor.shouldBeExported(force: Boolean) = force || shouldBeExported(context.config)
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -50,6 +50,7 @@ import org.jetbrains.kotlin.serialization.js.ModuleKind;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.kotlin.js.descriptorUtils.DescriptorUtilsKt.isCoroutineLambda;
|
||||
import static org.jetbrains.kotlin.js.descriptorUtils.DescriptorUtilsKt.shouldBeExported;
|
||||
import static org.jetbrains.kotlin.js.translate.context.UsageTrackerKt.getNameForCapturedDescriptor;
|
||||
import static org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.isNativeObject;
|
||||
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getDescriptorForElement;
|
||||
@@ -285,7 +286,7 @@ public class TranslationContext {
|
||||
@NotNull
|
||||
public JsName getInlineableInnerNameForDescriptor(@NotNull DeclarationDescriptor descriptor) {
|
||||
JsName name;
|
||||
if (inlineFunctionContext == null || !isPublicInlineFunction() ||
|
||||
if (inlineFunctionContext == null || !isPublicInlineFunction() || !shouldBeExported(descriptor, getConfig()) ||
|
||||
DescriptorUtils.isAncestor(inlineFunctionContext.getDescriptor(), descriptor, false)) {
|
||||
name = getInnerNameForDescriptor(descriptor);
|
||||
}
|
||||
@@ -802,8 +803,7 @@ public class TranslationContext {
|
||||
public boolean isPublicInlineFunction() {
|
||||
if (inlineFunctionContext == null) return false;
|
||||
|
||||
CallableDescriptor function = inlineFunctionContext.getDescriptor();
|
||||
return function.getVisibility().effectiveVisibility(function, true).getPublicApi();
|
||||
return shouldBeExported(inlineFunctionContext.getDescriptor(), getConfig());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+2
-2
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.descriptor
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.functionDescriptor
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.hasDefaultValue
|
||||
import org.jetbrains.kotlin.js.descriptorUtils.shouldBeExported
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
import org.jetbrains.kotlin.js.inline.util.FunctionWithWrapper
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
@@ -35,7 +36,6 @@ import org.jetbrains.kotlin.psi.KtDeclarationWithBody
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyPublicApi
|
||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
import org.jetbrains.kotlin.resolve.source.PsiSourceFile
|
||||
|
||||
@@ -106,7 +106,7 @@ fun TranslationContext.wrapWithInlineMetadata(
|
||||
function: JsFunction, descriptor: FunctionDescriptor
|
||||
): JsExpression {
|
||||
val sourceInfo = descriptor.source.getPsi()
|
||||
return if (descriptor.isInline && descriptor.isEffectivelyPublicApi) {
|
||||
return if (descriptor.isInline && descriptor.shouldBeExported(config)) {
|
||||
val metadata = InlineMetadata.compose(function, descriptor, this)
|
||||
val functionWithMetadata = metadata.functionWithMetadata(outerContext, sourceInfo)
|
||||
|
||||
|
||||
+3
-1
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.js.backend.ast.JsName;
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsNameRef;
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.MetadataProperties;
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.SideEffectKind;
|
||||
import org.jetbrains.kotlin.js.descriptorUtils.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils;
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
||||
@@ -109,7 +110,8 @@ public final class ReferenceTranslator {
|
||||
}
|
||||
|
||||
private static boolean isLocallyAvailableDeclaration(@NotNull TranslationContext context, @NotNull DeclarationDescriptor descriptor) {
|
||||
return context.isFromCurrentModule(descriptor) && !context.isPublicInlineFunction();
|
||||
return context.isFromCurrentModule(descriptor) && !(context.isPublicInlineFunction() &&
|
||||
DescriptorUtilsKt.shouldBeExported(descriptor, context.getConfig()));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -9,7 +9,7 @@ package foo
|
||||
// CHECK_HAS_INLINE_METADATA: apply
|
||||
// CHECK_HAS_INLINE_METADATA: applyL_h43q6c$
|
||||
// CHECK_HAS_INLINE_METADATA: applyM_h43q6c$
|
||||
// CHECK_HAS_NO_INLINE_METADATA: applyN_h43q6c$
|
||||
// CHECK_HAS_INLINE_METADATA: applyN_h43q6c$
|
||||
// CHECK_HAS_NO_INLINE_METADATA: applyO_h43q6c$
|
||||
|
||||
inline
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// EXPECTED_REACHABLE_NODES: 992
|
||||
// MODULE: lib
|
||||
// FILE: lib.kt
|
||||
internal fun bar() = "OK"
|
||||
|
||||
internal inline fun foo() = bar()
|
||||
|
||||
// MODULE: main(lib)(lib)
|
||||
// FILE: main.kt
|
||||
fun box(): String = foo()
|
||||
Reference in New Issue
Block a user