From 344d35bbe93eff4fe9ee575caff2b4ab6c4aee8c Mon Sep 17 00:00:00 2001 From: Daniel Tschinder Date: Mon, 4 Feb 2019 13:01:17 -0800 Subject: [PATCH] Simplify await and yield tracking in params (#9405) --- .../babel-parser/src/parser/expression.js | 105 ++++++++---------- packages/babel-parser/src/parser/statement.js | 7 ++ packages/babel-parser/src/parser/util.js | 18 +++ packages/babel-parser/src/tokenizer/state.js | 10 +- .../options.json | 2 +- .../options.json | 2 +- .../options.json | 2 +- .../options.json | 2 +- .../options.json | 2 +- .../options.json | 2 +- .../options.json | 2 +- .../options.json | 2 +- .../options.json | 2 +- .../options.json | 2 +- .../options.json | 2 +- .../options.json | 2 +- .../options.json | 2 +- .../options.json | 2 +- .../options.json | 2 +- .../options.json | 2 +- 20 files changed, 90 insertions(+), 82 deletions(-) diff --git a/packages/babel-parser/src/parser/expression.js b/packages/babel-parser/src/parser/expression.js index 4f27187123a9..01f7dc03a2e1 100644 --- a/packages/babel-parser/src/parser/expression.js +++ b/packages/babel-parser/src/parser/expression.js @@ -597,9 +597,11 @@ export default class ExpressionParser extends LValParser { return this.finishNode(node, "MemberExpression"); } else if (!noCalls && this.match(tt.parenL)) { const oldMaybeInArrowParameters = this.state.maybeInArrowParameters; - const oldYOAIPAP = this.state.yieldOrAwaitInPossibleArrowParameters; + const oldYieldPos = this.state.yieldPos; + const oldAwaitPos = this.state.awaitPos; this.state.maybeInArrowParameters = true; - this.state.yieldOrAwaitInPossibleArrowParameters = null; + this.state.yieldPos = 0; + this.state.awaitPos = 0; const possibleAsync = this.atPossibleAsync(base); this.next(); @@ -630,14 +632,16 @@ export default class ExpressionParser extends LValParser { this.startNodeAt(startPos, startLoc), node, ); - this.state.yieldOrAwaitInPossibleArrowParameters = oldYOAIPAP; + this.checkYieldAwaitInDefaultParams(); + this.state.yieldPos = oldYieldPos; + this.state.awaitPos = oldAwaitPos; } else { this.toReferencedListDeep(node.arguments); // We keep the old value if it isn't null, for cases like // (x = async(yield)) => {} - this.state.yieldOrAwaitInPossibleArrowParameters = - this.state.yieldOrAwaitInPossibleArrowParameters || oldYOAIPAP; + this.state.yieldPos = oldYieldPos || this.state.yieldPos; + this.state.awaitPos = oldAwaitPos || this.state.awaitPos; } this.state.maybeInArrowParameters = oldMaybeInArrowParameters; @@ -873,25 +877,19 @@ export default class ExpressionParser extends LValParser { this.match(tt.name) && !this.canInsertSemicolon() ) { - const oldYOAIPAP = this.state.yieldOrAwaitInPossibleArrowParameters; const oldInAsync = this.state.inAsync; - this.state.yieldOrAwaitInPossibleArrowParameters = null; this.state.inAsync = true; const params = [this.parseIdentifier()]; this.expect(tt.arrow); // let foo = async bar => {}; this.parseArrowExpression(node, params, true); - this.state.yieldOrAwaitInPossibleArrowParameters = oldYOAIPAP; this.state.inAsync = oldInAsync; return node; } if (canBeArrow && this.match(tt.arrow) && !this.canInsertSemicolon()) { this.next(); - const oldYOAIPAP = this.state.yieldOrAwaitInPossibleArrowParameters; - this.state.yieldOrAwaitInPossibleArrowParameters = null; - this.parseArrowExpression(node, [id]); - this.state.yieldOrAwaitInPossibleArrowParameters = oldYOAIPAP; + this.parseArrowExpression(node, [id], false); return node; } @@ -1172,9 +1170,11 @@ export default class ExpressionParser extends LValParser { this.expect(tt.parenL); const oldMaybeInArrowParameters = this.state.maybeInArrowParameters; - const oldYOAIPAP = this.state.yieldOrAwaitInPossibleArrowParameters; + const oldYieldPos = this.state.yieldPos; + const oldAwaitPos = this.state.awaitPos; this.state.maybeInArrowParameters = true; - this.state.yieldOrAwaitInPossibleArrowParameters = null; + this.state.yieldPos = 0; + this.state.awaitPos = 0; const innerStartPos = this.state.start; const innerStartLoc = this.state.startLoc; @@ -1235,21 +1235,23 @@ export default class ExpressionParser extends LValParser { this.shouldParseArrow() && (arrowNode = this.parseArrow(arrowNode)) ) { + this.checkYieldAwaitInDefaultParams(); + this.state.yieldPos = oldYieldPos; + this.state.awaitPos = oldAwaitPos; for (const param of exprList) { if (param.extra && param.extra.parenthesized) { this.unexpected(param.extra.parenStart); } } - this.parseArrowExpression(arrowNode, exprList); - this.state.yieldOrAwaitInPossibleArrowParameters = oldYOAIPAP; + this.parseArrowExpression(arrowNode, exprList, false); return arrowNode; } // We keep the old value if it isn't null, for cases like // (x = (yield)) => {} - this.state.yieldOrAwaitInPossibleArrowParameters = - this.state.yieldOrAwaitInPossibleArrowParameters || oldYOAIPAP; + this.state.yieldPos = oldYieldPos || this.state.yieldPos; + this.state.awaitPos = oldAwaitPos || this.state.awaitPos; if (!exprList.length) { this.unexpected(this.state.lastTokStart); @@ -1717,21 +1719,28 @@ export default class ExpressionParser extends LValParser { const oldInMethod = this.state.inMethod; const oldInAsync = this.state.inAsync; const oldInGenerator = this.state.inGenerator; + const oldYieldPos = this.state.yieldPos; + const oldAwaitPos = this.state.awaitPos; this.state.inFunction = true; this.state.inMethod = node.kind || true; this.state.inAsync = isAsync; this.state.inGenerator = isGenerator; + this.state.yieldPos = 0; + this.state.awaitPos = 0; this.initFunction(node, isAsync); node.generator = !!isGenerator; const allowModifiers = isConstructor; // For TypeScript parameter properties this.parseFunctionParams((node: any), allowModifiers); + this.checkYieldAwaitInDefaultParams(); this.parseFunctionBodyAndFinish(node, type); this.state.inFunction = oldInFunc; this.state.inMethod = oldInMethod; this.state.inAsync = oldInAsync; this.state.inGenerator = oldInGenerator; + this.state.yieldPos = oldYieldPos; + this.state.awaitPos = oldAwaitPos; return node; } @@ -1741,44 +1750,33 @@ export default class ExpressionParser extends LValParser { // assignable list. parseArrowExpression( node: N.ArrowFunctionExpression, - params?: ?(N.Expression[]), - isAsync?: boolean = false, + params: ?(N.Expression[]), + isAsync: boolean, ): N.ArrowFunctionExpression { - // if we got there, it's no more "yield in possible arrow parameters"; - // it's just "yield in arrow parameters" - const yOAIPAP = this.state.yieldOrAwaitInPossibleArrowParameters; - if (yOAIPAP) { - if (yOAIPAP.type === "YieldExpression") { - this.raise( - yOAIPAP.start, - "yield is not allowed in the parameters of an arrow function" + - " inside a generator", - ); - } else { - this.raise( - yOAIPAP.start, - "await is not allowed in the parameters of an arrow function" + - " inside an async function", - ); - } - } - - const oldInFunc = this.state.inFunction; - this.state.inFunction = true; this.initFunction(node, isAsync); - if (params) this.setArrowFunctionParameters(node, params); + const oldInFunc = this.state.inFunction; const oldInAsync = this.state.inAsync; const oldInGenerator = this.state.inGenerator; const oldMaybeInArrowParameters = this.state.maybeInArrowParameters; + const oldYieldPos = this.state.yieldPos; + const oldAwaitPos = this.state.awaitPos; + this.state.inFunction = true; this.state.inAsync = isAsync; this.state.inGenerator = false; this.state.maybeInArrowParameters = false; + this.state.yieldPos = 0; + this.state.awaitPos = 0; + + if (params) this.setArrowFunctionParameters(node, params); this.parseFunctionBody(node, true); + this.state.inAsync = oldInAsync; this.state.inGenerator = oldInGenerator; this.state.inFunction = oldInFunc; this.state.maybeInArrowParameters = oldMaybeInArrowParameters; + this.state.yieldPos = oldYieldPos; + this.state.awaitPos = oldAwaitPos; return this.finishNode(node, "ArrowFunctionExpression"); } @@ -2034,16 +2032,10 @@ export default class ExpressionParser extends LValParser { // Parses await expression inside async function. parseAwait(): N.AwaitExpression { - const node = this.startNode(); - - if ( - this.state.maybeInArrowParameters && - // We only set yieldOrAwaitInPossibleArrowParameters if we haven't already - // found a possible invalid AwaitExpression. - !this.state.yieldOrAwaitInPossibleArrowParameters - ) { - this.state.yieldOrAwaitInPossibleArrowParameters = node; + if (!this.state.awaitPos) { + this.state.awaitPos = this.state.start; } + const node = this.startNode(); this.next(); @@ -2067,19 +2059,14 @@ export default class ExpressionParser extends LValParser { // Parses yield expression inside generator. parseYield(noIn?: ?boolean): N.YieldExpression { + if (!this.state.yieldPos) { + this.state.yieldPos = this.state.start; + } const node = this.startNode(); if (this.state.inParameters) { this.raise(node.start, "yield is not allowed in generator parameters"); } - if ( - this.state.maybeInArrowParameters && - // We only set yieldOrAwaitInPossibleArrowParameters if we haven't already - // found a possible invalid YieldExpression. - !this.state.yieldOrAwaitInPossibleArrowParameters - ) { - this.state.yieldOrAwaitInPossibleArrowParameters = node; - } this.next(); if ( diff --git a/packages/babel-parser/src/parser/statement.js b/packages/babel-parser/src/parser/statement.js index f7c4ff88ef3b..9bee7358f53b 100644 --- a/packages/babel-parser/src/parser/statement.js +++ b/packages/babel-parser/src/parser/statement.js @@ -969,9 +969,13 @@ export default class StatementParser extends ExpressionParser { const oldInAsync = this.state.inAsync; const oldInGenerator = this.state.inGenerator; const oldInClassProperty = this.state.inClassProperty; + const oldYieldPos = this.state.yieldPos; + const oldAwaitPos = this.state.awaitPos; this.state.inFunction = true; this.state.inMethod = false; this.state.inClassProperty = false; + this.state.yieldPos = 0; + this.state.awaitPos = 0; this.initFunction(node, isAsync); @@ -1021,6 +1025,8 @@ export default class StatementParser extends ExpressionParser { this.state.inAsync = oldInAsync; this.state.inGenerator = oldInGenerator; this.state.inClassProperty = oldInClassProperty; + this.state.yieldPos = oldYieldPos; + this.state.awaitPos = oldAwaitPos; return node; } @@ -1037,6 +1043,7 @@ export default class StatementParser extends ExpressionParser { ); this.state.inParameters = oldInParameters; + this.checkYieldAwaitInDefaultParams(); } // Parse a class declaration or literal (depending on the diff --git a/packages/babel-parser/src/parser/util.js b/packages/babel-parser/src/parser/util.js index 1a8fa35a133c..1ea8aeaf8f1c 100644 --- a/packages/babel-parser/src/parser/util.js +++ b/packages/babel-parser/src/parser/util.js @@ -147,4 +147,22 @@ export default class UtilParser extends Tokenizer { ); } } + + checkYieldAwaitInDefaultParams() { + if ( + this.state.yieldPos && + (!this.state.awaitPos || this.state.yieldPos < this.state.awaitPos) + ) { + this.raise( + this.state.yieldPos, + "Yield cannot be used as name inside a generator function", + ); + } + if (this.state.awaitPos) { + this.raise( + this.state.awaitPos, + "Await cannot be used as name inside an async function", + ); + } + } } diff --git a/packages/babel-parser/src/tokenizer/state.js b/packages/babel-parser/src/tokenizer/state.js index 9bc2b81c02e2..0215532dd0f8 100644 --- a/packages/babel-parser/src/tokenizer/state.js +++ b/packages/babel-parser/src/tokenizer/state.js @@ -102,13 +102,9 @@ export default class State { // where @foo belongs to the outer class and @bar to the inner decoratorStack: Array> = [[]]; - // The first yield or await expression inside parenthesized expressions - // and arrow function parameters. It is used to disallow yield and await in - // arrow function parameters. - yieldOrAwaitInPossibleArrowParameters: - | N.YieldExpression - | N.AwaitExpression - | null = null; + // Positions to delayed-check that yield/await does not exist in default parameters. + yieldPos: number = 0; + awaitPos: number = 0; // Token store. tokens: Array = []; diff --git a/packages/babel-parser/test/fixtures/es2015/yield/parameter-default-inside-arrow-inside-generator-1/options.json b/packages/babel-parser/test/fixtures/es2015/yield/parameter-default-inside-arrow-inside-generator-1/options.json index 695fe418b904..75b3f62fdacb 100644 --- a/packages/babel-parser/test/fixtures/es2015/yield/parameter-default-inside-arrow-inside-generator-1/options.json +++ b/packages/babel-parser/test/fixtures/es2015/yield/parameter-default-inside-arrow-inside-generator-1/options.json @@ -1,3 +1,3 @@ { - "throws": "yield is not allowed in the parameters of an arrow function inside a generator (2:7)" + "throws": "Yield cannot be used as name inside a generator function (2:7)" } diff --git a/packages/babel-parser/test/fixtures/es2015/yield/parameter-default-inside-arrow-inside-generator-2/options.json b/packages/babel-parser/test/fixtures/es2015/yield/parameter-default-inside-arrow-inside-generator-2/options.json index 28b45c949dcf..9d35f54190c8 100644 --- a/packages/babel-parser/test/fixtures/es2015/yield/parameter-default-inside-arrow-inside-generator-2/options.json +++ b/packages/babel-parser/test/fixtures/es2015/yield/parameter-default-inside-arrow-inside-generator-2/options.json @@ -1,3 +1,3 @@ { - "throws": "yield is not allowed in the parameters of an arrow function inside a generator (2:15)" + "throws": "Yield cannot be used as name inside a generator function (2:15)" } diff --git a/packages/babel-parser/test/fixtures/es2015/yield/parameter-default-inside-arrow-inside-generator-3/options.json b/packages/babel-parser/test/fixtures/es2015/yield/parameter-default-inside-arrow-inside-generator-3/options.json index 695fe418b904..75b3f62fdacb 100644 --- a/packages/babel-parser/test/fixtures/es2015/yield/parameter-default-inside-arrow-inside-generator-3/options.json +++ b/packages/babel-parser/test/fixtures/es2015/yield/parameter-default-inside-arrow-inside-generator-3/options.json @@ -1,3 +1,3 @@ { - "throws": "yield is not allowed in the parameters of an arrow function inside a generator (2:7)" + "throws": "Yield cannot be used as name inside a generator function (2:7)" } diff --git a/packages/babel-parser/test/fixtures/es2015/yield/parameter-default-inside-arrow-inside-generator-4/options.json b/packages/babel-parser/test/fixtures/es2015/yield/parameter-default-inside-arrow-inside-generator-4/options.json index b0fd9b81d1e7..b3ac060855bb 100644 --- a/packages/babel-parser/test/fixtures/es2015/yield/parameter-default-inside-arrow-inside-generator-4/options.json +++ b/packages/babel-parser/test/fixtures/es2015/yield/parameter-default-inside-arrow-inside-generator-4/options.json @@ -1,3 +1,3 @@ { - "throws": "yield is not allowed in the parameters of an arrow function inside a generator (2:17)" + "throws": "Yield cannot be used as name inside a generator function (2:17)" } diff --git a/packages/babel-parser/test/fixtures/es2015/yield/parameter-default-inside-arrow-inside-generator-5/options.json b/packages/babel-parser/test/fixtures/es2015/yield/parameter-default-inside-arrow-inside-generator-5/options.json index a70dd2ba957e..379c08c57e90 100644 --- a/packages/babel-parser/test/fixtures/es2015/yield/parameter-default-inside-arrow-inside-generator-5/options.json +++ b/packages/babel-parser/test/fixtures/es2015/yield/parameter-default-inside-arrow-inside-generator-5/options.json @@ -1,3 +1,3 @@ { - "throws": "yield is not allowed in the parameters of an arrow function inside a generator (2:8)" + "throws": "Yield cannot be used as name inside a generator function (2:8)" } diff --git a/packages/babel-parser/test/fixtures/es2015/yield/parameter-default-inside-arrow-inside-generator-6/options.json b/packages/babel-parser/test/fixtures/es2015/yield/parameter-default-inside-arrow-inside-generator-6/options.json index a70dd2ba957e..379c08c57e90 100644 --- a/packages/babel-parser/test/fixtures/es2015/yield/parameter-default-inside-arrow-inside-generator-6/options.json +++ b/packages/babel-parser/test/fixtures/es2015/yield/parameter-default-inside-arrow-inside-generator-6/options.json @@ -1,3 +1,3 @@ { - "throws": "yield is not allowed in the parameters of an arrow function inside a generator (2:8)" + "throws": "Yield cannot be used as name inside a generator function (2:8)" } diff --git a/packages/babel-parser/test/fixtures/es2015/yield/parameter-name-arrow-inside-generator-1/options.json b/packages/babel-parser/test/fixtures/es2015/yield/parameter-name-arrow-inside-generator-1/options.json index c636ce99024b..b566d4944c2c 100644 --- a/packages/babel-parser/test/fixtures/es2015/yield/parameter-name-arrow-inside-generator-1/options.json +++ b/packages/babel-parser/test/fixtures/es2015/yield/parameter-name-arrow-inside-generator-1/options.json @@ -1,3 +1,3 @@ { - "throws": "yield is not allowed in the parameters of an arrow function inside a generator (2:3)" + "throws": "Yield cannot be used as name inside a generator function (2:3)" } diff --git a/packages/babel-parser/test/fixtures/es2015/yield/parameter-name-arrow-inside-generator-2/options.json b/packages/babel-parser/test/fixtures/es2015/yield/parameter-name-arrow-inside-generator-2/options.json index c636ce99024b..b566d4944c2c 100644 --- a/packages/babel-parser/test/fixtures/es2015/yield/parameter-name-arrow-inside-generator-2/options.json +++ b/packages/babel-parser/test/fixtures/es2015/yield/parameter-name-arrow-inside-generator-2/options.json @@ -1,3 +1,3 @@ { - "throws": "yield is not allowed in the parameters of an arrow function inside a generator (2:3)" + "throws": "Yield cannot be used as name inside a generator function (2:3)" } diff --git a/packages/babel-parser/test/fixtures/es2015/yield/parameter-name-arrow-inside-generator-3/options.json b/packages/babel-parser/test/fixtures/es2015/yield/parameter-name-arrow-inside-generator-3/options.json index d82d23bca0b4..479a9a79f900 100644 --- a/packages/babel-parser/test/fixtures/es2015/yield/parameter-name-arrow-inside-generator-3/options.json +++ b/packages/babel-parser/test/fixtures/es2015/yield/parameter-name-arrow-inside-generator-3/options.json @@ -1,3 +1,3 @@ { - "throws": "yield is not allowed in the parameters of an arrow function inside a generator (2:9)" + "throws": "Yield cannot be used as name inside a generator function (2:9)" } diff --git a/packages/babel-parser/test/fixtures/es2017/async-functions/await-inside-arguments-of-async-call-inside-parameters-of-async-arrow-function/options.json b/packages/babel-parser/test/fixtures/es2017/async-functions/await-inside-arguments-of-async-call-inside-parameters-of-async-arrow-function/options.json index f7e1f0a54d38..9a4cb65743b5 100644 --- a/packages/babel-parser/test/fixtures/es2017/async-functions/await-inside-arguments-of-async-call-inside-parameters-of-async-arrow-function/options.json +++ b/packages/babel-parser/test/fixtures/es2017/async-functions/await-inside-arguments-of-async-call-inside-parameters-of-async-arrow-function/options.json @@ -1,3 +1,3 @@ { - "throws": "await is not allowed in the parameters of an arrow function inside an async function (2:23)" + "throws": "Await cannot be used as name inside an async function (2:23)" } diff --git a/packages/babel-parser/test/fixtures/es2017/async-functions/await-inside-parameters-of-nested-arrow-function/options.json b/packages/babel-parser/test/fixtures/es2017/async-functions/await-inside-parameters-of-nested-arrow-function/options.json index 3d590911be50..7cec39290c2a 100644 --- a/packages/babel-parser/test/fixtures/es2017/async-functions/await-inside-parameters-of-nested-arrow-function/options.json +++ b/packages/babel-parser/test/fixtures/es2017/async-functions/await-inside-parameters-of-nested-arrow-function/options.json @@ -1,3 +1,3 @@ { - "throws": "await is not allowed in the parameters of an arrow function inside an async function (2:7)" + "throws": "Await cannot be used as name inside an async function (2:7)" } diff --git a/packages/babel-parser/test/fixtures/es2017/async-functions/await-inside-parameters-of-nested-async-arrow-function/options.json b/packages/babel-parser/test/fixtures/es2017/async-functions/await-inside-parameters-of-nested-async-arrow-function/options.json index 51430f6aa61b..b45bba7cab4a 100644 --- a/packages/babel-parser/test/fixtures/es2017/async-functions/await-inside-parameters-of-nested-async-arrow-function/options.json +++ b/packages/babel-parser/test/fixtures/es2017/async-functions/await-inside-parameters-of-nested-async-arrow-function/options.json @@ -1,3 +1,3 @@ { - "throws": "await is not allowed in the parameters of an arrow function inside an async function (2:13)" + "throws": "Await cannot be used as name inside an async function (2:13)" } diff --git a/packages/babel-parser/test/fixtures/esprima/es2015-yield/invalid-yield-generator-arrow-default/options.json b/packages/babel-parser/test/fixtures/esprima/es2015-yield/invalid-yield-generator-arrow-default/options.json index 1bc56676810e..f81e206da65d 100644 --- a/packages/babel-parser/test/fixtures/esprima/es2015-yield/invalid-yield-generator-arrow-default/options.json +++ b/packages/babel-parser/test/fixtures/esprima/es2015-yield/invalid-yield-generator-arrow-default/options.json @@ -1,3 +1,3 @@ { - "throws": "yield is not allowed in the parameters of an arrow function inside a generator (1:21)" + "throws": "Yield cannot be used as name inside a generator function (1:21)" } diff --git a/packages/babel-parser/test/fixtures/esprima/es2015-yield/invalid-yield-generator-arrow-parameter/options.json b/packages/babel-parser/test/fixtures/esprima/es2015-yield/invalid-yield-generator-arrow-parameter/options.json index c9b7ef33bbf2..efa8ac523c48 100644 --- a/packages/babel-parser/test/fixtures/esprima/es2015-yield/invalid-yield-generator-arrow-parameter/options.json +++ b/packages/babel-parser/test/fixtures/esprima/es2015-yield/invalid-yield-generator-arrow-parameter/options.json @@ -1,3 +1,3 @@ { - "throws": "yield is not allowed in the parameters of an arrow function inside a generator (1:16)" + "throws": "Yield cannot be used as name inside a generator function (1:16)" } diff --git a/packages/babel-parser/test/fixtures/esprima/es2015-yield/invalid-yield-generator-arrow-parameters/options.json b/packages/babel-parser/test/fixtures/esprima/es2015-yield/invalid-yield-generator-arrow-parameters/options.json index 65c34eefb48e..185008241333 100644 --- a/packages/babel-parser/test/fixtures/esprima/es2015-yield/invalid-yield-generator-arrow-parameters/options.json +++ b/packages/babel-parser/test/fixtures/esprima/es2015-yield/invalid-yield-generator-arrow-parameters/options.json @@ -1,3 +1,3 @@ { - "throws": "yield is not allowed in the parameters of an arrow function inside a generator (1:25)" + "throws": "Yield cannot be used as name inside a generator function (1:25)" } diff --git a/packages/babel-parser/test/fixtures/esprima/es2015-yield/yield-generator-arrow-default/options.json b/packages/babel-parser/test/fixtures/esprima/es2015-yield/yield-generator-arrow-default/options.json index 1bc56676810e..f81e206da65d 100644 --- a/packages/babel-parser/test/fixtures/esprima/es2015-yield/yield-generator-arrow-default/options.json +++ b/packages/babel-parser/test/fixtures/esprima/es2015-yield/yield-generator-arrow-default/options.json @@ -1,3 +1,3 @@ { - "throws": "yield is not allowed in the parameters of an arrow function inside a generator (1:21)" + "throws": "Yield cannot be used as name inside a generator function (1:21)" }