mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 09:43:08 +00:00
[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:
parent
b97737c3b5
commit
0afb365804
3 changed files with 148 additions and 11 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
42
tests/language/regress/regress47566_test.dart
Normal file
42
tests/language/regress/regress47566_test.dart
Normal 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(','));
|
||||
}
|
Loading…
Reference in a new issue