提交 1ab78dff 编写于 作者: A Alexey Andreev

JS: fix translation of `for` statement when either `next` or `hasNext` method...

JS: fix translation of `for` statement when either `next` or `hasNext` method translates to multiple statements. Fix KT-15367
上级 cef32b33
// 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");
......@@ -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 {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册