diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 6ef6912d650..76a547b11e4 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -73,7 +73,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge const generatorHelper = ` var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, f; + var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, y, f, v, r; function step(op) { if (f) throw new TypeError("Generator is already executing."); while (1) { @@ -83,12 +83,18 @@ var __generator = (this && this.__generator) || function (thisArg, body) { case 2: return { value: op[1], done: true }; } try { - switch (f = 1, op[0]) { + if (f = 1, y) { + v = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]; + if (v && !(v = v.call(y, op[1])).done) return v; + if (y = void 0, v) op[0] = 0, op[1] = v.value; continue; + } + switch (op[0]) { case 0: case 1: sent = op; break; case 4: return _.label++, { value: op[1], done: false }; + case 5: _.label++, y = op[1], op = [0]; continue; case 7: op = _.stack.pop(), _.trys.pop(); continue; default: - var r = _.trys.length > 0 && _.trys[_.trys.length - 1]; + r = _.trys.length > 0 && _.trys[_.trys.length - 1]; if (!r && (op[0] === 6 || op[0] === 2)) { _.done = 1; continue; } if (op[0] === 3 && (!r || (op[1] > r[0] && op[1] < r[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < r[1]) { _.label = r[1], sent = op; break; } @@ -99,8 +105,8 @@ var __generator = (this && this.__generator) || function (thisArg, body) { } op = body.call(thisArg, _); } - catch (e) { op = [6, e]; } - finally { f = 0, sent = void 0; } + catch (e) { op = [6, e], y = void 0; } + finally { f = 0, sent = v = r = void 0; } } } return { diff --git a/src/compiler/transformers/es6.ts b/src/compiler/transformers/es6.ts index 9cb759027e6..44deac04279 100644 --- a/src/compiler/transformers/es6.ts +++ b/src/compiler/transformers/es6.ts @@ -2055,9 +2055,24 @@ namespace ts { if (!isBlock(loopBody)) { loopBody = createBlock([loopBody], /*location*/ undefined, /*multiline*/ true); } + + const isAsyncBlockContainingAwait = + containingNonArrowFunction + && (containingNonArrowFunction.emitFlags & NodeEmitFlags.AsyncFunctionBody) !== 0 + && (node.statement.transformFlags & TransformFlags.ContainsYield) !== 0; + + let loopBodyFlags: NodeEmitFlags = 0; + if (currentState.containsLexicalThis) { + loopBodyFlags |= NodeEmitFlags.CapturesThis; + } + + if (isAsyncBlockContainingAwait) { + loopBodyFlags |= NodeEmitFlags.AsyncFunctionBody; + } + const convertedLoopVariable = createVariableStatement( - /*modifiers*/ undefined, + /*modifiers*/ undefined, createVariableDeclarationList( [ createVariableDeclaration( @@ -2065,16 +2080,14 @@ namespace ts { /*type*/ undefined, setNodeEmitFlags( createFunctionExpression( - /*asteriskToken*/ undefined, + isAsyncBlockContainingAwait ? createToken(SyntaxKind.AsteriskToken) : undefined, /*name*/ undefined, /*typeParameters*/ undefined, loopParameters, /*type*/ undefined, loopBody ), - currentState.containsLexicalThis - ? NodeEmitFlags.CapturesThis - : 0 + loopBodyFlags ) ) ] @@ -2160,7 +2173,7 @@ namespace ts { )); } - const convertedLoopBodyStatements = generateCallToConvertedLoop(functionName, loopParameters, currentState); + const convertedLoopBodyStatements = generateCallToConvertedLoop(functionName, loopParameters, currentState, isAsyncBlockContainingAwait); let loop: IterationStatement; if (convert) { loop = convert(node, convertedLoopBodyStatements); @@ -2173,12 +2186,17 @@ namespace ts { loop = visitEachChild(loop, visitor, context); // set loop statement loop.statement = createBlock( - generateCallToConvertedLoop(functionName, loopParameters, currentState), + convertedLoopBodyStatements, /*location*/ undefined, /*multiline*/ true ); + + // reset and re-aggregate the transform flags + loop.transformFlags = 0; + aggregateTransformFlags(loop); } + statements.push( currentParent.kind === SyntaxKind.LabeledStatement ? createLabel((currentParent).label, loop) @@ -2199,7 +2217,7 @@ namespace ts { } } - function generateCallToConvertedLoop(loopFunctionExpressionName: Identifier, parameters: ParameterDeclaration[], state: ConvertedLoopState): Statement[] { + function generateCallToConvertedLoop(loopFunctionExpressionName: Identifier, parameters: ParameterDeclaration[], state: ConvertedLoopState, isAsyncBlockContainingAwait: boolean): Statement[] { const outerConvertedLoopState = convertedLoopState; const statements: Statement[] = []; @@ -2212,8 +2230,9 @@ namespace ts { !state.labeledNonLocalContinues; const call = createCall(loopFunctionExpressionName, /*typeArguments*/ undefined, map(parameters, p => p.name)); + const callResult = isAsyncBlockContainingAwait ? createYield(createToken(SyntaxKind.AsteriskToken), call) : call; if (isSimpleLoop) { - statements.push(createStatement(call)); + statements.push(createStatement(callResult)); copyOutParameters(state.loopOutParameters, CopyDirection.ToOriginal, statements); } else { @@ -2221,7 +2240,7 @@ namespace ts { const stateVariable = createVariableStatement( /*modifiers*/ undefined, createVariableDeclarationList( - [createVariableDeclaration(loopResultName, /*type*/ undefined, call)] + [createVariableDeclaration(loopResultName, /*type*/ undefined, callResult)] ) ); statements.push(stateVariable); diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index 9a4b567cb80..60e4a0cb546 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -906,7 +906,7 @@ namespace ts { * * @param node The node to visit. */ - function visitYieldExpression(node: YieldExpression) { + function visitYieldExpression(node: YieldExpression): LeftHandSideExpression { // [source] // x = yield a(); // @@ -917,7 +917,14 @@ namespace ts { // NOTE: we are explicitly not handling YieldStar at this time. const resumeLabel = defineLabel(); - emitYield(visitNode(node.expression, visitor, isExpression), /*location*/ node); + const expression = visitNode(node.expression, visitor, isExpression); + if (node.asteriskToken) { + emitYieldStar(expression, /*location*/ node); + } + else { + emitYield(expression, /*location*/ node); + } + markLabel(resumeLabel); return createGeneratorResume(); } @@ -2480,6 +2487,16 @@ namespace ts { emitWorker(OpCode.BreakWhenFalse, [label, condition], location); } + /** + * Emits a YieldStar operation for the provided expression. + * + * @param expression An optional value for the yield operation. + * @param location An optional source map location for the assignment. + */ + function emitYieldStar(expression?: Expression, location?: TextRange): void { + emitWorker(OpCode.YieldStar, [expression], location); + } + /** * Emits a Yield operation for the provided expression. * diff --git a/tests/baselines/reference/asyncAwaitIsolatedModules_es5.js b/tests/baselines/reference/asyncAwaitIsolatedModules_es5.js index 95416f3aaa2..02da40c6c23 100644 --- a/tests/baselines/reference/asyncAwaitIsolatedModules_es5.js +++ b/tests/baselines/reference/asyncAwaitIsolatedModules_es5.js @@ -50,7 +50,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }); }; var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, f; + var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, y, f, v, r; function step(op) { if (f) throw new TypeError("Generator is already executing."); while (1) { @@ -60,12 +60,18 @@ var __generator = (this && this.__generator) || function (thisArg, body) { case 2: return { value: op[1], done: true }; } try { - switch (f = 1, op[0]) { + if (f = 1, y) { + v = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]; + if (v && !(v = v.call(y, op[1])).done) return v; + if (y = void 0, v) op[0] = 0, op[1] = v.value; continue; + } + switch (op[0]) { case 0: case 1: sent = op; break; case 4: return _.label++, { value: op[1], done: false }; + case 5: _.label++, y = op[1], op = [0]; continue; case 7: op = _.stack.pop(), _.trys.pop(); continue; default: - var r = _.trys.length > 0 && _.trys[_.trys.length - 1]; + r = _.trys.length > 0 && _.trys[_.trys.length - 1]; if (!r && (op[0] === 6 || op[0] === 2)) { _.done = 1; continue; } if (op[0] === 3 && (!r || (op[1] > r[0] && op[1] < r[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < r[1]) { _.label = r[1], sent = op; break; } @@ -76,8 +82,8 @@ var __generator = (this && this.__generator) || function (thisArg, body) { } op = body.call(thisArg, _); } - catch (e) { op = [6, e]; } - finally { f = 0, sent = void 0; } + catch (e) { op = [6, e], y = void 0; } + finally { f = 0, sent = v = r = void 0; } } } return { diff --git a/tests/baselines/reference/asyncAwaitWithCapturedBlockScopeVar.js b/tests/baselines/reference/asyncAwaitWithCapturedBlockScopeVar.js new file mode 100644 index 00000000000..49566904ae1 --- /dev/null +++ b/tests/baselines/reference/asyncAwaitWithCapturedBlockScopeVar.js @@ -0,0 +1,182 @@ +//// [asyncAwaitWithCapturedBlockScopeVar.ts] +async function fn1() { + let ar = []; + for (let i = 0; i < 1; i++) { + await 1; + ar.push(() => i); + } +} + +async function fn2() { + let ar = []; + for (let i = 0; i < 1; i++) { + await 1; + ar.push(() => i); + break; + } +} + +async function fn3() { + let ar = []; + for (let i = 0; i < 1; i++) { + await 1; + ar.push(() => i); + continue; + } +} + +async function fn4(): Promise { + let ar = []; + for (let i = 0; i < 1; i++) { + await 1; + ar.push(() => i); + return 1; + } +} + + +//// [asyncAwaitWithCapturedBlockScopeVar.js] +function fn1() { + return __awaiter(this, void 0, void 0, function () { + var ar, _loop_1, i; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + ar = []; + _loop_1 = function (i) { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, 1]; + case 1: + _a.sent(); + ar.push(function () { return i; }); + return [2 /*return*/]; + } + }); + }; + i = 0; + _a.label = 1; + case 1: + if (!(i < 1)) + return [3 /*break*/, 4]; + return [5 /*yield**/, _loop_1(i)]; + case 2: + _a.sent(); + _a.label = 3; + case 3: + i++; + return [3 /*break*/, 1]; + case 4: return [2 /*return*/]; + } + }); + }); +} +function fn2() { + return __awaiter(this, void 0, void 0, function () { + var ar, _loop_2, i, state_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + ar = []; + _loop_2 = function (i) { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, 1]; + case 1: + _a.sent(); + ar.push(function () { return i; }); + return [2 /*return*/, "break"]; + } + }); + }; + i = 0; + _a.label = 1; + case 1: + if (!(i < 1)) + return [3 /*break*/, 4]; + return [5 /*yield**/, _loop_2(i)]; + case 2: + state_1 = _a.sent(); + if (state_1 === "break") + return [3 /*break*/, 4]; + _a.label = 3; + case 3: + i++; + return [3 /*break*/, 1]; + case 4: return [2 /*return*/]; + } + }); + }); +} +function fn3() { + return __awaiter(this, void 0, void 0, function () { + var ar, _loop_3, i; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + ar = []; + _loop_3 = function (i) { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, 1]; + case 1: + _a.sent(); + ar.push(function () { return i; }); + return [2 /*return*/, "continue"]; + } + }); + }; + i = 0; + _a.label = 1; + case 1: + if (!(i < 1)) + return [3 /*break*/, 4]; + return [5 /*yield**/, _loop_3(i)]; + case 2: + _a.sent(); + _a.label = 3; + case 3: + i++; + return [3 /*break*/, 1]; + case 4: return [2 /*return*/]; + } + }); + }); +} +function fn4() { + return __awaiter(this, void 0, void 0, function () { + var ar, _loop_4, i, state_2; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + ar = []; + _loop_4 = function (i) { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, 1]; + case 1: + _a.sent(); + ar.push(function () { return i; }); + return [2 /*return*/, { value: 1 }]; + } + }); + }; + i = 0; + _a.label = 1; + case 1: + if (!(i < 1)) + return [3 /*break*/, 4]; + return [5 /*yield**/, _loop_4(i)]; + case 2: + state_2 = _a.sent(); + if (typeof state_2 === "object") + return [2 /*return*/, state_2.value]; + _a.label = 3; + case 3: + i++; + return [3 /*break*/, 1]; + case 4: return [2 /*return*/]; + } + }); + }); +} diff --git a/tests/baselines/reference/asyncAwaitWithCapturedBlockScopeVar.symbols b/tests/baselines/reference/asyncAwaitWithCapturedBlockScopeVar.symbols new file mode 100644 index 00000000000..12a60509f4f --- /dev/null +++ b/tests/baselines/reference/asyncAwaitWithCapturedBlockScopeVar.symbols @@ -0,0 +1,88 @@ +=== tests/cases/compiler/asyncAwaitWithCapturedBlockScopeVar.ts === +async function fn1() { +>fn1 : Symbol(fn1, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 0, 0)) + + let ar = []; +>ar : Symbol(ar, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 1, 7)) + + for (let i = 0; i < 1; i++) { +>i : Symbol(i, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 2, 12)) +>i : Symbol(i, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 2, 12)) +>i : Symbol(i, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 2, 12)) + + await 1; + ar.push(() => i); +>ar.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>ar : Symbol(ar, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 1, 7)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>i : Symbol(i, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 2, 12)) + } +} + +async function fn2() { +>fn2 : Symbol(fn2, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 6, 1)) + + let ar = []; +>ar : Symbol(ar, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 9, 7)) + + for (let i = 0; i < 1; i++) { +>i : Symbol(i, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 10, 12)) +>i : Symbol(i, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 10, 12)) +>i : Symbol(i, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 10, 12)) + + await 1; + ar.push(() => i); +>ar.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>ar : Symbol(ar, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 9, 7)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>i : Symbol(i, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 10, 12)) + + break; + } +} + +async function fn3() { +>fn3 : Symbol(fn3, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 15, 1)) + + let ar = []; +>ar : Symbol(ar, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 18, 7)) + + for (let i = 0; i < 1; i++) { +>i : Symbol(i, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 19, 12)) +>i : Symbol(i, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 19, 12)) +>i : Symbol(i, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 19, 12)) + + await 1; + ar.push(() => i); +>ar.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>ar : Symbol(ar, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 18, 7)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>i : Symbol(i, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 19, 12)) + + continue; + } +} + +async function fn4(): Promise { +>fn4 : Symbol(fn4, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 24, 1)) +>Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --)) + + let ar = []; +>ar : Symbol(ar, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 27, 7)) + + for (let i = 0; i < 1; i++) { +>i : Symbol(i, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 28, 12)) +>i : Symbol(i, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 28, 12)) +>i : Symbol(i, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 28, 12)) + + await 1; + ar.push(() => i); +>ar.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>ar : Symbol(ar, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 27, 7)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>i : Symbol(i, Decl(asyncAwaitWithCapturedBlockScopeVar.ts, 28, 12)) + + return 1; + } +} + diff --git a/tests/baselines/reference/asyncAwaitWithCapturedBlockScopeVar.types b/tests/baselines/reference/asyncAwaitWithCapturedBlockScopeVar.types new file mode 100644 index 00000000000..424959ddb22 --- /dev/null +++ b/tests/baselines/reference/asyncAwaitWithCapturedBlockScopeVar.types @@ -0,0 +1,129 @@ +=== tests/cases/compiler/asyncAwaitWithCapturedBlockScopeVar.ts === +async function fn1() { +>fn1 : () => Promise + + let ar = []; +>ar : any[] +>[] : undefined[] + + for (let i = 0; i < 1; i++) { +>i : number +>0 : 0 +>i < 1 : boolean +>i : number +>1 : 1 +>i++ : number +>i : number + + await 1; +>await 1 : 1 +>1 : 1 + + ar.push(() => i); +>ar.push(() => i) : number +>ar.push : (...items: any[]) => number +>ar : any[] +>push : (...items: any[]) => number +>() => i : () => number +>i : number + } +} + +async function fn2() { +>fn2 : () => Promise + + let ar = []; +>ar : any[] +>[] : undefined[] + + for (let i = 0; i < 1; i++) { +>i : number +>0 : 0 +>i < 1 : boolean +>i : number +>1 : 1 +>i++ : number +>i : number + + await 1; +>await 1 : 1 +>1 : 1 + + ar.push(() => i); +>ar.push(() => i) : number +>ar.push : (...items: any[]) => number +>ar : any[] +>push : (...items: any[]) => number +>() => i : () => number +>i : number + + break; + } +} + +async function fn3() { +>fn3 : () => Promise + + let ar = []; +>ar : any[] +>[] : undefined[] + + for (let i = 0; i < 1; i++) { +>i : number +>0 : 0 +>i < 1 : boolean +>i : number +>1 : 1 +>i++ : number +>i : number + + await 1; +>await 1 : 1 +>1 : 1 + + ar.push(() => i); +>ar.push(() => i) : number +>ar.push : (...items: any[]) => number +>ar : any[] +>push : (...items: any[]) => number +>() => i : () => number +>i : number + + continue; + } +} + +async function fn4(): Promise { +>fn4 : () => Promise +>Promise : Promise + + let ar = []; +>ar : any[] +>[] : undefined[] + + for (let i = 0; i < 1; i++) { +>i : number +>0 : 0 +>i < 1 : boolean +>i : number +>1 : 1 +>i++ : number +>i : number + + await 1; +>await 1 : 1 +>1 : 1 + + ar.push(() => i); +>ar.push(() => i) : number +>ar.push : (...items: any[]) => number +>ar : any[] +>push : (...items: any[]) => number +>() => i : () => number +>i : number + + return 1; +>1 : 1 + } +} + diff --git a/tests/baselines/reference/asyncAwait_es5.js b/tests/baselines/reference/asyncAwait_es5.js index e148de70ad2..aff57260248 100644 --- a/tests/baselines/reference/asyncAwait_es5.js +++ b/tests/baselines/reference/asyncAwait_es5.js @@ -49,7 +49,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }); }; var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, f; + var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, y, f, v, r; function step(op) { if (f) throw new TypeError("Generator is already executing."); while (1) { @@ -59,12 +59,18 @@ var __generator = (this && this.__generator) || function (thisArg, body) { case 2: return { value: op[1], done: true }; } try { - switch (f = 1, op[0]) { + if (f = 1, y) { + v = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]; + if (v && !(v = v.call(y, op[1])).done) return v; + if (y = void 0, v) op[0] = 0, op[1] = v.value; continue; + } + switch (op[0]) { case 0: case 1: sent = op; break; case 4: return _.label++, { value: op[1], done: false }; + case 5: _.label++, y = op[1], op = [0]; continue; case 7: op = _.stack.pop(), _.trys.pop(); continue; default: - var r = _.trys.length > 0 && _.trys[_.trys.length - 1]; + r = _.trys.length > 0 && _.trys[_.trys.length - 1]; if (!r && (op[0] === 6 || op[0] === 2)) { _.done = 1; continue; } if (op[0] === 3 && (!r || (op[1] > r[0] && op[1] < r[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < r[1]) { _.label = r[1], sent = op; break; } @@ -75,8 +81,8 @@ var __generator = (this && this.__generator) || function (thisArg, body) { } op = body.call(thisArg, _); } - catch (e) { op = [6, e]; } - finally { f = 0, sent = void 0; } + catch (e) { op = [6, e], y = void 0; } + finally { f = 0, sent = v = r = void 0; } } } return { diff --git a/tests/baselines/reference/asyncFunctionNoReturnType.js b/tests/baselines/reference/asyncFunctionNoReturnType.js index a3635b85a09..50f9526ea58 100644 --- a/tests/baselines/reference/asyncFunctionNoReturnType.js +++ b/tests/baselines/reference/asyncFunctionNoReturnType.js @@ -15,7 +15,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }); }; var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, f; + var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, y, f, v, r; function step(op) { if (f) throw new TypeError("Generator is already executing."); while (1) { @@ -25,12 +25,18 @@ var __generator = (this && this.__generator) || function (thisArg, body) { case 2: return { value: op[1], done: true }; } try { - switch (f = 1, op[0]) { + if (f = 1, y) { + v = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]; + if (v && !(v = v.call(y, op[1])).done) return v; + if (y = void 0, v) op[0] = 0, op[1] = v.value; continue; + } + switch (op[0]) { case 0: case 1: sent = op; break; case 4: return _.label++, { value: op[1], done: false }; + case 5: _.label++, y = op[1], op = [0]; continue; case 7: op = _.stack.pop(), _.trys.pop(); continue; default: - var r = _.trys.length > 0 && _.trys[_.trys.length - 1]; + r = _.trys.length > 0 && _.trys[_.trys.length - 1]; if (!r && (op[0] === 6 || op[0] === 2)) { _.done = 1; continue; } if (op[0] === 3 && (!r || (op[1] > r[0] && op[1] < r[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < r[1]) { _.label = r[1], sent = op; break; } @@ -41,8 +47,8 @@ var __generator = (this && this.__generator) || function (thisArg, body) { } op = body.call(thisArg, _); } - catch (e) { op = [6, e]; } - finally { f = 0, sent = void 0; } + catch (e) { op = [6, e], y = void 0; } + finally { f = 0, sent = v = r = void 0; } } } return { diff --git a/tests/baselines/reference/asyncImportedPromise_es5.js b/tests/baselines/reference/asyncImportedPromise_es5.js index 54d1b0fdac8..e96e55b7b97 100644 --- a/tests/baselines/reference/asyncImportedPromise_es5.js +++ b/tests/baselines/reference/asyncImportedPromise_es5.js @@ -35,7 +35,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }); }; var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, f; + var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, y, f, v, r; function step(op) { if (f) throw new TypeError("Generator is already executing."); while (1) { @@ -45,12 +45,18 @@ var __generator = (this && this.__generator) || function (thisArg, body) { case 2: return { value: op[1], done: true }; } try { - switch (f = 1, op[0]) { + if (f = 1, y) { + v = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]; + if (v && !(v = v.call(y, op[1])).done) return v; + if (y = void 0, v) op[0] = 0, op[1] = v.value; continue; + } + switch (op[0]) { case 0: case 1: sent = op; break; case 4: return _.label++, { value: op[1], done: false }; + case 5: _.label++, y = op[1], op = [0]; continue; case 7: op = _.stack.pop(), _.trys.pop(); continue; default: - var r = _.trys.length > 0 && _.trys[_.trys.length - 1]; + r = _.trys.length > 0 && _.trys[_.trys.length - 1]; if (!r && (op[0] === 6 || op[0] === 2)) { _.done = 1; continue; } if (op[0] === 3 && (!r || (op[1] > r[0] && op[1] < r[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < r[1]) { _.label = r[1], sent = op; break; } @@ -61,8 +67,8 @@ var __generator = (this && this.__generator) || function (thisArg, body) { } op = body.call(thisArg, _); } - catch (e) { op = [6, e]; } - finally { f = 0, sent = void 0; } + catch (e) { op = [6, e], y = void 0; } + finally { f = 0, sent = v = r = void 0; } } } return { diff --git a/tests/baselines/reference/asyncMultiFile_es5.js b/tests/baselines/reference/asyncMultiFile_es5.js index 197127c5f10..75473908a75 100644 --- a/tests/baselines/reference/asyncMultiFile_es5.js +++ b/tests/baselines/reference/asyncMultiFile_es5.js @@ -15,7 +15,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }); }; var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, f; + var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, y, f, v, r; function step(op) { if (f) throw new TypeError("Generator is already executing."); while (1) { @@ -25,12 +25,18 @@ var __generator = (this && this.__generator) || function (thisArg, body) { case 2: return { value: op[1], done: true }; } try { - switch (f = 1, op[0]) { + if (f = 1, y) { + v = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]; + if (v && !(v = v.call(y, op[1])).done) return v; + if (y = void 0, v) op[0] = 0, op[1] = v.value; continue; + } + switch (op[0]) { case 0: case 1: sent = op; break; case 4: return _.label++, { value: op[1], done: false }; + case 5: _.label++, y = op[1], op = [0]; continue; case 7: op = _.stack.pop(), _.trys.pop(); continue; default: - var r = _.trys.length > 0 && _.trys[_.trys.length - 1]; + r = _.trys.length > 0 && _.trys[_.trys.length - 1]; if (!r && (op[0] === 6 || op[0] === 2)) { _.done = 1; continue; } if (op[0] === 3 && (!r || (op[1] > r[0] && op[1] < r[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < r[1]) { _.label = r[1], sent = op; break; } @@ -41,8 +47,8 @@ var __generator = (this && this.__generator) || function (thisArg, body) { } op = body.call(thisArg, _); } - catch (e) { op = [6, e]; } - finally { f = 0, sent = void 0; } + catch (e) { op = [6, e], y = void 0; } + finally { f = 0, sent = v = r = void 0; } } } return { diff --git a/tests/baselines/reference/es5-asyncFunction.js b/tests/baselines/reference/es5-asyncFunction.js index 9cb6f1d3674..35080dda75b 100644 --- a/tests/baselines/reference/es5-asyncFunction.js +++ b/tests/baselines/reference/es5-asyncFunction.js @@ -18,7 +18,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }); }; var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, f; + var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, y, f, v, r; function step(op) { if (f) throw new TypeError("Generator is already executing."); while (1) { @@ -28,12 +28,18 @@ var __generator = (this && this.__generator) || function (thisArg, body) { case 2: return { value: op[1], done: true }; } try { - switch (f = 1, op[0]) { + if (f = 1, y) { + v = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]; + if (v && !(v = v.call(y, op[1])).done) return v; + if (y = void 0, v) op[0] = 0, op[1] = v.value; continue; + } + switch (op[0]) { case 0: case 1: sent = op; break; case 4: return _.label++, { value: op[1], done: false }; + case 5: _.label++, y = op[1], op = [0]; continue; case 7: op = _.stack.pop(), _.trys.pop(); continue; default: - var r = _.trys.length > 0 && _.trys[_.trys.length - 1]; + r = _.trys.length > 0 && _.trys[_.trys.length - 1]; if (!r && (op[0] === 6 || op[0] === 2)) { _.done = 1; continue; } if (op[0] === 3 && (!r || (op[1] > r[0] && op[1] < r[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < r[1]) { _.label = r[1], sent = op; break; } @@ -44,8 +50,8 @@ var __generator = (this && this.__generator) || function (thisArg, body) { } op = body.call(thisArg, _); } - catch (e) { op = [6, e]; } - finally { f = 0, sent = void 0; } + catch (e) { op = [6, e], y = void 0; } + finally { f = 0, sent = v = r = void 0; } } } return { diff --git a/tests/baselines/reference/es5-importHelpersAsyncFunctions.js b/tests/baselines/reference/es5-importHelpersAsyncFunctions.js index 0fcd8897018..11a8b1d9d29 100644 --- a/tests/baselines/reference/es5-importHelpersAsyncFunctions.js +++ b/tests/baselines/reference/es5-importHelpersAsyncFunctions.js @@ -38,7 +38,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }); }; var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, f; + var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, y, f, v, r; function step(op) { if (f) throw new TypeError("Generator is already executing."); while (1) { @@ -48,12 +48,18 @@ var __generator = (this && this.__generator) || function (thisArg, body) { case 2: return { value: op[1], done: true }; } try { - switch (f = 1, op[0]) { + if (f = 1, y) { + v = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]; + if (v && !(v = v.call(y, op[1])).done) return v; + if (y = void 0, v) op[0] = 0, op[1] = v.value; continue; + } + switch (op[0]) { case 0: case 1: sent = op; break; case 4: return _.label++, { value: op[1], done: false }; + case 5: _.label++, y = op[1], op = [0]; continue; case 7: op = _.stack.pop(), _.trys.pop(); continue; default: - var r = _.trys.length > 0 && _.trys[_.trys.length - 1]; + r = _.trys.length > 0 && _.trys[_.trys.length - 1]; if (!r && (op[0] === 6 || op[0] === 2)) { _.done = 1; continue; } if (op[0] === 3 && (!r || (op[1] > r[0] && op[1] < r[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < r[1]) { _.label = r[1], sent = op; break; } @@ -64,8 +70,8 @@ var __generator = (this && this.__generator) || function (thisArg, body) { } op = body.call(thisArg, _); } - catch (e) { op = [6, e]; } - finally { f = 0, sent = void 0; } + catch (e) { op = [6, e], y = void 0; } + finally { f = 0, sent = v = r = void 0; } } } return { diff --git a/tests/cases/compiler/asyncAwaitWithCapturedBlockScopeVar.ts b/tests/cases/compiler/asyncAwaitWithCapturedBlockScopeVar.ts new file mode 100644 index 00000000000..6db92f0273d --- /dev/null +++ b/tests/cases/compiler/asyncAwaitWithCapturedBlockScopeVar.ts @@ -0,0 +1,37 @@ +// @target: es5 +// @lib: es6 +// @noEmitHelpers: true +async function fn1() { + let ar = []; + for (let i = 0; i < 1; i++) { + await 1; + ar.push(() => i); + } +} + +async function fn2() { + let ar = []; + for (let i = 0; i < 1; i++) { + await 1; + ar.push(() => i); + break; + } +} + +async function fn3() { + let ar = []; + for (let i = 0; i < 1; i++) { + await 1; + ar.push(() => i); + continue; + } +} + +async function fn4(): Promise { + let ar = []; + for (let i = 0; i < 1; i++) { + await 1; + ar.push(() => i); + return 1; + } +}