[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_INTRINSICS_STUB : IrDeclarationOriginImpl("JS_INTRINSICS_STUB")
|
||||||
object JS_CLOSURE_BOX_CLASS : IrStatementOriginImpl("JS_CLOSURE_BOX_CLASS")
|
object JS_CLOSURE_BOX_CLASS : IrStatementOriginImpl("JS_CLOSURE_BOX_CLASS")
|
||||||
object JS_CLOSURE_BOX_CLASS_DECLARATION : IrDeclarationOriginImpl("JS_CLOSURE_BOX_CLASS_DECLARATION")
|
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.createIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.common.lower.irBlockBody
|
import org.jetbrains.kotlin.backend.common.lower.irBlockBody
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
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.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.ir.JsIrBuilder
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.asString
|
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.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
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.IrType
|
||||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||||
import org.jetbrains.kotlin.ir.types.isUnit
|
import org.jetbrains.kotlin.ir.types.isUnit
|
||||||
import org.jetbrains.kotlin.ir.util.isInlined
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
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.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
|
||||||
// Constructs bridges for inherited generic functions
|
// Constructs bridges for inherited generic functions
|
||||||
@@ -82,6 +79,11 @@ class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass {
|
|||||||
continue
|
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))
|
irClass.declarations.add(createBridge(function, from.function, to.function))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,6 +97,12 @@ class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass {
|
|||||||
delegateTo: IrSimpleFunction
|
delegateTo: IrSimpleFunction
|
||||||
): IrFunction {
|
): IrFunction {
|
||||||
|
|
||||||
|
val origin =
|
||||||
|
if (bridge.isEffectivelyExternal())
|
||||||
|
JsLoweredDeclarationOrigin.BRIDGE_TO_EXTERNAL_FUNCTION
|
||||||
|
else
|
||||||
|
IrDeclarationOrigin.BRIDGE
|
||||||
|
|
||||||
// TODO: Support offsets for debug info
|
// TODO: Support offsets for debug info
|
||||||
val irFunction = JsIrBuilder.buildFunction(
|
val irFunction = JsIrBuilder.buildFunction(
|
||||||
bridge.name,
|
bridge.name,
|
||||||
@@ -106,7 +114,7 @@ class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass {
|
|||||||
bridge.isExternal,
|
bridge.isExternal,
|
||||||
bridge.isTailrec,
|
bridge.isTailrec,
|
||||||
bridge.isSuspend,
|
bridge.isSuspend,
|
||||||
IrDeclarationOrigin.BRIDGE
|
origin
|
||||||
).apply {
|
).apply {
|
||||||
|
|
||||||
// TODO: should dispatch receiver be copied?
|
// 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
|
// Currently strings are used for compatibility with a hack-based name generator
|
||||||
|
|
||||||
private data class Signature(
|
private data class Signature(
|
||||||
val name: Name,
|
val name: String,
|
||||||
val extensionReceiverType: String?,
|
val extensionReceiverType: String? = null,
|
||||||
val valueParameters: List<String?>,
|
val valueParameters: List<String?> = emptyList(),
|
||||||
val returnType: String?
|
val returnType: String? = null
|
||||||
)
|
)
|
||||||
|
|
||||||
private val signature = Signature(
|
private val jsName = function.getJsName()
|
||||||
function.name,
|
private val signature = when {
|
||||||
function.extensionReceiverParameter?.type?.asString(),
|
jsName != null -> Signature(jsName)
|
||||||
function.valueParameters.map { it.type.asString() },
|
function.isEffectivelyExternal() -> Signature(function.name.asString())
|
||||||
// Return type used in signature for inline classes only because
|
else -> Signature(
|
||||||
// they are binary incompatible with supertypes and require bridges.
|
function.name.asString(),
|
||||||
function.returnType.run { if (isInlined()) asString() else null }
|
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 {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
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.backend.common.ir.isTopLevel
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrLoop
|
import org.jetbrains.kotlin.ir.expressions.IrLoop
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||||
@@ -106,6 +107,10 @@ class SimpleNameGenerator : NameGenerator {
|
|||||||
return@getOrPut context.currentScope.declareName(jsName)
|
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()) {
|
if (declaration.isEffectivelyExternal()) {
|
||||||
// TODO: descriptors are still used here due to the corresponding declaration doesn't have enough information yet
|
// TODO: descriptors are still used here due to the corresponding declaration doesn't have enough information yet
|
||||||
val descriptorName = when (descriptor) {
|
val descriptorName = when (descriptor) {
|
||||||
|
|||||||
+3
-1
@@ -54,7 +54,9 @@ fun box(): String {
|
|||||||
val dd: dynamic = E()
|
val dd: dynamic = E()
|
||||||
assertEquals("D.foo(42)", dd.foo(42))
|
assertEquals("D.foo(42)", dd.foo(42))
|
||||||
assertEquals("D.foo(99)", dd.bar(99))
|
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"
|
return "OK"
|
||||||
}
|
}
|
||||||
+7
-2
@@ -29,7 +29,9 @@ fun box(): String {
|
|||||||
|
|
||||||
val d: dynamic = C()
|
val d: dynamic = C()
|
||||||
assertEquals("C.foo(42)", d.foo(42))
|
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()
|
val da: A = E()
|
||||||
assertEquals("D.foo(55)", da.foo(55))
|
assertEquals("D.foo(55)", da.foo(55))
|
||||||
@@ -39,7 +41,10 @@ fun box(): String {
|
|||||||
|
|
||||||
val dd: dynamic = E()
|
val dd: dynamic = E()
|
||||||
assertEquals("D.foo(42)", dd.foo(42))
|
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"
|
return "OK"
|
||||||
}
|
}
|
||||||
+1
-2
@@ -1,6 +1,5 @@
|
|||||||
// IGNORE_BACKEND: JS_IR
|
// IGNORE_BACKEND: JS_IR
|
||||||
// EXPECTED_REACHABLE_NODES: 1303
|
// EXPECTED_REACHABLE_NODES: 1303
|
||||||
package foo
|
|
||||||
|
|
||||||
open class A {
|
open class A {
|
||||||
open val x: Int
|
open val x: Int
|
||||||
@@ -30,7 +29,7 @@ class B : A(), C {
|
|||||||
override val z = 55
|
override val z = 55
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getPackage() = js("return JS_TESTS.foo")
|
fun getPackage() = js("JS_TESTS")
|
||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
val a = B()
|
val a = B()
|
||||||
|
|||||||
Reference in New Issue
Block a user