From 973508943785dce164a3c84f2b6fa489e80ede8e Mon Sep 17 00:00:00 2001 From: tm-kwon Date: Tue, 14 Feb 2023 22:39:16 +0900 Subject: [PATCH 1/3] Ensure call return() for an abrupt completion at for await of loop --- src/compiler/transformers/es2018.ts | 11 ++--- .../unittests/evaluation/forAwaitOf.ts | 28 +++++++++++++ .../emitter.forAwait(target=es2015).js | 42 +++++++------------ .../emitter.forAwait(target=es2017).js | 42 +++++++------------ .../reference/emitter.forAwait(target=es5).js | 42 +++++++------------ .../forAwaitPerIterationBindingDownlevel.js | 6 +-- ...ulesAllowJsTopLevelAwait(module=node16).js | 12 ++---- ...esAllowJsTopLevelAwait(module=nodenext).js | 12 ++---- ...nodeModulesTopLevelAwait(module=node16).js | 12 ++---- ...deModulesTopLevelAwait(module=nodenext).js | 12 ++---- .../operationsAvailableOnPromisedType.js | 6 +-- ...velAwait.1(module=es2022,target=es2015).js | 6 +-- ...velAwait.1(module=es2022,target=es2017).js | 6 +-- ...velAwait.1(module=esnext,target=es2015).js | 6 +-- ...velAwait.1(module=esnext,target=es2017).js | 6 +-- ...velAwait.1(module=system,target=es2015).js | 6 +-- ...velAwait.1(module=system,target=es2017).js | 6 +-- 17 files changed, 105 insertions(+), 156 deletions(-) diff --git a/src/compiler/transformers/es2018.ts b/src/compiler/transformers/es2018.ts index 35f28a2ee8d6b..980cc48a3d49c 100644 --- a/src/compiler/transformers/es2018.ts +++ b/src/compiler/transformers/es2018.ts @@ -767,7 +767,7 @@ export function transformES2018(context: TransformationContext): (x: SourceFile const enterNonUserCodeExpression = factory.createAssignment(nonUserCode, factory.createTrue()); const enterNonUserCodeStatement = factory.createExpressionStatement(enterNonUserCodeExpression); - setSourceMapRange(exitNonUserCodeStatement, node.expression); + setSourceMapRange(enterNonUserCodeStatement, node.expression); const statements: Statement[] = []; const binding = createForOfBindingStatement(factory, node.initializer, value); @@ -799,13 +799,8 @@ export function transformES2018(context: TransformationContext): (x: SourceFile return factory.createBlock([ iteratorValueStatement, exitNonUserCodeStatement, - factory.createTryStatement( - body, - /*catchClause*/ undefined, - factory.createBlock([ - enterNonUserCodeStatement - ]) - ) + body, + enterNonUserCodeStatement ]); } diff --git a/src/testRunner/unittests/evaluation/forAwaitOf.ts b/src/testRunner/unittests/evaluation/forAwaitOf.ts index 270d1c234e71f..72e7bb23722b8 100644 --- a/src/testRunner/unittests/evaluation/forAwaitOf.ts +++ b/src/testRunner/unittests/evaluation/forAwaitOf.ts @@ -106,6 +106,34 @@ describe("unittests:: evaluation:: forAwaitOfEvaluation", () => { assert.instanceOf(result.output[2], Promise); }); + it("call return when user code throws (es2015)", async () => { + const result = evaluator.evaluateTypeScript(` + let returnCalled = false; + async function f() { + let i = 0; + const iterator = { + [Symbol.asyncIterator](): AsyncIterableIterator { return this; }, + async next() { + i++; + if (i < 2) return { value: undefined, done: false }; + throw new Error(); + }, + async return() { + returnCalled = true; + } + }; + for await (const item of iterator) { + throw new Error(); + } + } + export async function main() { + try { await f(); } catch { } + return returnCalled; + } + `, { target: ts.ScriptTarget.ES2015 }); + assert.isTrue(await result.main()); + }); + it("don't call return when non-user code throws (es2015)", async () => { const result = evaluator.evaluateTypeScript(` let returnCalled = false; diff --git a/tests/baselines/reference/emitter.forAwait(target=es2015).js b/tests/baselines/reference/emitter.forAwait(target=es2015).js index 7281878c798eb..35e001c89155f 100644 --- a/tests/baselines/reference/emitter.forAwait(target=es2015).js +++ b/tests/baselines/reference/emitter.forAwait(target=es2015).js @@ -75,12 +75,10 @@ function f1() { for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield y_1.next(), _a = y_1_1.done, !_a;) { _c = y_1_1.value; _d = false; - try { + { const x = _c; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -117,12 +115,10 @@ function f2() { for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield y_1.next(), _a = y_1_1.done, !_a;) { _c = y_1_1.value; _d = false; - try { + { x = _c; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -162,12 +158,10 @@ function f3() { for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), _a = y_1_1.done, !_a;) { _c = y_1_1.value; _d = false; - try { + { const x = _c; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -207,12 +201,10 @@ function f4() { for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), _a = y_1_1.done, !_a;) { _c = y_1_1.value; _d = false; - try { + { x = _c; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -250,13 +242,11 @@ function f5() { outer: for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield y_1.next(), _a = y_1_1.done, !_a;) { _c = y_1_1.value; _d = false; - try { + { const x = _c; continue outer; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -297,13 +287,11 @@ function f6() { outer: for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), _a = y_1_1.done, !_a;) { _c = y_1_1.value; _d = false; - try { + { const x = _c; continue outer; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -345,12 +333,10 @@ function f7() { for (var _d = true, y_1 = (e_1 = void 0, __asyncValues(y)), y_1_1; y_1_1 = yield __await(y_1.next()), _a = y_1_1.done, !_a;) { _c = y_1_1.value; _d = false; - try { + { const x = _c; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } diff --git a/tests/baselines/reference/emitter.forAwait(target=es2017).js b/tests/baselines/reference/emitter.forAwait(target=es2017).js index d1abbe9a92429..463f15a322402 100644 --- a/tests/baselines/reference/emitter.forAwait(target=es2017).js +++ b/tests/baselines/reference/emitter.forAwait(target=es2017).js @@ -65,12 +65,10 @@ async function f1() { for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = await y_1.next(), _a = y_1_1.done, !_a;) { _c = y_1_1.value; _d = false; - try { + { const x = _c; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -96,12 +94,10 @@ async function f2() { for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = await y_1.next(), _a = y_1_1.done, !_a;) { _c = y_1_1.value; _d = false; - try { + { x = _c; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -140,12 +136,10 @@ function f3() { for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), _a = y_1_1.done, !_a;) { _c = y_1_1.value; _d = false; - try { + { const x = _c; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -185,12 +179,10 @@ function f4() { for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), _a = y_1_1.done, !_a;) { _c = y_1_1.value; _d = false; - try { + { x = _c; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -218,13 +210,11 @@ async function f5() { outer: for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = await y_1.next(), _a = y_1_1.done, !_a;) { _c = y_1_1.value; _d = false; - try { + { const x = _c; continue outer; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -264,13 +254,11 @@ function f6() { outer: for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), _a = y_1_1.done, !_a;) { _c = y_1_1.value; _d = false; - try { + { const x = _c; continue outer; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -312,12 +300,10 @@ function f7() { for (var _d = true, y_1 = (e_1 = void 0, __asyncValues(y)), y_1_1; y_1_1 = yield __await(y_1.next()), _a = y_1_1.done, !_a;) { _c = y_1_1.value; _d = false; - try { + { const x = _c; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } diff --git a/tests/baselines/reference/emitter.forAwait(target=es5).js b/tests/baselines/reference/emitter.forAwait(target=es5).js index d8bf8898381a5..c5f25cdd716ae 100644 --- a/tests/baselines/reference/emitter.forAwait(target=es5).js +++ b/tests/baselines/reference/emitter.forAwait(target=es5).js @@ -109,12 +109,10 @@ function f1() { if (!(y_1_1 = _e.sent(), _a = y_1_1.done, !_a)) return [3 /*break*/, 4]; _c = y_1_1.value; _d = false; - try { + { x = _c; } - finally { - _d = true; - } + _d = true; _e.label = 3; case 3: return [3 /*break*/, 1]; case 4: return [3 /*break*/, 11]; @@ -198,12 +196,10 @@ function f2() { if (!(y_1_1 = _e.sent(), _a = y_1_1.done, !_a)) return [3 /*break*/, 4]; _c = y_1_1.value; _d = false; - try { + { x = _c; } - finally { - _d = true; - } + _d = true; _e.label = 3; case 3: return [3 /*break*/, 1]; case 4: return [3 /*break*/, 11]; @@ -290,12 +286,10 @@ function f3() { if (!(y_1_1 = _e.sent(), _b = y_1_1.done, !_b)) return [3 /*break*/, 4]; _d = y_1_1.value; _a = false; - try { + { x = _d; } - finally { - _a = true; - } + _a = true; _e.label = 3; case 3: return [3 /*break*/, 1]; case 4: return [3 /*break*/, 11]; @@ -382,12 +376,10 @@ function f4() { if (!(y_1_1 = _e.sent(), _b = y_1_1.done, !_b)) return [3 /*break*/, 4]; _d = y_1_1.value; _a = false; - try { + { x = _d; } - finally { - _a = true; - } + _a = true; _e.label = 3; case 3: return [3 /*break*/, 1]; case 4: return [3 /*break*/, 11]; @@ -472,13 +464,11 @@ function f5() { if (!(y_1_1 = _e.sent(), _a = y_1_1.done, !_a)) return [3 /*break*/, 4]; _c = y_1_1.value; _d = false; - try { + { x = _c; return [3 /*break*/, 3]; } - finally { - _d = true; - } + _d = true; _e.label = 3; case 3: return [3 /*break*/, 1]; case 4: return [3 /*break*/, 11]; @@ -566,13 +556,11 @@ function f6() { if (!(y_1_1 = _e.sent(), _b = y_1_1.done, !_b)) return [3 /*break*/, 4]; _d = y_1_1.value; _a = false; - try { + { x = _d; return [3 /*break*/, 3]; } - finally { - _a = true; - } + _a = true; _e.label = 3; case 3: return [3 /*break*/, 1]; case 4: return [3 /*break*/, 11]; @@ -660,12 +648,10 @@ function f7() { if (!(y_1_1 = _e.sent(), _b = y_1_1.done, !_b)) return [3 /*break*/, 4]; _d = y_1_1.value; _a = false; - try { + { x = _d; } - finally { - _a = true; - } + _a = true; _e.label = 3; case 3: return [3 /*break*/, 1]; case 4: return [3 /*break*/, 11]; diff --git a/tests/baselines/reference/forAwaitPerIterationBindingDownlevel.js b/tests/baselines/reference/forAwaitPerIterationBindingDownlevel.js index 0c1fd96d2dd04..69367bfdc14a1 100644 --- a/tests/baselines/reference/forAwaitPerIterationBindingDownlevel.js +++ b/tests/baselines/reference/forAwaitPerIterationBindingDownlevel.js @@ -114,7 +114,7 @@ var log = console.log; _loop_1 = function () { _f = _c.value; _a = false; - try { + { var outer = _f; log("I'm loop ".concat(outer)); (function () { return __awaiter(_this, void 0, void 0, function () { @@ -137,9 +137,7 @@ var log = console.log; }); }); })(); } - finally { - _a = true; - } + _a = true; }; _a = true, _b = __asyncValues(gen()); _g.label = 1; diff --git a/tests/baselines/reference/nodeModulesAllowJsTopLevelAwait(module=node16).js b/tests/baselines/reference/nodeModulesAllowJsTopLevelAwait(module=node16).js index 835db86b366c8..e565bd23a34e6 100644 --- a/tests/baselines/reference/nodeModulesAllowJsTopLevelAwait(module=node16).js +++ b/tests/baselines/reference/nodeModulesAllowJsTopLevelAwait(module=node16).js @@ -40,12 +40,10 @@ try { for (var _d = true, _e = __asyncValues([]), _f; _f = await _e.next(), _a = _f.done, !_a;) { _c = _f.value; _d = false; - try { + { var y = _c; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -71,12 +69,10 @@ try { for (var _d = true, _e = __asyncValues([]), _f; _f = await _e.next(), _a = _f.done, !_a;) { _c = _f.value; _d = false; - try { + { var y = _c; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } diff --git a/tests/baselines/reference/nodeModulesAllowJsTopLevelAwait(module=nodenext).js b/tests/baselines/reference/nodeModulesAllowJsTopLevelAwait(module=nodenext).js index 835db86b366c8..e565bd23a34e6 100644 --- a/tests/baselines/reference/nodeModulesAllowJsTopLevelAwait(module=nodenext).js +++ b/tests/baselines/reference/nodeModulesAllowJsTopLevelAwait(module=nodenext).js @@ -40,12 +40,10 @@ try { for (var _d = true, _e = __asyncValues([]), _f; _f = await _e.next(), _a = _f.done, !_a;) { _c = _f.value; _d = false; - try { + { var y = _c; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -71,12 +69,10 @@ try { for (var _d = true, _e = __asyncValues([]), _f; _f = await _e.next(), _a = _f.done, !_a;) { _c = _f.value; _d = false; - try { + { var y = _c; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } diff --git a/tests/baselines/reference/nodeModulesTopLevelAwait(module=node16).js b/tests/baselines/reference/nodeModulesTopLevelAwait(module=node16).js index a609845caa396..e4899288e2438 100644 --- a/tests/baselines/reference/nodeModulesTopLevelAwait(module=node16).js +++ b/tests/baselines/reference/nodeModulesTopLevelAwait(module=node16).js @@ -40,12 +40,10 @@ try { for (var _d = true, _e = __asyncValues([]), _f; _f = await _e.next(), _a = _f.done, !_a;) { _c = _f.value; _d = false; - try { + { var y = _c; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -71,12 +69,10 @@ try { for (var _d = true, _e = __asyncValues([]), _f; _f = await _e.next(), _a = _f.done, !_a;) { _c = _f.value; _d = false; - try { + { var y = _c; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } diff --git a/tests/baselines/reference/nodeModulesTopLevelAwait(module=nodenext).js b/tests/baselines/reference/nodeModulesTopLevelAwait(module=nodenext).js index a609845caa396..e4899288e2438 100644 --- a/tests/baselines/reference/nodeModulesTopLevelAwait(module=nodenext).js +++ b/tests/baselines/reference/nodeModulesTopLevelAwait(module=nodenext).js @@ -40,12 +40,10 @@ try { for (var _d = true, _e = __asyncValues([]), _f; _f = await _e.next(), _a = _f.done, !_a;) { _c = _f.value; _d = false; - try { + { var y = _c; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -71,12 +69,10 @@ try { for (var _d = true, _e = __asyncValues([]), _f; _f = await _e.next(), _a = _f.done, !_a;) { _c = _f.value; _d = false; - try { + { var y = _c; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } diff --git a/tests/baselines/reference/operationsAvailableOnPromisedType.js b/tests/baselines/reference/operationsAvailableOnPromisedType.js index ed380e5941a76..2ff31e67a5059 100644 --- a/tests/baselines/reference/operationsAvailableOnPromisedType.js +++ b/tests/baselines/reference/operationsAvailableOnPromisedType.js @@ -114,12 +114,10 @@ function fn(a, b, c, d, e, f, g) { if (!(c_1_1 = _e.sent(), _b = c_1_1.done, !_b)) return [3 /*break*/, 5]; _d = c_1_1.value; _a = false; - try { + { s = _d; } - finally { - _a = true; - } + _a = true; _e.label = 4; case 4: return [3 /*break*/, 2]; case 5: return [3 /*break*/, 12]; diff --git a/tests/baselines/reference/topLevelAwait.1(module=es2022,target=es2015).js b/tests/baselines/reference/topLevelAwait.1(module=es2022,target=es2015).js index 98481f493ed89..9fa28db58857b 100644 --- a/tests/baselines/reference/topLevelAwait.1(module=es2022,target=es2015).js +++ b/tests/baselines/reference/topLevelAwait.1(module=es2022,target=es2015).js @@ -91,13 +91,11 @@ try { for (var _d = true, arr_1 = __asyncValues(arr), arr_1_1; arr_1_1 = await arr_1.next(), _a = arr_1_1.done, !_a;) { _c = arr_1_1.value; _d = false; - try { + { const item = _c; item; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } diff --git a/tests/baselines/reference/topLevelAwait.1(module=es2022,target=es2017).js b/tests/baselines/reference/topLevelAwait.1(module=es2022,target=es2017).js index 98481f493ed89..9fa28db58857b 100644 --- a/tests/baselines/reference/topLevelAwait.1(module=es2022,target=es2017).js +++ b/tests/baselines/reference/topLevelAwait.1(module=es2022,target=es2017).js @@ -91,13 +91,11 @@ try { for (var _d = true, arr_1 = __asyncValues(arr), arr_1_1; arr_1_1 = await arr_1.next(), _a = arr_1_1.done, !_a;) { _c = arr_1_1.value; _d = false; - try { + { const item = _c; item; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } diff --git a/tests/baselines/reference/topLevelAwait.1(module=esnext,target=es2015).js b/tests/baselines/reference/topLevelAwait.1(module=esnext,target=es2015).js index 98481f493ed89..9fa28db58857b 100644 --- a/tests/baselines/reference/topLevelAwait.1(module=esnext,target=es2015).js +++ b/tests/baselines/reference/topLevelAwait.1(module=esnext,target=es2015).js @@ -91,13 +91,11 @@ try { for (var _d = true, arr_1 = __asyncValues(arr), arr_1_1; arr_1_1 = await arr_1.next(), _a = arr_1_1.done, !_a;) { _c = arr_1_1.value; _d = false; - try { + { const item = _c; item; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } diff --git a/tests/baselines/reference/topLevelAwait.1(module=esnext,target=es2017).js b/tests/baselines/reference/topLevelAwait.1(module=esnext,target=es2017).js index 98481f493ed89..9fa28db58857b 100644 --- a/tests/baselines/reference/topLevelAwait.1(module=esnext,target=es2017).js +++ b/tests/baselines/reference/topLevelAwait.1(module=esnext,target=es2017).js @@ -91,13 +91,11 @@ try { for (var _d = true, arr_1 = __asyncValues(arr), arr_1_1; arr_1_1 = await arr_1.next(), _a = arr_1_1.done, !_a;) { _c = arr_1_1.value; _d = false; - try { + { const item = _c; item; } - finally { - _d = true; - } + _d = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } diff --git a/tests/baselines/reference/topLevelAwait.1(module=system,target=es2015).js b/tests/baselines/reference/topLevelAwait.1(module=system,target=es2015).js index 71d9ac2e23794..6e7b77c35eca5 100644 --- a/tests/baselines/reference/topLevelAwait.1(module=system,target=es2015).js +++ b/tests/baselines/reference/topLevelAwait.1(module=system,target=es2015).js @@ -96,13 +96,11 @@ System.register([], function (exports_1, context_1) { for (var _a = true, arr_1 = __asyncValues(arr), arr_1_1; arr_1_1 = await arr_1.next(), _a = arr_1_1.done, !_a;) { _c = arr_1_1.value; _a = false; - try { + { const item = _c; item; } - finally { - _a = true; - } + _a = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } diff --git a/tests/baselines/reference/topLevelAwait.1(module=system,target=es2017).js b/tests/baselines/reference/topLevelAwait.1(module=system,target=es2017).js index 71d9ac2e23794..6e7b77c35eca5 100644 --- a/tests/baselines/reference/topLevelAwait.1(module=system,target=es2017).js +++ b/tests/baselines/reference/topLevelAwait.1(module=system,target=es2017).js @@ -96,13 +96,11 @@ System.register([], function (exports_1, context_1) { for (var _a = true, arr_1 = __asyncValues(arr), arr_1_1; arr_1_1 = await arr_1.next(), _a = arr_1_1.done, !_a;) { _c = arr_1_1.value; _a = false; - try { + { const item = _c; item; } - finally { - _a = true; - } + _a = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } From 287e104ded1241dc6a022cbcfd7f218e7304b508 Mon Sep 17 00:00:00 2001 From: niceandneat Date: Sun, 30 Apr 2023 00:05:03 +0900 Subject: [PATCH 2/3] Set non-user code flag at incrementor to make `continue` work again. --- src/compiler/transformers/es2018.ts | 28 ++------ .../unittests/evaluation/forAwaitOf.ts | 28 ++++++++ .../emitter.forAwait(target=es2015).js | 53 +++++---------- .../emitter.forAwait(target=es2017).js | 53 +++++---------- .../reference/emitter.forAwait(target=es5).js | 65 ++++++++----------- .../forAwaitPerIterationBindingDownlevel.js | 49 +++++++------- ...ulesAllowJsTopLevelAwait(module=node16).js | 14 ++-- ...esAllowJsTopLevelAwait(module=nodenext).js | 14 ++-- ...nodeModulesTopLevelAwait(module=node16).js | 14 ++-- ...deModulesTopLevelAwait(module=nodenext).js | 14 ++-- .../operationsAvailableOnPromisedType.js | 9 ++- ...velAwait.1(module=es2022,target=es2015).js | 9 +-- ...velAwait.1(module=es2022,target=es2017).js | 9 +-- ...velAwait.1(module=esnext,target=es2015).js | 9 +-- ...velAwait.1(module=esnext,target=es2017).js | 9 +-- ...velAwait.1(module=system,target=es2015).js | 9 +-- ...velAwait.1(module=system,target=es2017).js | 9 +-- 17 files changed, 156 insertions(+), 239 deletions(-) diff --git a/src/compiler/transformers/es2018.ts b/src/compiler/transformers/es2018.ts index 980cc48a3d49c..db141572e5d13 100644 --- a/src/compiler/transformers/es2018.ts +++ b/src/compiler/transformers/es2018.ts @@ -765,43 +765,27 @@ export function transformES2018(context: TransformationContext): (x: SourceFile const exitNonUserCodeStatement = factory.createExpressionStatement(exitNonUserCodeExpression); setSourceMapRange(exitNonUserCodeStatement, node.expression); - const enterNonUserCodeExpression = factory.createAssignment(nonUserCode, factory.createTrue()); - const enterNonUserCodeStatement = factory.createExpressionStatement(enterNonUserCodeExpression); - setSourceMapRange(enterNonUserCodeStatement, node.expression); - - const statements: Statement[] = []; + const statements: Statement[] = [iteratorValueStatement, exitNonUserCodeStatement]; const binding = createForOfBindingStatement(factory, node.initializer, value); statements.push(visitNode(binding, visitor, isStatement)); - let bodyLocation: TextRange | undefined; let statementsLocation: TextRange | undefined; const statement = visitIterationBody(node.statement, visitor, context); if (isBlock(statement)) { addRange(statements, statement.statements); - bodyLocation = statement; statementsLocation = statement.statements; } else { statements.push(statement); } - const body = setEmitFlags( - setTextRange( - factory.createBlock( - setTextRange(factory.createNodeArray(statements), statementsLocation), - /*multiLine*/ true - ), - bodyLocation + return setEmitFlags( + factory.createBlock( + setTextRange(factory.createNodeArray(statements), statementsLocation), + /*multiLine*/ true ), EmitFlags.NoSourceMap | EmitFlags.NoTokenSourceMaps ); - - return factory.createBlock([ - iteratorValueStatement, - exitNonUserCodeStatement, - body, - enterNonUserCodeStatement - ]); } function createDownlevelAwait(expression: Expression) { @@ -852,7 +836,7 @@ export function transformES2018(context: TransformationContext): (x: SourceFile factory.createAssignment(done, getDone), factory.createLogicalNot(done) ]), - /*incrementor*/ undefined, + /*incrementor*/ factory.createAssignment(nonUserCode, factory.createTrue()), /*statement*/ convertForOfStatementHead(node, getValue, nonUserCode) ), /*location*/ node diff --git a/src/testRunner/unittests/evaluation/forAwaitOf.ts b/src/testRunner/unittests/evaluation/forAwaitOf.ts index 72e7bb23722b8..7e4acc96ecb8f 100644 --- a/src/testRunner/unittests/evaluation/forAwaitOf.ts +++ b/src/testRunner/unittests/evaluation/forAwaitOf.ts @@ -134,6 +134,34 @@ describe("unittests:: evaluation:: forAwaitOfEvaluation", () => { assert.isTrue(await result.main()); }); + it("don't call return when user code continue (es2015)", async () => { + const result = evaluator.evaluateTypeScript(` + let returnCalled = false; + async function f() { + let i = 0; + const iterator = { + [Symbol.asyncIterator](): AsyncIterableIterator { return this; }, + async next() { + i++; + if (i < 2) return { value: undefined, done: false }; + throw new Error(); + }, + async return() { + returnCalled = true; + } + }; + for await (const item of iterator) { + continue; + } + } + export async function main() { + try { await f(); } catch { } + return returnCalled; + } + `, { target: ts.ScriptTarget.ES2015 }); + assert.isFalse(await result.main()); + }); + it("don't call return when non-user code throws (es2015)", async () => { const result = evaluator.evaluateTypeScript(` let returnCalled = false; diff --git a/tests/baselines/reference/emitter.forAwait(target=es2015).js b/tests/baselines/reference/emitter.forAwait(target=es2015).js index 35e001c89155f..dccf5e8a179d2 100644 --- a/tests/baselines/reference/emitter.forAwait(target=es2015).js +++ b/tests/baselines/reference/emitter.forAwait(target=es2015).js @@ -72,13 +72,10 @@ function f1() { return __awaiter(this, void 0, void 0, function* () { let y; try { - for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield y_1.next(), _a = y_1_1.done, !_a;) { + for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield y_1.next(), _a = y_1_1.done, !_a; _d = true) { _c = y_1_1.value; _d = false; - { - const x = _c; - } - _d = true; + const x = _c; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -112,13 +109,10 @@ function f2() { return __awaiter(this, void 0, void 0, function* () { let x, y; try { - for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield y_1.next(), _a = y_1_1.done, !_a;) { + for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield y_1.next(), _a = y_1_1.done, !_a; _d = true) { _c = y_1_1.value; _d = false; - { - x = _c; - } - _d = true; + x = _c; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -155,13 +149,10 @@ function f3() { var _a, e_1, _b, _c; let y; try { - for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), _a = y_1_1.done, !_a;) { + for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), _a = y_1_1.done, !_a; _d = true) { _c = y_1_1.value; _d = false; - { - const x = _c; - } - _d = true; + const x = _c; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -198,13 +189,10 @@ function f4() { var _a, e_1, _b, _c; let x, y; try { - for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), _a = y_1_1.done, !_a;) { + for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), _a = y_1_1.done, !_a; _d = true) { _c = y_1_1.value; _d = false; - { - x = _c; - } - _d = true; + x = _c; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -239,14 +227,11 @@ function f5() { return __awaiter(this, void 0, void 0, function* () { let y; try { - outer: for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield y_1.next(), _a = y_1_1.done, !_a;) { + outer: for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield y_1.next(), _a = y_1_1.done, !_a; _d = true) { _c = y_1_1.value; _d = false; - { - const x = _c; - continue outer; - } - _d = true; + const x = _c; + continue outer; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -284,14 +269,11 @@ function f6() { var _a, e_1, _b, _c; let y; try { - outer: for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), _a = y_1_1.done, !_a;) { + outer: for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), _a = y_1_1.done, !_a; _d = true) { _c = y_1_1.value; _d = false; - { - const x = _c; - continue outer; - } - _d = true; + const x = _c; + continue outer; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -330,13 +312,10 @@ function f7() { let y; for (;;) { try { - for (var _d = true, y_1 = (e_1 = void 0, __asyncValues(y)), y_1_1; y_1_1 = yield __await(y_1.next()), _a = y_1_1.done, !_a;) { + for (var _d = true, y_1 = (e_1 = void 0, __asyncValues(y)), y_1_1; y_1_1 = yield __await(y_1.next()), _a = y_1_1.done, !_a; _d = true) { _c = y_1_1.value; _d = false; - { - const x = _c; - } - _d = true; + const x = _c; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } diff --git a/tests/baselines/reference/emitter.forAwait(target=es2017).js b/tests/baselines/reference/emitter.forAwait(target=es2017).js index 463f15a322402..b05a5a8f95161 100644 --- a/tests/baselines/reference/emitter.forAwait(target=es2017).js +++ b/tests/baselines/reference/emitter.forAwait(target=es2017).js @@ -62,13 +62,10 @@ async function f1() { var _a, e_1, _b, _c; let y; try { - for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = await y_1.next(), _a = y_1_1.done, !_a;) { + for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = await y_1.next(), _a = y_1_1.done, !_a; _d = true) { _c = y_1_1.value; _d = false; - { - const x = _c; - } - _d = true; + const x = _c; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -91,13 +88,10 @@ async function f2() { var _a, e_1, _b, _c; let x, y; try { - for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = await y_1.next(), _a = y_1_1.done, !_a;) { + for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = await y_1.next(), _a = y_1_1.done, !_a; _d = true) { _c = y_1_1.value; _d = false; - { - x = _c; - } - _d = true; + x = _c; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -133,13 +127,10 @@ function f3() { var _a, e_1, _b, _c; let y; try { - for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), _a = y_1_1.done, !_a;) { + for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), _a = y_1_1.done, !_a; _d = true) { _c = y_1_1.value; _d = false; - { - const x = _c; - } - _d = true; + const x = _c; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -176,13 +167,10 @@ function f4() { var _a, e_1, _b, _c; let x, y; try { - for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), _a = y_1_1.done, !_a;) { + for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), _a = y_1_1.done, !_a; _d = true) { _c = y_1_1.value; _d = false; - { - x = _c; - } - _d = true; + x = _c; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -207,14 +195,11 @@ async function f5() { var _a, e_1, _b, _c; let y; try { - outer: for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = await y_1.next(), _a = y_1_1.done, !_a;) { + outer: for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = await y_1.next(), _a = y_1_1.done, !_a; _d = true) { _c = y_1_1.value; _d = false; - { - const x = _c; - continue outer; - } - _d = true; + const x = _c; + continue outer; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -251,14 +236,11 @@ function f6() { var _a, e_1, _b, _c; let y; try { - outer: for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), _a = y_1_1.done, !_a;) { + outer: for (var _d = true, y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), _a = y_1_1.done, !_a; _d = true) { _c = y_1_1.value; _d = false; - { - const x = _c; - continue outer; - } - _d = true; + const x = _c; + continue outer; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -297,13 +279,10 @@ function f7() { let y; for (;;) { try { - for (var _d = true, y_1 = (e_1 = void 0, __asyncValues(y)), y_1_1; y_1_1 = yield __await(y_1.next()), _a = y_1_1.done, !_a;) { + for (var _d = true, y_1 = (e_1 = void 0, __asyncValues(y)), y_1_1; y_1_1 = yield __await(y_1.next()), _a = y_1_1.done, !_a; _d = true) { _c = y_1_1.value; _d = false; - { - const x = _c; - } - _d = true; + const x = _c; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } diff --git a/tests/baselines/reference/emitter.forAwait(target=es5).js b/tests/baselines/reference/emitter.forAwait(target=es5).js index c5f25cdd716ae..2ac0550142693 100644 --- a/tests/baselines/reference/emitter.forAwait(target=es5).js +++ b/tests/baselines/reference/emitter.forAwait(target=es5).js @@ -109,12 +109,11 @@ function f1() { if (!(y_1_1 = _e.sent(), _a = y_1_1.done, !_a)) return [3 /*break*/, 4]; _c = y_1_1.value; _d = false; - { - x = _c; - } - _d = true; + x = _c; _e.label = 3; - case 3: return [3 /*break*/, 1]; + case 3: + _d = true; + return [3 /*break*/, 1]; case 4: return [3 /*break*/, 11]; case 5: e_1_1 = _e.sent(); @@ -196,12 +195,11 @@ function f2() { if (!(y_1_1 = _e.sent(), _a = y_1_1.done, !_a)) return [3 /*break*/, 4]; _c = y_1_1.value; _d = false; - { - x = _c; - } - _d = true; + x = _c; _e.label = 3; - case 3: return [3 /*break*/, 1]; + case 3: + _d = true; + return [3 /*break*/, 1]; case 4: return [3 /*break*/, 11]; case 5: e_1_1 = _e.sent(); @@ -286,12 +284,11 @@ function f3() { if (!(y_1_1 = _e.sent(), _b = y_1_1.done, !_b)) return [3 /*break*/, 4]; _d = y_1_1.value; _a = false; - { - x = _d; - } - _a = true; + x = _d; _e.label = 3; - case 3: return [3 /*break*/, 1]; + case 3: + _a = true; + return [3 /*break*/, 1]; case 4: return [3 /*break*/, 11]; case 5: e_1_1 = _e.sent(); @@ -376,12 +373,11 @@ function f4() { if (!(y_1_1 = _e.sent(), _b = y_1_1.done, !_b)) return [3 /*break*/, 4]; _d = y_1_1.value; _a = false; - { - x = _d; - } - _a = true; + x = _d; _e.label = 3; - case 3: return [3 /*break*/, 1]; + case 3: + _a = true; + return [3 /*break*/, 1]; case 4: return [3 /*break*/, 11]; case 5: e_1_1 = _e.sent(); @@ -464,13 +460,11 @@ function f5() { if (!(y_1_1 = _e.sent(), _a = y_1_1.done, !_a)) return [3 /*break*/, 4]; _c = y_1_1.value; _d = false; - { - x = _c; - return [3 /*break*/, 3]; - } + x = _c; + return [3 /*break*/, 3]; + case 3: _d = true; - _e.label = 3; - case 3: return [3 /*break*/, 1]; + return [3 /*break*/, 1]; case 4: return [3 /*break*/, 11]; case 5: e_1_1 = _e.sent(); @@ -556,13 +550,11 @@ function f6() { if (!(y_1_1 = _e.sent(), _b = y_1_1.done, !_b)) return [3 /*break*/, 4]; _d = y_1_1.value; _a = false; - { - x = _d; - return [3 /*break*/, 3]; - } + x = _d; + return [3 /*break*/, 3]; + case 3: _a = true; - _e.label = 3; - case 3: return [3 /*break*/, 1]; + return [3 /*break*/, 1]; case 4: return [3 /*break*/, 11]; case 5: e_1_1 = _e.sent(); @@ -648,12 +640,11 @@ function f7() { if (!(y_1_1 = _e.sent(), _b = y_1_1.done, !_b)) return [3 /*break*/, 4]; _d = y_1_1.value; _a = false; - { - x = _d; - } - _a = true; + x = _d; _e.label = 3; - case 3: return [3 /*break*/, 1]; + case 3: + _a = true; + return [3 /*break*/, 1]; case 4: return [3 /*break*/, 11]; case 5: e_1_1 = _e.sent(); diff --git a/tests/baselines/reference/forAwaitPerIterationBindingDownlevel.js b/tests/baselines/reference/forAwaitPerIterationBindingDownlevel.js index 69367bfdc14a1..65f3820627cf8 100644 --- a/tests/baselines/reference/forAwaitPerIterationBindingDownlevel.js +++ b/tests/baselines/reference/forAwaitPerIterationBindingDownlevel.js @@ -114,30 +114,27 @@ var log = console.log; _loop_1 = function () { _f = _c.value; _a = false; - { - var outer = _f; - log("I'm loop ".concat(outer)); - (function () { return __awaiter(_this, void 0, void 0, function () { - var inner; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - inner = outer; - return [4 /*yield*/, sleep(2000)]; - case 1: - _a.sent(); - if (inner === outer) { - log("I'm loop ".concat(inner, " and I know I'm loop ").concat(outer)); - } - else { - log("I'm loop ".concat(inner, ", but I think I'm loop ").concat(outer)); - } - return [2 /*return*/]; - } - }); - }); })(); - } - _a = true; + var outer = _f; + log("I'm loop ".concat(outer)); + (function () { return __awaiter(_this, void 0, void 0, function () { + var inner; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + inner = outer; + return [4 /*yield*/, sleep(2000)]; + case 1: + _a.sent(); + if (inner === outer) { + log("I'm loop ".concat(inner, " and I know I'm loop ").concat(outer)); + } + else { + log("I'm loop ".concat(inner, ", but I think I'm loop ").concat(outer)); + } + return [2 /*return*/]; + } + }); + }); })(); }; _a = true, _b = __asyncValues(gen()); _g.label = 1; @@ -146,7 +143,9 @@ var log = console.log; if (!(_c = _g.sent(), _d = _c.done, !_d)) return [3 /*break*/, 4]; _loop_1(); _g.label = 3; - case 3: return [3 /*break*/, 1]; + case 3: + _a = true; + return [3 /*break*/, 1]; case 4: return [3 /*break*/, 11]; case 5: e_1_1 = _g.sent(); diff --git a/tests/baselines/reference/nodeModulesAllowJsTopLevelAwait(module=node16).js b/tests/baselines/reference/nodeModulesAllowJsTopLevelAwait(module=node16).js index e565bd23a34e6..e49885b29c591 100644 --- a/tests/baselines/reference/nodeModulesAllowJsTopLevelAwait(module=node16).js +++ b/tests/baselines/reference/nodeModulesAllowJsTopLevelAwait(module=node16).js @@ -37,13 +37,10 @@ exports.x = void 0; var x = await 1; exports.x = x; try { - for (var _d = true, _e = __asyncValues([]), _f; _f = await _e.next(), _a = _f.done, !_a;) { + for (var _d = true, _e = __asyncValues([]), _f; _f = await _e.next(), _a = _f.done, !_a; _d = true) { _c = _f.value; _d = false; - { - var y = _c; - } - _d = true; + var y = _c; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -66,13 +63,10 @@ var _a, e_1, _b, _c; var x = await 1; export { x }; try { - for (var _d = true, _e = __asyncValues([]), _f; _f = await _e.next(), _a = _f.done, !_a;) { + for (var _d = true, _e = __asyncValues([]), _f; _f = await _e.next(), _a = _f.done, !_a; _d = true) { _c = _f.value; _d = false; - { - var y = _c; - } - _d = true; + var y = _c; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } diff --git a/tests/baselines/reference/nodeModulesAllowJsTopLevelAwait(module=nodenext).js b/tests/baselines/reference/nodeModulesAllowJsTopLevelAwait(module=nodenext).js index e565bd23a34e6..e49885b29c591 100644 --- a/tests/baselines/reference/nodeModulesAllowJsTopLevelAwait(module=nodenext).js +++ b/tests/baselines/reference/nodeModulesAllowJsTopLevelAwait(module=nodenext).js @@ -37,13 +37,10 @@ exports.x = void 0; var x = await 1; exports.x = x; try { - for (var _d = true, _e = __asyncValues([]), _f; _f = await _e.next(), _a = _f.done, !_a;) { + for (var _d = true, _e = __asyncValues([]), _f; _f = await _e.next(), _a = _f.done, !_a; _d = true) { _c = _f.value; _d = false; - { - var y = _c; - } - _d = true; + var y = _c; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -66,13 +63,10 @@ var _a, e_1, _b, _c; var x = await 1; export { x }; try { - for (var _d = true, _e = __asyncValues([]), _f; _f = await _e.next(), _a = _f.done, !_a;) { + for (var _d = true, _e = __asyncValues([]), _f; _f = await _e.next(), _a = _f.done, !_a; _d = true) { _c = _f.value; _d = false; - { - var y = _c; - } - _d = true; + var y = _c; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } diff --git a/tests/baselines/reference/nodeModulesTopLevelAwait(module=node16).js b/tests/baselines/reference/nodeModulesTopLevelAwait(module=node16).js index e4899288e2438..004793e4dc0d8 100644 --- a/tests/baselines/reference/nodeModulesTopLevelAwait(module=node16).js +++ b/tests/baselines/reference/nodeModulesTopLevelAwait(module=node16).js @@ -37,13 +37,10 @@ exports.x = void 0; var x = await 1; exports.x = x; try { - for (var _d = true, _e = __asyncValues([]), _f; _f = await _e.next(), _a = _f.done, !_a;) { + for (var _d = true, _e = __asyncValues([]), _f; _f = await _e.next(), _a = _f.done, !_a; _d = true) { _c = _f.value; _d = false; - { - var y = _c; - } - _d = true; + var y = _c; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -66,13 +63,10 @@ var _a, e_1, _b, _c; var x = await 1; export { x }; try { - for (var _d = true, _e = __asyncValues([]), _f; _f = await _e.next(), _a = _f.done, !_a;) { + for (var _d = true, _e = __asyncValues([]), _f; _f = await _e.next(), _a = _f.done, !_a; _d = true) { _c = _f.value; _d = false; - { - var y = _c; - } - _d = true; + var y = _c; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } diff --git a/tests/baselines/reference/nodeModulesTopLevelAwait(module=nodenext).js b/tests/baselines/reference/nodeModulesTopLevelAwait(module=nodenext).js index e4899288e2438..004793e4dc0d8 100644 --- a/tests/baselines/reference/nodeModulesTopLevelAwait(module=nodenext).js +++ b/tests/baselines/reference/nodeModulesTopLevelAwait(module=nodenext).js @@ -37,13 +37,10 @@ exports.x = void 0; var x = await 1; exports.x = x; try { - for (var _d = true, _e = __asyncValues([]), _f; _f = await _e.next(), _a = _f.done, !_a;) { + for (var _d = true, _e = __asyncValues([]), _f; _f = await _e.next(), _a = _f.done, !_a; _d = true) { _c = _f.value; _d = false; - { - var y = _c; - } - _d = true; + var y = _c; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -66,13 +63,10 @@ var _a, e_1, _b, _c; var x = await 1; export { x }; try { - for (var _d = true, _e = __asyncValues([]), _f; _f = await _e.next(), _a = _f.done, !_a;) { + for (var _d = true, _e = __asyncValues([]), _f; _f = await _e.next(), _a = _f.done, !_a; _d = true) { _c = _f.value; _d = false; - { - var y = _c; - } - _d = true; + var y = _c; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } diff --git a/tests/baselines/reference/operationsAvailableOnPromisedType.js b/tests/baselines/reference/operationsAvailableOnPromisedType.js index 2ff31e67a5059..c9ad39418c204 100644 --- a/tests/baselines/reference/operationsAvailableOnPromisedType.js +++ b/tests/baselines/reference/operationsAvailableOnPromisedType.js @@ -114,12 +114,11 @@ function fn(a, b, c, d, e, f, g) { if (!(c_1_1 = _e.sent(), _b = c_1_1.done, !_b)) return [3 /*break*/, 5]; _d = c_1_1.value; _a = false; - { - s = _d; - } - _a = true; + s = _d; _e.label = 4; - case 4: return [3 /*break*/, 2]; + case 4: + _a = true; + return [3 /*break*/, 2]; case 5: return [3 /*break*/, 12]; case 6: e_1_1 = _e.sent(); diff --git a/tests/baselines/reference/topLevelAwait.1(module=es2022,target=es2015).js b/tests/baselines/reference/topLevelAwait.1(module=es2022,target=es2015).js index 9fa28db58857b..5043115f1da2d 100644 --- a/tests/baselines/reference/topLevelAwait.1(module=es2022,target=es2015).js +++ b/tests/baselines/reference/topLevelAwait.1(module=es2022,target=es2015).js @@ -88,14 +88,11 @@ export { _await as await }; // for-await-of const arr = [Promise.resolve()]; try { - for (var _d = true, arr_1 = __asyncValues(arr), arr_1_1; arr_1_1 = await arr_1.next(), _a = arr_1_1.done, !_a;) { + for (var _d = true, arr_1 = __asyncValues(arr), arr_1_1; arr_1_1 = await arr_1.next(), _a = arr_1_1.done, !_a; _d = true) { _c = arr_1_1.value; _d = false; - { - const item = _c; - item; - } - _d = true; + const item = _c; + item; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } diff --git a/tests/baselines/reference/topLevelAwait.1(module=es2022,target=es2017).js b/tests/baselines/reference/topLevelAwait.1(module=es2022,target=es2017).js index 9fa28db58857b..5043115f1da2d 100644 --- a/tests/baselines/reference/topLevelAwait.1(module=es2022,target=es2017).js +++ b/tests/baselines/reference/topLevelAwait.1(module=es2022,target=es2017).js @@ -88,14 +88,11 @@ export { _await as await }; // for-await-of const arr = [Promise.resolve()]; try { - for (var _d = true, arr_1 = __asyncValues(arr), arr_1_1; arr_1_1 = await arr_1.next(), _a = arr_1_1.done, !_a;) { + for (var _d = true, arr_1 = __asyncValues(arr), arr_1_1; arr_1_1 = await arr_1.next(), _a = arr_1_1.done, !_a; _d = true) { _c = arr_1_1.value; _d = false; - { - const item = _c; - item; - } - _d = true; + const item = _c; + item; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } diff --git a/tests/baselines/reference/topLevelAwait.1(module=esnext,target=es2015).js b/tests/baselines/reference/topLevelAwait.1(module=esnext,target=es2015).js index 9fa28db58857b..5043115f1da2d 100644 --- a/tests/baselines/reference/topLevelAwait.1(module=esnext,target=es2015).js +++ b/tests/baselines/reference/topLevelAwait.1(module=esnext,target=es2015).js @@ -88,14 +88,11 @@ export { _await as await }; // for-await-of const arr = [Promise.resolve()]; try { - for (var _d = true, arr_1 = __asyncValues(arr), arr_1_1; arr_1_1 = await arr_1.next(), _a = arr_1_1.done, !_a;) { + for (var _d = true, arr_1 = __asyncValues(arr), arr_1_1; arr_1_1 = await arr_1.next(), _a = arr_1_1.done, !_a; _d = true) { _c = arr_1_1.value; _d = false; - { - const item = _c; - item; - } - _d = true; + const item = _c; + item; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } diff --git a/tests/baselines/reference/topLevelAwait.1(module=esnext,target=es2017).js b/tests/baselines/reference/topLevelAwait.1(module=esnext,target=es2017).js index 9fa28db58857b..5043115f1da2d 100644 --- a/tests/baselines/reference/topLevelAwait.1(module=esnext,target=es2017).js +++ b/tests/baselines/reference/topLevelAwait.1(module=esnext,target=es2017).js @@ -88,14 +88,11 @@ export { _await as await }; // for-await-of const arr = [Promise.resolve()]; try { - for (var _d = true, arr_1 = __asyncValues(arr), arr_1_1; arr_1_1 = await arr_1.next(), _a = arr_1_1.done, !_a;) { + for (var _d = true, arr_1 = __asyncValues(arr), arr_1_1; arr_1_1 = await arr_1.next(), _a = arr_1_1.done, !_a; _d = true) { _c = arr_1_1.value; _d = false; - { - const item = _c; - item; - } - _d = true; + const item = _c; + item; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } diff --git a/tests/baselines/reference/topLevelAwait.1(module=system,target=es2015).js b/tests/baselines/reference/topLevelAwait.1(module=system,target=es2015).js index 6e7b77c35eca5..e8fae7f268c8c 100644 --- a/tests/baselines/reference/topLevelAwait.1(module=system,target=es2015).js +++ b/tests/baselines/reference/topLevelAwait.1(module=system,target=es2015).js @@ -93,14 +93,11 @@ System.register([], function (exports_1, context_1) { // for-await-of arr = [Promise.resolve()]; try { - for (var _a = true, arr_1 = __asyncValues(arr), arr_1_1; arr_1_1 = await arr_1.next(), _a = arr_1_1.done, !_a;) { + for (var _a = true, arr_1 = __asyncValues(arr), arr_1_1; arr_1_1 = await arr_1.next(), _a = arr_1_1.done, !_a; _a = true) { _c = arr_1_1.value; _a = false; - { - const item = _c; - item; - } - _a = true; + const item = _c; + item; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } diff --git a/tests/baselines/reference/topLevelAwait.1(module=system,target=es2017).js b/tests/baselines/reference/topLevelAwait.1(module=system,target=es2017).js index 6e7b77c35eca5..e8fae7f268c8c 100644 --- a/tests/baselines/reference/topLevelAwait.1(module=system,target=es2017).js +++ b/tests/baselines/reference/topLevelAwait.1(module=system,target=es2017).js @@ -93,14 +93,11 @@ System.register([], function (exports_1, context_1) { // for-await-of arr = [Promise.resolve()]; try { - for (var _a = true, arr_1 = __asyncValues(arr), arr_1_1; arr_1_1 = await arr_1.next(), _a = arr_1_1.done, !_a;) { + for (var _a = true, arr_1 = __asyncValues(arr), arr_1_1; arr_1_1 = await arr_1.next(), _a = arr_1_1.done, !_a; _a = true) { _c = arr_1_1.value; _a = false; - { - const item = _c; - item; - } - _a = true; + const item = _c; + item; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } From a29c2f53b8b02f789ad68ccf3c0fec27f3380da4 Mon Sep 17 00:00:00 2001 From: niceandneat Date: Mon, 1 May 2023 11:30:52 +0900 Subject: [PATCH 3/3] Add test cases for other loop contiditons. --- src/compiler/transformers/es2018.ts | 6 +- .../unittests/evaluation/forAwaitOf.ts | 119 +++++++++++++++++- 2 files changed, 119 insertions(+), 6 deletions(-) diff --git a/src/compiler/transformers/es2018.ts b/src/compiler/transformers/es2018.ts index db141572e5d13..9bcade65617e5 100644 --- a/src/compiler/transformers/es2018.ts +++ b/src/compiler/transformers/es2018.ts @@ -769,22 +769,24 @@ export function transformES2018(context: TransformationContext): (x: SourceFile const binding = createForOfBindingStatement(factory, node.initializer, value); statements.push(visitNode(binding, visitor, isStatement)); + let bodyLocation: TextRange | undefined; let statementsLocation: TextRange | undefined; const statement = visitIterationBody(node.statement, visitor, context); if (isBlock(statement)) { addRange(statements, statement.statements); + bodyLocation = statement; statementsLocation = statement.statements; } else { statements.push(statement); } - return setEmitFlags( + return setTextRange( factory.createBlock( setTextRange(factory.createNodeArray(statements), statementsLocation), /*multiLine*/ true ), - EmitFlags.NoSourceMap | EmitFlags.NoTokenSourceMaps + bodyLocation ); } diff --git a/src/testRunner/unittests/evaluation/forAwaitOf.ts b/src/testRunner/unittests/evaluation/forAwaitOf.ts index 7e4acc96ecb8f..ad5aba9c295f9 100644 --- a/src/testRunner/unittests/evaluation/forAwaitOf.ts +++ b/src/testRunner/unittests/evaluation/forAwaitOf.ts @@ -106,7 +106,82 @@ describe("unittests:: evaluation:: forAwaitOfEvaluation", () => { assert.instanceOf(result.output[2], Promise); }); + it("call return when user code return (es2015)", async () => { + const result = evaluator.evaluateTypeScript(` + let returnCalled = false; + async function f() { + const iterator = { + [Symbol.asyncIterator](): AsyncIterableIterator { return this; }, + async next() { + return { value: undefined, done: false }; + }, + async return() { + returnCalled = true; + } + }; + for await (const item of iterator) { + return; + } + } + export async function main() { + try { await f(); } catch { } + return returnCalled; + } + `, { target: ts.ScriptTarget.ES2015 }); + assert.isTrue(await result.main()); + }); + + it("call return when user code break (es2015)", async () => { + const result = evaluator.evaluateTypeScript(` + let returnCalled = false; + async function f() { + const iterator = { + [Symbol.asyncIterator](): AsyncIterableIterator { return this; }, + async next() { + return { value: undefined, done: false }; + }, + async return() { + returnCalled = true; + } + }; + for await (const item of iterator) { + break; + } + } + export async function main() { + try { await f(); } catch { } + return returnCalled; + } + `, { target: ts.ScriptTarget.ES2015 }); + assert.isTrue(await result.main()); + }); + it("call return when user code throws (es2015)", async () => { + const result = evaluator.evaluateTypeScript(` + let returnCalled = false; + async function f() { + const iterator = { + [Symbol.asyncIterator](): AsyncIterableIterator { return this; }, + async next() { + return { value: undefined, done: false }; + }, + async return() { + returnCalled = true; + } + }; + for await (const item of iterator) { + throw new Error(); + } + } + export async function main() { + try { await f(); } catch { } + return returnCalled; + } + `, { target: ts.ScriptTarget.ES2015 }); + assert.isTrue(await result.main()); + }); + + it("don't call return when non-user code throws (es2015)", async () => { const result = evaluator.evaluateTypeScript(` let returnCalled = false; async function f() { @@ -123,7 +198,6 @@ describe("unittests:: evaluation:: forAwaitOfEvaluation", () => { } }; for await (const item of iterator) { - throw new Error(); } } export async function main() { @@ -131,7 +205,7 @@ describe("unittests:: evaluation:: forAwaitOfEvaluation", () => { return returnCalled; } `, { target: ts.ScriptTarget.ES2015 }); - assert.isTrue(await result.main()); + assert.isFalse(await result.main()); }); it("don't call return when user code continue (es2015)", async () => { @@ -162,7 +236,7 @@ describe("unittests:: evaluation:: forAwaitOfEvaluation", () => { assert.isFalse(await result.main()); }); - it("don't call return when non-user code throws (es2015)", async () => { + it("don't call return when user code continue to local label (es2015)", async () => { const result = evaluator.evaluateTypeScript(` let returnCalled = false; async function f() { @@ -178,7 +252,12 @@ describe("unittests:: evaluation:: forAwaitOfEvaluation", () => { returnCalled = true; } }; - for await (const item of iterator) { + outerLoop: + for (const outerItem of [1, 2, 3]) { + innerLoop: + for await (const item of iterator) { + continue innerLoop; + } } } export async function main() { @@ -188,4 +267,36 @@ describe("unittests:: evaluation:: forAwaitOfEvaluation", () => { `, { target: ts.ScriptTarget.ES2015 }); assert.isFalse(await result.main()); }); + + it("call return when user code continue to non-local label (es2015)", async () => { + const result = evaluator.evaluateTypeScript(` + let returnCalled = false; + async function f() { + let i = 0; + const iterator = { + [Symbol.asyncIterator](): AsyncIterableIterator { return this; }, + async next() { + i++; + if (i < 2) return { value: undefined, done: false }; + return { value: undefined, done: true }; + }, + async return() { + returnCalled = true; + } + }; + outerLoop: + for (const outerItem of [1, 2, 3]) { + innerLoop: + for await (const item of iterator) { + continue outerLoop; + } + } + } + export async function main() { + try { await f(); } catch { } + return returnCalled; + } + `, { target: ts.ScriptTarget.ES2015 }); + assert.isTrue(await result.main()); + }); });