Skip to content

Commit 14729b0

Browse files
Alexey AndreevAlexey Andreev
authored andcommitted
JS: fix exception handling in coroutines when initializing via resumeWithException
1 parent bb61fb0 commit 14729b0

File tree

3 files changed

+10
-6
lines changed

3 files changed

+10
-6
lines changed

js/js.inliner/src/org/jetbrains/kotlin/js/coroutine/CoroutineBodyTransformer.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,11 @@ class CoroutineBodyTransformer(
5252
fun preProcess(node: JsNode) {
5353
breakContinueTargetStatements += node.collectBreakContinueTargets()
5454
nodesToSplit = node.collectNodesToSplit()
55-
currentStatements += exceptionState(currentCatchBlock)
5655
}
5756

5857
fun postProcess(): List<CoroutineBlock> {
5958
currentBlock.statements += JsReturn()
60-
val graph = entryBlock.buildGraph()
59+
val graph = entryBlock.buildGraph(globalCatchBlock)
6160
val orderedBlocks = DFS.topologicalOrder(listOf(entryBlock)) { graph[it].orEmpty() }
6261
orderedBlocks.replaceCoroutineFlowStatements(context, program)
6362
return orderedBlocks

js/js.inliner/src/org/jetbrains/kotlin/js/coroutine/CoroutineFunctionTransformer.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,14 @@ class CoroutineFunctionTransformer(
5353
bodyTransformer.preProcess(body)
5454
body.statements.forEach { it.accept(bodyTransformer) }
5555
val coroutineBlocks = bodyTransformer.postProcess()
56+
val globalCatchBlockIndex = coroutineBlocks.indexOf(context.globalCatchBlock)
5657

5758
coroutineBlocks.forEach { it.jsBlock.collectAdditionalLocalVariables() }
5859
coroutineBlocks.forEach { it.jsBlock.replaceLocalVariables(function.scope, context, localVariables) }
5960

6061
val additionalStatements = mutableListOf<JsStatement>()
6162
val resumeName = generateDoResume(coroutineBlocks, context, additionalStatements, throwName)
62-
generateContinuationConstructor(context, additionalStatements, bodyTransformer.hasFinallyBlocks)
63+
generateContinuationConstructor(context, additionalStatements, bodyTransformer.hasFinallyBlocks, globalCatchBlockIndex)
6364
generateContinuationMethods(resumeName, additionalStatements)
6465

6566
generateCoroutineInstantiation()
@@ -70,7 +71,8 @@ class CoroutineFunctionTransformer(
7071
private fun generateContinuationConstructor(
7172
context: CoroutineTransformationContext,
7273
statements: MutableList<JsStatement>,
73-
hasFinallyBlocks: Boolean
74+
hasFinallyBlocks: Boolean,
75+
globalCatchBlockIndex: Int
7476
) {
7577
val constructor = JsFunction(function.scope.parent, JsBlock(), "Continuation")
7678
constructor.name = className
@@ -86,7 +88,7 @@ class CoroutineFunctionTransformer(
8688

8789
constructor.body.statements.run {
8890
assign(context.stateFieldName, program.getNumberLiteral(0))
89-
assign(context.exceptionStateName, program.getNumberLiteral(0))
91+
assign(context.exceptionStateName, program.getNumberLiteral(globalCatchBlockIndex))
9092
if (hasFinallyBlocks) {
9193
assign(context.finallyPathFieldName, JsLiteral.NULL)
9294
}

js/js.inliner/src/org/jetbrains/kotlin/js/coroutine/CoroutinePasses.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ fun List<CoroutineBlock>.replaceCoroutineFlowStatements(context: CoroutineTransf
118118
return forEach { blockReplacementVisitor.accept(it.jsBlock) }
119119
}
120120

121-
fun CoroutineBlock.buildGraph(): Map<CoroutineBlock, Set<CoroutineBlock>> {
121+
fun CoroutineBlock.buildGraph(globalCatchBlock: CoroutineBlock?): Map<CoroutineBlock, Set<CoroutineBlock>> {
122122
// That's a little more than DFS due to need of tracking finally paths
123123

124124
val visitedBlocks = mutableSetOf<CoroutineBlock>()
@@ -139,6 +139,9 @@ fun CoroutineBlock.buildGraph(): Map<CoroutineBlock, Set<CoroutineBlock>> {
139139

140140
val successors = graph.getOrPut(block) { mutableSetOf() }
141141
successors += block.collectTargetBlocks()
142+
if (block == this && globalCatchBlock != null) {
143+
successors += globalCatchBlock
144+
}
142145
successors.forEach(::visitBlock)
143146
}
144147

0 commit comments

Comments
 (0)