Fix early call to return/throw on generator (#51294)

This commit is contained in:
Ron Buckton
2022-10-24 22:37:42 -04:00
committed by GitHub
parent 2c12b14999
commit 702de1eeaa
68 changed files with 134 additions and 98 deletions

View File

@@ -705,6 +705,8 @@ namespace ts {
// - The verb (`next`, `throw`, or `return` method) to delegate to the expression
// of a `yield*`.
// - The result of evaluating the verb delegated to the expression of a `yield*`.
// g A temporary variable that holds onto the generator object until the generator
// is started, allowing it to also act as the `suspendedStart` state.
//
// functions:
// verb(n) Creates a bound callback to the `step` function for opcode `n`.
@@ -750,7 +752,7 @@ namespace ts {
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
while (g && (g = 0, op[0] && (_ = 0)), _) try {
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;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {

View File

@@ -96,6 +96,7 @@
"unittests/evaluation/externalModules.ts",
"unittests/evaluation/forAwaitOf.ts",
"unittests/evaluation/forOf.ts",
"unittests/evaluation/generator.ts",
"unittests/evaluation/optionalCall.ts",
"unittests/evaluation/objectRest.ts",
"unittests/evaluation/superInStaticInitializer.ts",

View File

@@ -0,0 +1,33 @@
describe("unittests:: evaluation:: generatorEvaluation", () => {
it("throw before start (es5)", () => {
const { gen, output } = evaluator.evaluateTypeScript(`
export const output: string[] = [];
export function * gen() {
output.push("start");
yield 1;
output.push("end");
}
`, { target: ts.ScriptTarget.ES5 });
const g = gen();
const e = new Error();
assert.throws(() => g.throw(e), e);
assert.deepEqual(g.next(), { value: undefined, done: true });
assert.deepEqual(output, []);
});
it("return before start (es5)", () => {
const { gen, output } = evaluator.evaluateTypeScript(`
export const output: string[] = [];
export function * gen() {
output.push("start");
yield 1;
output.push("end");
}
`, { target: ts.ScriptTarget.ES5 });
const g = gen();
assert.deepEqual(g.return(2), { value: 2, done: true });
assert.deepEqual(g.next(), { value: undefined, done: true });
assert.deepEqual(output, []);
});
});