diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/DeclarationOrigins.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/DeclarationOrigins.kt index 8fca9a55867..f5f6d381ea3 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/DeclarationOrigins.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/DeclarationOrigins.kt @@ -14,4 +14,5 @@ object JsLoweredDeclarationOrigin : IrDeclarationOrigin { object JS_INTRINSICS_STUB : IrDeclarationOriginImpl("JS_INTRINSICS_STUB") object JS_CLOSURE_BOX_CLASS : IrStatementOriginImpl("JS_CLOSURE_BOX_CLASS") object JS_CLOSURE_BOX_CLASS_DECLARATION : IrDeclarationOriginImpl("JS_CLOSURE_BOX_CLASS_DECLARATION") + object BRIDGE_TO_EXTERNAL_FUNCTION : IrDeclarationOriginImpl("BRIDGE_TO_EXTERNAL_FUNCTION") } \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BridgesConstruction.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BridgesConstruction.kt index d2e4cd901cd..29fc22cd48d 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BridgesConstruction.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BridgesConstruction.kt @@ -15,10 +15,11 @@ import org.jetbrains.kotlin.backend.common.ir.isSuspend import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.irBlockBody import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext +import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder import org.jetbrains.kotlin.ir.backend.js.utils.asString +import org.jetbrains.kotlin.ir.backend.js.utils.getJsName import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl @@ -26,11 +27,7 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.types.isUnit -import org.jetbrains.kotlin.ir.util.isInlined -import org.jetbrains.kotlin.ir.util.isInterface -import org.jetbrains.kotlin.ir.util.isReal -import org.jetbrains.kotlin.ir.util.parentAsClass -import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.resolve.DescriptorUtils // Constructs bridges for inherited generic functions @@ -82,6 +79,11 @@ class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass { continue } + if (from.function.correspondingProperty != null && from.function.isEffectivelyExternal()) { + // TODO: Revisit bridges from external properties + continue + } + irClass.declarations.add(createBridge(function, from.function, to.function)) } } @@ -95,6 +97,12 @@ class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass { delegateTo: IrSimpleFunction ): IrFunction { + val origin = + if (bridge.isEffectivelyExternal()) + JsLoweredDeclarationOrigin.BRIDGE_TO_EXTERNAL_FUNCTION + else + IrDeclarationOrigin.BRIDGE + // TODO: Support offsets for debug info val irFunction = JsIrBuilder.buildFunction( bridge.name, @@ -106,7 +114,7 @@ class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass { bridge.isExternal, bridge.isTailrec, bridge.isSuspend, - IrDeclarationOrigin.BRIDGE + origin ).apply { // TODO: should dispatch receiver be copied? @@ -180,20 +188,25 @@ class FunctionAndSignature(val function: IrSimpleFunction) { // Currently strings are used for compatibility with a hack-based name generator private data class Signature( - val name: Name, - val extensionReceiverType: String?, - val valueParameters: List, - val returnType: String? + val name: String, + val extensionReceiverType: String? = null, + val valueParameters: List = emptyList(), + val returnType: String? = null ) - private val signature = Signature( - function.name, - function.extensionReceiverParameter?.type?.asString(), - function.valueParameters.map { it.type.asString() }, - // Return type used in signature for inline classes only because - // they are binary incompatible with supertypes and require bridges. - function.returnType.run { if (isInlined()) asString() else null } - ) + private val jsName = function.getJsName() + private val signature = when { + jsName != null -> Signature(jsName) + function.isEffectivelyExternal() -> Signature(function.name.asString()) + else -> Signature( + function.name.asString(), + function.extensionReceiverParameter?.type?.asString(), + function.valueParameters.map { it.type.asString() }, + // Return type used in signature for inline classes only because + // they are binary incompatible with supertypes and require bridges. + function.returnType.run { if (isInlined()) asString() else null } + ) + } override fun equals(other: Any?): Boolean { if (this === other) return true diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/SimpleNameGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/SimpleNameGenerator.kt index 54d9860e9d1..6dc374460c8 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/SimpleNameGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/SimpleNameGenerator.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.backend.js.utils import org.jetbrains.kotlin.backend.common.ir.isTopLevel import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrLoop import org.jetbrains.kotlin.ir.symbols.IrSymbol @@ -106,6 +107,10 @@ class SimpleNameGenerator : NameGenerator { return@getOrPut context.currentScope.declareName(jsName) } + if (declaration is IrSimpleFunction && declaration.origin == JsLoweredDeclarationOrigin.BRIDGE_TO_EXTERNAL_FUNCTION) { + return@getOrPut context.staticContext.rootScope.declareName(declaration.name.identifier) + } + if (declaration.isEffectivelyExternal()) { // TODO: descriptors are still used here due to the corresponding declaration doesn't have enough information yet val descriptorName = when (descriptor) { diff --git a/compiler/testData/codegen/box/bridges/jsName.kt b/compiler/testData/codegen/box/bridges/jsName.kt index b44af1618e7..a54e1ce8112 100644 --- a/compiler/testData/codegen/box/bridges/jsName.kt +++ b/compiler/testData/codegen/box/bridges/jsName.kt @@ -54,7 +54,9 @@ fun box(): String { val dd: dynamic = E() assertEquals("D.foo(42)", dd.foo(42)) assertEquals("D.foo(99)", dd.bar(99)) - assertEquals("D.foo(88)", dd.`foo_za3lpa$`(88)) + if (testUtils.isLegacyBackend()) { + assertEquals("D.foo(88)", dd.`foo_za3lpa$`(88)) + } return "OK" } \ No newline at end of file diff --git a/compiler/testData/codegen/box/bridges/jsNative.kt b/compiler/testData/codegen/box/bridges/jsNative.kt index 107dc70ca33..cfc8e673238 100644 --- a/compiler/testData/codegen/box/bridges/jsNative.kt +++ b/compiler/testData/codegen/box/bridges/jsNative.kt @@ -29,7 +29,9 @@ fun box(): String { val d: dynamic = C() assertEquals("C.foo(42)", d.foo(42)) - assertEquals("C.foo(99)", d.`foo_za3lpa$`(99)) + if (testUtils.isLegacyBackend()) { + assertEquals("C.foo(99)", d.`foo_za3lpa$`(99)) + } val da: A = E() assertEquals("D.foo(55)", da.foo(55)) @@ -39,7 +41,10 @@ fun box(): String { val dd: dynamic = E() assertEquals("D.foo(42)", dd.foo(42)) - assertEquals("D.foo(99)", dd.`foo_za3lpa$`(99)) + + if (testUtils.isLegacyBackend()) { + assertEquals("D.foo(99)", dd.`foo_za3lpa$`(99)) + } return "OK" } \ No newline at end of file diff --git a/js/js.translator/testData/box/propertyAccess/subclassAccessorsWithJsNameInSuper.kt b/js/js.translator/testData/box/propertyAccess/subclassAccessorsWithJsNameInSuper.kt index c740c6fed32..c43a2be6c0b 100644 --- a/js/js.translator/testData/box/propertyAccess/subclassAccessorsWithJsNameInSuper.kt +++ b/js/js.translator/testData/box/propertyAccess/subclassAccessorsWithJsNameInSuper.kt @@ -1,6 +1,5 @@ // IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1303 -package foo open class A { open val x: Int @@ -30,7 +29,7 @@ class B : A(), C { override val z = 55 } -fun getPackage() = js("return JS_TESTS.foo") +fun getPackage() = js("JS_TESTS") fun box(): String { val a = B()