[K/JS] Reset exceptionState inside coroutines with a finally block ^KT-58685 Fixed
This commit is contained in:
+8
-2
@@ -27,6 +27,8 @@ import org.jetbrains.kotlin.ir.util.setDeclarationsParent
|
|||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
|
object FINALLY_EXPRESSION : IrStatementOriginImpl("FINALLY_EXPRESSION")
|
||||||
|
|
||||||
class FinallyBlocksLowering(val context: CommonBackendContext, private val throwableType: IrType): FileLoweringPass, IrElementTransformerVoidWithContext() {
|
class FinallyBlocksLowering(val context: CommonBackendContext, private val throwableType: IrType): FileLoweringPass, IrElementTransformerVoidWithContext() {
|
||||||
|
|
||||||
private interface HighLevelJump {
|
private interface HighLevelJump {
|
||||||
@@ -271,13 +273,17 @@ class FinallyBlocksLowering(val context: CommonBackendContext, private val throw
|
|||||||
+irReturnableBlock(symbol, type) {
|
+irReturnableBlock(symbol, type) {
|
||||||
+value
|
+value
|
||||||
}
|
}
|
||||||
+copy(finallyExpression)
|
+irComposite(resultType = context.irBuiltIns.unitType, origin = FINALLY_EXPRESSION) {
|
||||||
|
+copy(finallyExpression)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else -> irBlock(value, null, type) {
|
else -> irBlock(value, null, type) {
|
||||||
val tmp = createTmpVariable(irReturnableBlock(symbol, type) {
|
val tmp = createTmpVariable(irReturnableBlock(symbol, type) {
|
||||||
+irReturn(symbol, value)
|
+irReturn(symbol, value)
|
||||||
})
|
})
|
||||||
+copy(finallyExpression)
|
+irComposite(resultType = context.irBuiltIns.unitType, origin = FINALLY_EXPRESSION) {
|
||||||
|
+copy(finallyExpression)
|
||||||
|
}
|
||||||
+irGet(tmp)
|
+irGet(tmp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-1
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.ir.backend.js.lower.coroutines
|
package org.jetbrains.kotlin.ir.backend.js.lower.coroutines
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.ir.isPure
|
import org.jetbrains.kotlin.backend.common.ir.isPure
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.FINALLY_EXPRESSION
|
||||||
import org.jetbrains.kotlin.backend.common.peek
|
import org.jetbrains.kotlin.backend.common.peek
|
||||||
import org.jetbrains.kotlin.backend.common.pop
|
import org.jetbrains.kotlin.backend.common.pop
|
||||||
import org.jetbrains.kotlin.backend.common.push
|
import org.jetbrains.kotlin.backend.common.push
|
||||||
@@ -396,6 +397,13 @@ class StateMachineBuilder(
|
|||||||
private fun wrap(expression: IrExpression, variable: IrVariableSymbol) =
|
private fun wrap(expression: IrExpression, variable: IrVariableSymbol) =
|
||||||
JsIrBuilder.buildSetVariable(variable, expression, unit)
|
JsIrBuilder.buildSetVariable(variable, expression, unit)
|
||||||
|
|
||||||
|
override fun visitComposite(expression: IrComposite) {
|
||||||
|
if (expression.origin == FINALLY_EXPRESSION) {
|
||||||
|
catchBlockStack.peek()?.let(::setupExceptionState)
|
||||||
|
}
|
||||||
|
super.visitComposite(expression)
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitWhen(expression: IrWhen) {
|
override fun visitWhen(expression: IrWhen) {
|
||||||
|
|
||||||
if (expression !in suspendableNodes) return addStatement(expression)
|
if (expression !in suspendableNodes) return addStatement(expression)
|
||||||
@@ -709,7 +717,6 @@ class StateMachineBuilder(
|
|||||||
catchBlockStack.pop()
|
catchBlockStack.pop()
|
||||||
|
|
||||||
updateState(tryState.catchState)
|
updateState(tryState.catchState)
|
||||||
|
|
||||||
setupExceptionState(enclosingCatch)
|
setupExceptionState(enclosingCatch)
|
||||||
|
|
||||||
var rethrowNeeded = true
|
var rethrowNeeded = true
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
// IGNORE_BACKEND_K2: WASM
|
|
||||||
// ^ KT-59800 K2 + Wasm: test failure after changing `finally` block generation
|
|
||||||
|
|
||||||
fun test1() : Boolean {
|
fun test1() : Boolean {
|
||||||
try {
|
try {
|
||||||
return true
|
return true
|
||||||
|
|||||||
+6
@@ -961,6 +961,12 @@ public class FirJsBoxTestGenerated extends AbstractFirJsBoxTest {
|
|||||||
public void testSuspendMethodWithSuperCall() throws Exception {
|
public void testSuspendMethodWithSuperCall() throws Exception {
|
||||||
runTest("js/js.translator/testData/box/coroutines/suspendMethodWithSuperCall.kt");
|
runTest("js/js.translator/testData/box/coroutines/suspendMethodWithSuperCall.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tryFinally.kt")
|
||||||
|
public void testTryFinally() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/coroutines/tryFinally.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
+6
@@ -961,6 +961,12 @@ public class FirJsES6BoxTestGenerated extends AbstractFirJsES6BoxTest {
|
|||||||
public void testSuspendMethodWithSuperCall() throws Exception {
|
public void testSuspendMethodWithSuperCall() throws Exception {
|
||||||
runTest("js/js.translator/testData/box/coroutines/suspendMethodWithSuperCall.kt");
|
runTest("js/js.translator/testData/box/coroutines/suspendMethodWithSuperCall.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tryFinally.kt")
|
||||||
|
public void testTryFinally() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/coroutines/tryFinally.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
+6
@@ -961,6 +961,12 @@ public class IrBoxJsES6TestGenerated extends AbstractIrBoxJsES6Test {
|
|||||||
public void testSuspendMethodWithSuperCall() throws Exception {
|
public void testSuspendMethodWithSuperCall() throws Exception {
|
||||||
runTest("js/js.translator/testData/box/coroutines/suspendMethodWithSuperCall.kt");
|
runTest("js/js.translator/testData/box/coroutines/suspendMethodWithSuperCall.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tryFinally.kt")
|
||||||
|
public void testTryFinally() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/coroutines/tryFinally.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
+6
@@ -961,6 +961,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
|||||||
public void testSuspendMethodWithSuperCall() throws Exception {
|
public void testSuspendMethodWithSuperCall() throws Exception {
|
||||||
runTest("js/js.translator/testData/box/coroutines/suspendMethodWithSuperCall.kt");
|
runTest("js/js.translator/testData/box/coroutines/suspendMethodWithSuperCall.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tryFinally.kt")
|
||||||
|
public void testTryFinally() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/coroutines/tryFinally.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import kotlin.coroutines.*
|
||||||
|
import kotlin.coroutines.intrinsics.*
|
||||||
|
|
||||||
|
var isLocked = false
|
||||||
|
|
||||||
|
fun builder(c: suspend () -> Unit) {
|
||||||
|
c.startCoroutine(object : Continuation<Unit> {
|
||||||
|
override val context = EmptyCoroutineContext
|
||||||
|
override fun resumeWith(result: Result<Unit>) {}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun lock() {
|
||||||
|
isLocked = true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun unlock() {
|
||||||
|
if (isLocked) {
|
||||||
|
isLocked = false
|
||||||
|
} else {
|
||||||
|
throw IllegalStateException("Not locked")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend inline fun <T> withLock(block: () -> T): T {
|
||||||
|
lock()
|
||||||
|
try {
|
||||||
|
return block()
|
||||||
|
} finally {
|
||||||
|
unlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var error: Exception? = null
|
||||||
|
builder {
|
||||||
|
try {
|
||||||
|
withLock {}
|
||||||
|
throw Exception("seems fine")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
error = e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (error !is IllegalStateException) "OK" else "fail"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user