Skip to content

Commit a38e265

Browse files
rakudramacommit-bot@chromium.org
authored andcommitted
Fix #42531
Bad identifier for async closure generator body names in extension methods. Fixed: 42531 Change-Id: Ice29bb5ac03c67b1024c0fd53ffdb9b9b1d2131f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/153484 Commit-Queue: Stephen Adams <[email protected]> Reviewed-by: Sigmund Cherem <[email protected]> Reviewed-by: Nicholas Shahan <[email protected]>
1 parent db5cda8 commit a38e265

File tree

3 files changed

+94
-1
lines changed

3 files changed

+94
-1
lines changed

pkg/compiler/lib/src/js_backend/namer.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,8 @@ class Namer extends ModularNamer {
681681
String invocationName = operatorNameToIdentifier(function.name);
682682
// TODO(sra): If the generator is for a closure's 'call' method, we don't
683683
// need to incorporate the enclosing class.
684-
String className = method.enclosingClass.name.replaceAll('&', '_');
684+
String className =
685+
method.enclosingClass.name.replaceAll(_nonIdentifierRE, '_');
685686
return '${invocationName}\$body\$${className}';
686687
});
687688
}

tests/dart2js/42531_test.dart

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:expect/expect.dart';
6+
7+
// Regression test for badly named generator body.
8+
9+
Future<void> goo(Future Function() f) async {
10+
Expect.equals(102, (await f()).keys.single);
11+
Expect.equals(104, (await f()).keys.single);
12+
}
13+
14+
Future<T> identity<T>(T x) async => x;
15+
16+
extension Gloop<T> on Map<T, List<T>> {
17+
// An async method using a 'complex' generator type `Map<T, List<T>>`. This
18+
// requires a separated entry and body, which requires a name, and the name
19+
// must be legal JavaScript.
20+
Future<Map<T, List<T>>> foo(int x) async {
21+
var result = await identity({(x += this.length) as T: <T>[]});
22+
return result;
23+
}
24+
25+
Future<int> bar(int x) async {
26+
// An async closure using a 'complex' generator type `Map<T, Set<T>>`. This
27+
// requires a separated entry and body, which requires a name, and the name
28+
// must be legal JavaScript.
29+
await goo(() async => {(x += this.length) as T: <T>{}});
30+
return x;
31+
}
32+
}
33+
34+
main() async {
35+
// Test method.
36+
Map<int, List<int>> o1 = {1: [], 2: []};
37+
var o2 = await o1.foo(100);
38+
var o3 = await o2.foo(100);
39+
Expect.equals('{102: []}', '$o2');
40+
Expect.equals('{101: []}', '$o3');
41+
42+
// Test closure.
43+
Map<int, List<int>> o = {1: [], 2: []};
44+
int x = await o.bar(100);
45+
Expect.equals(104, x);
46+
}

tests/dart2js_2/42531_test.dart

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:expect/expect.dart';
6+
7+
// Regression test for badly named generator body.
8+
9+
Future<void> goo(Future Function() f) async {
10+
Expect.equals(102, (await f()).keys.single);
11+
Expect.equals(104, (await f()).keys.single);
12+
}
13+
14+
Future<T> identity<T>(T x) async => x;
15+
16+
extension Gloop<T> on Map<T, List<T>> {
17+
// An async method using a 'complex' generator type `Map<T, List<T>>`. This
18+
// requires a separated entry and body, which requires a name, and the name
19+
// must be legal JavaScript.
20+
Future<Map<T, List<T>>> foo(int x) async {
21+
var result = await identity({(x += this.length) as T: <T>[]});
22+
return result;
23+
}
24+
25+
Future<int> bar(int x) async {
26+
// An async closure using a 'complex' generator type `Map<T, Set<T>>`. This
27+
// requires a separated entry and body, which requires a name, and the name
28+
// must be legal JavaScript.
29+
await goo(() async => {(x += this.length) as T: <T>{}});
30+
return x;
31+
}
32+
}
33+
34+
main() async {
35+
// Test method.
36+
Map<int, List<int>> o1 = {1: [], 2: []};
37+
var o2 = await o1.foo(100);
38+
var o3 = await o2.foo(100);
39+
Expect.equals('{102: []}', '$o2');
40+
Expect.equals('{101: []}', '$o3');
41+
42+
// Test closure.
43+
Map<int, List<int>> o = {1: [], 2: []};
44+
int x = await o.bar(100);
45+
Expect.equals(104, x);
46+
}

0 commit comments

Comments
 (0)