Skip to content

Commit 7f8426f

Browse files
authoredOct 28, 2022
fix for-in enumeration containing yield in generator (#51295)
1 parent 3d2b401 commit 7f8426f

6 files changed

+244
-92
lines changed
 

‎src/compiler/transformers/generators.ts

+20-13
Original file line numberDiff line numberDiff line change
@@ -1516,40 +1516,44 @@ namespace ts {
15161516
}
15171517

15181518
function transformAndEmitForInStatement(node: ForInStatement) {
1519-
// TODO(rbuckton): Source map locations
15201519
if (containsYield(node)) {
15211520
// [source]
15221521
// for (var p in o) {
15231522
// /*body*/
15241523
// }
15251524
//
15261525
// [intermediate]
1527-
// .local _a, _b, _i
1528-
// _a = [];
1529-
// for (_b in o) _a.push(_b);
1526+
// .local _b, _a, _c, _i
1527+
// _b = [];
1528+
// _a = o;
1529+
// for (_c in _a) _b.push(_c);
15301530
// _i = 0;
15311531
// .loop incrementLabel, endLoopLabel
15321532
// .mark conditionLabel
1533-
// .brfalse endLoopLabel, (_i < _a.length)
1534-
// p = _a[_i];
1533+
// .brfalse endLoopLabel, (_i < _b.length)
1534+
// _c = _b[_i];
1535+
// .brfalse incrementLabel, (_c in _a)
1536+
// p = _c;
15351537
// /*body*/
15361538
// .mark incrementLabel
1537-
// _b++;
1539+
// _c++;
15381540
// .br conditionLabel
15391541
// .endloop
15401542
// .mark endLoopLabel
15411543

1542-
const keysArray = declareLocal(); // _a
1543-
const key = declareLocal(); // _b
1544+
const obj = declareLocal(); // _a
1545+
const keysArray = declareLocal(); // _b
1546+
const key = declareLocal(); // _c
15441547
const keysIndex = factory.createLoopVariable(); // _i
15451548
const initializer = node.initializer;
15461549
hoistVariableDeclaration(keysIndex);
1550+
emitAssignment(obj, visitNode(node.expression, visitor, isExpression));
15471551
emitAssignment(keysArray, factory.createArrayLiteralExpression());
15481552

15491553
emitStatement(
15501554
factory.createForInStatement(
15511555
key,
1552-
visitNode(node.expression, visitor, isExpression),
1556+
obj,
15531557
factory.createExpressionStatement(
15541558
factory.createCallExpression(
15551559
factory.createPropertyAccessExpression(keysArray, "push"),
@@ -1564,10 +1568,13 @@ namespace ts {
15641568

15651569
const conditionLabel = defineLabel();
15661570
const incrementLabel = defineLabel();
1567-
const endLabel = beginLoopBlock(incrementLabel);
1571+
const endLoopLabel = beginLoopBlock(incrementLabel);
15681572

15691573
markLabel(conditionLabel);
1570-
emitBreakWhenFalse(endLabel, factory.createLessThan(keysIndex, factory.createPropertyAccessExpression(keysArray, "length")));
1574+
emitBreakWhenFalse(endLoopLabel, factory.createLessThan(keysIndex, factory.createPropertyAccessExpression(keysArray, "length")));
1575+
1576+
emitAssignment(key, factory.createElementAccessExpression(keysArray, keysIndex));
1577+
emitBreakWhenFalse(incrementLabel, factory.createBinaryExpression(key, SyntaxKind.InKeyword, obj));
15711578

15721579
let variable: Expression;
15731580
if (isVariableDeclarationList(initializer)) {
@@ -1582,7 +1589,7 @@ namespace ts {
15821589
Debug.assert(isLeftHandSideExpression(variable));
15831590
}
15841591

1585-
emitAssignment(variable, factory.createElementAccessExpression(keysArray, keysIndex));
1592+
emitAssignment(variable, key);
15861593
transformAndEmitEmbeddedStatement(node.statement);
15871594

15881595
markLabel(incrementLabel);

‎tests/baselines/reference/es5-asyncFunctionForInStatements.js

+97-79
Original file line numberDiff line numberDiff line change
@@ -50,22 +50,24 @@ function forInStatement0() {
5050
}
5151
function forInStatement1() {
5252
return __awaiter(this, void 0, void 0, function () {
53-
var _a, _b, _i;
54-
return __generator(this, function (_c) {
55-
switch (_c.label) {
56-
case 0:
57-
_a = [];
58-
return [4 /*yield*/, y];
53+
var _a, _b, _c, _i;
54+
return __generator(this, function (_d) {
55+
switch (_d.label) {
56+
case 0: return [4 /*yield*/, y];
5957
case 1:
60-
for (_b in _c.sent())
61-
_a.push(_b);
58+
_a = _d.sent();
59+
_b = [];
60+
for (_c in _a)
61+
_b.push(_c);
6262
_i = 0;
63-
_c.label = 2;
63+
_d.label = 2;
6464
case 2:
65-
if (!(_i < _a.length)) return [3 /*break*/, 4];
66-
x = _a[_i];
65+
if (!(_i < _b.length)) return [3 /*break*/, 4];
66+
_c = _b[_i];
67+
if (!(_c in _a)) return [3 /*break*/, 3];
68+
x = _c;
6769
z;
68-
_c.label = 3;
70+
_d.label = 3;
6971
case 3:
7072
_i++;
7173
return [3 /*break*/, 2];
@@ -76,22 +78,25 @@ function forInStatement1() {
7678
}
7779
function forInStatement2() {
7880
return __awaiter(this, void 0, void 0, function () {
79-
var _a, _b, _i;
80-
return __generator(this, function (_c) {
81-
switch (_c.label) {
81+
var _a, _b, _c, _i;
82+
return __generator(this, function (_d) {
83+
switch (_d.label) {
8284
case 0:
83-
_a = [];
84-
for (_b in y)
85-
_a.push(_b);
85+
_a = y;
86+
_b = [];
87+
for (_c in _a)
88+
_b.push(_c);
8689
_i = 0;
87-
_c.label = 1;
90+
_d.label = 1;
8891
case 1:
89-
if (!(_i < _a.length)) return [3 /*break*/, 4];
90-
x = _a[_i];
92+
if (!(_i < _b.length)) return [3 /*break*/, 4];
93+
_c = _b[_i];
94+
if (!(_c in _a)) return [3 /*break*/, 3];
95+
x = _c;
9196
return [4 /*yield*/, z];
9297
case 2:
93-
_c.sent();
94-
_c.label = 3;
98+
_d.sent();
99+
_d.label = 3;
95100
case 3:
96101
_i++;
97102
return [3 /*break*/, 1];
@@ -102,22 +107,25 @@ function forInStatement2() {
102107
}
103108
function forInStatement3() {
104109
return __awaiter(this, void 0, void 0, function () {
105-
var _a, _b, _i;
106-
return __generator(this, function (_c) {
107-
switch (_c.label) {
110+
var _a, _b, _c, _i;
111+
return __generator(this, function (_d) {
112+
switch (_d.label) {
108113
case 0:
109-
_a = [];
110-
for (_b in y)
111-
_a.push(_b);
114+
_a = y;
115+
_b = [];
116+
for (_c in _a)
117+
_b.push(_c);
112118
_i = 0;
113-
_c.label = 1;
119+
_d.label = 1;
114120
case 1:
115-
if (!(_i < _a.length)) return [3 /*break*/, 4];
121+
if (!(_i < _b.length)) return [3 /*break*/, 4];
122+
_c = _b[_i];
123+
if (!(_c in _a)) return [3 /*break*/, 3];
116124
return [4 /*yield*/, x];
117125
case 2:
118-
(_c.sent()).a = _a[_i];
126+
(_d.sent()).a = _c;
119127
z;
120-
_c.label = 3;
128+
_d.label = 3;
121129
case 3:
122130
_i++;
123131
return [3 /*break*/, 1];
@@ -128,22 +136,24 @@ function forInStatement3() {
128136
}
129137
function forInStatement4() {
130138
return __awaiter(this, void 0, void 0, function () {
131-
var _a, _b, _i;
132-
return __generator(this, function (_c) {
133-
switch (_c.label) {
134-
case 0:
135-
_a = [];
136-
return [4 /*yield*/, y];
139+
var _a, _b, _c, _i;
140+
return __generator(this, function (_d) {
141+
switch (_d.label) {
142+
case 0: return [4 /*yield*/, y];
137143
case 1:
138-
for (_b in _c.sent())
139-
_a.push(_b);
144+
_a = _d.sent();
145+
_b = [];
146+
for (_c in _a)
147+
_b.push(_c);
140148
_i = 0;
141-
_c.label = 2;
149+
_d.label = 2;
142150
case 2:
143-
if (!(_i < _a.length)) return [3 /*break*/, 4];
144-
x.a = _a[_i];
151+
if (!(_i < _b.length)) return [3 /*break*/, 4];
152+
_c = _b[_i];
153+
if (!(_c in _a)) return [3 /*break*/, 3];
154+
x.a = _c;
145155
z;
146-
_c.label = 3;
156+
_d.label = 3;
147157
case 3:
148158
_i++;
149159
return [3 /*break*/, 2];
@@ -154,22 +164,25 @@ function forInStatement4() {
154164
}
155165
function forInStatement5() {
156166
return __awaiter(this, void 0, void 0, function () {
157-
var _a, _b, _i;
158-
return __generator(this, function (_c) {
159-
switch (_c.label) {
167+
var _a, _b, _c, _i;
168+
return __generator(this, function (_d) {
169+
switch (_d.label) {
160170
case 0:
161-
_a = [];
162-
for (_b in y)
163-
_a.push(_b);
171+
_a = y;
172+
_b = [];
173+
for (_c in _a)
174+
_b.push(_c);
164175
_i = 0;
165-
_c.label = 1;
176+
_d.label = 1;
166177
case 1:
167-
if (!(_i < _a.length)) return [3 /*break*/, 4];
168-
x.a = _a[_i];
178+
if (!(_i < _b.length)) return [3 /*break*/, 4];
179+
_c = _b[_i];
180+
if (!(_c in _a)) return [3 /*break*/, 3];
181+
x.a = _c;
169182
return [4 /*yield*/, z];
170183
case 2:
171-
_c.sent();
172-
_c.label = 3;
184+
_d.sent();
185+
_d.label = 3;
173186
case 3:
174187
_i++;
175188
return [3 /*break*/, 1];
@@ -191,22 +204,24 @@ function forInStatement6() {
191204
}
192205
function forInStatement7() {
193206
return __awaiter(this, void 0, void 0, function () {
194-
var _a, _b, _i, b;
195-
return __generator(this, function (_c) {
196-
switch (_c.label) {
197-
case 0:
198-
_a = [];
199-
return [4 /*yield*/, y];
207+
var _a, _b, _c, _i, b;
208+
return __generator(this, function (_d) {
209+
switch (_d.label) {
210+
case 0: return [4 /*yield*/, y];
200211
case 1:
201-
for (_b in _c.sent())
202-
_a.push(_b);
212+
_a = _d.sent();
213+
_b = [];
214+
for (_c in _a)
215+
_b.push(_c);
203216
_i = 0;
204-
_c.label = 2;
217+
_d.label = 2;
205218
case 2:
206-
if (!(_i < _a.length)) return [3 /*break*/, 4];
207-
b = _a[_i];
219+
if (!(_i < _b.length)) return [3 /*break*/, 4];
220+
_c = _b[_i];
221+
if (!(_c in _a)) return [3 /*break*/, 3];
222+
b = _c;
208223
z;
209-
_c.label = 3;
224+
_d.label = 3;
210225
case 3:
211226
_i++;
212227
return [3 /*break*/, 2];
@@ -217,22 +232,25 @@ function forInStatement7() {
217232
}
218233
function forInStatement8() {
219234
return __awaiter(this, void 0, void 0, function () {
220-
var _a, _b, _i, c;
221-
return __generator(this, function (_c) {
222-
switch (_c.label) {
235+
var _a, _b, _c, _i, c;
236+
return __generator(this, function (_d) {
237+
switch (_d.label) {
223238
case 0:
224-
_a = [];
225-
for (_b in y)
226-
_a.push(_b);
239+
_a = y;
240+
_b = [];
241+
for (_c in _a)
242+
_b.push(_c);
227243
_i = 0;
228-
_c.label = 1;
244+
_d.label = 1;
229245
case 1:
230-
if (!(_i < _a.length)) return [3 /*break*/, 4];
231-
c = _a[_i];
246+
if (!(_i < _b.length)) return [3 /*break*/, 4];
247+
_c = _b[_i];
248+
if (!(_c in _a)) return [3 /*break*/, 3];
249+
c = _c;
232250
return [4 /*yield*/, z];
233251
case 2:
234-
_c.sent();
235-
_c.label = 3;
252+
_d.sent();
253+
_d.label = 3;
236254
case 3:
237255
_i++;
238256
return [3 /*break*/, 1];

0 commit comments

Comments
 (0)
Please sign in to comment.