diff --git a/pkg/compiler/lib/src/js/rewrite_async.dart b/pkg/compiler/lib/src/js/rewrite_async.dart index 69a999f8e4b..8a48496c105 100644 --- a/pkg/compiler/lib/src/js/rewrite_async.dart +++ b/pkg/compiler/lib/src/js/rewrite_async.dart @@ -1397,8 +1397,8 @@ abstract class AsyncRewriterBase extends js.NodeVisitor { @override void visitSwitch(js.Switch node) { - if (!node.cases.any(shouldTransform)) { - // If only the key has an await, translation can be simplified. + if (!shouldTransform(node)) { + // TODO(sra): If only the key has an await, translation can be simplified. bool oldInsideUntranslated = insideUntranslatedBreakable; insideUntranslatedBreakable = true; withExpression(node.key, (js.Expression key) { @@ -2824,10 +2824,9 @@ class PreTranslationAnalysis extends js.BaseVisitor { @override bool visitSwitch(js.Switch node) { loopsAndSwitches.add(node); - // If the key has an `await` expression, do not transform the - // body of the switch. - visit(node.key); - bool result = false; + // TODO(sra): If just the key has an `await` expression, do not transform + // the body of the switch. + bool result = visit(node.key); for (js.SwitchClause clause in node.cases) { if (visit(clause)) result = true; } diff --git a/pkg/compiler/test/async_await/async_await_js_transform_test.dart b/pkg/compiler/test/async_await/async_await_js_transform_test.dart index 4ea675b229f..58972595332 100644 --- a/pkg/compiler/test/async_await/async_await_js_transform_test.dart +++ b/pkg/compiler/test/async_await/async_await_js_transform_test.dart @@ -1085,20 +1085,116 @@ function(l) { switch (__goto) { case 0: // Function start - __goto = 2; - return awaitHelper(l, body); case 2: + // switch + __goto = 7; + return awaitHelper(l, body); + case 7: // returning from await. switch (__result) { case 1: - print(1); + // goto case + __goto = 4; break; case 2: - print(1); + // goto case + __goto = 5; + break; default: - print(2); + // goto default + __goto = 6; break; } + break; + case 4: + // case + print(1); + // goto after switch + __goto = 3; + break; + case 5: + // case + print(1); + case 6: + // default + print(2); + // goto after switch + __goto = 3; + break; + case 3: + // after switch + // implicit return + return returnHelper(null, __completer); + } + }); + return startHelper(body, __completer); +}"""); + + testAsyncTransform(""" + // This example is like #47566 + function(b, l) async { + print("start"); + if (b) { + switch(await l) { + case 1: + print(1); + break; + default: + print(2); + break; + } + } + print("end"); + }""", """ +function(b, l) { + var __goto = 0, + __completer = NewCompleter(CompleterType); + var body = _wrapJsFunctionForAsync(function(__errorCode, __result) { + if (__errorCode === 1) + return rethrowHelper(__result, __completer); + while (true) + switch (__goto) { + case 0: + // Function start + print("start"); + __goto = b ? 2 : 3; + break; + case 2: + // then + case 4: + // switch + __goto = 8; + return awaitHelper(l, body); + case 8: + // returning from await. + switch (__result) { + case 1: + // goto case + __goto = 6; + break; + default: + // goto default + __goto = 7; + break; + } + break; + case 6: + // case + print(1); + // goto after switch + __goto = 5; + break; + case 7: + // default + print(2); + // goto after switch + __goto = 5; + break; + case 5: + // after switch + case 3: + // join + print("end"); // implicit return return returnHelper(null, __completer); } diff --git a/tests/language/regress/regress47566_test.dart b/tests/language/regress/regress47566_test.dart new file mode 100644 index 00000000000..4ba35ae3f09 --- /dev/null +++ b/tests/language/regress/regress47566_test.dart @@ -0,0 +1,42 @@ +// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Regression test for https://github.com/dart-lang/sdk/issues/47566 + +import 'package:expect/expect.dart'; + +final List trace = []; +void log(String s) { + trace.add(s); +} + +Future test(bool value) async { + log('f1'); + + if (value) { + final result = await bar(); + switch (result) { + case 1: + log('sb'); + break; + case 0: + return; + } + log('sc'); + } + + log('f2'); +} + +Future bar() async => 1; + +Future main() async { + trace.clear(); + await test(true); + Expect.equals('f1,sb,sc,f2', trace.join(',')); + + trace.clear(); + await test(false); + Expect.equals('f1,f2', trace.join(',')); +}