[JS IR BE] Support @JsName in bridges
This commit is contained in:
@@ -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")
|
||||
}
|
||||
+32
-19
@@ -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<String?>,
|
||||
val returnType: String?
|
||||
val name: String,
|
||||
val extensionReceiverType: String? = null,
|
||||
val valueParameters: List<String?> = 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
|
||||
|
||||
+5
@@ -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) {
|
||||
|
||||
+3
-1
@@ -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"
|
||||
}
|
||||
+7
-2
@@ -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"
|
||||
}
|
||||
+1
-2
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user