From 0674899b88859b91a1f304c3f27cd02de50d7bc0 Mon Sep 17 00:00:00 2001 From: Boshen Date: Wed, 5 Apr 2023 14:36:37 +0800 Subject: [PATCH] Fuzz async (#257) * fix(parser): parse `async(...null)` as call expression relates #255 * fix(parser): parse `null?async():null` relates #255 --- crates/oxc_parser/src/js/function.rs | 26 +++++++++++++++++--------- crates/oxc_parser/src/lib.rs | 11 +++++++++-- tasks/coverage/babel.snap | 7 +++---- tasks/coverage/typescript.snap | 14 +++++++++++--- 4 files changed, 40 insertions(+), 18 deletions(-) diff --git a/crates/oxc_parser/src/js/function.rs b/crates/oxc_parser/src/js/function.rs index a94d33cad..14f095341 100644 --- a/crates/oxc_parser/src/js/function.rs +++ b/crates/oxc_parser/src/js/function.rs @@ -351,16 +351,24 @@ impl<'a> Parser<'a> { Kind::LParen => match self.nth_kind(offset + 1) { // '()' is an arrow expression if followed by an '=>', a type annotation or body. // Otherwise, a parenthesized expression with a missing inner expression - Kind::RParen - if matches!( - self.nth_kind(offset + 2), - Kind::Arrow | Kind::Colon | Kind::LCurly - ) => - { - IsParenthesizedArrowFunction::True + Kind::RParen => { + let kind = self.nth_kind(offset + 2); + if self.ts_enabled() && kind == Kind::Colon { + IsParenthesizedArrowFunction::Maybe + } else if matches!(kind, Kind::Arrow | Kind::LCurly) { + IsParenthesizedArrowFunction::True + } else { + IsParenthesizedArrowFunction::False + } } - // Rest parameter '(...a' is certainly not a parenthesized expression - Kind::Dot3 => IsParenthesizedArrowFunction::True, + // Rest parameter + // '(...ident' is not a parenthesized expression + // '(...null' is a parenthesized expression + Kind::Dot3 => match self.nth_kind(offset + 1) { + Kind::Ident => IsParenthesizedArrowFunction::True, + kind if kind.is_literal() => IsParenthesizedArrowFunction::False, + _ => IsParenthesizedArrowFunction::Maybe, + }, // '([ ...', '({ ... } can either be a parenthesized object or array expression or a destructing parameter Kind::LBrack | Kind::LCurly => IsParenthesizedArrowFunction::Maybe, _ if self.nth_kind(offset + 1).is_binding_identifier() diff --git a/crates/oxc_parser/src/lib.rs b/crates/oxc_parser/src/lib.rs index 748d151f9..be2b6408a 100644 --- a/crates/oxc_parser/src/lib.rs +++ b/crates/oxc_parser/src/lib.rs @@ -276,13 +276,20 @@ mod test { let allocator = Allocator::default(); let source_type = SourceType::default(); - let tests = [ + let fail = [ "1<(V=82<", ]; - for source in tests { + for source in fail { let ret = Parser::new(&allocator, source, source_type).parse(); assert!(!ret.errors.is_empty()); } + + let pass = ["async(...null)", "null?async():null", "switch(null){case async():}"]; + + for source in pass { + let ret = Parser::new(&allocator, source, source_type).parse(); + assert!(ret.errors.is_empty()); + } } } diff --git a/tasks/coverage/babel.snap b/tasks/coverage/babel.snap index c8f83e6f0..55ea47f62 100644 --- a/tasks/coverage/babel.snap +++ b/tasks/coverage/babel.snap @@ -3925,7 +3925,7 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts" × Unexpected token ╭─[es2015/uncategorised/286/input.js:1:1] 1 │ (...[ 5 ]) => {} - · ─ + · ─── ╰──── × Cannot assign to 'eval' in strict mode @@ -6920,11 +6920,10 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts" · ─── ╰──── - × Expected `=>` but found `+` + × Unexpected token ╭─[esprima/es2015-arrow-function/rest-without-arrow/input.js:1:1] 1 │ (...a) + 1 - · ┬ - · ╰── `=>` expected + · ─── ╰──── × Cannot assign to 'eval' in strict mode diff --git a/tasks/coverage/typescript.snap b/tasks/coverage/typescript.snap index 548fd2967..70cd778e9 100644 --- a/tasks/coverage/typescript.snap +++ b/tasks/coverage/typescript.snap @@ -9214,15 +9214,23 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts" 5 │ ╰──── - × Expected `=>` but found `{` + × Empty parenthesized expression ╭─[parser/ecmascript5/RegressionTests/parser509669.ts:1:1] 1 │ function foo():any { 2 │ return ():void {}; - · ┬ - · ╰── `=>` expected + · ▲ 3 │ } ╰──── + × Expected a semicolon or an implicit semicolon after a statement, but found none + ╭─[parser/ecmascript5/RegressionTests/parser509669.ts:1:1] + 1 │ function foo():any { + 2 │ return ():void {}; + · ▲ + 3 │ } + ╰──── + help: Try insert a semicolon here + × Expected `}` but found `EOF` ╭─[parser/ecmascript5/RegressionTests/parser512084.ts:1:1] 1 │ class foo {