[JS IR] Rename and doc new intrinsics, add new intrinsic to call suspend fun as supertype

^KT-46204 fixed
This commit is contained in:
Ilya Goncharov
2021-08-02 15:40:38 +03:00
committed by Space
parent a70fc99130
commit e6af3ff6a8
3 changed files with 48 additions and 34 deletions
@@ -163,9 +163,12 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
get() = context.ir.symbols.coroutineContextGetter get() = context.ir.symbols.coroutineContextGetter
val jsGetContinuation = getInternalFunction("getContinuation") val jsGetContinuation = getInternalFunction("getContinuation")
val jsInvokeSuspendFunction = getInternalWithoutPackage("kotlin.coroutines.intrinsics.invokeSuspendFunction") val jsInvokeSuspendSuperType =
val jsInvokeSuspendFunctionWithReceiver = getInternalWithoutPackage("kotlin.coroutines.intrinsics.invokeSuspendFunctionWithReceiver") getInternalWithoutPackage("kotlin.coroutines.intrinsics.invokeSuspendSuperType")
val jsInvokeSuspendFunctionWithReceiverAndParam = getInternalWithoutPackage("kotlin.coroutines.intrinsics.invokeSuspendFunctionWithReceiverAndParam") val jsInvokeSuspendSuperTypeWithReceiver =
getInternalWithoutPackage("kotlin.coroutines.intrinsics.invokeSuspendSuperTypeWithReceiver")
val jsInvokeSuspendSuperTypeWithReceiverAndParam =
getInternalWithoutPackage("kotlin.coroutines.intrinsics.invokeSuspendSuperTypeWithReceiverAndParam")
val jsGetKClass = getInternalWithoutPackage("getKClass") val jsGetKClass = getInternalWithoutPackage("getKClass")
val jsGetKClassFromExpression = getInternalWithoutPackage("getKClassFromExpression") val jsGetKClassFromExpression = getInternalWithoutPackage("getKClassFromExpression")
@@ -13,15 +13,15 @@ import org.jetbrains.kotlin.ir.backend.js.utils.getClassRef
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
import org.jetbrains.kotlin.ir.expressions.IrGetField
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.classifierOrFail import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.util.getInlineClassBackingField import org.jetbrains.kotlin.ir.util.getInlineClassBackingField
import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.js.backend.ast.* import org.jetbrains.kotlin.js.backend.ast.*
import java.lang.IllegalArgumentException
typealias IrCallTransformer = (IrCall, context: JsGenerationContext) -> JsExpression typealias IrCallTransformer = (IrCall, context: JsGenerationContext) -> JsExpression
@@ -233,16 +233,9 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
// Because it is intrinsic, we know everything about this function // Because it is intrinsic, we know everything about this function
// There is callable reference as extension receiver // There is callable reference as extension receiver
val invokeFun = (call.extensionReceiver as IrCall) val invokeFun = (call.extensionReceiver as IrCall)
// Single parameter is field .getValueArgument(0)!!
.getValueArgument(0)
.let { it as IrGetField }
.symbol
.owner
// It should be SuspendFunctionN
.type .type
.classifierOrFail .getClass()!!
.owner
.let { it as IrClass }
.declarations .declarations
.filterIsInstance<IrSimpleFunction>() .filterIsInstance<IrSimpleFunction>()
.single { it.name.asString() == "invoke" } .single { it.name.asString() == "invoke" }
@@ -280,9 +273,9 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
JsInvocation(jsExtensionReceiver, args) JsInvocation(jsExtensionReceiver, args)
} }
add(intrinsics.jsInvokeSuspendFunction, suspendInvokeTransform) add(intrinsics.jsInvokeSuspendSuperType, suspendInvokeTransform)
add(intrinsics.jsInvokeSuspendFunctionWithReceiver, suspendInvokeTransform) add(intrinsics.jsInvokeSuspendSuperTypeWithReceiver, suspendInvokeTransform)
add(intrinsics.jsInvokeSuspendFunctionWithReceiverAndParam, suspendInvokeTransform) add(intrinsics.jsInvokeSuspendSuperTypeWithReceiverAndParam, suspendInvokeTransform)
} }
} }
@@ -10,23 +10,41 @@ package kotlin.coroutines.intrinsics
import kotlin.coroutines.* import kotlin.coroutines.*
import kotlin.internal.InlineOnly import kotlin.internal.InlineOnly
@SinceKotlin("1.3") /**
public fun <T> (suspend () -> T).invokeSuspendFunction( * Invoke 'invoke' method of suspend super type
* Because callable references translated with local classes,
* necessary to call it in special way, not in synamic way
*/
@Suppress("UNUSED_PARAMETER", "unused")
@SinceKotlin("1.5")
public fun <T> (suspend () -> T).invokeSuspendSuperType(
completion: Continuation<T> completion: Continuation<T>
): Any? { ): Any? {
throw NotImplementedError("It is intrinsic method") throw NotImplementedError("It is intrinsic method")
} }
@SinceKotlin("1.3") /**
public fun <R, T> (suspend R.() -> T).invokeSuspendFunctionWithReceiver( * Invoke 'invoke' method of suspend super type with receiver
* Because callable references translated with local classes,
* necessary to call it in special way, not in synamic way
*/
@Suppress("UNUSED_PARAMETER", "unused")
@SinceKotlin("1.5")
public fun <R, T> (suspend R.() -> T).invokeSuspendSuperTypeWithReceiver(
receiver: R, receiver: R,
completion: Continuation<T> completion: Continuation<T>
): Any? { ): Any? {
throw NotImplementedError("It is intrinsic method") throw NotImplementedError("It is intrinsic method")
} }
@SinceKotlin("1.3") /**
public fun <R, P, T> (suspend R.(P) -> T).invokeSuspendFunctionWithReceiverAndParam( * Invoke 'invoke' method of suspend super type with receiver and param
* Because callable references translated with local classes,
* necessary to call it in special way, not in synamic way
*/
@Suppress("UNUSED_PARAMETER", "unused")
@SinceKotlin("1.5")
public fun <R, P, T> (suspend R.(P) -> T).invokeSuspendSuperTypeWithReceiverAndParam(
receiver: R, receiver: R,
param: P, param: P,
completion: Continuation<T> completion: Continuation<T>
@@ -46,14 +64,14 @@ public fun <R, P, T> (suspend R.(P) -> T).invokeSuspendFunctionWithReceiverAndPa
* This function is designed to be used from inside of [suspendCoroutineUninterceptedOrReturn] to resume the execution of a suspended * This function is designed to be used from inside of [suspendCoroutineUninterceptedOrReturn] to resume the execution of a suspended
* coroutine using a reference to the suspending function. * coroutine using a reference to the suspending function.
*/ */
@SinceKotlin("1.3") @SinceKotlin("1.5")
@InlineOnly @InlineOnly
public actual inline fun <T> (suspend () -> T).startCoroutineUninterceptedOrReturn( public actual inline fun <T> (suspend () -> T).startCoroutineUninterceptedOrReturn(
completion: Continuation<T> completion: Continuation<T>
): Any? { ): Any? {
val a = this.asDynamic() val a = this.asDynamic()
return if (jsTypeOf(a) == "function") a(completion) return if (jsTypeOf(a) == "function") a(completion)
else ::invoke.invokeSuspendFunction(completion) else ::invoke.invokeSuspendSuperType(completion)
} }
/** /**
@@ -68,7 +86,7 @@ public actual inline fun <T> (suspend () -> T).startCoroutineUninterceptedOrRetu
* This function is designed to be used from inside of [suspendCoroutineUninterceptedOrReturn] to resume the execution of a suspended * This function is designed to be used from inside of [suspendCoroutineUninterceptedOrReturn] to resume the execution of a suspended
* coroutine using a reference to the suspending function. * coroutine using a reference to the suspending function.
*/ */
@SinceKotlin("1.3") @SinceKotlin("1.5")
@InlineOnly @InlineOnly
public actual inline fun <R, T> (suspend R.() -> T).startCoroutineUninterceptedOrReturn( public actual inline fun <R, T> (suspend R.() -> T).startCoroutineUninterceptedOrReturn(
receiver: R, receiver: R,
@@ -76,7 +94,7 @@ public actual inline fun <R, T> (suspend R.() -> T).startCoroutineUninterceptedO
): Any? { ): Any? {
val a = this.asDynamic() val a = this.asDynamic()
return if (jsTypeOf(a) == "function") a(receiver, completion) return if (jsTypeOf(a) == "function") a(receiver, completion)
else ::invoke.invokeSuspendFunctionWithReceiver(receiver, completion) else ::invoke.invokeSuspendSuperTypeWithReceiver(receiver, completion)
} }
@InlineOnly @InlineOnly
@@ -87,7 +105,7 @@ internal actual inline fun <R, P, T> (suspend R.(P) -> T).startCoroutineUninterc
): Any? { ): Any? {
val a = this.asDynamic() val a = this.asDynamic()
return if (jsTypeOf(a) == "function") a(receiver, param, completion) return if (jsTypeOf(a) == "function") a(receiver, param, completion)
else ::invoke.invokeSuspendFunctionWithReceiverAndParam(receiver, param, completion) else ::invoke.invokeSuspendSuperTypeWithReceiverAndParam(receiver, param, completion)
} }
/** /**
@@ -106,14 +124,14 @@ internal actual inline fun <R, P, T> (suspend R.(P) -> T).startCoroutineUninterc
* Repeated invocation of any resume function on the resulting continuation corrupts the * Repeated invocation of any resume function on the resulting continuation corrupts the
* state machine of the coroutine and may result in arbitrary behaviour or exception. * state machine of the coroutine and may result in arbitrary behaviour or exception.
*/ */
@SinceKotlin("1.3") @SinceKotlin("1.5")
public actual fun <T> (suspend () -> T).createCoroutineUnintercepted( public actual fun <T> (suspend () -> T).createCoroutineUnintercepted(
completion: Continuation<T> completion: Continuation<T>
): Continuation<Unit> = ): Continuation<Unit> =
createCoroutineFromSuspendFunction(completion) { createCoroutineFromSuspendFunction(completion) {
val a = this.asDynamic() val a = this.asDynamic()
if (jsTypeOf(a) == "function") a(completion) if (jsTypeOf(a) == "function") a(completion)
else ::invoke.invokeSuspendFunction(completion) else ::invoke.invokeSuspendSuperType(completion)
} }
/** /**
@@ -132,7 +150,7 @@ public actual fun <T> (suspend () -> T).createCoroutineUnintercepted(
* Repeated invocation of any resume function on the resulting continuation corrupts the * Repeated invocation of any resume function on the resulting continuation corrupts the
* state machine of the coroutine and may result in arbitrary behaviour or exception. * state machine of the coroutine and may result in arbitrary behaviour or exception.
*/ */
@SinceKotlin("1.3") @SinceKotlin("1.5")
public actual fun <R, T> (suspend R.() -> T).createCoroutineUnintercepted( public actual fun <R, T> (suspend R.() -> T).createCoroutineUnintercepted(
receiver: R, receiver: R,
completion: Continuation<T> completion: Continuation<T>
@@ -140,13 +158,13 @@ public actual fun <R, T> (suspend R.() -> T).createCoroutineUnintercepted(
createCoroutineFromSuspendFunction(completion) { createCoroutineFromSuspendFunction(completion) {
val a = this.asDynamic() val a = this.asDynamic()
if (jsTypeOf(a) == "function") a(receiver, completion) if (jsTypeOf(a) == "function") a(receiver, completion)
else ::invoke.invokeSuspendFunctionWithReceiver(receiver, completion) else ::invoke.invokeSuspendSuperTypeWithReceiver(receiver, completion)
} }
/** /**
* Intercepts this continuation with [ContinuationInterceptor]. * Intercepts this continuation with [ContinuationInterceptor].
*/ */
@SinceKotlin("1.3") @SinceKotlin("1.5")
public actual fun <T> Continuation<T>.intercepted(): Continuation<T> = public actual fun <T> Continuation<T>.intercepted(): Continuation<T> =
(this as? CoroutineImpl)?.intercepted() ?: this (this as? CoroutineImpl)?.intercepted() ?: this