Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions src/compiler/transformers/esnext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,10 @@ namespace ts {
);
}

function awaitAsYield(expression: Expression) {
return createYield(/*asteriskToken*/ undefined, enclosingFunctionFlags & FunctionFlags.Generator ? createAwaitHelper(context, expression) : expression);
function createDownlevelAwait(expression: Expression) {
return enclosingFunctionFlags & FunctionFlags.Generator
? createYield(/*asteriskToken*/ undefined, createAwaitHelper(context, expression))
: createAwait(expression);
}

function transformForAwaitOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement) {
Expand Down Expand Up @@ -385,11 +387,11 @@ namespace ts {
EmitFlags.NoHoisting
),
/*condition*/ createComma(
createAssignment(result, awaitAsYield(callNext)),
createAssignment(result, createDownlevelAwait(callNext)),
createLogicalNot(getDone)
),
/*incrementor*/ undefined,
/*statement*/ convertForOfStatementHead(node, awaitAsYield(getValue))
/*statement*/ convertForOfStatementHead(node, createDownlevelAwait(getValue))
),
/*location*/ node
),
Expand Down Expand Up @@ -434,7 +436,7 @@ namespace ts {
createPropertyAccess(iterator, "return")
)
),
createStatement(awaitAsYield(callReturn))
createStatement(createDownlevelAwait(callReturn))
),
EmitFlags.SingleLine
)
Expand Down
143 changes: 143 additions & 0 deletions tests/baselines/reference/emitter.forAwait.es2017.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
//// [tests/cases/conformance/emitter/es2017/forAwait/emitter.forAwait.es2017.ts] ////

//// [file1.ts]
async function f1() {
let y: any;
for await (const x of y) {
}
}
//// [file2.ts]
async function f2() {
let x: any, y: any;
for await (x of y) {
}
}
//// [file3.ts]
async function* f3() {
let y: any;
for await (const x of y) {
}
}
//// [file4.ts]
async function* f4() {
let x: any, y: any;
for await (x of y) {
}
}

//// [file1.js]
var __asyncValues = (this && this.__asyncIterator) || function (o) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var m = o[Symbol.asyncIterator];
return m ? m.call(o) : typeof __values === "function" ? __values(o) : o[Symbol.iterator]();
};
async function f1() {
let y;
try {
for (var y_1 = __asyncValues(y), y_1_1; y_1_1 = await y_1.next(), !y_1_1.done;) {
const x = await y_1_1.value;
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (y_1_1 && !y_1_1.done && (_a = y_1.return)) await _a.call(y_1);
}
finally { if (e_1) throw e_1.error; }
}
var e_1, _a;
}
//// [file2.js]
var __asyncValues = (this && this.__asyncIterator) || function (o) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var m = o[Symbol.asyncIterator];
return m ? m.call(o) : typeof __values === "function" ? __values(o) : o[Symbol.iterator]();
};
async function f2() {
let x, y;
try {
for (var y_1 = __asyncValues(y), y_1_1; y_1_1 = await y_1.next(), !y_1_1.done;) {
x = await y_1_1.value;
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (y_1_1 && !y_1_1.done && (_a = y_1.return)) await _a.call(y_1);
}
finally { if (e_1) throw e_1.error; }
}
var e_1, _a;
}
//// [file3.js]
var __asyncValues = (this && this.__asyncIterator) || function (o) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var m = o[Symbol.asyncIterator];
return m ? m.call(o) : typeof __values === "function" ? __values(o) : o[Symbol.iterator]();
};
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var g = generator.apply(thisArg, _arguments || []), i, q = [];
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
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); }); }; }
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
function fulfill(value) { resume("next", value); }
function reject(value) { resume("throw", value); }
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
};
function f3() {
return __asyncGenerator(this, arguments, function* f3_1() {
let y;
try {
for (var y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), !y_1_1.done;) {
const x = yield __await(y_1_1.value);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (y_1_1 && !y_1_1.done && (_a = y_1.return)) yield __await(_a.call(y_1));
}
finally { if (e_1) throw e_1.error; }
}
var e_1, _a;
});
}
//// [file4.js]
var __asyncValues = (this && this.__asyncIterator) || function (o) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var m = o[Symbol.asyncIterator];
return m ? m.call(o) : typeof __values === "function" ? __values(o) : o[Symbol.iterator]();
};
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var g = generator.apply(thisArg, _arguments || []), i, q = [];
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
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); }); }; }
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
function fulfill(value) { resume("next", value); }
function reject(value) { resume("throw", value); }
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
};
function f4() {
return __asyncGenerator(this, arguments, function* f4_1() {
let x, y;
try {
for (var y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), !y_1_1.done;) {
x = yield __await(y_1_1.value);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (y_1_1 && !y_1_1.done && (_a = y_1.return)) yield __await(_a.call(y_1));
}
finally { if (e_1) throw e_1.error; }
}
var e_1, _a;
});
}
50 changes: 50 additions & 0 deletions tests/baselines/reference/emitter.forAwait.es2017.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
=== tests/cases/conformance/emitter/es2017/forAwait/file1.ts ===
async function f1() {
>f1 : Symbol(f1, Decl(file1.ts, 0, 0))

let y: any;
>y : Symbol(y, Decl(file1.ts, 1, 7))

for await (const x of y) {
>x : Symbol(x, Decl(file1.ts, 2, 20))
>y : Symbol(y, Decl(file1.ts, 1, 7))
}
}
=== tests/cases/conformance/emitter/es2017/forAwait/file2.ts ===
async function f2() {
>f2 : Symbol(f2, Decl(file2.ts, 0, 0))

let x: any, y: any;
>x : Symbol(x, Decl(file2.ts, 1, 7))
>y : Symbol(y, Decl(file2.ts, 1, 15))

for await (x of y) {
>x : Symbol(x, Decl(file2.ts, 1, 7))
>y : Symbol(y, Decl(file2.ts, 1, 15))
}
}
=== tests/cases/conformance/emitter/es2017/forAwait/file3.ts ===
async function* f3() {
>f3 : Symbol(f3, Decl(file3.ts, 0, 0))

let y: any;
>y : Symbol(y, Decl(file3.ts, 1, 7))

for await (const x of y) {
>x : Symbol(x, Decl(file3.ts, 2, 20))
>y : Symbol(y, Decl(file3.ts, 1, 7))
}
}
=== tests/cases/conformance/emitter/es2017/forAwait/file4.ts ===
async function* f4() {
>f4 : Symbol(f4, Decl(file4.ts, 0, 0))

let x: any, y: any;
>x : Symbol(x, Decl(file4.ts, 1, 7))
>y : Symbol(y, Decl(file4.ts, 1, 15))

for await (x of y) {
>x : Symbol(x, Decl(file4.ts, 1, 7))
>y : Symbol(y, Decl(file4.ts, 1, 15))
}
}
50 changes: 50 additions & 0 deletions tests/baselines/reference/emitter.forAwait.es2017.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
=== tests/cases/conformance/emitter/es2017/forAwait/file1.ts ===
async function f1() {
>f1 : () => Promise<void>

let y: any;
>y : any

for await (const x of y) {
>x : any
>y : any
}
}
=== tests/cases/conformance/emitter/es2017/forAwait/file2.ts ===
async function f2() {
>f2 : () => Promise<void>

let x: any, y: any;
>x : any
>y : any

for await (x of y) {
>x : any
>y : any
}
}
=== tests/cases/conformance/emitter/es2017/forAwait/file3.ts ===
async function* f3() {
>f3 : () => AsyncIterableIterator<any>

let y: any;
>y : any

for await (const x of y) {
>x : any
>y : any
}
}
=== tests/cases/conformance/emitter/es2017/forAwait/file4.ts ===
async function* f4() {
>f4 : () => AsyncIterableIterator<any>

let x: any, y: any;
>x : any
>y : any

for await (x of y) {
>x : any
>y : any
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// @target: es2017
// @lib: esnext
// @filename: file1.ts
async function f1() {
let y: any;
for await (const x of y) {
}
}
// @filename: file2.ts
async function f2() {
let x: any, y: any;
for await (x of y) {
}
}
// @filename: file3.ts
async function* f3() {
let y: any;
for await (const x of y) {
}
}
// @filename: file4.ts
async function* f4() {
let x: any, y: any;
for await (x of y) {
}
}