[JS IR BE] Implement type check for SuspendFunctionN
This commit is contained in:
@@ -54,6 +54,7 @@ fun IrType.typeParameterSuperTypes(): List<IrType> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun IrType.isFunctionTypeOrSubtype(): Boolean = DFS.ifAny(listOf(this), { it.superTypes() }, { it.isFunction() })
|
fun IrType.isFunctionTypeOrSubtype(): Boolean = DFS.ifAny(listOf(this), { it.superTypes() }, { it.isFunction() })
|
||||||
|
fun IrType.isSuspendFunctionTypeOrSubtype(): Boolean = DFS.ifAny(listOf(this), { it.superTypes() }, { it.isSuspendFunction() })
|
||||||
|
|
||||||
fun IrType.isTypeParameter() = classifierOrNull is IrTypeParameterSymbol
|
fun IrType.isTypeParameter() = classifierOrNull is IrTypeParameterSymbol
|
||||||
|
|
||||||
|
|||||||
@@ -118,6 +118,7 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
|
|||||||
val isArraySymbol = getInternalFunction("isArray")
|
val isArraySymbol = getInternalFunction("isArray")
|
||||||
// val isCharSymbol = getInternalFunction("isChar")
|
// val isCharSymbol = getInternalFunction("isChar")
|
||||||
val isObjectSymbol = getInternalFunction("isObject")
|
val isObjectSymbol = getInternalFunction("isObject")
|
||||||
|
val isSuspendFunctionSymbol = getInternalFunction("isSuspendFunction")
|
||||||
|
|
||||||
val isNumberSymbol = getInternalFunction("isNumber")
|
val isNumberSymbol = getInternalFunction("isNumber")
|
||||||
val isComparableSymbol = getInternalFunction("isComparable")
|
val isComparableSymbol = getInternalFunction("isComparable")
|
||||||
|
|||||||
+12
@@ -42,6 +42,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
|
|||||||
|
|
||||||
private val isInterfaceSymbol get() = context.intrinsics.isInterfaceSymbol
|
private val isInterfaceSymbol get() = context.intrinsics.isInterfaceSymbol
|
||||||
private val isArraySymbol get() = context.intrinsics.isArraySymbol
|
private val isArraySymbol get() = context.intrinsics.isArraySymbol
|
||||||
|
private val isSuspenfFunctionSymbol = context.intrinsics.isSuspendFunctionSymbol
|
||||||
// private val isCharSymbol get() = context.intrinsics.isCharSymbol
|
// private val isCharSymbol get() = context.intrinsics.isCharSymbol
|
||||||
private val isObjectSymbol get() = context.intrinsics.isObjectSymbol
|
private val isObjectSymbol get() = context.intrinsics.isObjectSymbol
|
||||||
|
|
||||||
@@ -209,6 +210,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
|
|||||||
return when {
|
return when {
|
||||||
toType.isAny() -> generateIsObjectCheck(argument)
|
toType.isAny() -> generateIsObjectCheck(argument)
|
||||||
toType.isNothing() -> JsIrBuilder.buildComposite(context.irBuiltIns.booleanType, listOf(argument, litFalse))
|
toType.isNothing() -> JsIrBuilder.buildComposite(context.irBuiltIns.booleanType, listOf(argument, litFalse))
|
||||||
|
toType.isSuspendFunctionTypeOrSubtype() -> generateSuspendFunctionCheck(argument, toType)
|
||||||
isTypeOfCheckingType(toType) -> generateTypeOfCheck(argument, toType)
|
isTypeOfCheckingType(toType) -> generateTypeOfCheck(argument, toType)
|
||||||
// toType.isChar() -> generateCheckForChar(argument)
|
// toType.isChar() -> generateCheckForChar(argument)
|
||||||
toType.isNumber() -> generateNumberCheck(argument)
|
toType.isNumber() -> generateNumberCheck(argument)
|
||||||
@@ -254,6 +256,16 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
|
|||||||
// private fun generateCheckForChar(argument: IrExpression) =
|
// private fun generateCheckForChar(argument: IrExpression) =
|
||||||
// JsIrBuilder.buildCall(isCharSymbol).apply { dispatchReceiver = argument }
|
// JsIrBuilder.buildCall(isCharSymbol).apply { dispatchReceiver = argument }
|
||||||
|
|
||||||
|
private fun generateSuspendFunctionCheck(argument: IrExpression, toType: IrType): IrExpression {
|
||||||
|
val arity = (toType.classifierOrFail.owner as IrClass).typeParameters.size - 1 // drop return type
|
||||||
|
|
||||||
|
val irBuiltIns = context.irBuiltIns
|
||||||
|
return JsIrBuilder.buildCall(isSuspenfFunctionSymbol, irBuiltIns.booleanType).apply {
|
||||||
|
putValueArgument(0, argument)
|
||||||
|
putValueArgument(1, JsIrBuilder.buildInt(irBuiltIns.intType, arity))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun generateTypeOfCheck(argument: IrExpression, toType: IrType): IrExpression {
|
private fun generateTypeOfCheck(argument: IrExpression, toType: IrType): IrExpression {
|
||||||
val marker = when {
|
val marker = when {
|
||||||
toType.isFunctionOrKFunction() -> functionMarker
|
toType.isFunctionOrKFunction() -> functionMarker
|
||||||
|
|||||||
+12
@@ -240,9 +240,21 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
|||||||
metadataLiteral.propertyInitializers += JsPropertyInitializer(JsNameRef(Namer.METADATA_CLASS_KIND), classKind)
|
metadataLiteral.propertyInitializers += JsPropertyInitializer(JsNameRef(Namer.METADATA_CLASS_KIND), classKind)
|
||||||
|
|
||||||
metadataLiteral.propertyInitializers += generateSuperClasses()
|
metadataLiteral.propertyInitializers += generateSuperClasses()
|
||||||
|
|
||||||
|
if (isCoroutineClass()) {
|
||||||
|
metadataLiteral.propertyInitializers += generateSuspendArity()
|
||||||
|
}
|
||||||
|
|
||||||
return jsAssignment(JsNameRef(Namer.METADATA, classNameRef), metadataLiteral).makeStmt()
|
return jsAssignment(JsNameRef(Namer.METADATA, classNameRef), metadataLiteral).makeStmt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isCoroutineClass(): Boolean = irClass.superTypes.any { it.isSuspendFunctionTypeOrSubtype() }
|
||||||
|
|
||||||
|
private fun generateSuspendArity(): JsPropertyInitializer {
|
||||||
|
val arity = irClass.declarations.filterIsInstance<IrSimpleFunction>().first { it.isSuspend }.valueParameters.size
|
||||||
|
return JsPropertyInitializer(JsNameRef(Namer.METADATA_SUSPEND_ARITY), JsIntLiteral(arity))
|
||||||
|
}
|
||||||
|
|
||||||
private fun generateSuperClasses(): JsPropertyInitializer {
|
private fun generateSuperClasses(): JsPropertyInitializer {
|
||||||
val functionTypeOrSubtype = irClass.defaultType.isFunctionTypeOrSubtype()
|
val functionTypeOrSubtype = irClass.defaultType.isFunctionTypeOrSubtype()
|
||||||
return JsPropertyInitializer(
|
return JsPropertyInitializer(
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ object Namer {
|
|||||||
val METADATA_INTERFACES = "interfaces"
|
val METADATA_INTERFACES = "interfaces"
|
||||||
val METADATA_SIMPLE_NAME = "simpleName"
|
val METADATA_SIMPLE_NAME = "simpleName"
|
||||||
val METADATA_CLASS_KIND = "kind"
|
val METADATA_CLASS_KIND = "kind"
|
||||||
|
val METADATA_SUSPEND_ARITY = "suspendArity"
|
||||||
|
|
||||||
val KCALLABLE_GET_NAME = "<get-name>"
|
val KCALLABLE_GET_NAME = "<get-name>"
|
||||||
val KCALLABLE_NAME = "callableName"
|
val KCALLABLE_NAME = "callableName"
|
||||||
|
|||||||
-1
@@ -1,5 +1,4 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
// IGNORE_BACKEND: JVM_IR
|
||||||
// IGNORE_BACKEND: JS_IR
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// COMMON_COROUTINES_TEST
|
// COMMON_COROUTINES_TEST
|
||||||
|
|||||||
Vendored
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JS_IR
|
|
||||||
// IGNORE_BACKEND: JVM_IR
|
// IGNORE_BACKEND: JVM_IR
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ package kotlin.js
|
|||||||
|
|
||||||
private external interface Metadata {
|
private external interface Metadata {
|
||||||
val interfaces: Array<Ctor>
|
val interfaces: Array<Ctor>
|
||||||
|
val suspendArity: Int?
|
||||||
}
|
}
|
||||||
|
|
||||||
private external interface Ctor {
|
private external interface Ctor {
|
||||||
@@ -33,9 +34,7 @@ private fun isInterfaceImpl(ctor: Ctor, iface: dynamic): Boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fun isInterface(obj: dynamic, iface: dynamic): Boolean {
|
public fun isInterface(obj: dynamic, iface: dynamic): Boolean {
|
||||||
val ctor = obj.constructor
|
val ctor = obj.constructor ?: return false
|
||||||
|
|
||||||
if (ctor == null) return false
|
|
||||||
|
|
||||||
return isInterfaceImpl(ctor, iface)
|
return isInterfaceImpl(ctor, iface)
|
||||||
}
|
}
|
||||||
@@ -75,6 +74,13 @@ public fun isInterface(ctor: dynamic, IType: dynamic): Boolean {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
internal fun isSuspendFunction(obj: dynamic, arity: Int): Boolean {
|
||||||
|
val ctor = obj.constructor?.unsafeCast<Ctor>() ?: return false
|
||||||
|
|
||||||
|
val metadata = ctor.`$metadata$`?.unsafeCast<Metadata>() ?: return false
|
||||||
|
|
||||||
|
return metadata.suspendArity === arity
|
||||||
|
}
|
||||||
|
|
||||||
fun isObject(obj: dynamic): Boolean {
|
fun isObject(obj: dynamic): Boolean {
|
||||||
val objTypeOf = jsTypeOf(obj)
|
val objTypeOf = jsTypeOf(obj)
|
||||||
|
|||||||
Reference in New Issue
Block a user