diff --git a/compiler/testData/codegen/box/coroutines/beginWithException.kt b/compiler/testData/codegen/box/coroutines/beginWithException.kt index 940d33330dc..120b0effc37 100644 --- a/compiler/testData/codegen/box/coroutines/beginWithException.kt +++ b/compiler/testData/codegen/box/coroutines/beginWithException.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - // WITH_RUNTIME class Controller { var exception: Throwable? = null diff --git a/compiler/testData/codegen/box/coroutines/beginWithExceptionNoHandleException.kt b/compiler/testData/codegen/box/coroutines/beginWithExceptionNoHandleException.kt index e1ba6521797..c7687613777 100644 --- a/compiler/testData/codegen/box/coroutines/beginWithExceptionNoHandleException.kt +++ b/compiler/testData/codegen/box/coroutines/beginWithExceptionNoHandleException.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - // WITH_RUNTIME class Controller { suspend fun suspendHere(x: Continuation) {} diff --git a/compiler/testData/codegen/box/coroutines/coercionToUnit.kt b/compiler/testData/codegen/box/coroutines/coercionToUnit.kt index 679d54b5207..b80fb589b2d 100644 --- a/compiler/testData/codegen/box/coroutines/coercionToUnit.kt +++ b/compiler/testData/codegen/box/coroutines/coercionToUnit.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { var result = "fail" operator fun handleResult(u: Unit, c: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/controllerAccessFromInnerLambda.kt b/compiler/testData/codegen/box/coroutines/controllerAccessFromInnerLambda.kt index d637af84cfb..b40605fa74f 100644 --- a/compiler/testData/codegen/box/coroutines/controllerAccessFromInnerLambda.kt +++ b/compiler/testData/codegen/box/coroutines/controllerAccessFromInnerLambda.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { var result = false suspend fun suspendHere(x: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/defaultParametersInSuspend.kt b/compiler/testData/codegen/box/coroutines/defaultParametersInSuspend.kt index 2e045cb9fa4..8a6b3532842 100644 --- a/compiler/testData/codegen/box/coroutines/defaultParametersInSuspend.kt +++ b/compiler/testData/codegen/box/coroutines/defaultParametersInSuspend.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { suspend fun suspendHere(a: String = "abc", i: Int = 2, x: Continuation) { x.resume(a + "#" + (i + 1)) diff --git a/compiler/testData/codegen/box/coroutines/emptyClosure.kt b/compiler/testData/codegen/box/coroutines/emptyClosure.kt index acd46e7a7a3..409b9163d2a 100644 --- a/compiler/testData/codegen/box/coroutines/emptyClosure.kt +++ b/compiler/testData/codegen/box/coroutines/emptyClosure.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - var result = 0 class Controller { diff --git a/compiler/testData/codegen/box/coroutines/falseUnitCoercion.kt b/compiler/testData/codegen/box/coroutines/falseUnitCoercion.kt index 73c9de50bc6..c827d4dea5b 100644 --- a/compiler/testData/codegen/box/coroutines/falseUnitCoercion.kt +++ b/compiler/testData/codegen/box/coroutines/falseUnitCoercion.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { suspend fun suspendHere(v: T, x: Continuation) { x.resume(v) diff --git a/compiler/testData/codegen/box/coroutines/generate.kt b/compiler/testData/codegen/box/coroutines/generate.kt index 9b026300d9c..51158972a04 100644 --- a/compiler/testData/codegen/box/coroutines/generate.kt +++ b/compiler/testData/codegen/box/coroutines/generate.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - // WITH_RUNTIME // FULL_JDK diff --git a/compiler/testData/codegen/box/coroutines/handleException.kt b/compiler/testData/codegen/box/coroutines/handleException.kt index a64653f259f..c1e5140c003 100644 --- a/compiler/testData/codegen/box/coroutines/handleException.kt +++ b/compiler/testData/codegen/box/coroutines/handleException.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - // WITH_RUNTIME class Controller { var exception: Throwable? = null diff --git a/compiler/testData/codegen/box/coroutines/handleResultCallEmptyBody.kt b/compiler/testData/codegen/box/coroutines/handleResultCallEmptyBody.kt index 0bbc56b1c81..a8f72899d7d 100644 --- a/compiler/testData/codegen/box/coroutines/handleResultCallEmptyBody.kt +++ b/compiler/testData/codegen/box/coroutines/handleResultCallEmptyBody.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { var ok = false diff --git a/compiler/testData/codegen/box/coroutines/handleResultNonUnitExpression.kt b/compiler/testData/codegen/box/coroutines/handleResultNonUnitExpression.kt index 41a7512ee2a..9da50876350 100644 --- a/compiler/testData/codegen/box/coroutines/handleResultNonUnitExpression.kt +++ b/compiler/testData/codegen/box/coroutines/handleResultNonUnitExpression.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { var isCompleted = false suspend fun suspendHere(x: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/illegalState.kt b/compiler/testData/codegen/box/coroutines/illegalState.kt index 8e7a9cb6174..74e22cf5c80 100644 --- a/compiler/testData/codegen/box/coroutines/illegalState.kt +++ b/compiler/testData/codegen/box/coroutines/illegalState.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - // WITH_RUNTIME class Controller { suspend fun suspendHere(x: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/inlineSuspendFunction.kt b/compiler/testData/codegen/box/coroutines/inlineSuspendFunction.kt index 85588333385..e8d07ad7d16 100644 --- a/compiler/testData/codegen/box/coroutines/inlineSuspendFunction.kt +++ b/compiler/testData/codegen/box/coroutines/inlineSuspendFunction.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - // WITH_RUNTIME class Controller { fun withValue(v: String, x: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/inlinedTryCatchFinally.kt b/compiler/testData/codegen/box/coroutines/inlinedTryCatchFinally.kt index 533ac570c93..34234c06041 100644 --- a/compiler/testData/codegen/box/coroutines/inlinedTryCatchFinally.kt +++ b/compiler/testData/codegen/box/coroutines/inlinedTryCatchFinally.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - // WITH_RUNTIME var globalResult = "" var wasCalled = false diff --git a/compiler/testData/codegen/box/coroutines/innerSuspensionCalls.kt b/compiler/testData/codegen/box/coroutines/innerSuspensionCalls.kt index 8d7237b6b87..acacbf92695 100644 --- a/compiler/testData/codegen/box/coroutines/innerSuspensionCalls.kt +++ b/compiler/testData/codegen/box/coroutines/innerSuspensionCalls.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { var i = 0 suspend fun suspendHere(x: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/complicatedMerge.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/complicatedMerge.kt index c863d84f026..8e8c9f5d9f1 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/complicatedMerge.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/complicatedMerge.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { suspend fun suspendHere(x: Continuation) { x.resume(Unit) diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/i2bResult.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/i2bResult.kt index b8363eb6dae..f4c86ef86fd 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/i2bResult.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/i2bResult.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { suspend fun suspendHere(x: Continuation) { x.resume(Unit) diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromBooleanArray.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromBooleanArray.kt index 72596c4fa00..f791030fd76 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromBooleanArray.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromBooleanArray.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { suspend fun suspendHere(x: Continuation) { x.resume(Unit) diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromByteArray.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromByteArray.kt index 567d1b998d8..888b7c76543 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromByteArray.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromByteArray.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { suspend fun suspendHere(x: Continuation) { x.resume(Unit) diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/noVariableInTable.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/noVariableInTable.kt index 750f690a5e7..2d4af13cabf 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/noVariableInTable.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/noVariableInTable.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { suspend fun suspendHere(x: Continuation) { x.resume(Unit) diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/sameIconst1ManyVars.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/sameIconst1ManyVars.kt index cad612398af..4c10a589253 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/sameIconst1ManyVars.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/sameIconst1ManyVars.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { suspend fun suspendHere(x: Continuation) { x.resume(Unit) diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInArrayStore.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInArrayStore.kt index aefb014b416..866998b14c7 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInArrayStore.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInArrayStore.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - // WITH_RUNTIME class Controller { suspend fun suspendHere(x: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInMethodCall.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInMethodCall.kt index 40f244a1eff..a9939ff9721 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInMethodCall.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInMethodCall.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { suspend fun suspendHere(x: Continuation) { x.resume(Unit) diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInPutfield.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInPutfield.kt index ad198b0b964..f3996b77b4e 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInPutfield.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInPutfield.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - // WITH_RUNTIME class Controller { suspend fun suspendHere(x: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInVarStore.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInVarStore.kt index d6a0db8a56e..2ddb6f1b790 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInVarStore.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInVarStore.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { suspend fun suspendHere(x: Continuation) { x.resume(Unit) diff --git a/compiler/testData/codegen/box/coroutines/iterateOverArray.kt b/compiler/testData/codegen/box/coroutines/iterateOverArray.kt index 021122d8b42..7fbfb772254 100644 --- a/compiler/testData/codegen/box/coroutines/iterateOverArray.kt +++ b/compiler/testData/codegen/box/coroutines/iterateOverArray.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { suspend fun suspendHere(x: Continuation) { x.resume("OK") diff --git a/compiler/testData/codegen/box/coroutines/kt12958.kt b/compiler/testData/codegen/box/coroutines/kt12958.kt index ade5f730149..978b80c54a5 100644 --- a/compiler/testData/codegen/box/coroutines/kt12958.kt +++ b/compiler/testData/codegen/box/coroutines/kt12958.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { var result = "fail" suspend fun suspendHere(v: V, x: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/lambdaParameters.kt b/compiler/testData/codegen/box/coroutines/lambdaParameters.kt index 1cb199b6fde..31b98ee0129 100644 --- a/compiler/testData/codegen/box/coroutines/lambdaParameters.kt +++ b/compiler/testData/codegen/box/coroutines/lambdaParameters.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { suspend fun suspendHere(v: String, x: Continuation) { x.resume(v) diff --git a/compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt b/compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt index b80f66a9874..d5686ab6128 100644 --- a/compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt +++ b/compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { var result = "" var ok = false diff --git a/compiler/testData/codegen/box/coroutines/lastStatementInc.kt b/compiler/testData/codegen/box/coroutines/lastStatementInc.kt index 8cfd780a271..be98bbc480d 100644 --- a/compiler/testData/codegen/box/coroutines/lastStatementInc.kt +++ b/compiler/testData/codegen/box/coroutines/lastStatementInc.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { var wasHandleResultCalled = false suspend fun suspendHere(x: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/lastStementAssignment.kt b/compiler/testData/codegen/box/coroutines/lastStementAssignment.kt index 6e975360640..75e0f914a12 100644 --- a/compiler/testData/codegen/box/coroutines/lastStementAssignment.kt +++ b/compiler/testData/codegen/box/coroutines/lastStementAssignment.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { var wasHandleResultCalled = false suspend fun suspendHere(x: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/lastUnitExpression.kt b/compiler/testData/codegen/box/coroutines/lastUnitExpression.kt index abecf6b3eb9..fea95ccff0d 100644 --- a/compiler/testData/codegen/box/coroutines/lastUnitExpression.kt +++ b/compiler/testData/codegen/box/coroutines/lastUnitExpression.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { var ok = false var v = "fail" diff --git a/compiler/testData/codegen/box/coroutines/manualContinuationImpl.kt b/compiler/testData/codegen/box/coroutines/manualContinuationImpl.kt index 84a43c0e55b..4709b25fd0e 100644 --- a/compiler/testData/codegen/box/coroutines/manualContinuationImpl.kt +++ b/compiler/testData/codegen/box/coroutines/manualContinuationImpl.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { suspend fun suspendHere(x: Continuation) { x.resume("OK") diff --git a/compiler/testData/codegen/box/coroutines/multipleInvokeCalls.kt b/compiler/testData/codegen/box/coroutines/multipleInvokeCalls.kt index 27c961b93c1..f9a28899110 100644 --- a/compiler/testData/codegen/box/coroutines/multipleInvokeCalls.kt +++ b/compiler/testData/codegen/box/coroutines/multipleInvokeCalls.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { var lastSuspension: Continuation? = null var result = "fail" diff --git a/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda1.kt b/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda1.kt index bb224185678..75a2a71e1d1 100644 --- a/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda1.kt +++ b/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda1.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { var lastSuspension: Continuation? = null var result = "fail" diff --git a/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda2.kt b/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda2.kt index 444a19e581d..d2e93661f23 100644 --- a/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda2.kt +++ b/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda2.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { var lastSuspension: Continuation? = null var result = "fail" diff --git a/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda3.kt b/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda3.kt index 1beb788b73b..a54bf7ae7af 100644 --- a/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda3.kt +++ b/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda3.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { var lastSuspension: Continuation? = null var result = "fail" diff --git a/compiler/testData/codegen/box/coroutines/nestedTryCatch.kt b/compiler/testData/codegen/box/coroutines/nestedTryCatch.kt index f5af948726f..f2c991e8ec9 100644 --- a/compiler/testData/codegen/box/coroutines/nestedTryCatch.kt +++ b/compiler/testData/codegen/box/coroutines/nestedTryCatch.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - // WITH_RUNTIME var globalResult = "" var wasCalled = false diff --git a/compiler/testData/codegen/box/coroutines/noSuspensionPoints.kt b/compiler/testData/codegen/box/coroutines/noSuspensionPoints.kt index cef97c96bd4..03da19b5897 100644 --- a/compiler/testData/codegen/box/coroutines/noSuspensionPoints.kt +++ b/compiler/testData/codegen/box/coroutines/noSuspensionPoints.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { var res = 0 operator fun handleResult(x: Int, y: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambda.kt b/compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambda.kt index 5675c48524b..fa43e81de5d 100644 --- a/compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambda.kt +++ b/compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambda.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { var cResult = 0 suspend fun suspendHere(v: Int, x: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambdaDeep.kt b/compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambdaDeep.kt index 77f06a52f12..8075f9b3a96 100644 --- a/compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambdaDeep.kt +++ b/compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambdaDeep.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - // WITH_RUNTIME class Controller { diff --git a/compiler/testData/codegen/box/coroutines/returnByLabel.kt b/compiler/testData/codegen/box/coroutines/returnByLabel.kt index 3fe2ea129dc..0ac5d8cfbbc 100644 --- a/compiler/testData/codegen/box/coroutines/returnByLabel.kt +++ b/compiler/testData/codegen/box/coroutines/returnByLabel.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { var res = 0 suspend fun suspendHere(x: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/simple.kt b/compiler/testData/codegen/box/coroutines/simple.kt index 690ec36add9..05dc60e0c70 100644 --- a/compiler/testData/codegen/box/coroutines/simple.kt +++ b/compiler/testData/codegen/box/coroutines/simple.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { suspend fun suspendHere(x: Continuation) { x.resume("OK") diff --git a/compiler/testData/codegen/box/coroutines/simpleException.kt b/compiler/testData/codegen/box/coroutines/simpleException.kt index 95b556f3efd..d84b75ac988 100644 --- a/compiler/testData/codegen/box/coroutines/simpleException.kt +++ b/compiler/testData/codegen/box/coroutines/simpleException.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { suspend fun suspendHere(x: Continuation) { x.resumeWithException(RuntimeException("OK")) diff --git a/compiler/testData/codegen/box/coroutines/simpleWithHandleResult.kt b/compiler/testData/codegen/box/coroutines/simpleWithHandleResult.kt index f1d632d4a99..647b98aaaf3 100644 --- a/compiler/testData/codegen/box/coroutines/simpleWithHandleResult.kt +++ b/compiler/testData/codegen/box/coroutines/simpleWithHandleResult.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { var res = 0 suspend fun suspendHere(x: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/statementLikeLastExpression.kt b/compiler/testData/codegen/box/coroutines/statementLikeLastExpression.kt index acd070bbb44..6b3e8fe3be9 100644 --- a/compiler/testData/codegen/box/coroutines/statementLikeLastExpression.kt +++ b/compiler/testData/codegen/box/coroutines/statementLikeLastExpression.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - var globalResult = "" class Controller { suspend fun suspendWithValue(v: String, x: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/suspendDelegation.kt b/compiler/testData/codegen/box/coroutines/suspendDelegation.kt index b33da03387f..361b65d1d3c 100644 --- a/compiler/testData/codegen/box/coroutines/suspendDelegation.kt +++ b/compiler/testData/codegen/box/coroutines/suspendDelegation.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { suspend fun suspendHere(x: Continuation) { suspendThere(x) diff --git a/compiler/testData/codegen/box/coroutines/suspendExtension.kt b/compiler/testData/codegen/box/coroutines/suspendExtension.kt index 435286da863..e46bef9323a 100644 --- a/compiler/testData/codegen/box/coroutines/suspendExtension.kt +++ b/compiler/testData/codegen/box/coroutines/suspendExtension.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - @AllowSuspendExtensions class Controller { suspend fun String.suspendHere(x: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/suspendFromInlineLambda.kt b/compiler/testData/codegen/box/coroutines/suspendFromInlineLambda.kt index cb31ab8c6e6..05af6e01711 100644 --- a/compiler/testData/codegen/box/coroutines/suspendFromInlineLambda.kt +++ b/compiler/testData/codegen/box/coroutines/suspendFromInlineLambda.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { suspend fun suspendHere(v: Int, x: Continuation) { x.resume(v * 2) diff --git a/compiler/testData/codegen/box/coroutines/suspendInCycle.kt b/compiler/testData/codegen/box/coroutines/suspendInCycle.kt index 58a5a4a9452..b3d3b99b6c9 100644 --- a/compiler/testData/codegen/box/coroutines/suspendInCycle.kt +++ b/compiler/testData/codegen/box/coroutines/suspendInCycle.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { var i = 0 suspend fun suspendHere(x: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstruction.kt b/compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstruction.kt index a821fa9d163..3d45dab49f7 100644 --- a/compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstruction.kt +++ b/compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstruction.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { suspend fun suspendHere(x: Continuation) { x.resume("K") diff --git a/compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt b/compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt index c644d6b1ae5..1bd9e4958fa 100644 --- a/compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt +++ b/compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - // WITH_RUNTIME var globalResult = "" var wasCalled = false diff --git a/compiler/testData/codegen/box/coroutines/tryCatchWithHandleResult.kt b/compiler/testData/codegen/box/coroutines/tryCatchWithHandleResult.kt index b342a099928..55c898531b3 100644 --- a/compiler/testData/codegen/box/coroutines/tryCatchWithHandleResult.kt +++ b/compiler/testData/codegen/box/coroutines/tryCatchWithHandleResult.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - // WITH_RUNTIME var globalResult = "" var wasCalled = false diff --git a/compiler/testData/codegen/box/coroutines/tryFinallyInsideInlineLambda.kt b/compiler/testData/codegen/box/coroutines/tryFinallyInsideInlineLambda.kt index 96b2da468a1..4bbd39697cf 100644 --- a/compiler/testData/codegen/box/coroutines/tryFinallyInsideInlineLambda.kt +++ b/compiler/testData/codegen/box/coroutines/tryFinallyInsideInlineLambda.kt @@ -1,7 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - - class Controller { suspend fun suspendHere(v: String, x: Continuation) { x.resume(v) diff --git a/compiler/testData/codegen/box/coroutines/tryFinallyWithHandleResult.kt b/compiler/testData/codegen/box/coroutines/tryFinallyWithHandleResult.kt index 55f08c8044c..e134bf24687 100644 --- a/compiler/testData/codegen/box/coroutines/tryFinallyWithHandleResult.kt +++ b/compiler/testData/codegen/box/coroutines/tryFinallyWithHandleResult.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - // WITH_RUNTIME var globalResult = "" var wasCalled = false diff --git a/compiler/testData/codegen/box/coroutines/varValueConflictsWithTable.kt b/compiler/testData/codegen/box/coroutines/varValueConflictsWithTable.kt index c2c6692315f..798641da29a 100644 --- a/compiler/testData/codegen/box/coroutines/varValueConflictsWithTable.kt +++ b/compiler/testData/codegen/box/coroutines/varValueConflictsWithTable.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { suspend fun suspendHere(x: Continuation) { x.resume("OK") diff --git a/compiler/testData/codegen/box/coroutines/varValueConflictsWithTableSameSort.kt b/compiler/testData/codegen/box/coroutines/varValueConflictsWithTableSameSort.kt index 17ca3b8c9ba..29a3eb3136d 100644 --- a/compiler/testData/codegen/box/coroutines/varValueConflictsWithTableSameSort.kt +++ b/compiler/testData/codegen/box/coroutines/varValueConflictsWithTableSameSort.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class Controller { suspend fun suspendHere(x: Continuation) { x.resume("OK") diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/metadata/MetadataProperty.kt b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/metadata/MetadataProperty.kt index 51bee2888e4..8afffeb78e1 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/metadata/MetadataProperty.kt +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/metadata/MetadataProperty.kt @@ -18,7 +18,7 @@ package com.google.dart.compiler.backend.js.ast.metadata import kotlin.reflect.KProperty -internal class MetadataProperty(val default: R) { +class MetadataProperty(val default: R) { operator fun getValue(thisRef: T, desc: KProperty<*>): R { if (!thisRef.hasData(desc.name)) return default return thisRef.getData(desc.name) diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/metadata/metadataProperties.kt b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/metadata/metadataProperties.kt index cadb11e7f58..f4ea46d4396 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/metadata/metadataProperties.kt +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/metadata/metadataProperties.kt @@ -20,6 +20,7 @@ package com.google.dart.compiler.backend.js.ast.metadata import com.google.dart.compiler.backend.js.ast.* import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.resolve.inline.InlineStrategy @@ -57,6 +58,14 @@ var HasMetadata.synthetic: Boolean by MetadataProperty(default = false) var HasMetadata.sideEffects: SideEffectKind by MetadataProperty(default = SideEffectKind.AFFECTS_STATE) +var JsFunction.coroutineType: ClassDescriptor? by MetadataProperty(default = null) + +var JsFunction.controllerType: ClassDescriptor? by MetadataProperty(default = null) + +var JsInvocation.isSuspend: Boolean by MetadataProperty(default = false) + +var JsInvocation.isHandleResult: Boolean by MetadataProperty(default = false) + enum class TypeCheck { TYPEOF, INSTANCEOF, diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/naming/NameSuggestion.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/naming/NameSuggestion.kt index 6ed8728c315..34f888c0f93 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/naming/NameSuggestion.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/naming/NameSuggestion.kt @@ -68,6 +68,12 @@ class NameSuggestion { return suggest(descriptor.containingDeclaration!!) } + if (descriptor is FunctionDescriptor && descriptor.isSuspend) { + descriptor.initialSignatureDescriptor?.let { + return suggest(it) + } + } + // Dynamic declarations always require stable names as defined in Kotlin source code if (descriptor.isDynamic()) { return SuggestedName(listOf(descriptor.name.asString()), true, descriptor, descriptor.containingDeclaration!!) diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/coroutine/CoroutineBlock.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/coroutine/CoroutineBlock.kt new file mode 100644 index 00000000000..d13fa4a43bb --- /dev/null +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/coroutine/CoroutineBlock.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.js.coroutine + +import com.google.dart.compiler.backend.js.ast.JsBlock +import com.google.dart.compiler.backend.js.ast.JsStatement + +class CoroutineBlock { + val statements = mutableListOf() + val jsBlock = JsBlock(statements) +} \ No newline at end of file diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/coroutine/CoroutineBodyTransformer.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/coroutine/CoroutineBodyTransformer.kt new file mode 100644 index 00000000000..74b6d9aca4a --- /dev/null +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/coroutine/CoroutineBodyTransformer.kt @@ -0,0 +1,464 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.js.coroutine + +import com.google.dart.compiler.backend.js.ast.* +import com.google.dart.compiler.backend.js.ast.metadata.MetadataProperty +import com.google.dart.compiler.backend.js.ast.metadata.isSuspend +import org.jetbrains.kotlin.js.translate.utils.JsAstUtils +import org.jetbrains.kotlin.utils.DFS +import org.jetbrains.kotlin.utils.singletonOrEmptyList + +class CoroutineBodyTransformer(val program: JsProgram, val scope: JsScope, val throwFunctionName: JsName?) : RecursiveJsVisitor() { + val entryBlock = CoroutineBlock() + val globalCatchBlock = CoroutineBlock() + private var currentBlock = entryBlock + private val currentStatements: MutableList + get() = currentBlock.statements + val resultFieldName by lazy { scope.declareFreshName("\$result") } + val stateFieldName by lazy { scope.declareFreshName("\$state") } + val controllerFieldName by lazy { scope.declareFreshName("\$controller") } + val exceptionStateName by lazy { scope.declareFreshName("\$exceptionState") } + private val breakTargets = mutableMapOf() + private val continueTargets = mutableMapOf() + private var defaultBreakTarget: JsStatement = JsEmpty + private var defaultContinueTarget: JsStatement = JsEmpty + private val referencedBlocks = mutableSetOf() + private val breakBlocks = mutableMapOf() + private val continueBlocks = mutableMapOf() + private lateinit var nodesToSplit: Set + private var currentCatchBlock = globalCatchBlock + + fun preProcess(node: JsNode) { + val nodes = mutableSetOf() + + node.accept(object : RecursiveJsVisitor() { + var childrenInSet = false + + override fun visitInvocation(invocation: JsInvocation) { + super.visitInvocation(invocation) + if (invocation.isSuspend) { + nodes += invocation + childrenInSet = true + } + } + + override fun visitElement(node: JsNode) { + val oldChildrenInSet = childrenInSet + childrenInSet = false + node.acceptChildren(this) + if (childrenInSet) { + nodes += node + } + else { + childrenInSet = oldChildrenInSet + } + } + }) + + nodesToSplit = nodes + } + + fun postProcess(): List { + if (entryBlock == currentBlock) return listOf(entryBlock) + + currentBlock.statements += JsReturn() + val orderedBlocks = DFS.topologicalOrder(listOf(entryBlock)) { it.collectTargetBlocks() } + val blockIndexes = orderedBlocks.withIndex().associate { (index, block) -> Pair(block, index) } + + val blockReplacementVisitor = object : JsVisitorWithContextImpl() { + override fun endVisit(x: JsDebugger, ctx: JsContext) { + val target = x.targetBlock + if (target != null) { + val lhs = JsNameRef(stateFieldName, JsLiteral.THIS) + val rhs = program.getNumberLiteral(blockIndexes[target]!!) + ctx.replaceMe(JsAstUtils.assignment(lhs, rhs).makeStmt()) + } + + val exceptionTarget = x.targetExceptionBlock + if (exceptionTarget != null) { + val lhs = JsNameRef(exceptionStateName, JsLiteral.THIS) + val rhs = program.getNumberLiteral(blockIndexes[exceptionTarget]!!) + ctx.replaceMe(JsAstUtils.assignment(lhs, rhs).makeStmt()) + } + } + } + for (block in orderedBlocks) { + blockReplacementVisitor.accept(block.jsBlock) + } + + return orderedBlocks + } + + override fun visitBlock(x: JsBlock) = splitIfNecessary(x) { + for (statement in x.statements) { + statement.accept(this) + } + } + + override fun visitIf(x: JsIf) = splitIfNecessary(x) { + x.ifExpression = handleExpression(x.ifExpression) + + val ifBlock = currentBlock + + val thenEntryBlock = CoroutineBlock() + currentBlock = thenEntryBlock + x.thenStatement?.accept(this) + val thenExitBlock = currentBlock + + val elseEntryBlock = CoroutineBlock() + currentBlock = elseEntryBlock + x.elseStatement?.accept(this) + val elseExitBlock = currentBlock + + x.thenStatement = JsBlock(thenEntryBlock.statements) + x.elseStatement = JsBlock(elseEntryBlock.statements) + ifBlock.statements += x + + val jointBlock = CoroutineBlock() + thenExitBlock.statements += stateAndJump(jointBlock) + elseExitBlock.statements += stateAndJump(jointBlock) + currentBlock = jointBlock + } + + override fun visitLabel(x: JsLabel) { + val inner = x.statement + when (inner) { + is JsDoWhile -> handleDoWhile(inner, x.name) + + is JsWhile -> handleWhile(inner, x.name) + + is JsFor -> handleFor(inner, x.name) + + else -> splitIfNecessary(x) { + val successor = CoroutineBlock() + accept(inner) + if (successor in referencedBlocks) { + currentBlock.statements += stateAndJump(successor) + currentBlock = successor + } + } + } + } + + override fun visitWhile(x: JsWhile) = handleWhile(x, null) + + private fun handleWhile(x: JsWhile, label: JsName?) = splitIfNecessary(x) { + val predecessor = currentBlock + val successor = CoroutineBlock() + + val bodyEntryBlock = CoroutineBlock() + currentBlock = bodyEntryBlock + withBreakAndContinue(label, x, successor, bodyEntryBlock) { + x.body.accept(this) + } + + if (x.condition != JsLiteral.TRUE) { + val jsIf = JsIf(JsAstUtils.notOptimized(x.condition), JsBlock(stateAndJump(successor))).apply { source = x.source } + bodyEntryBlock.statements.add(0, jsIf) + } + currentBlock.statements += stateAndJump(bodyEntryBlock) + predecessor.statements += stateAndJump(bodyEntryBlock) + currentBlock = successor + } + + override fun visitDoWhile(x: JsDoWhile) = handleDoWhile(x, null) + + private fun handleDoWhile(x: JsDoWhile, label: JsName?) = splitIfNecessary(x) { + val predecessor = currentBlock + val successor = CoroutineBlock() + + val bodyEntryBlock = CoroutineBlock() + currentBlock = bodyEntryBlock + withBreakAndContinue(label, x, successor, bodyEntryBlock) { + x.body.accept(this) + } + + if (x.condition != JsLiteral.TRUE) { + val jsIf = JsIf(JsAstUtils.notOptimized(x.condition), JsBlock(stateAndJump(successor))).apply { source = x.source } + currentBlock.statements.add(jsIf) + } + currentBlock.statements += stateAndJump(bodyEntryBlock) + predecessor.statements += stateAndJump(bodyEntryBlock) + currentBlock = successor + } + + override fun visitFor(x: JsFor) = handleFor(x, null) + + private fun handleFor(x: JsFor, label: JsName?) = splitIfNecessary(x) { + x.initExpression?.let { + JsExpressionStatement(it).accept(this) + } + x.initVars?.let { initVars -> + if (initVars.vars.isNotEmpty()) { + initVars.accept(this) + } + } + + val predecessor = currentBlock + val increment = CoroutineBlock() + val successor = CoroutineBlock() + + val bodyEntryBlock = CoroutineBlock() + currentBlock = bodyEntryBlock + withBreakAndContinue(label, x, successor, predecessor) { + x.body.accept(this) + } + val bodyExitBlock = currentBlock + + if (x.condition != null && x.condition != JsLiteral.TRUE) { + val jsIf = JsIf(JsAstUtils.notOptimized(x.condition), JsBlock(stateAndJump(successor))).apply { source = x.source } + bodyEntryBlock.statements.add(0, jsIf) + } + + bodyExitBlock.statements += stateAndJump(increment) + currentBlock = increment + + x.incrementExpression?.let { JsExpressionStatement(it).accept(this) } + currentStatements += stateAndJump(bodyEntryBlock) + + predecessor.statements += stateAndJump(bodyEntryBlock) + currentBlock = successor + } + + override fun visitBreak(x: JsBreak) { + val targetLabel = x.label?.name + val targetStatement = if (targetLabel == null) { + defaultBreakTarget + } + else { + breakTargets[targetLabel]!! + } + + if (targetStatement in nodesToSplit) { + val targetBlock = breakBlocks[targetStatement]!! + referencedBlocks += targetBlock + currentStatements += stateAndJump(targetBlock) + } + else { + currentStatements += x + } + } + + override fun visitContinue(x: JsContinue) { + val targetLabel = x.label?.name + val targetStatement = if (targetLabel == null) { + defaultContinueTarget + } + else { + continueTargets[targetLabel]!! + } + + if (targetStatement in nodesToSplit) { + val targetBlock = continueBlocks[targetStatement]!! + referencedBlocks += targetBlock + currentStatements += stateAndJump(targetBlock) + } + else { + currentStatements += x + } + } + + override fun visitTry(x: JsTry) = splitIfNecessary(x) { + val catch = x.catches.firstOrNull() + val successor = CoroutineBlock() + + val catchBlock = CoroutineBlock() + val oldCatchBlock = currentCatchBlock + if (catch != null) { + currentCatchBlock = catchBlock + } + + x.tryBlock.statements.forEach { it.accept(this) } + currentBlock.statements += stateAndJump(successor) + + currentCatchBlock = oldCatchBlock + + if (catch != null) { + currentBlock = catchBlock + currentBlock.statements += JsAstUtils.newVar(catch.parameter.name, JsNameRef(resultFieldName, JsLiteral.THIS)) + + catch.body.statements.forEach { it.accept(this) } + currentBlock.statements += stateAndJump(successor) + } + + currentBlock = successor + } + + override fun visitExpressionStatement(x: JsExpressionStatement) { + val expression = x.expression + if (expression is JsInvocation && expression.isSuspend) { + handleSuspend(expression) + } + else { + val splitExpression = handleExpression(x.expression) + currentStatements += if (splitExpression == expression) x else JsExpressionStatement(expression) + } + } + + override fun visitVars(x: JsVars) { + super.visitVars(x) + currentStatements += x + } + + override fun visit(x: JsVars.JsVar) { + val initExpression = x.initExpression + if (initExpression != null) { + x.initExpression = handleExpression(initExpression) + } + } + + override fun visitReturn(x: JsReturn) { + val returnExpression = x.expression + if (returnExpression != null) { + x.expression = handleExpression(returnExpression) + } + currentStatements += x + } + + override fun visitThrow(x: JsThrow) { + if (throwFunctionName != null) { + val exception = handleExpression(x.expression) + val methodRef = JsNameRef(throwFunctionName, JsNameRef(controllerFieldName, JsLiteral.THIS)) + val invocation = JsInvocation(methodRef, exception).apply { + source = x.source + } + currentStatements += JsReturn(invocation) + } + else { + currentStatements += x + } + } + + private fun handleExpression(expression: JsExpression): JsExpression { + if (expression !in nodesToSplit) return expression + + val visitor = object : JsVisitorWithContextImpl() { + override fun endVisit(x: JsInvocation, ctx: JsContext) { + if (x.isSuspend) { + ctx.replaceMe(handleSuspend(x)) + } + super.endVisit(x, ctx) + } + } + + return visitor.accept(expression) + } + + private fun handleSuspend(invocation: JsInvocation): JsExpression { + val methodRef = invocation.qualifier as JsNameRef + methodRef.qualifier = JsNameRef(controllerFieldName, methodRef.qualifier) + + invocation.arguments += JsLiteral.THIS + val nextBlock = CoroutineBlock() + currentStatements += state(nextBlock) + currentStatements += JsReturn(invocation) + currentBlock = nextBlock + + return JsNameRef(resultFieldName, JsLiteral.THIS) + } + + private fun state(target: CoroutineBlock): List { + val nextPlaceholder = JsDebugger() + nextPlaceholder.targetBlock = target + + val exceptionPlaceholder = JsDebugger() + exceptionPlaceholder.targetExceptionBlock = currentCatchBlock + + return listOf(nextPlaceholder, exceptionPlaceholder) + } + + private fun jump() = JsContinue() + + private fun stateAndJump(target: CoroutineBlock): List { + return state(target) + jump() + } + + private inline fun splitIfNecessary(statement: JsStatement, action: () -> Unit) { + if (statement in nodesToSplit) { + action() + } + else { + currentStatements += statement + } + } + + private fun withBreakAndContinue( + label: JsName?, + statement: JsStatement, + breakBlock: CoroutineBlock, + continueBlock: CoroutineBlock? = null, + action: () -> Unit + ) { + breakBlocks[statement] = breakBlock + if (continueBlock != null) { + continueBlocks[statement] = continueBlock + } + + val oldDefaultBreakTarget = defaultBreakTarget + val oldDefaultContinueTarget = defaultContinueTarget + val (oldBreakTarget, oldContinueTarget) = if (label != null) { + Pair(breakTargets[label], continueTargets[label]) + } + else { + Pair(null, null) + } + + defaultBreakTarget = statement + if (label != null) { + breakTargets[label] = statement + if (continueBlock != null) { + continueTargets[label] = statement + } + } + if (continueBlock != null) { + defaultContinueTarget = statement + } + + action() + + defaultBreakTarget = oldDefaultBreakTarget + defaultContinueTarget = oldDefaultContinueTarget + if (label != null) { + if (oldBreakTarget == null) { + breakTargets.keys -= label + } + else { + breakTargets[label] = oldBreakTarget + } + if (oldContinueTarget == null) { + continueTargets.keys -= label + } + else { + continueTargets[label] = oldContinueTarget + } + } + } +} + +private fun CoroutineBlock.collectTargetBlocks(): Set { + val targetBlocks = mutableSetOf() + jsBlock.accept(object : RecursiveJsVisitor() { + override fun visitDebugger(x: JsDebugger) { + targetBlocks += x.targetExceptionBlock.singletonOrEmptyList() + x.targetBlock.singletonOrEmptyList() + } + }) + return targetBlocks +} + +private var JsDebugger.targetBlock: CoroutineBlock? by MetadataProperty(default = null) +private var JsDebugger.targetExceptionBlock: CoroutineBlock? by MetadataProperty(default = null) \ No newline at end of file diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/coroutine/CoroutineFunctionTransformer.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/coroutine/CoroutineFunctionTransformer.kt new file mode 100644 index 00000000000..59964f83fd1 --- /dev/null +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/coroutine/CoroutineFunctionTransformer.kt @@ -0,0 +1,306 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.js.coroutine + +import com.google.dart.compiler.backend.js.ast.* +import com.google.dart.compiler.backend.js.ast.metadata.isHandleResult +import com.google.dart.compiler.backend.js.ast.metadata.isSuspend +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.js.inline.ExpressionDecomposer +import org.jetbrains.kotlin.js.inline.clean.FunctionPostProcessor +import org.jetbrains.kotlin.js.inline.util.collectLocalVariables +import org.jetbrains.kotlin.js.inline.util.getInnerFunction +import org.jetbrains.kotlin.js.naming.NameSuggestion +import org.jetbrains.kotlin.js.translate.context.Namer +import org.jetbrains.kotlin.js.translate.utils.JsAstUtils +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter + +class CoroutineFunctionTransformer( + private val program: JsProgram, + private val function: JsFunction, + private val coroutineType: ClassDescriptor, + private val controllerType: ClassDescriptor +) { + private val innerFunction = function.getInnerFunction() + private val functionWithBody = innerFunction ?: function + private val body = functionWithBody.body + private val localVariables = (function.collectLocalVariables() + functionWithBody.collectLocalVariables()).toMutableSet() + private val nameSuggestion = NameSuggestion() + private val className = function.scope.parent.declareFreshName("Coroutine\$${function.name}") + + fun transform(): List { + val visitor = object : JsVisitorWithContextImpl() { + override fun doTraverse(node: T, ctx: JsContext) { + super.doTraverse(node, ctx) + if (node is JsStatement) { + val statements = ExpressionDecomposer.preserveEvaluationOrder(function.scope, node) { + it is JsInvocation && it.isSuspend + } + ctx.addPrevious(statements) + } + } + } + visitor.accept(body) + + val throwFunction = controllerType.findFunction("handleException") + val throwName = throwFunction?.let { + val throwId = nameSuggestion.suggest(it)!!.names.last() + function.scope.declareName(throwId) + } + + val bodyTransformer = CoroutineBodyTransformer(program, function.scope, throwName) + bodyTransformer.preProcess(body) + body.statements.forEach { it.accept(bodyTransformer) } + val coroutineBlocks = bodyTransformer.postProcess() + + for (coroutineBlock in coroutineBlocks) { + coroutineBlock.jsBlock.replaceLocalVariables(function.scope) + coroutineBlock.jsBlock.replaceHandleResult(bodyTransformer) + } + + val additionalStatements = mutableListOf() + val resumeName = generateDoResume(coroutineBlocks, bodyTransformer, additionalStatements, throwName) + generateContinuationConstructor(bodyTransformer, additionalStatements) + generateContinuationMethods(resumeName, additionalStatements) + + generateCoroutineInstantiation() + + return additionalStatements + } + + private fun generateContinuationConstructor(bodyTransformer: CoroutineBodyTransformer,statements: MutableList) { + val constructor = JsFunction(function.scope.parent, JsBlock(), "Continuation") + constructor.name = className + constructor.parameters += function.parameters.map { JsParameter(it.name) } + if (innerFunction != null) { + constructor.parameters += innerFunction.parameters.map { JsParameter(it.name) } + } + + val controllerName = function.scope.declareFreshName("controller") + constructor.parameters += JsParameter(controllerName) + + val parameterNames = (function.parameters.map { it.name } + innerFunction?.parameters?.map { it.name }.orEmpty()).toSet() + + constructor.body.statements.run { + assign(bodyTransformer.stateFieldName, program.getNumberLiteral(0)) + assign(bodyTransformer.controllerFieldName, controllerName.makeRef()) + for (localVariable in localVariables) { + val value = if (localVariable !in parameterNames) JsLiteral.NULL else localVariable.makeRef() + assign(function.scope.getFieldName(localVariable), value) + } + } + + statements.add(0, constructor.makeStmt()) + } + + private fun generateContinuationMethods(doResumeName: JsName, statements: MutableList) { + generateResumeFunction(doResumeName, statements, "resume", "data", listOf()) + generateResumeFunction(doResumeName, statements, "resumeWithException", "exception", listOf(Namer.getUndefinedExpression())) + } + + private fun generateResumeFunction( + doResumeName: JsName, + statements: MutableList, + name: String, + parameterName: String, + additionalArgs: List + ) { + val resumeDescriptor = coroutineType.findFunction(name)!! + val resumeId = nameSuggestion.suggest(resumeDescriptor)!!.names.last() + val resumeName = function.scope.declareName(resumeId) + + val resumeFunction = JsFunction(function.scope.parent, JsBlock(), resumeDescriptor.toString()) + val resumeParameter = resumeFunction.scope.declareFreshName(parameterName) + resumeFunction.parameters += JsParameter(resumeParameter) + + resumeFunction.body.statements.apply { + val invocation = JsInvocation(JsNameRef(doResumeName, JsLiteral.THIS), additionalArgs + resumeParameter.makeRef()) + this += JsReturn(invocation) + } + + statements.apply { + assignToPrototype(resumeName, resumeFunction) + } + } + + private fun generateDoResume( + coroutineBlocks: List, + bodyTransformer: CoroutineBodyTransformer, + statements: MutableList, + throwName: JsName? + ): JsName { + val resumeFunction = JsFunction(function.scope.parent, JsBlock(), "resume function") + val resumeParameter = resumeFunction.scope.declareFreshName("data") + val resumeException = resumeFunction.scope.declareFreshName("exception") + resumeFunction.parameters += listOf(JsParameter(resumeParameter), JsParameter(resumeException)) + + val coroutineBody = generateCoroutineBody(bodyTransformer, coroutineBlocks, throwName, resumeException) + functionWithBody.body.statements.clear() + + resumeFunction.body.statements.apply { + assign(bodyTransformer.resultFieldName, resumeParameter.makeRef()) + this += coroutineBody + } + + val resumeName = function.scope.parent.declareFreshName("doResume") + statements.apply { + assignToPrototype(resumeName, resumeFunction) + } + + FunctionPostProcessor(resumeFunction).apply() + + return resumeName + } + + private fun generateCoroutineInstantiation() { + val instantiation = JsNew(className.makeRef()) + instantiation.arguments += function.parameters.map { it.name.makeRef() } + if (innerFunction != null) { + instantiation.arguments += innerFunction.parameters.map { it.name.makeRef() } + } + + instantiation.arguments += JsLiteral.THIS + + functionWithBody.body.statements += JsReturn(instantiation) + } + + private fun generateCoroutineBody( + transformer: CoroutineBodyTransformer, + blocks: List, + throwName: JsName?, + exceptionName: JsName + ): List { + val catch = JsCatch(functionWithBody.scope, "e") + if (throwName != null) { + val throwMethodRef = JsNameRef(throwName, JsNameRef(transformer.controllerFieldName, JsLiteral.THIS)) + catch.body = JsBlock(JsReturn(JsInvocation(throwMethodRef, catch.parameter.name.makeRef()))) + + val resultRef = JsNameRef(transformer.resultFieldName, JsLiteral.THIS) + transformer.globalCatchBlock.statements += JsReturn(JsInvocation(throwMethodRef.deepCopy(), resultRef)) + } + + val cases = blocks.withIndex().map { (index, block) -> + JsCase().apply { + caseExpression = program.getNumberLiteral(index) + statements += block.statements + } + } + val stateRef = JsNameRef(transformer.stateFieldName, JsLiteral.THIS) + val switchStatement = JsSwitch(stateRef, cases) + val loop = JsDoWhile(JsLiteral.TRUE, switchStatement) + + val testExceptionPassed = JsAstUtils.notOptimized( + JsAstUtils.typeOfIs(exceptionName.makeRef(), program.getStringLiteral("undefined"))) + val stateToException = JsAstUtils.assignment( + JsNameRef(transformer.stateFieldName, JsLiteral.THIS), + JsNameRef(transformer.exceptionStateName, JsLiteral.THIS)) + val exceptionToResult = JsAstUtils.assignment(JsNameRef(transformer.resultFieldName, JsLiteral.THIS), exceptionName.makeRef()) + val throwExceptionIfNeeded = JsIf(testExceptionPassed, JsBlock(stateToException.makeStmt(), exceptionToResult.makeStmt())) + + val resultBlock = JsBlock(throwExceptionIfNeeded, loop) + return if (throwName != null) listOf(JsTry(resultBlock, catch, null)) else resultBlock.statements + } + + private fun JsBlock.replaceHandleResult(transformer: CoroutineBodyTransformer) { + accept(object : RecursiveJsVisitor() { + override fun visitInvocation(invocation: JsInvocation) { + super.visitInvocation(invocation) + if (invocation.isHandleResult) { + val methodRef = invocation.qualifier as JsNameRef + methodRef.qualifier = JsNameRef(transformer.controllerFieldName, methodRef.qualifier) + } + } + }) + } + + private fun JsBlock.replaceLocalVariables(scope: JsScope) { + accept(object : RecursiveJsVisitor() { + override fun visit(x: JsVars.JsVar) { + super.visit(x) + localVariables += x.name + } + }) + + val visitor = object : JsVisitorWithContextImpl() { + override fun endVisit(x: JsNameRef, ctx: JsContext) { + if (x.qualifier == null && x.name in localVariables) { + val fieldName = scope.getFieldName(x.name!!) + ctx.replaceMe(JsNameRef(fieldName, JsLiteral.THIS)) + } + } + + override fun endVisit(x: JsVars, ctx: JsContext) { + val declaredNames = x.vars.map { it.name } + val totalCount = declaredNames.size + val localVarCount = declaredNames.count() + + when { + totalCount == localVarCount -> { + val assignments = x.vars.mapNotNull { + val fieldName = scope.getFieldName(it.name) + val initExpression = it.initExpression + if (initExpression != null) { + JsAstUtils.assignment(JsNameRef(fieldName, JsLiteral.THIS), it.initExpression) + } + else { + null + } + } + if (assignments.isNotEmpty()) { + ctx.replaceMe(JsExpressionStatement(JsAstUtils.newSequence(assignments))) + } + else { + ctx.removeMe() + } + } + localVarCount > 0 -> { + for (declaration in x.vars) { + if (declaration.name in localVariables) { + val fieldName = scope.getFieldName(declaration.name) + val assignment = JsAstUtils.assignment(JsNameRef(fieldName, JsLiteral.THIS), declaration.initExpression) + ctx.addPrevious(assignment.makeStmt()) + } + else { + ctx.addPrevious(JsVars(declaration)) + } + } + ctx.removeMe() + } + } + super.endVisit(x, ctx) + } + } + visitor.accept(this) + } + + private fun ClassDescriptor.findFunction(name: String): FunctionDescriptor? { + val functions = unsubstitutedMemberScope.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS) + .filter { it.name.asString() == name } + return functions.mapNotNull { it as? FunctionDescriptor }.firstOrNull { it.kind.isReal } + } + + private fun JsScope.getFieldName(variableName: JsName) = declareName("local\$${variableName.ident}") + + private fun MutableList.assign(fieldName: JsName, value: JsExpression) { + this += JsAstUtils.assignment(JsNameRef(fieldName, JsLiteral.THIS), value).makeStmt() + } + + private fun MutableList.assignToPrototype(fieldName: JsName, value: JsExpression) { + this += JsAstUtils.assignment(JsNameRef(fieldName, JsAstUtils.prototypeOf(className.makeRef())), value).makeStmt() + } +} \ No newline at end of file diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/coroutine/CoroutineTransformer.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/coroutine/CoroutineTransformer.kt new file mode 100644 index 00000000000..056f9cfd808 --- /dev/null +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/coroutine/CoroutineTransformer.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.js.coroutine + +import com.google.dart.compiler.backend.js.ast.* +import com.google.dart.compiler.backend.js.ast.metadata.controllerType +import com.google.dart.compiler.backend.js.ast.metadata.coroutineType + +class CoroutineTransformer(private val program: JsProgram) : JsVisitorWithContextImpl() { + private val additionalStatements = mutableListOf() + + override fun endVisit(x: JsExpressionStatement, ctx: JsContext) { + additionalStatements.forEach { ctx.addNext(it) } + additionalStatements.clear() + super.endVisit(x, ctx) + } + + override fun endVisit(x: JsFunction, ctx: JsContext) { + val coroutineType = x.coroutineType + if (coroutineType != null) { + additionalStatements += CoroutineFunctionTransformer(program, x, coroutineType, x.controllerType!!).transform() + } + } +} diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/ExpressionDecomposer.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/ExpressionDecomposer.kt index 50f5987e2d7..7f0cadc06aa 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/ExpressionDecomposer.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/ExpressionDecomposer.kt @@ -455,7 +455,7 @@ internal open class JsExpressionVisitor() : JsVisitorWithContextImpl() { /** * Returns descendants of receiver, matched by [predicate]. */ -private fun JsNode.match(predicate: (JsNode) -> Boolean): Set { +fun JsNode.match(predicate: (JsNode) -> Boolean): Set { val visitor = object : JsExpressionVisitor() { val matched = IdentitySet() @@ -475,7 +475,7 @@ private fun JsNode.match(predicate: (JsNode) -> Boolean): Set { /** * Returns set of nodes, that satisfy transitive closure of `is parent` relation, starting from [nodes]. */ -private fun JsNode.withParentsOfNodes(nodes: Set): Set { +fun JsNode.withParentsOfNodes(nodes: Set): Set { val visitor = object : JsExpressionVisitor() { private val stack = SmartList() val matched = IdentitySet() diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/RedundantLabelRemoval.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/RedundantLabelRemoval.kt index 2f685516a17..4e9fbd4e6b7 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/RedundantLabelRemoval.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/RedundantLabelRemoval.kt @@ -112,7 +112,7 @@ internal class RedundantLabelRemoval(private val root: JsStatement) { hasChanges = true statement.thenStatement = statement.elseStatement statement.elseStatement = null - statement.ifExpression = JsAstUtils.negated(statement.ifExpression) + statement.ifExpression = JsAstUtils.not(statement.ifExpression) statement } else -> statement diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/WhileConditionFolding.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/WhileConditionFolding.kt index d946da41d2d..3605877e85e 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/WhileConditionFolding.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/WhileConditionFolding.kt @@ -141,9 +141,9 @@ class WhileConditionFolding(val body: JsBlock) { val result: JsExpression? = when (nextCondition) { // Just a little optimization. When inner statement is a single `break`, `nextCondition` would be false. // However, `A || false` can be rewritten as simply `A` - JsLiteral.FALSE -> JsAstUtils.negatedOptimized(statement.ifExpression) + JsLiteral.FALSE -> JsAstUtils.notOptimized(statement.ifExpression) null -> null - else -> JsAstUtils.or(JsAstUtils.negatedOptimized(statement.ifExpression), nextCondition) + else -> JsAstUtils.or(JsAstUtils.notOptimized(statement.ifExpression), nextCondition) } result } diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 87413d17bf8..353ee898fbb 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -5609,565 +5609,283 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { @TestMetadata("beginWithException.kt") public void testBeginWithException() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/beginWithException.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("beginWithExceptionNoHandleException.kt") public void testBeginWithExceptionNoHandleException() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/beginWithExceptionNoHandleException.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("coercionToUnit.kt") public void testCoercionToUnit() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/coercionToUnit.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("controllerAccessFromInnerLambda.kt") public void testControllerAccessFromInnerLambda() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/controllerAccessFromInnerLambda.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("defaultParametersInSuspend.kt") public void testDefaultParametersInSuspend() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/defaultParametersInSuspend.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("emptyClosure.kt") public void testEmptyClosure() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/emptyClosure.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("falseUnitCoercion.kt") public void testFalseUnitCoercion() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/falseUnitCoercion.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("generate.kt") public void testGenerate() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/generate.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("handleException.kt") public void testHandleException() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/handleException.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("handleResultCallEmptyBody.kt") public void testHandleResultCallEmptyBody() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/handleResultCallEmptyBody.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("handleResultNonUnitExpression.kt") public void testHandleResultNonUnitExpression() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/handleResultNonUnitExpression.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("illegalState.kt") public void testIllegalState() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/illegalState.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("inlineSuspendFunction.kt") public void testInlineSuspendFunction() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/inlineSuspendFunction.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("inlinedTryCatchFinally.kt") public void testInlinedTryCatchFinally() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/inlinedTryCatchFinally.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("innerSuspensionCalls.kt") public void testInnerSuspensionCalls() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/innerSuspensionCalls.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("iterateOverArray.kt") public void testIterateOverArray() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/iterateOverArray.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("kt12958.kt") public void testKt12958() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/kt12958.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("lambdaParameters.kt") public void testLambdaParameters() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/lambdaParameters.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("lastExpressionIsLoop.kt") public void testLastExpressionIsLoop() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("lastStatementInc.kt") public void testLastStatementInc() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/lastStatementInc.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("lastStementAssignment.kt") public void testLastStementAssignment() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/lastStementAssignment.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("lastUnitExpression.kt") public void testLastUnitExpression() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/lastUnitExpression.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("manualContinuationImpl.kt") public void testManualContinuationImpl() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/manualContinuationImpl.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("multipleInvokeCalls.kt") public void testMultipleInvokeCalls() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/multipleInvokeCalls.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("multipleInvokeCallsInsideInlineLambda1.kt") public void testMultipleInvokeCallsInsideInlineLambda1() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda1.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("multipleInvokeCallsInsideInlineLambda2.kt") public void testMultipleInvokeCallsInsideInlineLambda2() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda2.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("multipleInvokeCallsInsideInlineLambda3.kt") public void testMultipleInvokeCallsInsideInlineLambda3() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda3.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("nestedTryCatch.kt") public void testNestedTryCatch() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/nestedTryCatch.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("noSuspensionPoints.kt") public void testNoSuspensionPoints() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/noSuspensionPoints.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("nonLocalReturnFromInlineLambda.kt") public void testNonLocalReturnFromInlineLambda() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambda.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("nonLocalReturnFromInlineLambdaDeep.kt") public void testNonLocalReturnFromInlineLambdaDeep() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambdaDeep.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("returnByLabel.kt") public void testReturnByLabel() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/returnByLabel.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("simple.kt") public void testSimple() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/simple.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("simpleException.kt") public void testSimpleException() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/simpleException.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("simpleWithHandleResult.kt") public void testSimpleWithHandleResult() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/simpleWithHandleResult.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("statementLikeLastExpression.kt") public void testStatementLikeLastExpression() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/statementLikeLastExpression.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("suspendDelegation.kt") public void testSuspendDelegation() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendDelegation.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("suspendExtension.kt") public void testSuspendExtension() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendExtension.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("suspendFromInlineLambda.kt") public void testSuspendFromInlineLambda() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendFromInlineLambda.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("suspendInCycle.kt") public void testSuspendInCycle() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendInCycle.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("suspendInTheMiddleOfObjectConstruction.kt") public void testSuspendInTheMiddleOfObjectConstruction() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstruction.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("tryCatchFinallyWithHandleResult.kt") public void testTryCatchFinallyWithHandleResult() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("tryCatchWithHandleResult.kt") public void testTryCatchWithHandleResult() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tryCatchWithHandleResult.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("tryFinallyInsideInlineLambda.kt") public void testTryFinallyInsideInlineLambda() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tryFinallyInsideInlineLambda.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("tryFinallyWithHandleResult.kt") public void testTryFinallyWithHandleResult() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tryFinallyWithHandleResult.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("varValueConflictsWithTable.kt") public void testVarValueConflictsWithTable() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/varValueConflictsWithTable.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("varValueConflictsWithTableSameSort.kt") public void testVarValueConflictsWithTableSameSort() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/varValueConflictsWithTableSameSort.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("compiler/testData/codegen/box/coroutines/intLikeVarSpilling") @@ -6181,121 +5899,61 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { @TestMetadata("complicatedMerge.kt") public void testComplicatedMerge() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/intLikeVarSpilling/complicatedMerge.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("i2bResult.kt") public void testI2bResult() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/intLikeVarSpilling/i2bResult.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("loadFromBooleanArray.kt") public void testLoadFromBooleanArray() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromBooleanArray.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("loadFromByteArray.kt") public void testLoadFromByteArray() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromByteArray.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("noVariableInTable.kt") public void testNoVariableInTable() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/intLikeVarSpilling/noVariableInTable.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("sameIconst1ManyVars.kt") public void testSameIconst1ManyVars() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/intLikeVarSpilling/sameIconst1ManyVars.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("usedInArrayStore.kt") public void testUsedInArrayStore() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInArrayStore.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("usedInMethodCall.kt") public void testUsedInMethodCall() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInMethodCall.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("usedInPutfield.kt") public void testUsedInPutfield() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInPutfield.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("usedInVarStore.kt") public void testUsedInVarStore() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInVarStore.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } } } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/facade/K2JSTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/facade/K2JSTranslator.java index 35e79fedd3b..80759cd3e1b 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/facade/K2JSTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/facade/K2JSTranslator.java @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor; import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS; import org.jetbrains.kotlin.js.analyzer.JsAnalysisResult; import org.jetbrains.kotlin.js.config.JsConfig; +import org.jetbrains.kotlin.js.coroutine.CoroutineTransformer; import org.jetbrains.kotlin.js.facade.exceptions.TranslationException; import org.jetbrains.kotlin.js.inline.JsInliner; import org.jetbrains.kotlin.js.translate.context.TranslationContext; @@ -85,6 +86,11 @@ public final class K2JSTranslator { ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); if (hasError(diagnostics)) return new TranslationResult.Fail(diagnostics); + CoroutineTransformer coroutineTransformer = new CoroutineTransformer(program); + coroutineTransformer.accept(program); + ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); + if (hasError(diagnostics)) return new TranslationResult.Fail(diagnostics); + expandIsCalls(program, context); ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/CallTranslator.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/CallTranslator.kt index 2c6856faf0b..a06819f0fa5 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/CallTranslator.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/CallTranslator.kt @@ -17,6 +17,9 @@ package org.jetbrains.kotlin.js.translate.callTranslator import com.google.dart.compiler.backend.js.ast.JsExpression +import com.google.dart.compiler.backend.js.ast.JsFunction +import com.google.dart.compiler.backend.js.ast.JsInvocation +import com.google.dart.compiler.backend.js.ast.metadata.isSuspend import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptor @@ -115,7 +118,11 @@ private fun translateFunctionCall(context: TranslationContext, resolvedCall: ResolvedCall, explicitReceivers: ExplicitReceivers ): JsExpression { - return context.getCallInfo(resolvedCall, explicitReceivers).translateFunctionCall() + val callExpression = context.getCallInfo(resolvedCall, explicitReceivers).translateFunctionCall() + if (resolvedCall.resultingDescriptor.isSuspend) { + (callExpression as JsInvocation).isSuspend = true + } + return callExpression } fun computeExplicitReceiversForInvoke( diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/ExpressionVisitor.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/ExpressionVisitor.java index d6498266698..3160caabc18 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/ExpressionVisitor.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/ExpressionVisitor.java @@ -26,6 +26,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention; +import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator; import org.jetbrains.kotlin.js.translate.context.Namer; import org.jetbrains.kotlin.js.translate.context.TranslationContext; import org.jetbrains.kotlin.js.translate.declaration.ClassTranslator; @@ -37,6 +38,7 @@ import org.jetbrains.kotlin.js.translate.operation.UnaryOperationTranslator; import org.jetbrains.kotlin.js.translate.reference.*; import org.jetbrains.kotlin.js.translate.utils.BindingUtils; import org.jetbrains.kotlin.js.translate.utils.JsAstUtils; +import org.jetbrains.kotlin.js.translate.utils.TranslationUtils; import org.jetbrains.kotlin.js.translate.utils.UtilsKt; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt; @@ -44,6 +46,7 @@ import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.BindingContextUtils; import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; +import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument; import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant; import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator; import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; @@ -51,7 +54,9 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil; import org.jetbrains.kotlin.types.expressions.DoubleColonLHS; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import static org.jetbrains.kotlin.js.translate.context.Namer.GET_KCLASS; import static org.jetbrains.kotlin.js.translate.context.Namer.GET_KCLASS_FROM_EXPRESSION; @@ -129,7 +134,11 @@ public final class ExpressionVisitor extends TranslatorVisitor { } JsReturn jsReturn; - if (returned == null) { + JsExpression handleResultExpression = TranslationUtils.tryTranslateHandleResult(context, jetReturnExpression, returned); + if (handleResultExpression != null) { + jsReturn = new JsReturn(handleResultExpression); + } + else if (returned == null) { jsReturn = new JsReturn(null); } else { @@ -445,13 +454,13 @@ public final class ExpressionVisitor extends TranslatorVisitor { @Override @NotNull public JsNode visitLambdaExpression(@NotNull KtLambdaExpression expression, @NotNull TranslationContext context) { - return new LiteralFunctionTranslator(context).translate(expression.getFunctionLiteral()); + return new LiteralFunctionTranslator(context).translate(expression.getFunctionLiteral(), null, null); } @Override @NotNull public JsNode visitNamedFunction(@NotNull KtNamedFunction expression, @NotNull TranslationContext context) { - JsExpression alias = new LiteralFunctionTranslator(context).translate(expression); + JsExpression alias = new LiteralFunctionTranslator(context).translate(expression, null, null); FunctionDescriptor descriptor = getFunctionDescriptor(context.bindingContext(), expression); JsName name = context.getNameForDescriptor(descriptor); diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/LiteralFunctionTranslator.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/LiteralFunctionTranslator.kt index f1d34632f07..ab740cab90e 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/LiteralFunctionTranslator.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/LiteralFunctionTranslator.kt @@ -36,7 +36,11 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.inline.InlineUtil class LiteralFunctionTranslator(context: TranslationContext) : AbstractTranslator(context) { - fun translate(declaration: KtDeclarationWithBody): JsExpression { + fun translate( + declaration: KtDeclarationWithBody, + continuationType: ClassDescriptor? = null, + controllerType: ClassDescriptor? = null + ): JsExpression { val invokingContext = context() val descriptor = getFunctionDescriptor(invokingContext.bindingContext(), declaration) @@ -69,6 +73,8 @@ class LiteralFunctionTranslator(context: TranslationContext) : AbstractTranslato val lambdaCreator = simpleReturnFunction(invokingContext.scope(), lambda) lambdaCreator.name = invokingContext.getInnerNameForDescriptor(descriptor) lambdaCreator.isLocal = true + lambdaCreator.coroutineType = continuationType + lambdaCreator.controllerType = controllerType if (!isRecursive) { lambda.name = null } @@ -77,6 +83,8 @@ class LiteralFunctionTranslator(context: TranslationContext) : AbstractTranslato } lambda.isLocal = true + lambda.coroutineType = continuationType + lambda.controllerType = controllerType invokingContext.addDeclarationStatement(lambda.makeStmt()) lambda.name.staticRef = lambda diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/PatternTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/PatternTranslator.java index 08ebdcc7ef0..4f478beb0ac 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/PatternTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/PatternTranslator.java @@ -56,7 +56,7 @@ import static org.jetbrains.kotlin.js.descriptorUtils.DescriptorUtilsKt.getNameI import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getTypeByReference; import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getTypeForExpression; import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.equality; -import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.negated; +import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.not; import static org.jetbrains.kotlin.psi.KtPsiUtil.findChildByType; import static org.jetbrains.kotlin.types.TypeUtils.*; @@ -112,7 +112,7 @@ public final class PatternTranslator extends AbstractTranslator { if (result == null) return JsLiteral.getBoolean(!expression.isNegated()); if (expression.isNegated()) { - return negated(result); + return not(result); } return result; } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/WhenTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/WhenTranslator.java index c0381b7772d..22c1ced8ec7 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/WhenTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/WhenTranslator.java @@ -33,7 +33,7 @@ import org.jetbrains.kotlin.types.KotlinType; import java.util.HashMap; import java.util.Map; -import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.negated; +import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.not; public final class WhenTranslator extends AbstractTranslator { @Nullable @@ -141,7 +141,7 @@ public final class WhenTranslator extends AbstractTranslator { private JsExpression translateCondition(@NotNull KtWhenCondition condition, @NotNull TranslationContext context) { JsExpression patternMatchExpression = translateWhenConditionToBooleanExpression(condition, context); if (isNegated(condition)) { - return negated(patternMatchExpression); + return not(patternMatchExpression); } return patternMatchExpression; } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/operation/EqualsBOIF.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/operation/EqualsBOIF.kt index de581e02493..032575a3942 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/operation/EqualsBOIF.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/operation/EqualsBOIF.kt @@ -62,7 +62,7 @@ object EqualsBOIF : BinaryOperationIntrinsicFactory { } val result = TopLevelFIF.KOTLIN_EQUALS.apply(left, Arrays.asList(right), context) - return if (isNegated) JsAstUtils.negated(result) else result + return if (isNegated) JsAstUtils.not(result) else result } private fun canUseSimpleEquals(expression: KtBinaryExpression, context: TranslationContext): Boolean { diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/operation/InOperationTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/operation/InOperationTranslator.java index 376debf621e..e4789e04b59 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/operation/InOperationTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/operation/InOperationTranslator.java @@ -71,7 +71,7 @@ public class InOperationTranslator extends AbstractTranslator { private JsExpression translateGeneral(@NotNull ResolvedCall call, @NotNull JsExpression rightTranslated) { JsExpression result = CallTranslator.translate(context(), call, rightTranslated); if (negated) { - result = JsAstUtils.negated(result); + result = JsAstUtils.not(result); } return result; } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallArgumentTranslator.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallArgumentTranslator.kt index b0834bafc59..fce1bc7ac81 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallArgumentTranslator.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallArgumentTranslator.kt @@ -20,10 +20,13 @@ import com.google.dart.compiler.backend.js.ast.* import com.google.dart.compiler.backend.js.ast.metadata.SideEffectKind import com.google.dart.compiler.backend.js.ast.metadata.sideEffects import com.intellij.util.SmartList +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.js.translate.context.Namer import org.jetbrains.kotlin.js.translate.context.TemporaryConstVariable import org.jetbrains.kotlin.js.translate.context.TranslationContext +import org.jetbrains.kotlin.js.translate.expression.LiteralFunctionTranslator import org.jetbrains.kotlin.js.translate.expression.PatternTranslator import org.jetbrains.kotlin.js.translate.general.AbstractTranslator import org.jetbrains.kotlin.js.translate.general.Translation @@ -31,6 +34,8 @@ import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils import org.jetbrains.kotlin.js.translate.utils.JsAstUtils import org.jetbrains.kotlin.js.translate.utils.TranslationUtils import org.jetbrains.kotlin.js.translate.utils.getReferenceToJsClass +import org.jetbrains.kotlin.psi.KtLambdaExpression +import org.jetbrains.kotlin.psi.KtPsiUtil import org.jetbrains.kotlin.psi.ValueArgument import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.types.KotlinType @@ -119,7 +124,7 @@ class CallArgumentTranslator private constructor( } } else { - translateSingleArgument(actualArgument, result, argContext) + translateSingleArgument(parameterDescriptor, actualArgument, result, argContext) } context().moveVarsFrom(argContext) @@ -178,8 +183,12 @@ class CallArgumentTranslator private constructor( return result } - private fun translateSingleArgument(actualArgument: ResolvedValueArgument, result: MutableList, - context: TranslationContext) { + private fun translateSingleArgument( + parameterDescriptor: ValueParameterDescriptor, + actualArgument: ResolvedValueArgument, + result: MutableList, + context: TranslationContext + ) { val valueArguments = actualArgument.arguments if (actualArgument is DefaultValueArgument) { @@ -190,10 +199,19 @@ class CallArgumentTranslator private constructor( assert(actualArgument is ExpressionValueArgument) assert(valueArguments.size == 1) - val argumentExpression = valueArguments[0].getArgumentExpression()!! + val argumentExpression = KtPsiUtil.deparenthesize(valueArguments[0].getArgumentExpression())!! - val jsExpression = Translation.translateAsExpression(argumentExpression, context) - result.add(jsExpression) + result += if (parameterDescriptor.isCoroutine && argumentExpression is KtLambdaExpression) { + val continuationType = parameterDescriptor.type.arguments.last().type + val continuationDescriptor = continuationType.constructor.declarationDescriptor as ClassDescriptor + val controllerType = parameterDescriptor.type.arguments[0].type + val controllerDescriptor = controllerType.constructor.declarationDescriptor as ClassDescriptor + LiteralFunctionTranslator(context).translate( + argumentExpression.functionLiteral, continuationDescriptor, controllerDescriptor) + } + else { + Translation.translateAsExpression(argumentExpression, context) + } } private fun translateVarargArgument(arguments: List, result: MutableList, @@ -243,7 +261,7 @@ class CallArgumentTranslator private constructor( } private fun concatArgumentsIfNeeded(concatArguments: List): JsExpression { - assert(concatArguments.size > 0) { "concatArguments.size should not be 0" } + assert(concatArguments.isNotEmpty()) { "concatArguments.size should not be 0" } if (concatArguments.size > 1) { return JsInvocation(JsNameRef("concat", concatArguments[0]), concatArguments.subList(1, concatArguments.size)) @@ -255,7 +273,7 @@ class CallArgumentTranslator private constructor( } private fun prepareConcatArguments(arguments: List, list: List): MutableList { - assert(arguments.size != 0) { "arguments.size should not be 0" } + assert(arguments.isNotEmpty()) { "arguments.size should not be 0" } assert(arguments.size == list.size) { "arguments.size: " + arguments.size + " != list.size: " + list.size } val concatArguments = SmartList() diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/FunctionBodyTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/FunctionBodyTranslator.java index 649769e528b..a9334e9c0c2 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/FunctionBodyTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/FunctionBodyTranslator.java @@ -94,7 +94,19 @@ public final class FunctionBodyTranslator extends AbstractTranslator { jsBlock.getStatements().addAll(setDefaultValueForArguments(descriptor, context())); } - jsBlock.getStatements().addAll(mayBeWrapWithReturn(Translation.translateExpression(jetBodyExpression, context(), jsBlock)).getStatements()); + KotlinType returnType = descriptor.getReturnType(); + assert returnType != null; + + + TranslationContext handleResultContext = context().innerBlock(jsBlock); + JsExpression handleResultExpr = TranslationUtils.tryTranslateHandleResult(handleResultContext, declaration, jetBodyExpression); + if (handleResultExpr != null) { + jsBlock.getStatements().add(new JsReturn(handleResultExpr)); + } + else { + JsNode jsBody = Translation.translateExpression(jetBodyExpression, context(), jsBlock); + jsBlock.getStatements().addAll(mayBeWrapWithReturn(jsBody).getStatements()); + } return jsBlock; } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsAstUtils.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsAstUtils.java index e80084320db..6d95a00bb9b 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsAstUtils.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsAstUtils.java @@ -208,12 +208,7 @@ public final class JsAstUtils { } @NotNull - public static JsPrefixOperation negated(@NotNull JsExpression expression) { - return new JsPrefixOperation(JsUnaryOperator.NOT, expression); - } - - @NotNull - public static JsExpression negatedOptimized(@NotNull JsExpression expression) { + public static JsExpression notOptimized(@NotNull JsExpression expression) { if (expression instanceof JsUnaryOperation) { JsUnaryOperation unary = (JsUnaryOperation) expression; if (unary.getOperator() == JsUnaryOperator.NOT) return unary.getArg(); @@ -222,9 +217,9 @@ public final class JsAstUtils { JsBinaryOperation binary = (JsBinaryOperation) expression; switch (binary.getOperator()) { case AND: - return or(negatedOptimized(binary.getArg1()), negatedOptimized(binary.getArg2())); + return or(notOptimized(binary.getArg1()), notOptimized(binary.getArg2())); case OR: - return and(negatedOptimized(binary.getArg1()), negatedOptimized(binary.getArg2())); + return and(notOptimized(binary.getArg1()), notOptimized(binary.getArg2())); case EQ: return new JsBinaryOperation(JsBinaryOperator.NEQ, binary.getArg1(), binary.getArg2()); case NEQ: @@ -246,7 +241,7 @@ public final class JsAstUtils { } } - return negated(expression); + return not(expression); } @NotNull diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/TranslationUtils.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/TranslationUtils.java index 20307c9eb85..54d800e7bfd 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/TranslationUtils.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/TranslationUtils.java @@ -18,23 +18,30 @@ package org.jetbrains.kotlin.js.translate.utils; import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.backend.js.ast.JsBinaryOperator; +import com.google.dart.compiler.backend.js.ast.metadata.MetadataProperties; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.impl.LocalVariableAccessorDescriptor; import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor; +import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator; import org.jetbrains.kotlin.js.translate.context.Namer; import org.jetbrains.kotlin.js.translate.context.TemporaryConstVariable; import org.jetbrains.kotlin.js.translate.context.TranslationContext; import org.jetbrains.kotlin.js.translate.general.Translation; import org.jetbrains.kotlin.psi.*; +import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt; import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.DescriptorUtils; +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; +import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument; import org.jetbrains.kotlin.types.KotlinType; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import static com.google.dart.compiler.backend.js.ast.JsBinaryOperator.*; import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getCallableDescriptorForOperationExpression; @@ -289,4 +296,38 @@ public final class TranslationUtils { } return false; } + + @Nullable + public static JsExpression tryTranslateHandleResult( + @NotNull TranslationContext context, + @NotNull KtExpression expression, + @Nullable KtExpression returnExpression + ) { + ResolvedCall returnCall = context.bindingContext().get( + BindingContext.RETURN_HANDLE_RESULT_RESOLVED_CALL, expression); + if (returnCall == null) return null; + + Map aliases = new HashMap(); + List arguments = returnCall.getValueArgumentsByIndex(); + assert arguments != null : "Arguments should be defined here: " + PsiUtilsKt.getTextWithLocation(expression); + + KotlinType returnType = returnCall.getResultingDescriptor().getValueParameters().get(0).getType(); + + ValueArgument returnValueArgument = arguments.get(0).getArguments().get(0); + if (returnExpression != null) { + aliases.put(returnValueArgument.getArgumentExpression(), Translation.translateAsExpression(returnExpression, context)); + } + else if (KotlinBuiltIns.isUnit(returnType)) { + aliases.put(returnValueArgument.getArgumentExpression(), JsLiteral.NULL); + } + + ValueArgument continuationArgument = arguments.get(1).getArguments().get(0); + aliases.put(continuationArgument.getArgumentExpression(), JsLiteral.THIS); + + TranslationContext returnContext = context.innerContextWithAliasesForExpressions(aliases); + JsInvocation handleResultInvocation = (JsInvocation) CallTranslator.translate(returnContext, returnCall, JsLiteral.THIS); + MetadataProperties.setHandleResult(handleResultInvocation, true); + + return handleResultInvocation; + } } diff --git a/jslib_files.xml b/jslib_files.xml index 67c961c091c..b2c1ee77efb 100644 --- a/jslib_files.xml +++ b/jslib_files.xml @@ -24,6 +24,7 @@ +