Skip to content

Commit d9ec08c

Browse files
authored
Merge pull request #16279 from Microsoft/fix15928
Fix for..await emit for es2017
2 parents c179d9a + a05a53b commit d9ec08c

File tree

5 files changed

+276
-5
lines changed

5 files changed

+276
-5
lines changed

src/compiler/transformers/esnext.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -351,8 +351,10 @@ namespace ts {
351351
);
352352
}
353353

354-
function awaitAsYield(expression: Expression) {
355-
return createYield(/*asteriskToken*/ undefined, enclosingFunctionFlags & FunctionFlags.Generator ? createAwaitHelper(context, expression) : expression);
354+
function createDownlevelAwait(expression: Expression) {
355+
return enclosingFunctionFlags & FunctionFlags.Generator
356+
? createYield(/*asteriskToken*/ undefined, createAwaitHelper(context, expression))
357+
: createAwait(expression);
356358
}
357359

358360
function transformForAwaitOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement) {
@@ -385,11 +387,11 @@ namespace ts {
385387
EmitFlags.NoHoisting
386388
),
387389
/*condition*/ createComma(
388-
createAssignment(result, awaitAsYield(callNext)),
390+
createAssignment(result, createDownlevelAwait(callNext)),
389391
createLogicalNot(getDone)
390392
),
391393
/*incrementor*/ undefined,
392-
/*statement*/ convertForOfStatementHead(node, awaitAsYield(getValue))
394+
/*statement*/ convertForOfStatementHead(node, createDownlevelAwait(getValue))
393395
),
394396
/*location*/ node
395397
),
@@ -434,7 +436,7 @@ namespace ts {
434436
createPropertyAccess(iterator, "return")
435437
)
436438
),
437-
createStatement(awaitAsYield(callReturn))
439+
createStatement(createDownlevelAwait(callReturn))
438440
),
439441
EmitFlags.SingleLine
440442
)
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
//// [tests/cases/conformance/emitter/es2017/forAwait/emitter.forAwait.es2017.ts] ////
2+
3+
//// [file1.ts]
4+
async function f1() {
5+
let y: any;
6+
for await (const x of y) {
7+
}
8+
}
9+
//// [file2.ts]
10+
async function f2() {
11+
let x: any, y: any;
12+
for await (x of y) {
13+
}
14+
}
15+
//// [file3.ts]
16+
async function* f3() {
17+
let y: any;
18+
for await (const x of y) {
19+
}
20+
}
21+
//// [file4.ts]
22+
async function* f4() {
23+
let x: any, y: any;
24+
for await (x of y) {
25+
}
26+
}
27+
28+
//// [file1.js]
29+
var __asyncValues = (this && this.__asyncIterator) || function (o) {
30+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
31+
var m = o[Symbol.asyncIterator];
32+
return m ? m.call(o) : typeof __values === "function" ? __values(o) : o[Symbol.iterator]();
33+
};
34+
async function f1() {
35+
let y;
36+
try {
37+
for (var y_1 = __asyncValues(y), y_1_1; y_1_1 = await y_1.next(), !y_1_1.done;) {
38+
const x = await y_1_1.value;
39+
}
40+
}
41+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
42+
finally {
43+
try {
44+
if (y_1_1 && !y_1_1.done && (_a = y_1.return)) await _a.call(y_1);
45+
}
46+
finally { if (e_1) throw e_1.error; }
47+
}
48+
var e_1, _a;
49+
}
50+
//// [file2.js]
51+
var __asyncValues = (this && this.__asyncIterator) || function (o) {
52+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
53+
var m = o[Symbol.asyncIterator];
54+
return m ? m.call(o) : typeof __values === "function" ? __values(o) : o[Symbol.iterator]();
55+
};
56+
async function f2() {
57+
let x, y;
58+
try {
59+
for (var y_1 = __asyncValues(y), y_1_1; y_1_1 = await y_1.next(), !y_1_1.done;) {
60+
x = await y_1_1.value;
61+
}
62+
}
63+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
64+
finally {
65+
try {
66+
if (y_1_1 && !y_1_1.done && (_a = y_1.return)) await _a.call(y_1);
67+
}
68+
finally { if (e_1) throw e_1.error; }
69+
}
70+
var e_1, _a;
71+
}
72+
//// [file3.js]
73+
var __asyncValues = (this && this.__asyncIterator) || function (o) {
74+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
75+
var m = o[Symbol.asyncIterator];
76+
return m ? m.call(o) : typeof __values === "function" ? __values(o) : o[Symbol.iterator]();
77+
};
78+
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
79+
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
80+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
81+
var g = generator.apply(thisArg, _arguments || []), i, q = [];
82+
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
83+
function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
84+
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
85+
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
86+
function fulfill(value) { resume("next", value); }
87+
function reject(value) { resume("throw", value); }
88+
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
89+
};
90+
function f3() {
91+
return __asyncGenerator(this, arguments, function* f3_1() {
92+
let y;
93+
try {
94+
for (var y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), !y_1_1.done;) {
95+
const x = yield __await(y_1_1.value);
96+
}
97+
}
98+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
99+
finally {
100+
try {
101+
if (y_1_1 && !y_1_1.done && (_a = y_1.return)) yield __await(_a.call(y_1));
102+
}
103+
finally { if (e_1) throw e_1.error; }
104+
}
105+
var e_1, _a;
106+
});
107+
}
108+
//// [file4.js]
109+
var __asyncValues = (this && this.__asyncIterator) || function (o) {
110+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
111+
var m = o[Symbol.asyncIterator];
112+
return m ? m.call(o) : typeof __values === "function" ? __values(o) : o[Symbol.iterator]();
113+
};
114+
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
115+
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
116+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
117+
var g = generator.apply(thisArg, _arguments || []), i, q = [];
118+
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
119+
function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
120+
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
121+
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
122+
function fulfill(value) { resume("next", value); }
123+
function reject(value) { resume("throw", value); }
124+
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
125+
};
126+
function f4() {
127+
return __asyncGenerator(this, arguments, function* f4_1() {
128+
let x, y;
129+
try {
130+
for (var y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), !y_1_1.done;) {
131+
x = yield __await(y_1_1.value);
132+
}
133+
}
134+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
135+
finally {
136+
try {
137+
if (y_1_1 && !y_1_1.done && (_a = y_1.return)) yield __await(_a.call(y_1));
138+
}
139+
finally { if (e_1) throw e_1.error; }
140+
}
141+
var e_1, _a;
142+
});
143+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
=== tests/cases/conformance/emitter/es2017/forAwait/file1.ts ===
2+
async function f1() {
3+
>f1 : Symbol(f1, Decl(file1.ts, 0, 0))
4+
5+
let y: any;
6+
>y : Symbol(y, Decl(file1.ts, 1, 7))
7+
8+
for await (const x of y) {
9+
>x : Symbol(x, Decl(file1.ts, 2, 20))
10+
>y : Symbol(y, Decl(file1.ts, 1, 7))
11+
}
12+
}
13+
=== tests/cases/conformance/emitter/es2017/forAwait/file2.ts ===
14+
async function f2() {
15+
>f2 : Symbol(f2, Decl(file2.ts, 0, 0))
16+
17+
let x: any, y: any;
18+
>x : Symbol(x, Decl(file2.ts, 1, 7))
19+
>y : Symbol(y, Decl(file2.ts, 1, 15))
20+
21+
for await (x of y) {
22+
>x : Symbol(x, Decl(file2.ts, 1, 7))
23+
>y : Symbol(y, Decl(file2.ts, 1, 15))
24+
}
25+
}
26+
=== tests/cases/conformance/emitter/es2017/forAwait/file3.ts ===
27+
async function* f3() {
28+
>f3 : Symbol(f3, Decl(file3.ts, 0, 0))
29+
30+
let y: any;
31+
>y : Symbol(y, Decl(file3.ts, 1, 7))
32+
33+
for await (const x of y) {
34+
>x : Symbol(x, Decl(file3.ts, 2, 20))
35+
>y : Symbol(y, Decl(file3.ts, 1, 7))
36+
}
37+
}
38+
=== tests/cases/conformance/emitter/es2017/forAwait/file4.ts ===
39+
async function* f4() {
40+
>f4 : Symbol(f4, Decl(file4.ts, 0, 0))
41+
42+
let x: any, y: any;
43+
>x : Symbol(x, Decl(file4.ts, 1, 7))
44+
>y : Symbol(y, Decl(file4.ts, 1, 15))
45+
46+
for await (x of y) {
47+
>x : Symbol(x, Decl(file4.ts, 1, 7))
48+
>y : Symbol(y, Decl(file4.ts, 1, 15))
49+
}
50+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
=== tests/cases/conformance/emitter/es2017/forAwait/file1.ts ===
2+
async function f1() {
3+
>f1 : () => Promise<void>
4+
5+
let y: any;
6+
>y : any
7+
8+
for await (const x of y) {
9+
>x : any
10+
>y : any
11+
}
12+
}
13+
=== tests/cases/conformance/emitter/es2017/forAwait/file2.ts ===
14+
async function f2() {
15+
>f2 : () => Promise<void>
16+
17+
let x: any, y: any;
18+
>x : any
19+
>y : any
20+
21+
for await (x of y) {
22+
>x : any
23+
>y : any
24+
}
25+
}
26+
=== tests/cases/conformance/emitter/es2017/forAwait/file3.ts ===
27+
async function* f3() {
28+
>f3 : () => AsyncIterableIterator<any>
29+
30+
let y: any;
31+
>y : any
32+
33+
for await (const x of y) {
34+
>x : any
35+
>y : any
36+
}
37+
}
38+
=== tests/cases/conformance/emitter/es2017/forAwait/file4.ts ===
39+
async function* f4() {
40+
>f4 : () => AsyncIterableIterator<any>
41+
42+
let x: any, y: any;
43+
>x : any
44+
>y : any
45+
46+
for await (x of y) {
47+
>x : any
48+
>y : any
49+
}
50+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// @target: es2017
2+
// @lib: esnext
3+
// @filename: file1.ts
4+
async function f1() {
5+
let y: any;
6+
for await (const x of y) {
7+
}
8+
}
9+
// @filename: file2.ts
10+
async function f2() {
11+
let x: any, y: any;
12+
for await (x of y) {
13+
}
14+
}
15+
// @filename: file3.ts
16+
async function* f3() {
17+
let y: any;
18+
for await (const x of y) {
19+
}
20+
}
21+
// @filename: file4.ts
22+
async function* f4() {
23+
let x: any, y: any;
24+
for await (x of y) {
25+
}
26+
}

0 commit comments

Comments
 (0)