[JS] Invoke processing separately for suspend and non-suspend function
^KT-62771 fixed
This commit is contained in:
committed by
Space Team
parent
f227447837
commit
573bc34b56
+16
-10
@@ -49,7 +49,7 @@ fun <T : JsNode> IrWhen.toJsNode(
|
|||||||
tr: BaseIrElementToJsNodeTransformer<T, JsGenerationContext>,
|
tr: BaseIrElementToJsNodeTransformer<T, JsGenerationContext>,
|
||||||
context: JsGenerationContext,
|
context: JsGenerationContext,
|
||||||
node: (JsExpression, T, T?) -> T,
|
node: (JsExpression, T, T?) -> T,
|
||||||
implicitElse: T? = null
|
implicitElse: T? = null,
|
||||||
): T? =
|
): T? =
|
||||||
branches.foldRight(implicitElse) { br, n ->
|
branches.foldRight(implicitElse) { br, n ->
|
||||||
val body = br.result.accept(tr, context)
|
val body = br.result.accept(tr, context)
|
||||||
@@ -142,15 +142,21 @@ private fun isFunctionTypeInvoke(receiver: JsExpression?, call: IrCall): Boolean
|
|||||||
|
|
||||||
if (call.origin === JsStatementOrigins.EXPLICIT_INVOKE) return false
|
if (call.origin === JsStatementOrigins.EXPLICIT_INVOKE) return false
|
||||||
|
|
||||||
return simpleFunction.name == OperatorNameConventions.INVOKE
|
val isInvokeFun = simpleFunction.name == OperatorNameConventions.INVOKE
|
||||||
&& receiverType.isFunctionTypeOrSubtype()
|
if (!isInvokeFun) return false
|
||||||
&& (!receiverType.isSuspendFunctionTypeOrSubtype() || receiverType.isSuspendFunction())
|
|
||||||
|
val isNonSuspendFunction = receiverType.isFunctionTypeOrSubtype() && !receiverType.isSuspendFunctionTypeOrSubtype()
|
||||||
|
val isSuspendFunction = receiverType.isSuspendFunction()
|
||||||
|
|
||||||
|
// Dce can eliminate Function parent of SuspendFunctionN
|
||||||
|
// So we need to check them separately
|
||||||
|
return isNonSuspendFunction || isSuspendFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
fun translateCall(
|
fun translateCall(
|
||||||
expression: IrCall,
|
expression: IrCall,
|
||||||
context: JsGenerationContext,
|
context: JsGenerationContext,
|
||||||
transformer: IrElementToJsExpressionTransformer
|
transformer: IrElementToJsExpressionTransformer,
|
||||||
): JsExpression {
|
): JsExpression {
|
||||||
val function = expression.symbol.owner.realOverrideTarget
|
val function = expression.symbol.owner.realOverrideTarget
|
||||||
val currentDispatchReceiver = context.currentFunction?.parentClassOrNull
|
val currentDispatchReceiver = context.currentFunction?.parentClassOrNull
|
||||||
@@ -387,7 +393,7 @@ fun translateCallArguments(
|
|||||||
expression: IrMemberAccessExpression<IrFunctionSymbol>,
|
expression: IrMemberAccessExpression<IrFunctionSymbol>,
|
||||||
context: JsGenerationContext,
|
context: JsGenerationContext,
|
||||||
transformer: IrElementToJsExpressionTransformer,
|
transformer: IrElementToJsExpressionTransformer,
|
||||||
allowDropTailVoids: Boolean = true
|
allowDropTailVoids: Boolean = true,
|
||||||
): List<JsExpression> {
|
): List<JsExpression> {
|
||||||
val size = expression.valueArgumentsCount
|
val size = expression.valueArgumentsCount
|
||||||
|
|
||||||
@@ -450,7 +456,7 @@ object JsAstUtils {
|
|||||||
fun newJsIf(
|
fun newJsIf(
|
||||||
ifExpression: JsExpression,
|
ifExpression: JsExpression,
|
||||||
thenStatement: JsStatement,
|
thenStatement: JsStatement,
|
||||||
elseStatement: JsStatement? = null
|
elseStatement: JsStatement? = null,
|
||||||
): JsIf {
|
): JsIf {
|
||||||
return JsIf(ifExpression, deBlockIfPossible(thenStatement), elseStatement?.let { deBlockIfPossible(it) })
|
return JsIf(ifExpression, deBlockIfPossible(thenStatement), elseStatement?.let { deBlockIfPossible(it) })
|
||||||
}
|
}
|
||||||
@@ -543,7 +549,7 @@ internal fun <T : JsNode> T.withSource(
|
|||||||
node: IrElement,
|
node: IrElement,
|
||||||
context: JsGenerationContext,
|
context: JsGenerationContext,
|
||||||
useNameOf: IrDeclarationWithName? = null,
|
useNameOf: IrDeclarationWithName? = null,
|
||||||
container: IrDeclaration? = null
|
container: IrDeclaration? = null,
|
||||||
): T {
|
): T {
|
||||||
addSourceInfoIfNeed(node, context, useNameOf, container)
|
addSourceInfoIfNeed(node, context, useNameOf, container)
|
||||||
return this
|
return this
|
||||||
@@ -554,7 +560,7 @@ private inline fun <T : JsNode> T.addSourceInfoIfNeed(
|
|||||||
node: IrElement,
|
node: IrElement,
|
||||||
context: JsGenerationContext,
|
context: JsGenerationContext,
|
||||||
useNameOf: IrDeclarationWithName?,
|
useNameOf: IrDeclarationWithName?,
|
||||||
container: IrDeclaration?
|
container: IrDeclaration?,
|
||||||
) {
|
) {
|
||||||
val sourceMapsInfo = context.staticContext.backendContext.sourceMapsInfo ?: return
|
val sourceMapsInfo = context.staticContext.backendContext.sourceMapsInfo ?: return
|
||||||
val originalName = useNameOf?.originalNameForUseInSourceMap(sourceMapsInfo.namesPolicy)
|
val originalName = useNameOf?.originalNameForUseInSourceMap(sourceMapsInfo.namesPolicy)
|
||||||
@@ -588,7 +594,7 @@ private inline fun <T : JsNode> T.addSourceInfoIfNeed(
|
|||||||
|
|
||||||
private fun JsLocation.withEmbeddedSource(
|
private fun JsLocation.withEmbeddedSource(
|
||||||
@Suppress("UNUSED_PARAMETER")
|
@Suppress("UNUSED_PARAMETER")
|
||||||
context: JsGenerationContext
|
context: JsGenerationContext,
|
||||||
): JsLocationWithEmbeddedSource {
|
): JsLocationWithEmbeddedSource {
|
||||||
// FIXME: fileIdentity is used to distinguish between different files with the same paths.
|
// FIXME: fileIdentity is used to distinguish between different files with the same paths.
|
||||||
// For now we use the file's path to read its content, which makes fileIdentity useless.
|
// For now we use the file's path to read its content, which makes fileIdentity useless.
|
||||||
|
|||||||
+6
@@ -956,6 +956,12 @@ public class FirJsBoxTestGenerated extends AbstractFirJsBoxTest {
|
|||||||
runTest("js/js.translator/testData/box/coroutines/suspendFunctionalInterface.kt");
|
runTest("js/js.translator/testData/box/coroutines/suspendFunctionalInterface.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("suspendInvokeWithSuspendKlassRef.kt")
|
||||||
|
public void testSuspendInvokeWithSuspendKlassRef() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/coroutines/suspendInvokeWithSuspendKlassRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("suspendMethodWithSuperCall.kt")
|
@TestMetadata("suspendMethodWithSuperCall.kt")
|
||||||
public void testSuspendMethodWithSuperCall() throws Exception {
|
public void testSuspendMethodWithSuperCall() throws Exception {
|
||||||
|
|||||||
+6
@@ -956,6 +956,12 @@ public class FirJsES6BoxTestGenerated extends AbstractFirJsES6BoxTest {
|
|||||||
runTest("js/js.translator/testData/box/coroutines/suspendFunctionalInterface.kt");
|
runTest("js/js.translator/testData/box/coroutines/suspendFunctionalInterface.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("suspendInvokeWithSuspendKlassRef.kt")
|
||||||
|
public void testSuspendInvokeWithSuspendKlassRef() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/coroutines/suspendInvokeWithSuspendKlassRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("suspendMethodWithSuperCall.kt")
|
@TestMetadata("suspendMethodWithSuperCall.kt")
|
||||||
public void testSuspendMethodWithSuperCall() throws Exception {
|
public void testSuspendMethodWithSuperCall() throws Exception {
|
||||||
|
|||||||
+6
@@ -956,6 +956,12 @@ public class IrBoxJsES6TestGenerated extends AbstractIrBoxJsES6Test {
|
|||||||
runTest("js/js.translator/testData/box/coroutines/suspendFunctionalInterface.kt");
|
runTest("js/js.translator/testData/box/coroutines/suspendFunctionalInterface.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("suspendInvokeWithSuspendKlassRef.kt")
|
||||||
|
public void testSuspendInvokeWithSuspendKlassRef() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/coroutines/suspendInvokeWithSuspendKlassRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("suspendMethodWithSuperCall.kt")
|
@TestMetadata("suspendMethodWithSuperCall.kt")
|
||||||
public void testSuspendMethodWithSuperCall() throws Exception {
|
public void testSuspendMethodWithSuperCall() throws Exception {
|
||||||
|
|||||||
+6
@@ -956,6 +956,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
|||||||
runTest("js/js.translator/testData/box/coroutines/suspendFunctionalInterface.kt");
|
runTest("js/js.translator/testData/box/coroutines/suspendFunctionalInterface.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("suspendInvokeWithSuspendKlassRef.kt")
|
||||||
|
public void testSuspendInvokeWithSuspendKlassRef() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/coroutines/suspendInvokeWithSuspendKlassRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("suspendMethodWithSuperCall.kt")
|
@TestMetadata("suspendMethodWithSuperCall.kt")
|
||||||
public void testSuspendMethodWithSuperCall() throws Exception {
|
public void testSuspendMethodWithSuperCall() throws Exception {
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
// TARGET_BACKEND: JS_IR
|
||||||
|
// ONLY_IR_DCE
|
||||||
|
|
||||||
|
import kotlin.coroutines.*
|
||||||
|
import kotlin.coroutines.intrinsics.*
|
||||||
|
|
||||||
|
private var stopped = false
|
||||||
|
|
||||||
|
fun build(c: suspend () -> Unit) {
|
||||||
|
c.startCoroutine(object : Continuation<Unit> {
|
||||||
|
override fun resumeWith(x: Result<Unit>) {
|
||||||
|
stopped = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override val context = EmptyCoroutineContext
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T : Any> klassToString() = T::class.toString()
|
||||||
|
|
||||||
|
typealias SusFun0 = suspend () -> Unit
|
||||||
|
typealias SusFun1 = suspend (String) -> Unit
|
||||||
|
typealias SusFun2 = suspend (String, String) -> Unit
|
||||||
|
|
||||||
|
val SusFun0Prop = klassToString<SusFun0>()
|
||||||
|
val SusFun1Prop = klassToString<SusFun1>()
|
||||||
|
val SusFun2Prop = klassToString<SusFun2>()
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
suspend fun susFun0(
|
||||||
|
parse: suspend () -> String
|
||||||
|
): String {
|
||||||
|
return "0" + parse()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun susFun1(
|
||||||
|
parse: suspend (String) -> String
|
||||||
|
): String {
|
||||||
|
return "1" + parse("a")
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun susFun2(
|
||||||
|
parse: suspend (String, String) -> String
|
||||||
|
): String {
|
||||||
|
return "2" + parse("a", "b")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
SusFun0Prop
|
||||||
|
SusFun1Prop
|
||||||
|
SusFun2Prop
|
||||||
|
|
||||||
|
var log = ""
|
||||||
|
val foo = Foo()
|
||||||
|
|
||||||
|
build {
|
||||||
|
val foo0 = foo.susFun0 {
|
||||||
|
"0"
|
||||||
|
}
|
||||||
|
|
||||||
|
log += foo0
|
||||||
|
|
||||||
|
val foo1 = foo.susFun1 { one ->
|
||||||
|
one + "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log += foo1
|
||||||
|
|
||||||
|
val foo2 = foo.susFun2 { one, two ->
|
||||||
|
one + two + "2"
|
||||||
|
}
|
||||||
|
|
||||||
|
log += foo2
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!stopped) {
|
||||||
|
}
|
||||||
|
|
||||||
|
if (log != "001a12ab2") return "fail: $log"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user