diff --git a/crates/oxc_parser/src/js/expression.rs b/crates/oxc_parser/src/js/expression.rs index 713ceb1d9192c..271b8ac870115 100644 --- a/crates/oxc_parser/src/js/expression.rs +++ b/crates/oxc_parser/src/js/expression.rs @@ -170,8 +170,6 @@ impl<'a> ParserImpl<'a> { match self.cur_kind() { Kind::Ident => self.parse_identifier_expression(), // fast path, keywords are checked at the end - // Literal, RegularExpressionLiteral - kind if kind.is_literal() => self.parse_literal_expression(), // ArrayLiteral Kind::LBrack => self.parse_array_expression(), // ObjectLiteral @@ -199,6 +197,8 @@ impl<'a> ParserImpl<'a> { Kind::Slash | Kind::SlashEq => self .parse_literal_regexp() .map(|literal| Expression::RegExpLiteral(self.alloc(literal))), + // Literal, RegularExpressionLiteral + kind if kind.is_literal() => self.parse_literal_expression(), // JSXElement, JSXFragment Kind::LAngle if self.source_type.is_jsx() => self.parse_jsx_expression(), _ => self.parse_identifier_expression(), diff --git a/crates/oxc_parser/src/js/statement.rs b/crates/oxc_parser/src/js/statement.rs index 0d933bf2ece76..be87e6eee9fce 100644 --- a/crates/oxc_parser/src/js/statement.rs +++ b/crates/oxc_parser/src/js/statement.rs @@ -87,6 +87,10 @@ impl<'a> ParserImpl<'a> { self.eat_decorators()?; } + // For performance reasons, match orders are: + // 1. plain if check + // 2. check current token + // 3. peek token match self.cur_kind() { Kind::LCurly => self.parse_block_statement(), Kind::Semicolon => Ok(self.parse_empty_statement()), @@ -101,24 +105,28 @@ impl<'a> ParserImpl<'a> { Kind::Try => self.parse_try_statement(), Kind::Debugger => self.parse_debugger_statement(), Kind::Class => self.parse_class_statement(stmt_ctx, start_span), - Kind::Import if !matches!(self.peek_kind(), Kind::Dot | Kind::LParen) => { - self.parse_import_declaration() - } Kind::Export => self.parse_export_declaration(), // [+Return] ReturnStatement[?Yield, ?Await] Kind::Return => self.parse_return_statement(), Kind::Var => self.parse_variable_statement(stmt_ctx), + // Fast path + Kind::Function => self.parse_function_declaration(stmt_ctx), + Kind::Let if !self.cur_token().escaped() => self.parse_let(stmt_ctx), + Kind::Import if !matches!(self.peek_kind(), Kind::Dot | Kind::LParen) => { + self.parse_import_declaration() + } Kind::Const if !(self.is_ts && self.is_at_enum_declaration()) => { self.parse_variable_statement(stmt_ctx) } - Kind::Let if !self.cur_token().escaped() => self.parse_let(stmt_ctx), Kind::Await if self.peek_kind() == Kind::Using && self.nth_kind(2).is_binding_identifier() => { self.parse_using() } Kind::Using if self.peek_kind().is_binding_identifier() => self.parse_using(), - _ if self.at_function_with_async() => self.parse_function_declaration(stmt_ctx), + Kind::Async if self.peek_at(Kind::Function) && !self.peek_token().is_on_new_line => { + self.parse_function_declaration(stmt_ctx) + } _ if self.is_ts && self.at_start_of_ts_declaration() => { self.parse_ts_declaration_statement(start_span) }