From fce6e1ec73dcc33e87271f9cc1816650f114db1a Mon Sep 17 00:00:00 2001 From: Boshen Date: Sun, 12 Mar 2023 23:41:27 +0800 Subject: [PATCH] feat(parser): check `YieldExpression` --- crates/oxc_parser/src/diagnostics.rs | 4 +- crates/oxc_parser/src/js/function.rs | 6 ++- tasks/coverage/babel.snap | 71 +++++++++++++++++++++---- tasks/coverage/test262.snap | 17 +++++- tasks/coverage/typescript.snap | 78 +++++++++++++++++++++++++--- 5 files changed, 152 insertions(+), 24 deletions(-) diff --git a/crates/oxc_parser/src/diagnostics.rs b/crates/oxc_parser/src/diagnostics.rs index 26fb00582..f8a711a27 100644 --- a/crates/oxc_parser/src/diagnostics.rs +++ b/crates/oxc_parser/src/diagnostics.rs @@ -282,9 +282,7 @@ pub struct AwaitExpression(#[label] pub Span); #[derive(Debug, Error, Diagnostic)] #[error("A 'yield' expression is only allowed in a generator body.")] #[diagnostic()] -pub struct YieldExpression( - #[label("A 'yield' expression is only allowed in a generator body.")] pub Span, -); +pub struct YieldExpression(#[label] pub Span); #[derive(Debug, Error, Diagnostic)] #[error("Invalid class declaration")] diff --git a/crates/oxc_parser/src/js/function.rs b/crates/oxc_parser/src/js/function.rs index b14782f01..1d94c82cc 100644 --- a/crates/oxc_parser/src/js/function.rs +++ b/crates/oxc_parser/src/js/function.rs @@ -306,6 +306,11 @@ impl<'a> Parser<'a> { let span = self.start_span(); self.bump_any(); // advance `yield` + let has_yield = self.ctx.has_yield(); + if !has_yield { + self.error(diagnostics::YieldExpression(Span::new(span.start, span.start + 5))); + } + let mut delegate = false; let mut argument = None; @@ -322,7 +327,6 @@ impl<'a> Parser<'a> { | Kind::Comma ); if !not_assignment_expr || delegate { - let has_yield = self.ctx.has_yield(); self.ctx = self.ctx.union_yield_if(true); argument = Some(self.parse_assignment_expression_base()?); self.ctx = self.ctx.and_yield(has_yield); diff --git a/tasks/coverage/babel.snap b/tasks/coverage/babel.snap index 64741a422..1dbd82f43 100644 --- a/tasks/coverage/babel.snap +++ b/tasks/coverage/babel.snap @@ -1,7 +1,7 @@ Babel Summary: AST Parsed : 2051/2069 (99.13%) Positive Passed: 2051/2069 (99.13%) -Negative Passed: 1068/1502 (71.11%) +Negative Passed: 1077/1502 (71.70%) Expect Syntax Error: "annex-b/disabled/1.1-html-comments-close/input.js" Expect Syntax Error: "annex-b/disabled/3.1-sloppy-labeled-functions-if-body/input.js" Expect Syntax Error: "annex-b/disabled/3.1-sloppy-labeled-functions-multiple-labels/input.js" @@ -110,7 +110,6 @@ Expect Syntax Error: "es2015/object/disallow-duplicate-method-params/input.js" Expect Syntax Error: "es2015/shorthand/reserved-word-strict/input.js" Expect Syntax Error: "es2015/statements/label-invalid-func-strict/input.js" Expect Syntax Error: "es2015/uncategorised/.191/input.js" -Expect Syntax Error: "es2015/uncategorised/.260/input.js" Expect Syntax Error: "es2015/uncategorised/.335/input.js" Expect Syntax Error: "es2015/uncategorised/.343/input.js" Expect Syntax Error: "es2015/uncategorised/166/input.js" @@ -137,8 +136,6 @@ Expect Syntax Error: "es2015/yield/function-name-function-declaration-inside-gen Expect Syntax Error: "es2015/yield/function-name-generator-expression/input.js" Expect Syntax Error: "es2015/yield/function-name-strict-body/input.js" Expect Syntax Error: "es2015/yield/function-name-strict/input.js" -Expect Syntax Error: "es2015/yield/in-global-scope/input.js" -Expect Syntax Error: "es2015/yield/in-plain-function/input.js" Expect Syntax Error: "es2015/yield/parameter-default-inside-arrow-inside-generator-1/input.js" Expect Syntax Error: "es2015/yield/parameter-default-inside-arrow-inside-generator-2/input.js" Expect Syntax Error: "es2015/yield/parameter-default-inside-arrow-inside-generator-3/input.js" @@ -191,10 +188,6 @@ Expect Syntax Error: "esprima/es2015-arrow-function/invalid-duplicated-params/in Expect Syntax Error: "esprima/es2015-arrow-function/invalid-param-strict-mode/input.js" Expect Syntax Error: "esprima/es2015-export-declaration/invalid-export-named-default/input.js" Expect Syntax Error: "esprima/es2015-generator/.generator-parameter-binding-property-reserved/input.js" -Expect Syntax Error: "esprima/es2015-generator/generator-method-with-invalid-computed-name/input.js" -Expect Syntax Error: "esprima/es2015-generator/generator-parameter-binding-element/input.js" -Expect Syntax Error: "esprima/es2015-generator/generator-parameter-binding-property/input.js" -Expect Syntax Error: "esprima/es2015-generator/generator-parameter-computed-property-name/input.js" Expect Syntax Error: "esprima/es2015-generator/generator-parameter-invalid-binding-element/input.js" Expect Syntax Error: "esprima/es2015-generator/generator-parameter-invalid-binding-property/input.js" Expect Syntax Error: "esprima/es2015-generator/generator-parameter-invalid-computed-property-name/input.js" @@ -203,8 +196,6 @@ Expect Syntax Error: "esprima/es2015-identifier/invalid_expression_await/input.j Expect Syntax Error: "esprima/es2015-identifier/invalid_var_await/input.js" Expect Syntax Error: "esprima/es2015-meta-property/invalid-new-target/input.js" Expect Syntax Error: "esprima/es2015-meta-property/unknown-property/input.js" -Expect Syntax Error: "esprima/es2015-yield/invalid-yield-binding-property/input.js" -Expect Syntax Error: "esprima/es2015-yield/invalid-yield-expression/input.js" Expect Syntax Error: "esprima/es2015-yield/invalid-yield-generator-arrow-default/input.js" Expect Syntax Error: "esprima/es2015-yield/invalid-yield-generator-declaration/input.js" Expect Syntax Error: "esprima/es2015-yield/invalid-yield-generator-expression-name/input.js" @@ -2919,6 +2910,12 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts" 3 │ `; ╰──── + × A 'yield' expression is only allowed in a generator body. + ╭─[es2015/uncategorised/.260/input.js:1:1] + 1 │ (function() { "use strict"; f(yield v) }) + · ───── + ╰──── + × A 'get' accessor must not have any formal parameters. ╭─[es2015/uncategorised/.345/input.js:1:1] 1 │ class A { get prop(x) {} } @@ -3736,6 +3733,12 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts" · ╰── Expect `{` here, but found `Identifier` ╰──── + × A 'yield' expression is only allowed in a generator body. + ╭─[es2015/yield/in-global-scope/input.js:1:1] + 1 │ yield 10 + · ───── + ╰──── + × Unexpected token ╭─[es2015/yield/in-iterator-stmt/input.js:1:1] 1 │ function* g() { @@ -3744,6 +3747,12 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts" 3 │ } ╰──── + × A 'yield' expression is only allowed in a generator body. + ╭─[es2015/yield/in-plain-function/input.js:1:1] + 1 │ (function () { yield 10 }) + · ───── + ╰──── + × Cannot use `yield` as an identifier in a generator context ╭─[es2015/yield/parameter-default-inside-arrow-inside-generator-5/input.js:1:1] 1 │ function* fn() { @@ -6285,6 +6294,36 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts" · ╰── Expect `;` here, but found `decimal` ╰──── + × A 'yield' expression is only allowed in a generator body. + ╭─[esprima/es2015-generator/generator-method-with-invalid-computed-name/input.js:1:1] + 1 │ ({ *[yield iter]() {} }) + · ───── + ╰──── + + × A 'yield' expression is only allowed in a generator body. + ╭─[esprima/es2015-generator/generator-parameter-binding-element/input.js:1:1] + 1 │ (function*() { + 2 │ function(x = yield 3) {} + · ───── + 3 │ }) + ╰──── + + × A 'yield' expression is only allowed in a generator body. + ╭─[esprima/es2015-generator/generator-parameter-binding-property/input.js:1:1] + 1 │ (function*() { + 2 │ function({x: y = yield 3}) {} + · ───── + 3 │ }) + ╰──── + + × A 'yield' expression is only allowed in a generator body. + ╭─[esprima/es2015-generator/generator-parameter-computed-property-name/input.js:1:1] + 1 │ (function*() { + 2 │ function({[yield 3]: y}) {} + · ───── + 3 │ }) + ╰──── + × Unexpected token ╭─[esprima/es2015-generator/incomplete-yield-delegate/input.js:1:1] 1 │ (function*() { yield* }) @@ -6622,6 +6661,18 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts" · ╰── Unterminated string ╰──── + × A 'yield' expression is only allowed in a generator body. + ╭─[esprima/es2015-yield/invalid-yield-binding-property/input.js:1:1] + 1 │ var {x: y = yield 3} = z; + · ───── + ╰──── + + × A 'yield' expression is only allowed in a generator body. + ╭─[esprima/es2015-yield/invalid-yield-expression/input.js:1:1] + 1 │ (function() { yield 3; }) + · ───── + ╰──── + × Cannot use `yield` as an identifier in a generator context ╭─[esprima/es2015-yield/invalid-yield-generator-arrow-parameter/input.js:1:1] 1 │ function *g(){ (yield) => 42 } diff --git a/tasks/coverage/test262.snap b/tasks/coverage/test262.snap index 893edfa16..d68488d69 100644 --- a/tasks/coverage/test262.snap +++ b/tasks/coverage/test262.snap @@ -1,7 +1,7 @@ Test262 Summary: AST Parsed : 44015/44034 (99.96%) Positive Passed: 44015/44034 (99.96%) -Negative Passed: 3319/3917 (84.73%) +Negative Passed: 3320/3917 (84.76%) Expect Syntax Error: "language/block-scope/syntax/function-declarations/in-statement-position-do-statement-while-expression.js" Expect Syntax Error: "language/block-scope/syntax/function-declarations/in-statement-position-for-statement.js" Expect Syntax Error: "language/block-scope/syntax/function-declarations/in-statement-position-if-expression-statement-else-statement.js" @@ -43,7 +43,6 @@ Expect Syntax Error: "language/expressions/arrow-function/syntax/early-errors/ar Expect Syntax Error: "language/expressions/arrow-function/syntax/early-errors/arrowparameters-cover-no-duplicates-rest.js" Expect Syntax Error: "language/expressions/arrow-function/syntax/early-errors/arrowparameters-cover-no-duplicates.js" Expect Syntax Error: "language/expressions/arrow-function/syntax/early-errors/use-strict-with-non-simple-param.js" -Expect Syntax Error: "language/expressions/assignmenttargettype/direct-yieldexpression-0.js" Expect Syntax Error: "language/expressions/async-arrow-function/array-destructuring-param-strict-body.js" Expect Syntax Error: "language/expressions/async-arrow-function/await-as-param-nested-arrow-body-position.js" Expect Syntax Error: "language/expressions/async-arrow-function/dflt-params-duplicates.js" @@ -4723,6 +4722,13 @@ Expect to Parse: "language/statements/function/S14_A5_T2.js" · ╰── Cannot assign to this expression ╰──── + × A 'yield' expression is only allowed in a generator body. + ╭─[language/expressions/assignmenttargettype/direct-yieldexpression-0.js:19:1] + 19 │ + 20 │ yield x = 1; + · ───── + ╰──── + × Invalid assignment ╭─[language/expressions/assignmenttargettype/direct-yieldexpression-1.js:19:1] 19 │ @@ -5928,6 +5934,13 @@ Expect to Parse: "language/statements/function/S14_A5_T2.js" · ╰── Cannot assign to this expression ╰──── + × A 'yield' expression is only allowed in a generator body. + ╭─[language/expressions/assignmenttargettype/parenthesized-yieldexpression-0.js:22:1] + 22 │ + 23 │ (yield x) = 1; + · ───── + ╰──── + × Invalid assignment ╭─[language/expressions/assignmenttargettype/parenthesized-yieldexpression-0.js:22:1] 22 │ diff --git a/tasks/coverage/typescript.snap b/tasks/coverage/typescript.snap index 2fccae8c1..e5340c4a8 100644 --- a/tasks/coverage/typescript.snap +++ b/tasks/coverage/typescript.snap @@ -1,7 +1,7 @@ TypeScript Summary: AST Parsed : 2305/2338 (98.59%) Positive Passed: 2305/2338 (98.59%) -Negative Passed: 645/2532 (25.47%) +Negative Passed: 652/2532 (25.75%) Expect Syntax Error: "Symbols/ES5SymbolProperty2.ts" Expect Syntax Error: "Symbols/ES5SymbolProperty6.ts" Expect Syntax Error: "additionalChecks/noPropertyAccessFromIndexSignature1.ts" @@ -614,14 +614,8 @@ Expect Syntax Error: "es6/templates/templateStringsWithTypeErrorInFunctionExpres Expect Syntax Error: "es6/templates/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.ts" Expect Syntax Error: "es6/yieldExpressions/YieldExpression10_es6.ts" Expect Syntax Error: "es6/yieldExpressions/YieldExpression11_es6.ts" -Expect Syntax Error: "es6/yieldExpressions/YieldExpression12_es6.ts" -Expect Syntax Error: "es6/yieldExpressions/YieldExpression14_es6.ts" -Expect Syntax Error: "es6/yieldExpressions/YieldExpression15_es6.ts" -Expect Syntax Error: "es6/yieldExpressions/YieldExpression16_es6.ts" -Expect Syntax Error: "es6/yieldExpressions/YieldExpression17_es6.ts" Expect Syntax Error: "es6/yieldExpressions/YieldExpression18_es6.ts" Expect Syntax Error: "es6/yieldExpressions/YieldExpression1_es6.ts" -Expect Syntax Error: "es6/yieldExpressions/YieldExpression2_es6.ts" Expect Syntax Error: "es6/yieldExpressions/YieldExpression6_es6.ts" Expect Syntax Error: "es6/yieldExpressions/YieldExpression8_es6.ts" Expect Syntax Error: "es6/yieldExpressions/YieldExpression9_es6.ts" @@ -638,7 +632,6 @@ Expect Syntax Error: "es6/yieldExpressions/generatorTypeCheck20.ts" Expect Syntax Error: "es6/yieldExpressions/generatorTypeCheck21.ts" Expect Syntax Error: "es6/yieldExpressions/generatorTypeCheck25.ts" Expect Syntax Error: "es6/yieldExpressions/generatorTypeCheck31.ts" -Expect Syntax Error: "es6/yieldExpressions/generatorTypeCheck32.ts" Expect Syntax Error: "es6/yieldExpressions/generatorTypeCheck39.ts" Expect Syntax Error: "es6/yieldExpressions/generatorTypeCheck48.ts" Expect Syntax Error: "es6/yieldExpressions/generatorTypeCheck50.ts" @@ -2821,6 +2814,14 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts" 14 │ ╰──── + × A 'yield' expression is only allowed in a generator body. + ╭─[classes/classStaticBlock/classStaticBlock7.ts:3:1] + 3 │ await 1; + 4 │ yield 1; + · ───── + 5 │ return 1; + ╰──── + × TS1108: A 'return' statement can only be used within a function body ╭─[classes/classStaticBlock/classStaticBlock7.ts:4:1] 4 │ yield 1; @@ -2830,6 +2831,14 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts" 6 │ } ╰──── + × A 'yield' expression is only allowed in a generator body. + ╭─[classes/classStaticBlock/classStaticBlock7.ts:23:1] + 23 │ static { + 24 │ yield 1; + · ───── + 25 │ + ╰──── + × TS1108: A 'return' statement can only be used within a function body ╭─[classes/classStaticBlock/classStaticBlock7.ts:35:1] 35 │ static { @@ -5760,6 +5769,52 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts" · ─ ╰──── + × A 'yield' expression is only allowed in a generator body. + ╭─[es6/yieldExpressions/YieldExpression12_es6.ts:3:1] + 3 │ constructor() { + 4 │ yield foo + · ───── + 5 │ } + ╰──── + + × A 'yield' expression is only allowed in a generator body. + ╭─[es6/yieldExpressions/YieldExpression14_es6.ts:3:1] + 3 │ foo() { + 4 │ yield foo + · ───── + 5 │ } + ╰──── + + × A 'yield' expression is only allowed in a generator body. + ╭─[es6/yieldExpressions/YieldExpression15_es6.ts:2:1] + 2 │ var v = () => { + 3 │ yield foo + · ───── + 4 │ } + ╰──── + + × A 'yield' expression is only allowed in a generator body. + ╭─[es6/yieldExpressions/YieldExpression16_es6.ts:3:1] + 3 │ function bar() { + 4 │ yield foo; + · ───── + 5 │ } + ╰──── + + × A 'yield' expression is only allowed in a generator body. + ╭─[es6/yieldExpressions/YieldExpression17_es6.ts:1:1] + 1 │ // @target: es6 + 2 │ var v = { get foo() { yield foo; } } + · ───── + ╰──── + + × A 'yield' expression is only allowed in a generator body. + ╭─[es6/yieldExpressions/YieldExpression2_es6.ts:1:1] + 1 │ // @target: es6 + 2 │ yield foo; + · ───── + ╰──── + × Unexpected token ╭─[es6/yieldExpressions/YieldExpression5_es6.ts:3:1] 3 │ yield* @@ -5782,6 +5837,13 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts" 4 │ } ╰──── + × A 'yield' expression is only allowed in a generator body. + ╭─[es6/yieldExpressions/generatorTypeCheck32.ts:2:1] + 2 │ var s: string; + 3 │ var f: () => number = () => yield s; + · ───── + ╰──── + × Invalid assignment ╭─[es7/exponentiationOperator/compoundExponentiationAssignmentLHSIsValue.ts:7:1] 7 │ constructor() {