[dart2js] Fix #47566 by disabling optimization

The JavaScript-to-JavaScript async transform had an inconsisent
handling of switch statements that contained an await, but only in the
expression.

For now the special handling of the expression-only case is disabled.

Change-Id: Ia79ff3951d681ba933df638da7e0e518d401ed9a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/219746
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Commit-Queue: Stephen Adams <sra@google.com>
This commit is contained in:
Stephen Adams 2021-11-09 00:43:02 +00:00 committed by commit-bot@chromium.org
parent b97737c3b5
commit 0afb365804
3 changed files with 148 additions and 11 deletions

View file

@ -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<bool> {
@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;
}

View file

@ -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);
}

View file

@ -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<void> 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<int> bar() async => 1;
Future<void> 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(','));
}