File tree Expand file tree Collapse file tree 3 files changed +29
-27
lines changed Expand file tree Collapse file tree 3 files changed +29
-27
lines changed Original file line number Diff line number Diff line change @@ -192,20 +192,19 @@ impl<'a> ParserImpl<'a> {
192192 }
193193
194194 fn is_un_parenthesized_async_arrow_function_worker ( & mut self ) -> bool {
195- let checkpoint = self . checkpoint ( ) ;
196- self . bump ( Kind :: Async ) ;
197- // If the "async" is followed by "=>" token then it is not a beginning of an async arrow-function
198- // but instead a simple arrow-function which will be parsed inside "parseAssignmentExpressionOrHigher"
199- if !self . cur_token ( ) . is_on_new_line ( ) && self . cur_kind ( ) . is_binding_identifier ( ) {
200- // Arrow before newline is checked in `parse_simple_arrow_function_expression`
201- self . bump_any ( ) ;
202- if self . at ( Kind :: Arrow ) {
203- self . rewind ( checkpoint) ;
204- return true ;
195+ // Use lookahead to avoid checkpoint/rewind
196+ self . lookahead ( |parser| {
197+ parser. bump ( Kind :: Async ) ;
198+ // If the "async" is followed by "=>" token then it is not a beginning of an async arrow-function
199+ // but instead a simple arrow-function which will be parsed inside "parseAssignmentExpressionOrHigher"
200+ if !parser. cur_token ( ) . is_on_new_line ( ) && parser. cur_kind ( ) . is_binding_identifier ( ) {
201+ // Arrow before newline is checked in `parse_simple_arrow_function_expression`
202+ parser. bump_any ( ) ;
203+ parser. at ( Kind :: Arrow )
204+ } else {
205+ false
205206 }
206- }
207- self . rewind ( checkpoint) ;
208- false
207+ } )
209208 }
210209
211210 pub ( crate ) fn parse_simple_arrow_function_expression (
Original file line number Diff line number Diff line change @@ -731,24 +731,26 @@ impl<'a> ParserImpl<'a> {
731731 let mut question_dot = false ;
732732 let is_property_access = if allow_optional_chain && self . at ( Kind :: QuestionDot ) {
733733 // ?.
734- let checkpoint = self . checkpoint ( ) ;
735- self . bump_any ( ) ;
736- let kind = self . cur_kind ( ) ;
737- let is_identifier_or_keyword = kind. is_identifier_or_keyword ( ) ;
738- if kind == Kind :: LBrack
739- || is_identifier_or_keyword
740- || kind. is_template_start_of_tagged_template ( )
734+ // Fast check to avoid checkpoint/rewind in common cases
735+ let next_kind = self . lexer . peek_token ( ) . kind ( ) ;
736+ if next_kind == Kind :: LBrack
737+ || next_kind. is_identifier_or_keyword ( )
738+ || next_kind. is_template_start_of_tagged_template ( )
741739 {
740+ // This is likely a valid optional chain, proceed with normal parsing
741+ self . bump_any ( ) ; // consume ?.
742+ let kind = self . cur_kind ( ) ;
743+ let is_identifier_or_keyword = kind. is_identifier_or_keyword ( ) ;
742744 // ?.[
743745 // ?.something
744746 // ?.template`...`
745747 * in_optional_chain = true ;
746748 question_dot = true ;
747749 is_identifier_or_keyword
748750 } else {
751+ // This is not a valid optional chain pattern, don't consume ?.
749752 // Should be a cold branch here, as most real-world optional chaining will look like
750753 // `?.something` or `?.[expr]`
751- self . rewind ( checkpoint) ;
752754 false
753755 }
754756 } else {
Original file line number Diff line number Diff line change @@ -430,14 +430,15 @@ impl<'a> ParserImpl<'a> {
430430 Kind :: LParen => self . parse_parenthesized_type ( ) ,
431431 Kind :: Import => TSType :: TSImportType ( self . parse_ts_import_type ( ) ) ,
432432 Kind :: Asserts => {
433- let checkpoint = self . checkpoint ( ) ;
434- let asserts_start_span = self . start_span ( ) ;
435- self . bump_any ( ) ; // bump `asserts`
436-
437- if self . is_token_identifier_or_keyword_on_same_line ( ) {
433+ // Use lookahead to check if this is an asserts type predicate
434+ if self . lookahead ( |parser| {
435+ parser. bump ( Kind :: Asserts ) ;
436+ parser. is_token_identifier_or_keyword_on_same_line ( )
437+ } ) {
438+ let asserts_start_span = self . start_span ( ) ;
439+ self . bump_any ( ) ; // bump `asserts`
438440 self . parse_asserts_type_predicate ( asserts_start_span)
439441 } else {
440- self . rewind ( checkpoint) ;
441442 self . parse_type_reference ( )
442443 }
443444 }
You can’t perform that action at this time.
0 commit comments