JS: fix translation of for statement when either next or hasNext method translates to multiple statements. Fix KT-15367
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// TARGET_BACKEND: JVM
|
||||
import kotlin.coroutines.*
|
||||
|
||||
interface AsyncGenerator<in T> {
|
||||
|
||||
@@ -5298,6 +5298,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("asyncIterator.kt")
|
||||
public void testAsyncIterator() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/asyncIterator.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("await.kt")
|
||||
public void testAwait() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/await.kt");
|
||||
|
||||
+26
-8
@@ -179,25 +179,43 @@ fun translateForExpression(expression: KtForExpression, context: TranslationCont
|
||||
|
||||
fun translateForOverIterator(): JsStatement {
|
||||
|
||||
fun translateMethodInvocation(receiver: JsExpression?, resolvedCall: ResolvedCall<FunctionDescriptor>): JsExpression =
|
||||
CallTranslator.translate(context, resolvedCall, receiver)
|
||||
fun translateMethodInvocation(
|
||||
receiver: JsExpression?,
|
||||
resolvedCall: ResolvedCall<FunctionDescriptor>,
|
||||
block: JsBlock
|
||||
): JsExpression = CallTranslator.translate(context.innerBlock(block), resolvedCall, receiver)
|
||||
|
||||
fun iteratorMethodInvocation(): JsExpression {
|
||||
val range = Translation.translateAsExpression(loopRange, context)
|
||||
val resolvedCall = getIteratorFunction(context.bindingContext(), loopRange)
|
||||
return translateMethodInvocation(range, resolvedCall)
|
||||
return CallTranslator.translate(context, resolvedCall, range)
|
||||
}
|
||||
|
||||
val iteratorVar = context.defineTemporary(iteratorMethodInvocation())
|
||||
|
||||
fun hasNextMethodInvocation(): JsExpression {
|
||||
fun hasNextMethodInvocation(block: JsBlock): JsExpression {
|
||||
val resolvedCall = getHasNextCallable(context.bindingContext(), loopRange)
|
||||
return translateMethodInvocation(iteratorVar, resolvedCall)
|
||||
return translateMethodInvocation(iteratorVar, resolvedCall, block)
|
||||
}
|
||||
|
||||
val nextInvoke = translateMethodInvocation(iteratorVar, getNextFunction(context.bindingContext(), loopRange))
|
||||
val body = translateBody(nextInvoke)
|
||||
return JsWhile(hasNextMethodInvocation(), body ?: nextInvoke.makeStmt())
|
||||
val hasNextBlock = JsBlock()
|
||||
val hasNextInvocation = hasNextMethodInvocation(hasNextBlock)
|
||||
|
||||
val nextBlock = JsBlock()
|
||||
val nextInvoke = translateMethodInvocation(iteratorVar, getNextFunction(context.bindingContext(), loopRange), nextBlock)
|
||||
|
||||
val bodyStatements = mutableListOf<JsStatement>()
|
||||
val exitCondition = if (hasNextBlock.isEmpty) {
|
||||
hasNextInvocation
|
||||
}
|
||||
else {
|
||||
bodyStatements += hasNextBlock.statements
|
||||
bodyStatements += JsIf(notOptimized(hasNextInvocation), JsBreak())
|
||||
JsLiteral.TRUE
|
||||
}
|
||||
bodyStatements += nextBlock.statements
|
||||
bodyStatements += translateBody(nextInvoke)?.let(::flattenStatement).orEmpty()
|
||||
return JsWhile(exitCondition, bodyStatements.singleOrNull() ?: JsBlock(bodyStatements))
|
||||
}
|
||||
|
||||
return when {
|
||||
|
||||
Reference in New Issue
Block a user