Skip to content

Commit 702de1e

Browse files
authored
Fix early call to return/throw on generator (#51294)
1 parent 2c12b14 commit 702de1e

File tree

68 files changed

+134
-98
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+134
-98
lines changed

src/compiler/factory/emitHelpers.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,8 @@ namespace ts {
705705
// - The verb (`next`, `throw`, or `return` method) to delegate to the expression
706706
// of a `yield*`.
707707
// - The result of evaluating the verb delegated to the expression of a `yield*`.
708+
// g A temporary variable that holds onto the generator object until the generator
709+
// is started, allowing it to also act as the `suspendedStart` state.
708710
//
709711
// functions:
710712
// verb(n) Creates a bound callback to the `step` function for opcode `n`.
@@ -750,7 +752,7 @@ namespace ts {
750752
function verb(n) { return function (v) { return step([n, v]); }; }
751753
function step(op) {
752754
if (f) throw new TypeError("Generator is already executing.");
753-
while (_) try {
755+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
754756
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
755757
if (y = 0, t) op = [op[0] & 2, t.value];
756758
switch (op[0]) {

src/testRunner/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
"unittests/evaluation/externalModules.ts",
9797
"unittests/evaluation/forAwaitOf.ts",
9898
"unittests/evaluation/forOf.ts",
99+
"unittests/evaluation/generator.ts",
99100
"unittests/evaluation/optionalCall.ts",
100101
"unittests/evaluation/objectRest.ts",
101102
"unittests/evaluation/superInStaticInitializer.ts",
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
describe("unittests:: evaluation:: generatorEvaluation", () => {
2+
it("throw before start (es5)", () => {
3+
const { gen, output } = evaluator.evaluateTypeScript(`
4+
export const output: string[] = [];
5+
export function * gen() {
6+
output.push("start");
7+
yield 1;
8+
output.push("end");
9+
}
10+
`, { target: ts.ScriptTarget.ES5 });
11+
12+
const g = gen();
13+
const e = new Error();
14+
assert.throws(() => g.throw(e), e);
15+
assert.deepEqual(g.next(), { value: undefined, done: true });
16+
assert.deepEqual(output, []);
17+
});
18+
it("return before start (es5)", () => {
19+
const { gen, output } = evaluator.evaluateTypeScript(`
20+
export const output: string[] = [];
21+
export function * gen() {
22+
output.push("start");
23+
yield 1;
24+
output.push("end");
25+
}
26+
`, { target: ts.ScriptTarget.ES5 });
27+
28+
const g = gen();
29+
assert.deepEqual(g.return(2), { value: 2, done: true });
30+
assert.deepEqual(g.next(), { value: undefined, done: true });
31+
assert.deepEqual(output, []);
32+
});
33+
});

tests/baselines/reference/asyncArrowFunction11_es5.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
2323
function verb(n) { return function (v) { return step([n, v]); }; }
2424
function step(op) {
2525
if (f) throw new TypeError("Generator is already executing.");
26-
while (_) try {
26+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
2727
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
2828
if (y = 0, t) op = [op[0] & 2, t.value];
2929
switch (op[0]) {

tests/baselines/reference/asyncAwaitIsolatedModules_es5.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
5656
function verb(n) { return function (v) { return step([n, v]); }; }
5757
function step(op) {
5858
if (f) throw new TypeError("Generator is already executing.");
59-
while (_) try {
59+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
6060
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
6161
if (y = 0, t) op = [op[0] & 2, t.value];
6262
switch (op[0]) {

tests/baselines/reference/asyncAwait_es5.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
6262
function verb(n) { return function (v) { return step([n, v]); }; }
6363
function step(op) {
6464
if (f) throw new TypeError("Generator is already executing.");
65-
while (_) try {
65+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
6666
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
6767
if (y = 0, t) op = [op[0] & 2, t.value];
6868
switch (op[0]) {

tests/baselines/reference/asyncFunctionNoReturnType.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
2121
function verb(n) { return function (v) { return step([n, v]); }; }
2222
function step(op) {
2323
if (f) throw new TypeError("Generator is already executing.");
24-
while (_) try {
24+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
2525
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
2626
if (y = 0, t) op = [op[0] & 2, t.value];
2727
switch (op[0]) {

tests/baselines/reference/asyncFunctionReturnExpressionErrorSpans.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
3737
function verb(n) { return function (v) { return step([n, v]); }; }
3838
function step(op) {
3939
if (f) throw new TypeError("Generator is already executing.");
40-
while (_) try {
40+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
4141
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
4242
if (y = 0, t) op = [op[0] & 2, t.value];
4343
switch (op[0]) {

tests/baselines/reference/asyncFunctionTempVariableScoping.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
2020
function verb(n) { return function (v) { return step([n, v]); }; }
2121
function step(op) {
2222
if (f) throw new TypeError("Generator is already executing.");
23-
while (_) try {
23+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
2424
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
2525
if (y = 0, t) op = [op[0] & 2, t.value];
2626
switch (op[0]) {

tests/baselines/reference/asyncFunctionWithForStatementNoInitializer.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
4040
function verb(n) { return function (v) { return step([n, v]); }; }
4141
function step(op) {
4242
if (f) throw new TypeError("Generator is already executing.");
43-
while (_) try {
43+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
4444
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
4545
if (y = 0, t) op = [op[0] & 2, t.value];
4646
switch (op[0]) {

0 commit comments

Comments
 (0)