rra/ilgonmic/exported-bridges-2
[JS IR] Use js name for signature [JS] bridgeSavingExport only for JS IR [JS IR] Fix test [JS IR] Stable and non stable signatures [JS IR] Consider return type in js signature and erase for JS name signature [JS IR] Copy signature from wasm to JS and export bridge, not original Merge-request: KT-MR-5174
This commit is contained in:
+2
-5
@@ -74,10 +74,6 @@ class ExportModelGenerator(
|
||||
}
|
||||
|
||||
private fun exportFunction(function: IrSimpleFunction): ExportedDeclaration? {
|
||||
if (function.origin == JsLoweredDeclarationOrigin.ENUM_GET_INSTANCE_FUNCTION) {
|
||||
return null
|
||||
}
|
||||
|
||||
return when (val exportability = functionExportability(function)) {
|
||||
is Exportability.NotNeeded -> null
|
||||
is Exportability.Prohibited -> ErrorDeclaration(exportability.reason)
|
||||
@@ -533,7 +529,8 @@ class ExportModelGenerator(
|
||||
function.origin == JsLoweredDeclarationOrigin.BRIDGE_WITH_STABLE_NAME ||
|
||||
function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ||
|
||||
function.origin == JsLoweredDeclarationOrigin.OBJECT_GET_INSTANCE_FUNCTION ||
|
||||
function.origin == JsLoweredDeclarationOrigin.JS_SHADOWED_EXPORT
|
||||
function.origin == JsLoweredDeclarationOrigin.JS_SHADOWED_EXPORT ||
|
||||
function.origin == JsLoweredDeclarationOrigin.ENUM_GET_INSTANCE_FUNCTION
|
||||
) {
|
||||
return Exportability.NotNeeded
|
||||
}
|
||||
|
||||
-2
@@ -13,9 +13,7 @@ import org.jetbrains.kotlin.backend.common.lower.*
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.hasStableJsName
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
||||
|
||||
+41
-3
@@ -7,14 +7,31 @@ package org.jetbrains.kotlin.ir.backend.js.lower
|
||||
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.eraseGenerics
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.getJsInlinedClass
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.getJsNameOrKotlinName
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.hasStableJsName
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.jsFunctionSignature
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.isUnit
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class JsBridgesConstruction(context: JsIrBackendContext) : BridgesConstruction<JsIrBackendContext>(context) {
|
||||
override fun getFunctionSignature(function: IrSimpleFunction): String =
|
||||
jsFunctionSignature(function, context)
|
||||
override fun getFunctionSignature(function: IrSimpleFunction): JsSignature =
|
||||
if (function.hasStableJsName(context)) {
|
||||
JsStableNameSignature(function.getJsNameOrKotlinName())
|
||||
} else {
|
||||
JsNonStableSignature(
|
||||
function.name,
|
||||
function.extensionReceiverParameter?.type?.eraseGenerics(context.irBuiltIns),
|
||||
function.valueParameters.map { it.type.eraseGenerics(context.irBuiltIns) },
|
||||
function.returnType.takeIf {
|
||||
it.getJsInlinedClass() != null || it.isUnit()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun getBridgeOrigin(bridge: IrSimpleFunction): IrDeclarationOrigin =
|
||||
if (bridge.hasStableJsName(context))
|
||||
@@ -22,3 +39,24 @@ class JsBridgesConstruction(context: JsIrBackendContext) : BridgesConstruction<J
|
||||
else
|
||||
JsLoweredDeclarationOrigin.BRIDGE_WITHOUT_STABLE_NAME
|
||||
}
|
||||
|
||||
interface JsSignature {
|
||||
val name: Name
|
||||
}
|
||||
|
||||
data class JsNonStableSignature(
|
||||
override val name: Name,
|
||||
val extensionReceiverType: IrType?,
|
||||
val valueParametersType: List<IrType>,
|
||||
val returnType: IrType?,
|
||||
) : JsSignature {
|
||||
override fun toString(): String {
|
||||
val er = extensionReceiverType?.let { "(er: ${it.render()}) " } ?: ""
|
||||
val parameters = valueParametersType.joinToString(", ") { it.render() }
|
||||
return "[$er$name($parameters) -> ${returnType?.let { " -> ${it.render()}" } ?: ""}]"
|
||||
}
|
||||
}
|
||||
|
||||
data class JsStableNameSignature(
|
||||
override val name: Name,
|
||||
) : JsSignature
|
||||
@@ -13,11 +13,7 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
|
||||
import org.jetbrains.kotlin.ir.types.isUnit
|
||||
import org.jetbrains.kotlin.ir.util.file
|
||||
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
||||
import org.jetbrains.kotlin.ir.util.isInterface
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.js.common.isES5IdentifierPart
|
||||
@@ -109,7 +105,7 @@ fun NameTable<IrDeclaration>.dump(): String =
|
||||
|
||||
private const val RESERVED_MEMBER_NAME_SUFFIX = "_k$"
|
||||
|
||||
fun jsFunctionSignature(declaration: IrFunction, context: JsIrBackendContext?): String {
|
||||
fun jsFunctionSignature(declaration: IrFunction, context: JsIrBackendContext): String {
|
||||
require(!declaration.isStaticMethodOfClass)
|
||||
require(declaration.dispatchReceiverParameter != null)
|
||||
|
||||
@@ -126,16 +122,11 @@ fun jsFunctionSignature(declaration: IrFunction, context: JsIrBackendContext?):
|
||||
val nameBuilder = StringBuilder()
|
||||
nameBuilder.append(declarationName)
|
||||
|
||||
// TODO should we skip type parameters and use upper bound of type parameter when print type of value parameters?
|
||||
declaration.typeParameters.ifNotEmpty {
|
||||
nameBuilder.append("_\$t")
|
||||
joinTo(nameBuilder, "") { "_${it.name.asString()}" }
|
||||
}
|
||||
declaration.extensionReceiverParameter?.let {
|
||||
nameBuilder.append("_r$${it.type.asString()}")
|
||||
nameBuilder.append("_r$${it.type.eraseGenerics(context.irBuiltIns).asString()}")
|
||||
}
|
||||
declaration.valueParameters.ifNotEmpty {
|
||||
joinTo(nameBuilder, "") { "_${it.type.asString()}" }
|
||||
joinTo(nameBuilder, "") { "_${it.type.eraseGenerics(context.irBuiltIns).asString()}" }
|
||||
}
|
||||
declaration.returnType.let {
|
||||
// Return type is only used in signature for inline class and Unit types because
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.ir.backend.js.utils
|
||||
|
||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
|
||||
fun IrType.eraseGenerics(irBuiltIns: IrBuiltIns): IrType {
|
||||
if (this is IrDynamicType) return this
|
||||
val defaultType = this.erasedUpperBound?.defaultType ?: irBuiltIns.anyType
|
||||
if (!this.isNullable()) return defaultType
|
||||
return defaultType.makeNullable()
|
||||
}
|
||||
|
||||
// Return null if upper bound is Any
|
||||
private val IrTypeParameter.erasedUpperBound: IrClass?
|
||||
get() {
|
||||
// Pick the (necessarily unique) non-interface upper bound if it exists
|
||||
for (type in superTypes) {
|
||||
return type.erasedUpperBound ?: continue
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
val IrType.erasedUpperBound: IrClass?
|
||||
get() = when (val classifier = classifierOrNull) {
|
||||
is IrClassSymbol -> classifier.owner
|
||||
is IrTypeParameterSymbol -> classifier.owner.erasedUpperBound
|
||||
else -> throw IllegalStateException()
|
||||
}
|
||||
+1
-23
@@ -6,14 +6,10 @@
|
||||
package org.jetbrains.kotlin.backend.wasm.ir2wasm
|
||||
|
||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.erasedUpperBound
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||
import org.jetbrains.kotlin.ir.types.getClass
|
||||
import org.jetbrains.kotlin.ir.util.isInterface
|
||||
import org.jetbrains.kotlin.ir.util.packageFqName
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -126,24 +122,6 @@ fun isBuiltInWasmRefType(type: IrType): Boolean {
|
||||
fun isExternalType(type: IrType): Boolean =
|
||||
type.erasedUpperBound?.isExternal ?: false
|
||||
|
||||
// Return null if upper bound is Any
|
||||
private val IrTypeParameter.erasedUpperBound: IrClass?
|
||||
get() {
|
||||
// Pick the (necessarily unique) non-interface upper bound if it exists
|
||||
for (type in superTypes) {
|
||||
return type.erasedUpperBound ?: continue
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
val IrType.erasedUpperBound: IrClass?
|
||||
get() = when (val classifier = classifierOrNull) {
|
||||
is IrClassSymbol -> classifier.owner
|
||||
is IrTypeParameterSymbol -> classifier.owner.erasedUpperBound
|
||||
else -> throw IllegalStateException()
|
||||
}
|
||||
|
||||
val IrType.getRuntimeClass: IrClass?
|
||||
get() = erasedUpperBound.let {
|
||||
if (it?.isInterface == true) null
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irComposite
|
||||
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
|
||||
import org.jetbrains.kotlin.backend.wasm.ir2wasm.erasedUpperBound
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.erasedUpperBound
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget
|
||||
import org.jetbrains.kotlin.ir.builders.irImplicitCast
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
|
||||
+3
-13
@@ -6,16 +6,13 @@
|
||||
package org.jetbrains.kotlin.backend.wasm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ir.isOverridableOrOverrides
|
||||
import org.jetbrains.kotlin.backend.wasm.ir2wasm.erasedUpperBound
|
||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.BridgesConstruction
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.eraseGenerics
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.isNullable
|
||||
import org.jetbrains.kotlin.ir.types.makeNullable
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
@@ -44,7 +41,7 @@ data class WasmSignature(
|
||||
override fun toString(): String {
|
||||
val er = extensionReceiverType?.let { "(er: ${it.render()}) " } ?: ""
|
||||
val parameters = valueParametersType.joinToString(", ") { it.render() }
|
||||
val nonVirtual = if (!isVirtual) "(non-virtual) " else ""
|
||||
val nonVirtual = if (!isVirtual) "(non-virtual) " else ""
|
||||
return "[$nonVirtual$er$name($parameters) -> ${returnType.render()}]"
|
||||
}
|
||||
}
|
||||
@@ -56,11 +53,4 @@ fun IrSimpleFunction.wasmSignature(irBuiltIns: IrBuiltIns): WasmSignature =
|
||||
valueParameters.map { it.type.eraseGenerics(irBuiltIns) },
|
||||
returnType.eraseGenerics(irBuiltIns),
|
||||
isOverridableOrOverrides
|
||||
)
|
||||
|
||||
private fun IrType.eraseGenerics(irBuiltIns: IrBuiltIns): IrType {
|
||||
val defaultType = this.erasedUpperBound?.defaultType ?: irBuiltIns.anyType
|
||||
if (!this.isNullable()) return defaultType
|
||||
return defaultType.makeNullable()
|
||||
}
|
||||
|
||||
)
|
||||
+1
-1
@@ -13,10 +13,10 @@ import org.jetbrains.kotlin.backend.common.lower.at
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irNot
|
||||
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
|
||||
import org.jetbrains.kotlin.backend.wasm.ir2wasm.erasedUpperBound
|
||||
import org.jetbrains.kotlin.backend.wasm.ir2wasm.getRuntimeClass
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.erasedUpperBound
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
|
||||
+6
@@ -2448,6 +2448,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/export"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("bridgeSavingAfterExport.kt")
|
||||
public void testBridgeSavingAfterExport() throws Exception {
|
||||
runTest("js/js.translator/testData/box/export/bridgeSavingAfterExport.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("defaultInlineClassConstructorParam.kt")
|
||||
public void testDefaultInlineClassConstructorParam() throws Exception {
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// TARGET_BACKEND: JS_IR
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// INFER_MAIN_MODULE
|
||||
|
||||
// MODULE: bridge_saving_after_export
|
||||
// FILE: lib.kt
|
||||
|
||||
@JsExport
|
||||
open class A<T> {
|
||||
open fun foo(value: T): T = value
|
||||
}
|
||||
|
||||
@JsExport
|
||||
class B: A<String>() {
|
||||
override fun foo(value: String): String = value
|
||||
}
|
||||
|
||||
// FILE: test.js
|
||||
function box() {
|
||||
var a = new this["bridge_saving_after_export"].A()
|
||||
var aFoo = a.foo("ok")
|
||||
if (aFoo != "ok") return "fail 1"
|
||||
|
||||
var b = new this["bridge_saving_after_export"].B()
|
||||
var bFoo = b.foo("ok")
|
||||
if (bFoo != "ok") return "fail 2"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user