Skip to main content

swc_ecma_parser/parser/
expr.rs

1use either::Either;
2use swc_atoms::atom;
3use swc_common::{ast_node, util::take::Take, BytePos, Span, Spanned};
4
5use super::*;
6use crate::{
7    error::SyntaxError,
8    parser::{pat::PatType, util::IsSimpleParameterList, Parser},
9};
10
11#[ast_node]
12pub(crate) enum AssignTargetOrSpread {
13    #[tag("ExprOrSpread")]
14    ExprOrSpread(ExprOrSpread),
15    #[tag("*")]
16    Pat(Pat),
17}
18
19impl<I: Tokens> Parser<I> {
20    pub fn parse_expr(&mut self) -> PResult<Box<Expr>> {
21        trace_cur!(self, parse_expr);
22        debug_tracing!(self, "parse_expr");
23        let expr = self.parse_assignment_expr()?;
24        let start = expr.span_lo();
25
26        if self.input_mut().is(Token::Comma) {
27            let mut exprs = vec![expr];
28
29            while self.input_mut().eat(Token::Comma) {
30                exprs.push(self.parse_assignment_expr()?);
31            }
32
33            return Ok(SeqExpr {
34                span: self.span(start),
35                exprs,
36            }
37            .into());
38        }
39
40        Ok(expr)
41    }
42
43    /// AssignmentExpression[+In, ?Yield, ?Await]
44    /// ...AssignmentExpression[+In, ?Yield, ?Await]
45    fn parse_expr_or_spread(&mut self) -> PResult<ExprOrSpread> {
46        trace_cur!(self, parse_expr_or_spread);
47        let start = self.input().cur_pos();
48        if self.input_mut().eat(Token::DotDotDot) {
49            let spread_span = self.span(start);
50            let spread = Some(spread_span);
51            self.allow_in_expr(Self::parse_assignment_expr)
52                .map_err(|err| {
53                    Error::new(
54                        err.span(),
55                        SyntaxError::WithLabel {
56                            inner: Box::new(err),
57                            span: spread_span,
58                            note: "An expression should follow '...'",
59                        },
60                    )
61                })
62                .map(|expr| ExprOrSpread { spread, expr })
63        } else {
64            self.parse_assignment_expr()
65                .map(|expr| ExprOrSpread { spread: None, expr })
66        }
67    }
68
69    ///`parseMaybeAssign` (overridden)
70    #[cfg_attr(
71        feature = "tracing-spans",
72        tracing::instrument(level = "debug", skip_all)
73    )]
74    pub(crate) fn parse_assignment_expr(&mut self) -> PResult<Box<Expr>> {
75        trace_cur!(self, parse_assignment_expr);
76
77        if self.input().syntax().typescript() && self.input().is(Token::JSXTagStart) {
78            // Note: When the JSX plugin is on, type assertions (`<T> x`) aren't valid
79            // syntax.
80            let res = self.try_parse_ts(|p| p.parse_assignment_expr_base().map(Some));
81            if let Some(res) = res {
82                return Ok(res);
83            }
84        }
85
86        self.parse_assignment_expr_base()
87    }
88
89    /// Parse an assignment expression. This includes applications of
90    /// operators like `+=`.
91    ///
92    /// `parseMaybeAssign`
93    #[cfg_attr(feature = "tracing-spans", tracing::instrument(skip_all))]
94    fn parse_assignment_expr_base(&mut self) -> PResult<Box<Expr>> {
95        trace_cur!(self, parse_assignment_expr_base);
96        let start = self.input().cur_span();
97
98        if self.input().syntax().typescript()
99            && (self.input().cur() == Token::Lt || self.input().cur() == Token::JSXTagStart)
100            && (peek!(self).is_some_and(|peek| peek.is_word() || peek == Token::JSXName))
101        {
102            let res = self.do_outside_of_context(Context::WillExpectColonForCond, |p| {
103                p.try_parse_ts(|p| {
104                    let type_parameters = p.parse_ts_type_params(false, true)?;
105
106                    // In TSX mode, type parameters that could be mistaken for JSX
107                    // (single param without constraint and no trailing comma) are not
108                    // allowed. e.g., `<T>() => {}` is invalid in TSX because `<T>`
109                    // looks like JSX.
110                    // Valid alternatives: `<T,>() => {}` or `<T extends unknown>() =>
111                    // {}`
112                    if p.input().syntax().jsx() && type_parameters.params.len() == 1 {
113                        let single_param = &type_parameters.params[0];
114                        // Check if there was a trailing comma by examining spans.
115                        // For `<T>`: decl.span.hi - param.span.hi = 1 (just `>`)
116                        // For `<T,>`: decl.span.hi - param.span.hi > 1 (`,` and `>`)
117                        let has_trailing_comma =
118                            type_parameters.span.hi.0 - single_param.span.hi.0 > 1;
119                        let dominated_by_jsx = single_param.constraint.is_none()
120                            && single_param.default.is_none()
121                            && !has_trailing_comma;
122
123                        if dominated_by_jsx {
124                            return Ok(None);
125                        }
126                    }
127
128                    let mut arrow = p.parse_assignment_expr_base()?;
129                    match *arrow {
130                        Expr::Arrow(ArrowExpr {
131                            ref mut span,
132                            ref mut type_params,
133                            ..
134                        }) => {
135                            *span = Span::new_with_checked(type_parameters.span.lo, span.hi);
136                            *type_params = Some(type_parameters);
137                        }
138                        _ => unexpected!(p, "("),
139                    }
140                    Ok(Some(arrow))
141                })
142            });
143            if let Some(res) = res {
144                if self.input().syntax().disallow_ambiguous_jsx_like() {
145                    self.emit_err(start, SyntaxError::ReservedArrowTypeParam);
146                }
147                return Ok(res);
148            }
149        }
150
151        if self.ctx().contains(Context::InGenerator) && self.input().is(Token::Yield) {
152            return self.parse_yield_expr();
153        }
154
155        let cur = self.input().cur();
156
157        if cur == Token::Error {
158            let err = self.input_mut().expect_error_token_and_bump();
159            return Err(err);
160        }
161
162        self.state_mut().potential_arrow_start =
163            if cur.is_known_ident() || matches!(cur, Token::Ident | Token::Yield | Token::LParen) {
164                Some(self.cur_pos())
165            } else {
166                None
167            };
168
169        let start = self.cur_pos();
170
171        // Try to parse conditional expression.
172        let cond = self.parse_cond_expr()?;
173
174        return_if_arrow!(self, cond);
175
176        match *cond {
177            // if cond is conditional expression but not left-hand-side expression,
178            // just return it.
179            Expr::Cond(..) | Expr::Bin(..) | Expr::Unary(..) | Expr::Update(..) => return Ok(cond),
180            _ => {}
181        }
182
183        self.finish_assignment_expr(start, cond)
184    }
185
186    #[allow(dead_code)]
187    pub(crate) fn parse_member_expr(&mut self) -> PResult<Box<Expr>> {
188        self.parse_member_expr_or_new_expr(false)
189    }
190
191    pub(super) fn parse_unary_expr(&mut self) -> PResult<Box<Expr>> {
192        trace_cur!(self, parse_unary_expr);
193
194        let token_and_span = self.input().get_cur();
195        let start = token_and_span.span.lo;
196        let cur = token_and_span.token;
197
198        if cur == Token::Lt && self.input().syntax().typescript() && !self.input().syntax().jsx() {
199            self.bump(); // consume `<`
200            return if self.input_mut().eat(Token::Const) {
201                self.expect(Token::Gt)?;
202                let expr = self.parse_unary_expr()?;
203                Ok(TsConstAssertion {
204                    span: self.span(start),
205                    expr,
206                }
207                .into())
208            } else {
209                self.parse_ts_type_assertion(start)
210                    .map(Expr::from)
211                    .map(Box::new)
212            };
213        } else if cur == Token::Lt
214            && self.input().syntax().jsx()
215            && self.input_mut().peek().is_some_and(|peek| {
216                peek.is_word() || peek == Token::Gt || peek.should_rescan_into_gt_in_jsx()
217            })
218        {
219            fn into_expr(e: Either<JSXFragment, JSXElement>) -> Box<Expr> {
220                match e {
221                    Either::Left(l) => l.into(),
222                    Either::Right(r) => r.into(),
223                }
224            }
225            return self.parse_jsx_element(true).map(into_expr);
226        } else if matches!(cur, Token::PlusPlus | Token::MinusMinus) {
227            // Parse update expression
228            let op = if cur == Token::PlusPlus {
229                op!("++")
230            } else {
231                op!("--")
232            };
233            self.bump();
234
235            let arg = self.parse_unary_expr()?;
236            let span = Span::new_with_checked(start, arg.span_hi());
237            self.check_assign_target(&arg, false);
238
239            return Ok(UpdateExpr {
240                span,
241                prefix: true,
242                op,
243                arg,
244            }
245            .into());
246        } else if cur == Token::Delete
247            || cur == Token::Void
248            || cur == Token::TypeOf
249            || cur == Token::Plus
250            || cur == Token::Minus
251            || cur == Token::Tilde
252            || cur == Token::Bang
253        {
254            // Parse unary expression
255            let op = if cur == Token::Delete {
256                op!("delete")
257            } else if cur == Token::Void {
258                op!("void")
259            } else if cur == Token::TypeOf {
260                op!("typeof")
261            } else if cur == Token::Plus {
262                op!(unary, "+")
263            } else if cur == Token::Minus {
264                op!(unary, "-")
265            } else if cur == Token::Tilde {
266                op!("~")
267            } else {
268                debug_assert!(cur == Token::Bang);
269                op!("!")
270            };
271            self.bump();
272            let arg_start = self.cur_pos() - BytePos(1);
273            let arg = match self.parse_unary_expr() {
274                Ok(expr) => expr,
275                Err(err) => {
276                    self.emit_error(err);
277                    Invalid {
278                        span: Span::new_with_checked(arg_start, arg_start),
279                    }
280                    .into()
281                }
282            };
283
284            if op == op!("delete") {
285                // Skip emitting TS1102 in TypeScript mode because it's a semantic error
286                // that should be handled by the type checker, not the parser.
287                // See: https://github.com/swc-project/swc/issues/10558
288                if !self.input().syntax().typescript() {
289                    if let Expr::Ident(ref i) = *arg {
290                        self.emit_strict_mode_err(i.span, SyntaxError::TS1102)
291                    }
292                }
293            }
294
295            return Ok(UnaryExpr {
296                span: Span::new_with_checked(start, arg.span_hi()),
297                op,
298                arg,
299            }
300            .into());
301        } else if cur == Token::Await {
302            return self.parse_await_expr(None);
303        }
304
305        // UpdateExpression
306        let expr = self.parse_lhs_expr()?;
307        if let Expr::Arrow { .. } = *expr {
308            return Ok(expr);
309        }
310
311        // Line terminator isn't allowed here.
312        if self.input_mut().had_line_break_before_cur() {
313            return Ok(expr);
314        }
315
316        let cur = self.input().cur();
317        if cur == Token::PlusPlus || cur == Token::MinusMinus {
318            let op = if cur == Token::PlusPlus {
319                op!("++")
320            } else {
321                op!("--")
322            };
323
324            self.check_assign_target(&expr, false);
325            self.bump();
326
327            return Ok(UpdateExpr {
328                span: self.span(expr.span_lo()),
329                prefix: false,
330                op,
331                arg: expr,
332            }
333            .into());
334        }
335        Ok(expr)
336    }
337
338    #[inline(always)]
339    pub(super) fn parse_primary_expr(&mut self) -> PResult<Box<Expr>> {
340        trace_cur!(self, parse_primary_expr);
341        let start = self.input().cur_pos();
342        let can_be_arrow = self
343            .state
344            .potential_arrow_start
345            .map(|s| s == start)
346            .unwrap_or(false);
347        let tok = self.input.cur();
348        match tok {
349            Token::This => return self.parse_this_expr(start),
350            Token::Async => {
351                if let Some(res) = self.try_parse_async_start(can_be_arrow) {
352                    return res;
353                }
354            }
355            Token::LBracket => {
356                return self
357                    .do_outside_of_context(Context::WillExpectColonForCond, Self::parse_array_lit)
358            }
359            Token::LBrace => {
360                return self.parse_object_expr().map(Box::new);
361            }
362            // Handle FunctionExpression and GeneratorExpression
363            Token::Function => {
364                return self.parse_fn_expr();
365            }
366            // Literals
367            Token::Null | Token::True | Token::False | Token::Num | Token::BigInt | Token::Str => {
368                return self.parse_lit().map(|lit| lit.into());
369            }
370            // Regexp
371            Token::Slash | Token::DivEq => {
372                if let Some(res) = self.try_parse_regexp(start) {
373                    return Ok(res);
374                }
375            }
376            Token::LParen => return self.parse_paren_expr_or_arrow_fn(can_be_arrow, None),
377            Token::NoSubstitutionTemplateLiteral => {
378                return Ok(self.parse_no_substitution_template_literal(false)?.into())
379            }
380            Token::TemplateHead => {
381                // parse template literal
382                return Ok(self
383                    .do_outside_of_context(Context::WillExpectColonForCond, |p| p.parse_tpl(false))?
384                    .into());
385            }
386            _ => {}
387        }
388
389        self.parse_primary_expr_rest(start, can_be_arrow)
390    }
391
392    /// Parse call, dot, and `[]`-subscript expressions.
393    #[cfg_attr(
394        feature = "tracing-spans",
395        tracing::instrument(level = "debug", skip_all)
396    )]
397    pub(crate) fn parse_lhs_expr(&mut self) -> PResult<Box<Expr>> {
398        trace_cur!(self, parse_lhs_expr);
399
400        let token_and_span = self.input().get_cur();
401        let start = token_and_span.span.lo;
402        let cur = token_and_span.token;
403
404        // `super()` can't be handled from parse_new_expr()
405        if cur == Token::Super {
406            self.bump(); // eat `super`
407            let obj = Callee::Super(Super {
408                span: self.span(start),
409            });
410            return self.parse_subscripts(obj, false, false);
411        } else if cur == Token::Import {
412            self.bump(); // eat `import`
413            return self.parse_dynamic_import_or_import_meta(start, false);
414        }
415
416        let callee = self.parse_new_expr()?;
417        return_if_arrow!(self, callee);
418
419        let type_args = if self.input().syntax().typescript() && {
420            let cur = self.input().cur();
421            cur == Token::Lt || cur == Token::LShift
422        } {
423            self.try_parse_ts(|p| {
424                let type_args = p.parse_ts_type_args()?;
425                p.assert_and_bump(Token::Gt);
426                if p.input().is(Token::LParen) {
427                    Ok(Some(type_args))
428                } else {
429                    Ok(None)
430                }
431            })
432        } else {
433            None
434        };
435
436        if let Expr::New(ne @ NewExpr { args: None, .. }) = *callee {
437            // If this is parsed using 'NewExpression' rule, just return it.
438            // Because it's not left-recursive.
439            if type_args.is_some() {
440                // This fails with `expected (`
441                expect!(self, Token::LParen);
442            }
443            debug_assert!(
444                self.input().cur() != Token::LParen,
445                "parse_new_expr() should eat paren if it exists"
446            );
447            return Ok(NewExpr { type_args, ..ne }.into());
448        }
449        // 'CallExpr' rule contains 'MemberExpr (...)',
450        // and 'MemberExpr' rule contains 'new MemberExpr (...)'
451
452        if self.input().is(Token::LParen) {
453            // This is parsed using production MemberExpression,
454            // which is left-recursive.
455            let (callee, is_import) = match callee {
456                _ if callee.is_ident_ref_to("import") => (
457                    Callee::Import(Import {
458                        span: callee.span(),
459                        phase: Default::default(),
460                    }),
461                    true,
462                ),
463                _ => (Callee::Expr(callee), false),
464            };
465            let args = self.parse_args(is_import)?;
466
467            let call_expr = match callee {
468                Callee::Expr(e) if unwrap_ts_non_null(&e).is_opt_chain() => OptChainExpr {
469                    span: self.span(start),
470                    base: Box::new(OptChainBase::Call(OptCall {
471                        span: self.span(start),
472                        callee: e,
473                        args,
474                        type_args,
475                        ..Default::default()
476                    })),
477                    optional: false,
478                }
479                .into(),
480                _ => CallExpr {
481                    span: self.span(start),
482
483                    callee,
484                    args,
485                    type_args,
486                    ..Default::default()
487                }
488                .into(),
489            };
490
491            return self.parse_subscripts(Callee::Expr(call_expr), false, false);
492        }
493        if type_args.is_some() {
494            // This fails
495            expect!(self, Token::LParen);
496        }
497
498        // This is parsed using production 'NewExpression', which contains
499        // 'MemberExpression'
500        Ok(callee)
501    }
502
503    #[cfg_attr(
504        feature = "tracing-spans",
505        tracing::instrument(level = "debug", skip_all)
506    )]
507    fn parse_array_lit(&mut self) -> PResult<Box<Expr>> {
508        trace_cur!(self, parse_array_lit);
509
510        let start = self.input().cur_pos();
511
512        self.assert_and_bump(Token::LBracket);
513
514        let mut elems = Vec::with_capacity(8);
515
516        while !self.input().is(Token::RBracket) {
517            if self.input().is(Token::Comma) {
518                expect!(self, Token::Comma);
519                elems.push(None);
520                continue;
521            }
522
523            elems.push(self.allow_in_expr(|p| p.parse_expr_or_spread()).map(Some)?);
524
525            if !self.input().is(Token::RBracket) {
526                expect!(self, Token::Comma);
527                if self.input().is(Token::RBracket) {
528                    let prev_span = self.input().prev_span();
529                    self.state_mut().trailing_commas.insert(start, prev_span);
530                }
531            }
532        }
533
534        expect!(self, Token::RBracket);
535
536        let span = self.span(start);
537        Ok(ArrayLit { span, elems }.into())
538    }
539
540    fn at_possible_async(&mut self, expr: &Expr) -> bool {
541        // TODO(kdy1): !this.state.containsEsc &&
542        self.state().potential_arrow_start == Some(expr.span_lo()) && expr.is_ident_ref_to("async")
543    }
544
545    fn parse_yield_expr(&mut self) -> PResult<Box<Expr>> {
546        let start = self.input().cur_pos();
547        self.assert_and_bump(Token::Yield);
548        debug_assert!(self.ctx().contains(Context::InGenerator));
549
550        // Spec says
551        // YieldExpression cannot be used within the FormalParameters of a generator
552        // function because any expressions that are part of FormalParameters are
553        // evaluated before the resulting generator object is in a resumable state.
554        if self.ctx().contains(Context::InParameters) && !self.ctx().contains(Context::InFunction) {
555            syntax_error!(self, self.input().prev_span(), SyntaxError::YieldParamInGen)
556        }
557
558        let parse_with_arg = |p: &mut Self| {
559            let has_star = p.input_mut().eat(Token::Asterisk);
560            let err_span = p.span(start);
561            let arg = p.parse_assignment_expr().map_err(|err| {
562                Error::new(
563                    err.span(),
564                    SyntaxError::WithLabel {
565                        inner: Box::new(err),
566                        span: err_span,
567                        note: "Tried to parse an argument of yield",
568                    },
569                )
570            })?;
571            Ok(YieldExpr {
572                span: p.span(start),
573                arg: Some(arg),
574                delegate: has_star,
575            }
576            .into())
577        };
578
579        if self.is_general_semi() || {
580            let cur = self.input().cur();
581            cur != Token::Lt
582                && cur != Token::Asterisk
583                && cur != Token::Slash
584                && cur != Token::DivEq
585                && !cur.starts_expr()
586        } {
587            Ok(YieldExpr {
588                span: self.span(start),
589                arg: None,
590                delegate: false,
591            }
592            .into())
593        } else {
594            parse_with_arg(self)
595        }
596    }
597
598    fn parse_tpl_elements(
599        &mut self,
600        is_tagged_tpl: bool,
601    ) -> PResult<(Vec<Box<Expr>>, Vec<TplElement>)> {
602        trace_cur!(self, parse_tpl_elements);
603
604        let mut exprs = Vec::new();
605        let cur_elem = self.parse_template_head(is_tagged_tpl)?;
606        let mut is_tail = cur_elem.tail;
607        let mut quasis = vec![cur_elem];
608
609        while !is_tail {
610            exprs.push(self.allow_in_expr(|p| p.parse_expr())?);
611            let elem = self.parse_tpl_element(is_tagged_tpl)?;
612            is_tail = elem.tail;
613            quasis.push(elem);
614        }
615        Ok((exprs, quasis))
616    }
617
618    fn parse_tagged_tpl(
619        &mut self,
620        tag: Box<Expr>,
621        type_params: Option<Box<TsTypeParamInstantiation>>,
622    ) -> PResult<TaggedTpl> {
623        let tagged_tpl_start = tag.span_lo();
624        trace_cur!(self, parse_tagged_tpl);
625
626        let tpl = Box::new(
627            if self.input_mut().is(Token::NoSubstitutionTemplateLiteral) {
628                self.input_mut().rescan_template_token(true);
629                self.parse_no_substitution_template_literal(true)?
630            } else {
631                self.parse_tpl(true)?
632            },
633        );
634
635        let span = self.span(tagged_tpl_start);
636
637        if tag.is_opt_chain() {
638            self.emit_err(span, SyntaxError::TaggedTplInOptChain);
639        }
640
641        Ok(TaggedTpl {
642            span,
643            tag,
644            type_params,
645            tpl,
646            ..Default::default()
647        })
648    }
649
650    pub(super) fn parse_no_substitution_template_literal(
651        &mut self,
652        is_tagged_tpl: bool,
653    ) -> PResult<Tpl> {
654        let start = self.input.cur_pos();
655        let cur = self.input.cur();
656        let token_span = self.input.cur_span();
657        debug_assert!(matches!(cur, Token::NoSubstitutionTemplateLiteral));
658
659        // exclude the leading and the trailing `\``
660        let span = Span::new_with_checked(token_span.lo + BytePos(1), token_span.hi - BytePos(1));
661        let raw = Atom::new(self.input.iter.read_string(span));
662        let cooked = self.input.expect_template_token_value();
663        let cooked = match cooked {
664            Ok(cooked) => Some(cooked),
665            Err(err) => {
666                if is_tagged_tpl {
667                    None
668                } else {
669                    return Err(err);
670                }
671            }
672        };
673        self.bump();
674
675        Ok(Tpl {
676            span: self.span(start),
677            exprs: vec![],
678            quasis: vec![TplElement {
679                span,
680                tail: true,
681                raw,
682                cooked,
683            }],
684        })
685    }
686
687    fn parse_template_head(&mut self, is_tagged_tpl: bool) -> PResult<TplElement> {
688        let cur = self.input.cur();
689        let token_span = self.input.cur_span();
690        debug_assert!(matches!(cur, Token::TemplateHead));
691
692        // exclude the leading `\`` and the trailing `${`
693        let span = Span::new_with_checked(token_span.lo + BytePos(1), token_span.hi - BytePos(2));
694        let raw = Atom::new(self.input.iter.read_string(span));
695        let cooked = self.input.expect_template_token_value();
696        let cooked = match cooked {
697            Ok(cooked) => Some(cooked),
698            Err(err) => {
699                if is_tagged_tpl {
700                    None
701                } else {
702                    return Err(err);
703                }
704            }
705        };
706
707        self.bump();
708
709        Ok(TplElement {
710            span,
711            raw,
712            tail: false,
713            cooked,
714        })
715    }
716
717    pub(super) fn parse_tpl(&mut self, is_tagged_tpl: bool) -> PResult<Tpl> {
718        trace_cur!(self, parse_tpl);
719        debug_assert!(matches!(self.input.cur(), Token::TemplateHead));
720
721        let start = self.cur_pos();
722
723        let (exprs, quasis) = self.parse_tpl_elements(is_tagged_tpl)?;
724
725        Ok(Tpl {
726            span: self.span(start),
727            exprs,
728            quasis,
729        })
730    }
731
732    pub(crate) fn parse_tpl_element(&mut self, is_tagged_tpl: bool) -> PResult<TplElement> {
733        if self.input_mut().is(Token::RBrace) {
734            self.input_mut().rescan_template_token(false);
735        }
736        let cur = self.input_mut().cur();
737        let token_span = self.input.cur_span();
738
739        let (cooked, raw, tail, span) = match cur {
740            Token::TemplateMiddle => {
741                let span = Span::new_with_checked(token_span.lo, token_span.hi - BytePos(2));
742                let raw = Atom::new(self.input.iter.read_string(span));
743                let cooked = self.input.expect_template_token_value();
744                self.bump();
745
746                match cooked {
747                    Ok(cooked) => (Some(cooked), raw, false, span),
748                    Err(err) => {
749                        if is_tagged_tpl {
750                            (None, raw, false, span)
751                        } else {
752                            return Err(err);
753                        }
754                    }
755                }
756            }
757            Token::TemplateTail => {
758                let span = Span::new_with_checked(token_span.lo, token_span.hi - BytePos(1));
759                let raw = Atom::new(self.input.iter.read_string(span));
760                let cooked = self.input.expect_template_token_value();
761                self.bump();
762
763                match cooked {
764                    Ok(cooked) => (Some(cooked), raw, true, span),
765                    Err(err) => {
766                        if is_tagged_tpl {
767                            (None, raw, true, span)
768                        } else {
769                            return Err(err);
770                        }
771                    }
772                }
773            }
774            Token::Error => {
775                let err = cur.take_error(self.input_mut());
776                self.input_mut().bump();
777                return Err(err);
778            }
779            _ => {
780                unexpected!(self, "`}`")
781            }
782        };
783
784        Ok(TplElement {
785            span,
786            raw,
787            tail,
788            cooked,
789        })
790    }
791
792    #[cfg(feature = "typescript")]
793    fn parse_tpl_ty_elements(&mut self) -> PResult<(Vec<Box<TsType>>, Vec<TplElement>)> {
794        trace_cur!(self, parse_tpl_elements);
795
796        let mut tys = Vec::new();
797        let cur_elem = self.parse_template_head(false)?;
798        let mut is_tail = cur_elem.tail;
799        let mut quasis = vec![cur_elem];
800
801        while !is_tail {
802            tys.push(self.parse_ts_type()?);
803            let elem = self.parse_tpl_element(false)?;
804            is_tail = elem.tail;
805            quasis.push(elem);
806        }
807        Ok((tys, quasis))
808    }
809
810    #[cfg(feature = "typescript")]
811    fn parse_no_substitution_template_ty(&mut self) -> PResult<TsTplLitType> {
812        let start = self.input.cur_pos();
813        let cur = self.input.cur();
814        let token_span = self.input.cur_span();
815        debug_assert!(matches!(cur, Token::NoSubstitutionTemplateLiteral));
816
817        // exclude the leading and the trailing `\``
818        let span = Span::new_with_checked(token_span.lo + BytePos(1), token_span.hi - BytePos(1));
819        let raw = Atom::new(self.input.iter.read_string(span));
820        let cooked = self.input.expect_template_token_value().ok();
821        self.bump();
822
823        Ok(TsTplLitType {
824            span: self.span(start),
825            types: vec![],
826            quasis: vec![TplElement {
827                span,
828                tail: true,
829                raw,
830                cooked,
831            }],
832        })
833    }
834
835    #[cfg(feature = "typescript")]
836    fn parse_tpl_ty(&mut self) -> PResult<TsTplLitType> {
837        trace_cur!(self, parse_tpl_ty);
838        debug_assert!(matches!(self.input.cur(), Token::TemplateHead));
839
840        let start = self.cur_pos();
841
842        let (types, quasis) = self.parse_tpl_ty_elements()?;
843
844        let _ = self.input.cur();
845
846        Ok(TsTplLitType {
847            span: self.span(start),
848            types,
849            quasis,
850        })
851    }
852
853    #[cfg(feature = "typescript")]
854    pub(super) fn parse_tagged_tpl_ty(&mut self) -> PResult<TsLitType> {
855        let start = self.cur_pos();
856        debug_assert!(self.input().syntax().typescript());
857        trace_cur!(self, parse_tagged_tpl);
858        let tpl_ty = if self.input_mut().is(Token::NoSubstitutionTemplateLiteral) {
859            self.parse_no_substitution_template_ty()
860        } else {
861            self.parse_tpl_ty()
862        };
863        tpl_ty.map(|tpl_ty| {
864            let lit = TsLit::Tpl(tpl_ty);
865            TsLitType {
866                span: self.span(start),
867                lit,
868            }
869        })
870    }
871
872    pub(crate) fn parse_str_lit(&mut self) -> swc_ecma_ast::Str {
873        debug_assert!(self.input().cur() == Token::Str);
874        let start = self.input().get_cur().span.lo;
875        let raw = Atom::new(self.input.cur_string());
876        let value = self.input.expect_string_token_value();
877        self.bump();
878
879        swc_ecma_ast::Str {
880            span: self.span(start),
881            value,
882            raw: Some(raw),
883        }
884    }
885
886    pub(crate) fn parse_lit(&mut self) -> PResult<Lit> {
887        let token_and_span = self.input().get_cur();
888        let start = token_and_span.span.lo;
889        let cur = token_and_span.token;
890        let v = if cur == Token::Null {
891            self.bump();
892            let span = self.span(start);
893            Lit::Null(swc_ecma_ast::Null { span })
894        } else if cur == Token::True || cur == Token::False {
895            let value = cur == Token::True;
896            self.bump();
897            let span = self.span(start);
898            Lit::Bool(swc_ecma_ast::Bool { span, value })
899        } else if cur == Token::Str {
900            Lit::Str(self.parse_str_lit())
901        } else if cur == Token::Num {
902            let raw = Atom::new(self.input.cur_string());
903            let value = self.input_mut().expect_number_token_value();
904            self.bump();
905
906            Lit::Num(swc_ecma_ast::Number {
907                span: self.span(start),
908                value,
909                raw: Some(raw),
910            })
911        } else if cur == Token::BigInt {
912            let raw = Atom::new(self.input.cur_string());
913            let value = self.input_mut().expect_bigint_token_value();
914            self.bump();
915
916            Lit::BigInt(swc_ecma_ast::BigInt {
917                span: self.span(start),
918                value,
919                raw: Some(raw),
920            })
921        } else if cur == Token::Error {
922            let err = self.input_mut().expect_error_token_and_bump();
923            return Err(err);
924        } else if cur == Token::Eof {
925            return Err(self.eof_error());
926        } else {
927            unreachable!("parse_lit should not be called for {:?}", cur)
928        };
929        Ok(v)
930    }
931
932    /// Parse `Arguments[Yield, Await]`
933    #[cfg_attr(feature = "tracing-spans", tracing::instrument(skip_all))]
934    pub(crate) fn parse_args(&mut self, is_dynamic_import: bool) -> PResult<Vec<ExprOrSpread>> {
935        trace_cur!(self, parse_args);
936
937        self.do_outside_of_context(Context::WillExpectColonForCond, |p| {
938            let start = p.cur_pos();
939            expect!(p, Token::LParen);
940
941            let mut first = true;
942            let mut expr_or_spreads = Vec::with_capacity(2);
943
944            while !p.input().is(Token::RParen) {
945                if first {
946                    first = false;
947                } else {
948                    expect!(p, Token::Comma);
949                    // Handle trailing comma.
950                    if p.input().is(Token::RParen) {
951                        if is_dynamic_import && !p.input().syntax().import_attributes() {
952                            syntax_error!(p, p.span(start), SyntaxError::TrailingCommaInsideImport)
953                        }
954
955                        break;
956                    }
957                }
958
959                expr_or_spreads.push(p.allow_in_expr(|p| p.parse_expr_or_spread())?);
960            }
961
962            expect!(p, Token::RParen);
963            Ok(expr_or_spreads)
964        })
965    }
966
967    fn finish_assignment_expr(&mut self, start: BytePos, cond: Box<Expr>) -> PResult<Box<Expr>> {
968        trace_cur!(self, finish_assignment_expr);
969
970        if let Some(op) = self.input().cur().as_assign_op() {
971            let left = if op == AssignOp::Assign {
972                match AssignTarget::try_from(self.reparse_expr_as_pat(PatType::AssignPat, cond)?) {
973                    Ok(pat) => pat,
974                    Err(expr) => {
975                        syntax_error!(self, expr.span(), SyntaxError::InvalidAssignTarget)
976                    }
977                }
978            } else {
979                // It is an early Reference Error if IsValidSimpleAssignmentTarget of
980                // LeftHandSideExpression is false.
981                if !cond.is_valid_simple_assignment_target(self.ctx().contains(Context::Strict)) {
982                    if self.input().syntax().typescript() {
983                        self.emit_err(cond.span(), SyntaxError::TS2406);
984                    } else {
985                        self.emit_err(cond.span(), SyntaxError::NotSimpleAssign)
986                    }
987                }
988                if self.input().syntax().typescript()
989                    && cond
990                        .as_ident()
991                        .map(|i| i.is_reserved_in_strict_bind())
992                        .unwrap_or(false)
993                {
994                    self.emit_strict_mode_err(cond.span(), SyntaxError::TS1100);
995                }
996
997                // TODO
998                match AssignTarget::try_from(cond) {
999                    Ok(v) => v,
1000                    Err(v) => {
1001                        syntax_error!(self, v.span(), SyntaxError::InvalidAssignTarget);
1002                    }
1003                }
1004            };
1005
1006            self.bump();
1007            let right = self.parse_assignment_expr()?;
1008            Ok(AssignExpr {
1009                span: self.span(start),
1010                op,
1011                // TODO:
1012                left,
1013                right,
1014            }
1015            .into())
1016        } else {
1017            Ok(cond)
1018        }
1019    }
1020
1021    /// Spec: 'ConditionalExpression'
1022    #[cfg_attr(
1023        feature = "tracing-spans",
1024        tracing::instrument(level = "debug", skip_all)
1025    )]
1026    fn parse_cond_expr(&mut self) -> PResult<Box<Expr>> {
1027        trace_cur!(self, parse_cond_expr);
1028
1029        let start = self.cur_pos();
1030
1031        let test = self.parse_bin_expr()?;
1032        return_if_arrow!(self, test);
1033
1034        if self.input_mut().eat(Token::QuestionMark) {
1035            let cons = self.do_inside_of_context(
1036                Context::InCondExpr
1037                    .union(Context::WillExpectColonForCond)
1038                    .union(Context::IncludeInExpr),
1039                Self::parse_assignment_expr,
1040            )?;
1041
1042            expect!(self, Token::Colon);
1043
1044            let alt = self.do_inside_of_context(Context::InCondExpr, |p| {
1045                p.do_outside_of_context(
1046                    Context::WillExpectColonForCond,
1047                    Self::parse_assignment_expr,
1048                )
1049            })?;
1050
1051            let span = Span::new_with_checked(start, alt.span_hi());
1052            Ok(CondExpr {
1053                span,
1054                test,
1055                cons,
1056                alt,
1057            }
1058            .into())
1059        } else {
1060            Ok(test)
1061        }
1062    }
1063
1064    #[cfg_attr(feature = "tracing-spans", tracing::instrument(skip_all))]
1065    pub(crate) fn parse_subscripts(
1066        &mut self,
1067        obj: Callee,
1068        no_call: bool,
1069        no_computed_member: bool,
1070    ) -> PResult<Box<Expr>> {
1071        let start = obj.span().lo;
1072        let mut expr = match obj {
1073            Callee::Import(import) => self.parse_subscript_import_call(start, import)?,
1074            Callee::Super(s) => self.parse_subscript_super(start, s, no_call)?,
1075            Callee::Expr(expr) => expr,
1076            #[cfg(swc_ast_unknown)]
1077            _ => unreachable!(),
1078        };
1079
1080        loop {
1081            expr = match self.parse_subscript(start, expr, no_call, no_computed_member)? {
1082                (expr, false) => return Ok(expr),
1083                (expr, true) => expr,
1084            }
1085        }
1086    }
1087
1088    /// returned bool is true if this method should be called again.
1089    #[cfg_attr(feature = "tracing-spans", tracing::instrument(skip_all))]
1090    fn parse_subscript(
1091        &mut self,
1092        start: BytePos,
1093        mut callee: Box<Expr>,
1094        no_call: bool,
1095        no_computed_member: bool,
1096    ) -> PResult<(Box<Expr>, bool)> {
1097        trace_cur!(self, parse_subscript);
1098
1099        if self.input().syntax().typescript() {
1100            if !self.input().had_line_break_before_cur() && self.input().is(Token::Bang) {
1101                self.input_mut().set_expr_allowed(false);
1102                self.assert_and_bump(Token::Bang);
1103
1104                let expr = Box::new(Expr::TsNonNull(TsNonNullExpr {
1105                    span: self.span(start),
1106                    expr: callee,
1107                }));
1108
1109                return Ok((expr, true));
1110            }
1111
1112            if self.input().is(Token::Lt) {
1113                // tsTryParseAndCatch is expensive, so avoid if not necessary.
1114                // There are number of things we are going to "maybe" parse, like type arguments
1115                // on tagged template expressions. If any of them fail, walk it back and
1116                // continue.
1117
1118                let result = self.do_inside_of_context(Context::ShouldNotLexLtOrGtAsType, |p| {
1119                    p.try_parse_ts(|p| {
1120                        if !no_call && p.at_possible_async(&callee) {
1121                            // Almost certainly this is a generic async function `async <T>() =>
1122                            // ... But it might be a call with a
1123                            // type argument `async<T>();`
1124                            let async_arrow_fn = p.try_parse_ts_generic_async_arrow_fn(start)?;
1125                            if let Some(async_arrow_fn) = async_arrow_fn {
1126                                return Ok(Some((async_arrow_fn.into(), true)));
1127                            }
1128                        }
1129
1130                        let type_args = p.parse_ts_type_args()?;
1131                        p.assert_and_bump(Token::Gt);
1132                        let cur = p.input().cur();
1133
1134                        if !no_call && cur == Token::LParen {
1135                            // possibleAsync always false here, because we would have handled it
1136                            // above. (won't be any undefined arguments)
1137                            let args = p.parse_args(false)?;
1138
1139                            let expr = if callee.is_opt_chain() {
1140                                Expr::OptChain(OptChainExpr {
1141                                    span: p.span(start),
1142                                    base: Box::new(OptChainBase::Call(OptCall {
1143                                        span: p.span(start),
1144                                        callee: callee.take(),
1145                                        type_args: Some(type_args),
1146                                        args,
1147                                        ..Default::default()
1148                                    })),
1149                                    optional: false,
1150                                })
1151                            } else {
1152                                Expr::Call(CallExpr {
1153                                    span: p.span(start),
1154                                    callee: Callee::Expr(callee.take()),
1155                                    type_args: Some(type_args),
1156                                    args,
1157                                    ..Default::default()
1158                                })
1159                            };
1160
1161                            Ok(Some((Box::new(expr), true)))
1162                        } else if matches!(
1163                            cur,
1164                            Token::NoSubstitutionTemplateLiteral
1165                                | Token::TemplateHead
1166                                | Token::BackQuote
1167                        ) {
1168                            p.parse_tagged_tpl(callee.take(), Some(type_args))
1169                                .map(|expr| (expr.into(), true))
1170                                .map(Some)
1171                        } else if matches!(cur, Token::Eq | Token::As | Token::Satisfies) {
1172                            let expr = Expr::TsInstantiation(TsInstantiation {
1173                                span: p.span(start),
1174                                expr: callee.take(),
1175                                type_args,
1176                            });
1177                            Ok(Some((Box::new(expr), false)))
1178                        } else if no_call {
1179                            unexpected!(p, "`")
1180                        } else {
1181                            unexpected!(p, "( or `")
1182                        }
1183                    })
1184                });
1185
1186                if let Some(expr) = result {
1187                    return Ok(expr);
1188                }
1189            }
1190        }
1191
1192        let ts_instantiation = if self.syntax().typescript() && self.input().is(Token::Lt) {
1193            self.try_parse_ts_type_args()
1194        } else {
1195            None
1196        };
1197
1198        let question_dot_token = if self.input().is(Token::QuestionMark)
1199            && peek!(self).is_some_and(|peek| peek == Token::Dot)
1200        {
1201            let start = self.cur_pos();
1202            self.bump();
1203
1204            let span = Some(self.span(start));
1205            self.bump();
1206
1207            span
1208        } else {
1209            None
1210        };
1211
1212        // If question_dot_token is Some, then `self.cur == Token::Dot`
1213        let question_dot = question_dot_token.is_some();
1214
1215        // $obj[name()]
1216        if !no_computed_member && self.input_mut().eat(Token::LBracket) {
1217            let bracket_lo = self.input().prev_span().lo;
1218            let prop = self.allow_in_expr(|p| p.parse_expr())?;
1219            expect!(self, Token::RBracket);
1220            let span = Span::new_with_checked(callee.span_lo(), self.input().last_pos());
1221            debug_assert_eq!(callee.span_lo(), span.lo());
1222            let prop = ComputedPropName {
1223                span: Span::new_with_checked(bracket_lo, self.input().last_pos()),
1224                expr: prop,
1225            };
1226
1227            let type_args = if self.syntax().typescript() && self.input().is(Token::Lt) {
1228                self.try_parse_ts_type_args()
1229            } else {
1230                None
1231            };
1232
1233            let is_opt_chain = unwrap_ts_non_null(&callee).is_opt_chain();
1234            let expr = MemberExpr {
1235                span,
1236                obj: callee,
1237                prop: MemberProp::Computed(prop),
1238            };
1239            let expr = if is_opt_chain || question_dot {
1240                OptChainExpr {
1241                    span,
1242                    optional: question_dot,
1243                    base: Box::new(OptChainBase::Member(expr)),
1244                }
1245                .into()
1246            } else {
1247                expr.into()
1248            };
1249
1250            let expr = if let Some(type_args) = type_args {
1251                Expr::TsInstantiation(TsInstantiation {
1252                    expr: Box::new(expr),
1253                    type_args,
1254                    span: self.span(start),
1255                })
1256            } else {
1257                expr
1258            };
1259            return Ok((Box::new(expr), true));
1260        }
1261
1262        let type_args = if self.syntax().typescript() && self.input().is(Token::Lt) && question_dot
1263        {
1264            let ret = self.parse_ts_type_args()?;
1265            self.assert_and_bump(Token::Gt);
1266            Some(ret)
1267        } else {
1268            None
1269        };
1270
1271        if (self.input.is(Token::LParen) && (!no_call || question_dot)) || type_args.is_some() {
1272            let args = self.parse_args(false)?;
1273            let span = self.span(start);
1274            return if question_dot || unwrap_ts_non_null(&callee).is_opt_chain() {
1275                let expr = OptChainExpr {
1276                    span,
1277                    optional: question_dot,
1278                    base: Box::new(OptChainBase::Call(OptCall {
1279                        span: self.span(start),
1280                        callee,
1281                        args,
1282                        type_args,
1283                        ..Default::default()
1284                    })),
1285                };
1286                Ok((Box::new(Expr::OptChain(expr)), true))
1287            } else {
1288                let expr = CallExpr {
1289                    span: self.span(start),
1290                    callee: Callee::Expr(callee),
1291                    args,
1292                    ..Default::default()
1293                };
1294                Ok((Box::new(Expr::Call(expr)), true))
1295            };
1296        }
1297
1298        // member expression
1299        // $obj.name
1300        if question_dot || self.input_mut().eat(Token::Dot) {
1301            let prop = self.parse_maybe_private_name().map(|e| match e {
1302                Either::Left(p) => MemberProp::PrivateName(p),
1303                Either::Right(i) => MemberProp::Ident(i),
1304            })?;
1305            let span = self.span(callee.span_lo());
1306            debug_assert_eq!(callee.span_lo(), span.lo());
1307            debug_assert_eq!(prop.span_hi(), span.hi());
1308
1309            let type_args = if self.syntax().typescript() && self.input().is(Token::Lt) {
1310                self.try_parse_ts_type_args()
1311            } else {
1312                None
1313            };
1314
1315            let expr = MemberExpr {
1316                span,
1317                obj: callee,
1318                prop,
1319            };
1320            let expr = if unwrap_ts_non_null(&expr.obj).is_opt_chain() || question_dot {
1321                OptChainExpr {
1322                    span: self.span(start),
1323                    optional: question_dot,
1324                    base: Box::new(OptChainBase::Member(expr)),
1325                }
1326                .into()
1327            } else {
1328                expr.into()
1329            };
1330
1331            let expr = if let Some(type_args) = type_args {
1332                Expr::TsInstantiation(TsInstantiation {
1333                    expr: Box::new(expr),
1334                    type_args,
1335                    span: self.span(start),
1336                })
1337            } else {
1338                expr
1339            };
1340
1341            return Ok((Box::new(expr), true));
1342        }
1343
1344        let expr = if let Some(type_args) = ts_instantiation {
1345            TsInstantiation {
1346                expr: callee,
1347                type_args,
1348                span: self.span(start),
1349            }
1350            .into()
1351        } else {
1352            callee
1353        };
1354
1355        // MemberExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged]
1356        let cur = self.input().cur();
1357        if matches!(
1358            cur,
1359            Token::TemplateHead | Token::NoSubstitutionTemplateLiteral | Token::BackQuote
1360        ) {
1361            let tpl = self.do_outside_of_context(Context::WillExpectColonForCond, |p| {
1362                p.parse_tagged_tpl(expr, None)
1363            })?;
1364            return Ok((tpl.into(), true));
1365        }
1366
1367        Ok((expr, false))
1368    }
1369
1370    /// Section 13.3 ImportCall
1371    #[cfg_attr(feature = "tracing-spans", tracing::instrument(skip_all))]
1372    fn parse_subscript_super(
1373        &mut self,
1374        start: BytePos,
1375        lhs: Super,
1376        no_call: bool,
1377    ) -> PResult<Box<Expr>> {
1378        trace_cur!(self, parse_subscript_super);
1379        match self.input().cur() {
1380            Token::LBracket => {
1381                self.bump();
1382                let bracket_lo = self.input().prev_span().lo;
1383                let prop = self.allow_in_expr(|p| p.parse_expr())?;
1384                expect!(self, Token::RBracket);
1385                let span = Span::new_with_checked(lhs.span_lo(), self.input().last_pos());
1386                debug_assert_eq!(lhs.span_lo(), span.lo());
1387                let prop = ComputedPropName {
1388                    span: Span::new_with_checked(bracket_lo, self.input().last_pos()),
1389                    expr: prop,
1390                };
1391
1392                if !self.ctx().contains(Context::AllowDirectSuper)
1393                    && !self.input().syntax().allow_super_outside_method()
1394                {
1395                    syntax_error!(self, lhs.span, SyntaxError::InvalidSuper)
1396                } else {
1397                    Ok(Box::new(Expr::SuperProp(SuperPropExpr {
1398                        span,
1399                        obj: lhs,
1400                        prop: SuperProp::Computed(prop),
1401                    })))
1402                }
1403            }
1404            Token::LParen if !no_call => {
1405                let args = self.parse_args(false)?;
1406                Ok(Box::new(Expr::Call(CallExpr {
1407                    span: self.span(start),
1408                    callee: Callee::Super(lhs),
1409                    args,
1410                    ..Default::default()
1411                })))
1412            }
1413            Token::Dot => {
1414                self.bump();
1415                let prop = self.parse_maybe_private_name().map(|e| match e {
1416                    Either::Left(p) => MemberProp::PrivateName(p),
1417                    Either::Right(i) => MemberProp::Ident(i),
1418                })?;
1419                let span = self.span(lhs.span_lo());
1420                debug_assert_eq!(lhs.span_lo(), span.lo());
1421                debug_assert_eq!(prop.span_hi(), span.hi());
1422
1423                if !self.ctx().contains(Context::AllowDirectSuper)
1424                    && !self.input().syntax().allow_super_outside_method()
1425                {
1426                    syntax_error!(self, lhs.span, SyntaxError::InvalidSuper);
1427                } else {
1428                    let expr = match prop {
1429                        MemberProp::Ident(ident) => SuperPropExpr {
1430                            span,
1431                            obj: lhs,
1432                            prop: SuperProp::Ident(ident),
1433                        },
1434                        MemberProp::PrivateName(..) => {
1435                            syntax_error!(
1436                                self,
1437                                self.input().cur_span(),
1438                                SyntaxError::InvalidSuperCall
1439                            )
1440                        }
1441                        MemberProp::Computed(..) => unreachable!(),
1442                        #[cfg(swc_ast_unknown)]
1443                        _ => unreachable!(),
1444                    };
1445
1446                    Ok(Box::new(Expr::SuperProp(expr)))
1447                }
1448            }
1449            _ => {
1450                if no_call {
1451                    syntax_error!(self, self.input().cur_span(), SyntaxError::InvalidSuperCall)
1452                } else {
1453                    syntax_error!(self, self.input().cur_span(), SyntaxError::InvalidSuper)
1454                }
1455            }
1456        }
1457    }
1458
1459    /// Section 13.3 ImportCall
1460    #[cfg_attr(feature = "tracing-spans", tracing::instrument(skip_all))]
1461    fn parse_subscript_import_call(&mut self, start: BytePos, lhs: Import) -> PResult<Box<Expr>> {
1462        trace_cur!(self, parse_subscript_import);
1463
1464        if self.input().is(Token::LParen) {
1465            let args = self.parse_args(true)?;
1466
1467            // Dynamic import requires exactly one or two arguments
1468            if args.is_empty() || args.len() > 2 {
1469                syntax_error!(
1470                    self,
1471                    self.span(start),
1472                    SyntaxError::ImportRequiresOneOrTwoArgs
1473                );
1474            }
1475
1476            let expr = Box::new(Expr::Call(CallExpr {
1477                span: self.span(start),
1478                callee: Callee::Import(lhs),
1479                args,
1480                ..Default::default()
1481            }));
1482            return Ok(expr);
1483        }
1484
1485        syntax_error!(self, self.input().cur_span(), SyntaxError::InvalidImport);
1486    }
1487
1488    fn parse_dynamic_import_or_import_meta(
1489        &mut self,
1490        start: BytePos,
1491        no_call: bool,
1492    ) -> PResult<Box<Expr>> {
1493        if self.input_mut().eat(Token::Dot) {
1494            self.mark_found_module_item();
1495
1496            let ident = self.parse_ident_name()?;
1497
1498            match &*ident.sym {
1499                "meta" => {
1500                    let span = self.span(start);
1501                    if !self.ctx().contains(Context::CanBeModule) {
1502                        self.emit_err(span, SyntaxError::ImportMetaInScript);
1503                    }
1504                    let expr = MetaPropExpr {
1505                        span,
1506                        kind: MetaPropKind::ImportMeta,
1507                    };
1508                    self.parse_subscripts(Callee::Expr(expr.into()), no_call, false)
1509                }
1510                "defer" => self.parse_dynamic_import_call(start, ImportPhase::Defer),
1511                "source" => self.parse_dynamic_import_call(start, ImportPhase::Source),
1512                _ => unexpected!(self, "meta"),
1513            }
1514        } else {
1515            self.parse_dynamic_import_call(start, ImportPhase::Evaluation)
1516        }
1517    }
1518
1519    fn parse_dynamic_import_call(
1520        &mut self,
1521        start: BytePos,
1522        phase: ImportPhase,
1523    ) -> PResult<Box<Expr>> {
1524        let import = Callee::Import(Import {
1525            span: self.span(start),
1526            phase,
1527        });
1528        self.parse_subscripts(import, false, false)
1529    }
1530
1531    /// `is_new_expr`: true iff we are parsing production 'NewExpression'.
1532    #[cfg_attr(
1533        feature = "tracing-spans",
1534        tracing::instrument(level = "debug", skip_all)
1535    )]
1536    fn parse_member_expr_or_new_expr(&mut self, is_new_expr: bool) -> PResult<Box<Expr>> {
1537        self.do_inside_of_context(Context::ShouldNotLexLtOrGtAsType, |p| {
1538            p.parse_member_expr_or_new_expr_inner(is_new_expr)
1539        })
1540    }
1541
1542    fn parse_member_expr_or_new_expr_inner(&mut self, is_new_expr: bool) -> PResult<Box<Expr>> {
1543        trace_cur!(self, parse_member_expr_or_new_expr);
1544
1545        let start = self.cur_pos();
1546        if self.input_mut().eat(Token::New) {
1547            if self.input_mut().eat(Token::Dot) {
1548                if self.input_mut().eat(Token::Target) {
1549                    let span = self.span(start);
1550                    let expr = MetaPropExpr {
1551                        span,
1552                        kind: MetaPropKind::NewTarget,
1553                    }
1554                    .into();
1555
1556                    let ctx = self.ctx();
1557                    if !ctx.contains(Context::InsideNonArrowFunctionScope)
1558                        && !ctx.contains(Context::InParameters)
1559                        && !ctx.contains(Context::InClass)
1560                    {
1561                        self.emit_err(span, SyntaxError::InvalidNewTarget);
1562                    }
1563
1564                    return self.parse_subscripts(Callee::Expr(expr), true, false);
1565                }
1566
1567                unexpected!(self, "target")
1568            }
1569
1570            // 'NewExpression' allows new call without paren.
1571            let callee = self.parse_member_expr_or_new_expr(is_new_expr)?;
1572            return_if_arrow!(self, callee);
1573
1574            if is_new_expr {
1575                match *callee {
1576                    Expr::OptChain(OptChainExpr {
1577                        span,
1578                        optional: true,
1579                        ..
1580                    }) => {
1581                        syntax_error!(self, span, SyntaxError::OptChainCannotFollowConstructorCall)
1582                    }
1583                    Expr::Member(MemberExpr { ref obj, .. }) => {
1584                        if let Expr::OptChain(OptChainExpr {
1585                            span,
1586                            optional: true,
1587                            ..
1588                        }) = **obj
1589                        {
1590                            syntax_error!(
1591                                self,
1592                                span,
1593                                SyntaxError::OptChainCannotFollowConstructorCall
1594                            )
1595                        }
1596                    }
1597                    _ => {}
1598                }
1599            }
1600
1601            let type_args = if self.input().syntax().typescript() && {
1602                let cur = self.input().cur();
1603                cur == Token::Lt || cur == Token::LShift
1604            } {
1605                self.try_parse_ts(|p| {
1606                    let args = p.do_outside_of_context(
1607                        Context::ShouldNotLexLtOrGtAsType,
1608                        Self::parse_ts_type_args,
1609                    )?;
1610                    p.assert_and_bump(Token::Gt);
1611                    if !p.input().is(Token::LParen) {
1612                        let span = p.input().cur_span();
1613                        let cur = p.input_mut().dump_cur();
1614                        syntax_error!(p, span, SyntaxError::Expected('('.to_string(), cur))
1615                    }
1616                    Ok(Some(args))
1617                })
1618            } else {
1619                None
1620            };
1621
1622            if !is_new_expr || self.input().is(Token::LParen) {
1623                // Parsed with 'MemberExpression' production.
1624                let args = self.parse_args(false).map(Some)?;
1625
1626                let new_expr = Callee::Expr(
1627                    NewExpr {
1628                        span: self.span(start),
1629                        callee,
1630                        args,
1631                        type_args,
1632                        ..Default::default()
1633                    }
1634                    .into(),
1635                );
1636
1637                // We should parse subscripts for MemberExpression.
1638                // Because it's left recursive.
1639                return self.parse_subscripts(new_expr, true, false);
1640            }
1641
1642            // Parsed with 'NewExpression' production.
1643
1644            return Ok(NewExpr {
1645                span: self.span(start),
1646                callee,
1647                args: None,
1648                type_args,
1649                ..Default::default()
1650            }
1651            .into());
1652        }
1653
1654        if self.input_mut().eat(Token::Super) {
1655            let base = Callee::Super(Super {
1656                span: self.span(start),
1657            });
1658            return self.parse_subscripts(base, true, false);
1659        } else if self.input_mut().eat(Token::Import) {
1660            return self.parse_dynamic_import_or_import_meta(start, true);
1661        }
1662        let obj = self.parse_primary_expr()?;
1663        return_if_arrow!(self, obj);
1664
1665        let type_args = if self.syntax().typescript() && self.input().is(Token::Lt) {
1666            self.try_parse_ts_type_args()
1667        } else {
1668            None
1669        };
1670        let obj = if let Some(type_args) = type_args {
1671            trace_cur!(self, parse_member_expr_or_new_expr__with_type_args);
1672            TsInstantiation {
1673                expr: obj,
1674                type_args,
1675                span: self.span(start),
1676            }
1677            .into()
1678        } else {
1679            obj
1680        };
1681
1682        self.parse_subscripts(Callee::Expr(obj), true, false)
1683    }
1684
1685    /// Parse `NewExpression`.
1686    /// This includes `MemberExpression`.
1687    #[cfg_attr(feature = "tracing-spans", tracing::instrument(skip_all))]
1688    pub(crate) fn parse_new_expr(&mut self) -> PResult<Box<Expr>> {
1689        trace_cur!(self, parse_new_expr);
1690        self.parse_member_expr_or_new_expr(true)
1691    }
1692
1693    /// Name from spec: 'LogicalORExpression'
1694    pub(crate) fn parse_bin_expr(&mut self) -> PResult<Box<Expr>> {
1695        trace_cur!(self, parse_bin_expr);
1696
1697        let left = match self.parse_unary_expr() {
1698            Ok(v) => v,
1699            Err(err) => {
1700                trace_cur!(self, parse_bin_expr__recovery_unary_err);
1701
1702                let cur = self.input().cur();
1703                if cur == Token::Error {
1704                    let err = self.input_mut().expect_error_token_and_bump();
1705                    return Err(err);
1706                } else if (cur == Token::In && self.ctx().contains(Context::IncludeInExpr))
1707                    || cur == Token::InstanceOf
1708                    || cur.is_bin_op()
1709                {
1710                    self.emit_err(self.input().cur_span(), SyntaxError::TS1109);
1711                    Invalid { span: err.span() }.into()
1712                } else {
1713                    return Err(err);
1714                }
1715            }
1716        };
1717
1718        return_if_arrow!(self, left);
1719        self.parse_bin_op_recursively(left, 0)
1720    }
1721
1722    /// Parse binary operators with the operator precedence parsing
1723    /// algorithm. `left` is the left-hand side of the operator.
1724    /// `minPrec` provides context that allows the function to stop and
1725    /// defer further parser to one of its callers when it encounters an
1726    /// operator that has a lower precedence than the set it is parsing.
1727    ///
1728    /// `parseExprOp`
1729    pub(crate) fn parse_bin_op_recursively(
1730        &mut self,
1731        mut left: Box<Expr>,
1732        mut min_prec: u8,
1733    ) -> PResult<Box<Expr>> {
1734        loop {
1735            let (next_left, next_prec) = self.parse_bin_op_recursively_inner(left, min_prec)?;
1736
1737            match &*next_left {
1738                Expr::Bin(BinExpr {
1739                    span,
1740                    left,
1741                    op: op!("&&"),
1742                    ..
1743                })
1744                | Expr::Bin(BinExpr {
1745                    span,
1746                    left,
1747                    op: op!("||"),
1748                    ..
1749                }) => {
1750                    if let Expr::Bin(BinExpr { op: op!("??"), .. }) = &**left {
1751                        self.emit_err(*span, SyntaxError::NullishCoalescingWithLogicalOp);
1752                    }
1753                }
1754                _ => {}
1755            }
1756
1757            min_prec = match next_prec {
1758                Some(v) => v,
1759                None => return Ok(next_left),
1760            };
1761
1762            left = next_left;
1763        }
1764    }
1765
1766    /// Returns `(left, Some(next_prec))` or `(expr, None)`.
1767    fn parse_bin_op_recursively_inner(
1768        &mut self,
1769        left: Box<Expr>,
1770        min_prec: u8,
1771    ) -> PResult<(Box<Expr>, Option<u8>)> {
1772        const PREC_OF_IN: u8 = 7;
1773
1774        if self.input().syntax().typescript() && !self.input().had_line_break_before_cur() {
1775            if PREC_OF_IN > min_prec && self.input().is(Token::As) {
1776                let start = left.span_lo();
1777                let expr = left;
1778                let node = if peek!(self).is_some_and(|cur| cur == Token::Const) {
1779                    self.bump(); // as
1780                    self.bump(); // const
1781                    TsConstAssertion {
1782                        span: self.span(start),
1783                        expr,
1784                    }
1785                    .into()
1786                } else {
1787                    let type_ann = self.next_then_parse_ts_type()?;
1788                    TsAsExpr {
1789                        span: self.span(start),
1790                        expr,
1791                        type_ann,
1792                    }
1793                    .into()
1794                };
1795
1796                return self.parse_bin_op_recursively_inner(node, min_prec);
1797            } else if self.input().is(Token::Satisfies) {
1798                let start = left.span_lo();
1799                let expr = left;
1800                let node = {
1801                    let type_ann = self.next_then_parse_ts_type()?;
1802                    TsSatisfiesExpr {
1803                        span: self.span(start),
1804                        expr,
1805                        type_ann,
1806                    }
1807                    .into()
1808                };
1809
1810                return self.parse_bin_op_recursively_inner(node, min_prec);
1811            }
1812        }
1813
1814        // Return left on eof
1815        let cur = self.input().cur();
1816        let op = if cur == Token::In && self.ctx().contains(Context::IncludeInExpr) {
1817            op!("in")
1818        } else if cur == Token::InstanceOf {
1819            op!("instanceof")
1820        } else if let Some(op) = cur.as_bin_op() {
1821            op
1822        } else {
1823            return Ok((left, None));
1824        };
1825
1826        if op.precedence() <= min_prec {
1827            if cfg!(feature = "debug") {
1828                tracing::trace!(
1829                    "returning {:?} without parsing {:?} because min_prec={}, prec={}",
1830                    left,
1831                    op,
1832                    min_prec,
1833                    op.precedence()
1834                );
1835            }
1836
1837            return Ok((left, None));
1838        }
1839        self.bump();
1840        if cfg!(feature = "debug") {
1841            tracing::trace!(
1842                "parsing binary op {:?} min_prec={}, prec={}",
1843                op,
1844                min_prec,
1845                op.precedence()
1846            );
1847        }
1848        match *left {
1849            // This is invalid syntax.
1850            Expr::Unary { .. } | Expr::Await(..) if op == op!("**") => {
1851                // Correct implementation would be returning Ok(left) and
1852                // returning "unexpected token '**'" on next.
1853                // But it's not useful error message.
1854
1855                syntax_error!(
1856                    self,
1857                    SyntaxError::UnaryInExp {
1858                        // FIXME: Use display
1859                        left: format!("{left:?}"),
1860                        left_span: left.span(),
1861                    }
1862                )
1863            }
1864            _ => {}
1865        }
1866
1867        let right = {
1868            let left_of_right = self.parse_unary_expr()?;
1869            self.parse_bin_op_recursively(
1870                left_of_right,
1871                if op == op!("**") {
1872                    // exponential operator is right associative
1873                    op.precedence() - 1
1874                } else {
1875                    op.precedence()
1876                },
1877            )?
1878        };
1879        /* this check is for all ?? operators
1880         * a ?? b && c for this example
1881         * b && c => This is considered as a logical expression in the ast tree
1882         * a => Identifier
1883         * so for ?? operator we need to check in this case the right expression to
1884         * have parenthesis second case a && b ?? c
1885         * here a && b => This is considered as a logical expression in the ast tree
1886         * c => identifier
1887         * so now here for ?? operator we need to check the left expression to have
1888         * parenthesis if the parenthesis is missing we raise an error and
1889         * throw it
1890         */
1891        if op == op!("??") {
1892            match *left {
1893                Expr::Bin(BinExpr { span, op, .. }) if op == op!("&&") || op == op!("||") => {
1894                    self.emit_err(span, SyntaxError::NullishCoalescingWithLogicalOp);
1895                }
1896                _ => {}
1897            }
1898
1899            match *right {
1900                Expr::Bin(BinExpr { span, op, .. }) if op == op!("&&") || op == op!("||") => {
1901                    self.emit_err(span, SyntaxError::NullishCoalescingWithLogicalOp);
1902                }
1903                _ => {}
1904            }
1905        }
1906
1907        let node = BinExpr {
1908            span: Span::new_with_checked(left.span_lo(), right.span_hi()),
1909            op,
1910            left,
1911            right,
1912        }
1913        .into();
1914
1915        Ok((node, Some(min_prec)))
1916    }
1917
1918    pub(crate) fn parse_await_expr(
1919        &mut self,
1920        start_of_await_token: Option<BytePos>,
1921    ) -> PResult<Box<Expr>> {
1922        let start = start_of_await_token.unwrap_or_else(|| self.cur_pos());
1923
1924        if start_of_await_token.is_none() {
1925            self.assert_and_bump(Token::Await);
1926        }
1927
1928        let await_token = self.span(start);
1929
1930        if self.input().is(Token::Asterisk) {
1931            syntax_error!(self, SyntaxError::AwaitStar);
1932        }
1933
1934        let ctx = self.ctx();
1935
1936        let span = self.span(start);
1937
1938        if !ctx.contains(Context::InAsync)
1939            && (self.is_general_semi() || {
1940                let cur = self.input().cur();
1941                matches!(cur, Token::RParen | Token::RBracket | Token::Comma)
1942            })
1943        {
1944            if ctx.contains(Context::Module) {
1945                self.emit_err(span, SyntaxError::InvalidIdentInAsync);
1946            }
1947
1948            return Ok(Ident::new_no_ctxt(atom!("await"), span).into());
1949        }
1950
1951        // This has been checked if start_of_await_token == true,
1952        if start_of_await_token.is_none() && ctx.contains(Context::TopLevel) {
1953            self.mark_found_module_item();
1954            if !ctx.contains(Context::CanBeModule) {
1955                self.emit_err(await_token, SyntaxError::TopLevelAwaitInScript);
1956            }
1957        }
1958
1959        if ctx.contains(Context::InFunction) && !ctx.contains(Context::InAsync) {
1960            self.emit_err(await_token, SyntaxError::AwaitInFunction);
1961        }
1962
1963        if ctx.contains(Context::InParameters) && !ctx.contains(Context::InFunction) {
1964            self.emit_err(span, SyntaxError::AwaitParamInAsync);
1965        }
1966
1967        let arg = self.parse_unary_expr()?;
1968        Ok(AwaitExpr {
1969            span: self.span(start),
1970            arg,
1971        }
1972        .into())
1973    }
1974
1975    pub(crate) fn parse_for_head_prefix(&mut self) -> PResult<Box<Expr>> {
1976        self.parse_expr()
1977    }
1978
1979    // Returns (args_or_pats, trailing_comma)
1980    #[cfg_attr(
1981        feature = "tracing-spans",
1982        tracing::instrument(level = "debug", skip_all)
1983    )]
1984    fn parse_args_or_pats(&mut self) -> PResult<(Vec<AssignTargetOrSpread>, Option<Span>)> {
1985        self.do_outside_of_context(
1986            Context::WillExpectColonForCond,
1987            Self::parse_args_or_pats_inner,
1988        )
1989    }
1990
1991    fn parse_args_or_pats_inner(&mut self) -> PResult<(Vec<AssignTargetOrSpread>, Option<Span>)> {
1992        trace_cur!(self, parse_args_or_pats);
1993
1994        expect!(self, Token::LParen);
1995
1996        let mut items = Vec::new();
1997        let mut trailing_comma = None;
1998
1999        // TODO(kdy1): optimize (once we parsed a pattern, we can parse everything else
2000        // as a pattern instead of reparsing)
2001        while !self.input().is(Token::RParen) {
2002            // https://github.com/swc-project/swc/issues/410
2003            let is_async = self.input().is(Token::Async)
2004                && peek!(self)
2005                    .is_some_and(|t| t == Token::LParen || t == Token::Function || t.is_word());
2006
2007            let start = self.cur_pos();
2008            self.state_mut().potential_arrow_start = Some(start);
2009            let modifier_start = start;
2010
2011            let has_modifier = self.eat_any_ts_modifier()?;
2012            let pat_start = self.cur_pos();
2013
2014            let mut arg = {
2015                if self.input().syntax().typescript()
2016                    && (self.is_ident_ref()
2017                        || (self.input().is(Token::DotDotDot) && self.peek_is_ident_ref()))
2018                {
2019                    let spread = if self.input_mut().eat(Token::DotDotDot) {
2020                        Some(self.input().prev_span())
2021                    } else {
2022                        None
2023                    };
2024
2025                    // At here, we use parse_bin_expr() instead of parse_assignment_expr()
2026                    // because `x?: number` should not be parsed as a conditional expression
2027                    let expr = if spread.is_some() {
2028                        self.parse_bin_expr()?
2029                    } else {
2030                        let mut expr = self.parse_bin_expr()?;
2031
2032                        if self.input().cur().is_assign_op() {
2033                            expr = self.finish_assignment_expr(start, expr)?
2034                        }
2035
2036                        expr
2037                    };
2038
2039                    ExprOrSpread { spread, expr }
2040                } else {
2041                    self.allow_in_expr(|p| p.parse_expr_or_spread())?
2042                }
2043            };
2044
2045            let optional = if self.input().syntax().typescript() {
2046                if self.input().is(Token::QuestionMark) {
2047                    if peek!(self).is_some_and(|peek| {
2048                        matches!(
2049                            peek,
2050                            Token::Comma | Token::Eq | Token::RParen | Token::Colon
2051                        )
2052                    }) {
2053                        self.assert_and_bump(Token::QuestionMark);
2054                        if arg.spread.is_some() {
2055                            self.emit_err(self.input().prev_span(), SyntaxError::TS1047);
2056                        }
2057                        match *arg.expr {
2058                            Expr::Ident(..) => {}
2059                            _ => {
2060                                syntax_error!(
2061                                    self,
2062                                    arg.span(),
2063                                    SyntaxError::TsBindingPatCannotBeOptional
2064                                )
2065                            }
2066                        }
2067                        true
2068                    } else if matches!(arg, ExprOrSpread { spread: None, .. }) {
2069                        expect!(self, Token::QuestionMark);
2070                        let test = arg.expr;
2071
2072                        let cons = self.do_inside_of_context(
2073                            Context::InCondExpr
2074                                .union(Context::WillExpectColonForCond)
2075                                .union(Context::IncludeInExpr),
2076                            Self::parse_assignment_expr,
2077                        )?;
2078                        expect!(self, Token::Colon);
2079
2080                        let alt = self.do_inside_of_context(Context::InCondExpr, |p| {
2081                            p.do_outside_of_context(
2082                                Context::WillExpectColonForCond,
2083                                Self::parse_assignment_expr,
2084                            )
2085                        })?;
2086
2087                        arg = ExprOrSpread {
2088                            spread: None,
2089                            expr: CondExpr {
2090                                span: Span::new_with_checked(start, alt.span_hi()),
2091                                test,
2092                                cons,
2093                                alt,
2094                            }
2095                            .into(),
2096                        };
2097
2098                        false
2099                    } else {
2100                        false
2101                    }
2102                } else {
2103                    false
2104                }
2105            } else {
2106                false
2107            };
2108
2109            if optional || (self.input().syntax().typescript() && self.input().is(Token::Colon)) {
2110                // TODO: `async(...args?: any[]) : any => {}`
2111                //
2112                // if self.input().syntax().typescript() && optional && arg.spread.is_some() {
2113                //     self.emit_err(self.input().prev_span(), SyntaxError::TS1047)
2114                // }
2115
2116                let mut pat = self.reparse_expr_as_pat(PatType::BindingPat, arg.expr)?;
2117                if optional {
2118                    match pat {
2119                        Pat::Ident(ref mut i) => i.optional = true,
2120                        _ => unreachable!(),
2121                    }
2122                }
2123                if let Some(span) = arg.spread {
2124                    pat = RestPat {
2125                        span: self.span(pat_start),
2126                        dot3_token: span,
2127                        arg: Box::new(pat),
2128                        type_ann: None,
2129                    }
2130                    .into();
2131                }
2132                match pat {
2133                    Pat::Ident(BindingIdent {
2134                        id: Ident { ref mut span, .. },
2135                        ref mut type_ann,
2136                        ..
2137                    })
2138                    | Pat::Array(ArrayPat {
2139                        ref mut type_ann,
2140                        ref mut span,
2141                        ..
2142                    })
2143                    | Pat::Object(ObjectPat {
2144                        ref mut type_ann,
2145                        ref mut span,
2146                        ..
2147                    })
2148                    | Pat::Rest(RestPat {
2149                        ref mut type_ann,
2150                        ref mut span,
2151                        ..
2152                    }) => {
2153                        let new_type_ann = self.try_parse_ts_type_ann()?;
2154                        if new_type_ann.is_some() {
2155                            *span = Span::new_with_checked(pat_start, self.input().prev_span().hi);
2156                        }
2157                        *type_ann = new_type_ann;
2158                    }
2159                    Pat::Expr(ref expr) => unreachable!("invalid pattern: Expr({:?})", expr),
2160                    Pat::Assign(..) | Pat::Invalid(..) => {
2161                        // We don't have to panic here.
2162                        // See: https://github.com/swc-project/swc/issues/1170
2163                        //
2164                        // Also, as an exact error is added to the errors while
2165                        // creating `Invalid`, we don't have to emit a new
2166                        // error.
2167                    }
2168                    #[cfg(swc_ast_unknown)]
2169                    _ => unreachable!(),
2170                }
2171
2172                if self.input_mut().eat(Token::Eq) {
2173                    let right = self.parse_assignment_expr()?;
2174                    pat = AssignPat {
2175                        span: self.span(pat_start),
2176                        left: Box::new(pat),
2177                        right,
2178                    }
2179                    .into();
2180                }
2181
2182                if has_modifier {
2183                    self.emit_err(self.span(modifier_start), SyntaxError::TS2369);
2184                }
2185
2186                items.push(AssignTargetOrSpread::Pat(pat))
2187            } else {
2188                if has_modifier {
2189                    self.emit_err(self.span(modifier_start), SyntaxError::TS2369);
2190                }
2191
2192                items.push(AssignTargetOrSpread::ExprOrSpread(arg));
2193            }
2194
2195            // https://github.com/swc-project/swc/issues/433
2196            if self.input_mut().eat(Token::Arrow) && {
2197                debug_assert_eq!(items.len(), 1);
2198                match items[0] {
2199                    AssignTargetOrSpread::ExprOrSpread(ExprOrSpread { ref expr, .. })
2200                    | AssignTargetOrSpread::Pat(Pat::Expr(ref expr)) => {
2201                        matches!(**expr, Expr::Ident(..))
2202                    }
2203                    AssignTargetOrSpread::Pat(Pat::Ident(..)) => true,
2204                    _ => false,
2205                }
2206            } {
2207                let params: Vec<Pat> = self.parse_paren_items_as_params(items.clone(), None)?;
2208
2209                let body: Box<BlockStmtOrExpr> = self.parse_fn_block_or_expr_body(
2210                    false,
2211                    false,
2212                    true,
2213                    params.is_simple_parameter_list(),
2214                )?;
2215                let span = self.span(start);
2216
2217                items.push(AssignTargetOrSpread::ExprOrSpread(ExprOrSpread {
2218                    expr: Box::new(
2219                        ArrowExpr {
2220                            span,
2221                            body,
2222                            is_async,
2223                            is_generator: false,
2224                            params,
2225                            ..Default::default()
2226                        }
2227                        .into(),
2228                    ),
2229                    spread: None,
2230                }));
2231            }
2232
2233            if !self.input().is(Token::RParen) {
2234                expect!(self, Token::Comma);
2235                if self.input().is(Token::RParen) {
2236                    trailing_comma = Some(self.input().prev_span());
2237                }
2238            }
2239        }
2240
2241        expect!(self, Token::RParen);
2242        Ok((items, trailing_comma))
2243    }
2244
2245    #[cfg_attr(
2246        feature = "tracing-spans",
2247        tracing::instrument(level = "debug", skip_all)
2248    )]
2249    fn parse_paren_expr_or_arrow_fn(
2250        &mut self,
2251        can_be_arrow: bool,
2252        async_span: Option<Span>,
2253    ) -> PResult<Box<Expr>> {
2254        trace_cur!(self, parse_paren_expr_or_arrow_fn);
2255
2256        let expr_start = async_span.map(|x| x.lo()).unwrap_or_else(|| self.cur_pos());
2257
2258        // At this point, we can't know if it's parenthesized
2259        // expression or head of arrow function.
2260        // But as all patterns of javascript is subset of
2261        // expressions, we can parse both as expression.
2262
2263        let (paren_items, trailing_comma) = self
2264            .do_outside_of_context(Context::WillExpectColonForCond, |p| {
2265                p.allow_in_expr(Self::parse_args_or_pats)
2266            })?;
2267
2268        let has_pattern = paren_items
2269            .iter()
2270            .any(|item| matches!(item, AssignTargetOrSpread::Pat(..)));
2271
2272        let will_expect_colon_for_cond = self.ctx().contains(Context::WillExpectColonForCond);
2273        // This is slow path. We handle arrow in conditional expression.
2274        if self.syntax().typescript()
2275            && self.ctx().contains(Context::InCondExpr)
2276            && self.input().is(Token::Colon)
2277        {
2278            // TODO: Remove clone
2279            let items_ref = &paren_items;
2280            if let Some(expr) = self.try_parse_ts(|p| {
2281                let return_type = p.parse_ts_type_or_type_predicate_ann(Token::Colon)?;
2282
2283                expect!(p, Token::Arrow);
2284
2285                let params: Vec<Pat> =
2286                    p.parse_paren_items_as_params(items_ref.clone(), trailing_comma)?;
2287
2288                let body: Box<BlockStmtOrExpr> = p.parse_fn_block_or_expr_body(
2289                    async_span.is_some(),
2290                    false,
2291                    true,
2292                    params.is_simple_parameter_list(),
2293                )?;
2294
2295                if will_expect_colon_for_cond && !p.input().is(Token::Colon) {
2296                    trace_cur!(p, parse_arrow_in_cond__fail);
2297                    unexpected!(p, "fail")
2298                }
2299
2300                Ok(Some(
2301                    ArrowExpr {
2302                        span: p.span(expr_start),
2303                        is_async: async_span.is_some(),
2304                        is_generator: false,
2305                        params,
2306                        body,
2307                        return_type: Some(return_type),
2308                        ..Default::default()
2309                    }
2310                    .into(),
2311                ))
2312            }) {
2313                return Ok(expr);
2314            }
2315        }
2316
2317        let return_type = if !self.ctx().contains(Context::WillExpectColonForCond)
2318            && self.input().syntax().typescript()
2319            && self.input().is(Token::Colon)
2320        {
2321            self.try_parse_ts(|p| {
2322                let return_type = p.parse_ts_type_or_type_predicate_ann(Token::Colon)?;
2323
2324                if !p.input().is(Token::Arrow) {
2325                    unexpected!(p, "fail")
2326                }
2327
2328                Ok(Some(return_type))
2329            })
2330        } else {
2331            None
2332        };
2333
2334        // we parse arrow function at here, to handle it efficiently.
2335        if has_pattern || return_type.is_some() || self.input().is(Token::Arrow) {
2336            if self.input().had_line_break_before_cur() {
2337                syntax_error!(
2338                    self,
2339                    self.span(expr_start),
2340                    SyntaxError::LineBreakBeforeArrow
2341                );
2342            }
2343
2344            if !can_be_arrow {
2345                syntax_error!(self, self.span(expr_start), SyntaxError::ArrowNotAllowed);
2346            }
2347            expect!(self, Token::Arrow);
2348
2349            let params: Vec<Pat> = self.parse_paren_items_as_params(paren_items, trailing_comma)?;
2350
2351            let body: Box<BlockStmtOrExpr> = self.parse_fn_block_or_expr_body(
2352                async_span.is_some(),
2353                false,
2354                true,
2355                params.is_simple_parameter_list(),
2356            )?;
2357            let arrow_expr = ArrowExpr {
2358                span: self.span(expr_start),
2359                is_async: async_span.is_some(),
2360                is_generator: false,
2361                params,
2362                body,
2363                return_type,
2364                ..Default::default()
2365            };
2366            if let BlockStmtOrExpr::BlockStmt(..) = &*arrow_expr.body {
2367                if self.input().cur().is_bin_op() {
2368                    // ) is required
2369                    self.emit_err(self.input().cur_span(), SyntaxError::TS1005);
2370                    let errorred_expr =
2371                        self.parse_bin_op_recursively(Box::new(arrow_expr.into()), 0)?;
2372
2373                    if !self.is_general_semi() {
2374                        // ; is required
2375                        self.emit_err(self.input().cur_span(), SyntaxError::TS1005);
2376                    }
2377
2378                    return Ok(errorred_expr);
2379                }
2380            }
2381            return Ok(arrow_expr.into());
2382        } else {
2383            // If there's no arrow function, we have to check there's no
2384            // AssignProp in lhs to check against assignment in object literals
2385            // like (a, {b = 1});
2386            for expr_or_spread in paren_items.iter() {
2387                if let AssignTargetOrSpread::ExprOrSpread(e) = expr_or_spread {
2388                    if let Expr::Object(o) = &*e.expr {
2389                        for prop in o.props.iter() {
2390                            if let PropOrSpread::Prop(prop) = prop {
2391                                if let Prop::Assign(..) = **prop {
2392                                    self.emit_err(prop.span(), SyntaxError::AssignProperty);
2393                                }
2394                            }
2395                        }
2396                    }
2397                }
2398            }
2399        }
2400
2401        let expr_or_spreads = paren_items
2402            .into_iter()
2403            .map(|item| -> PResult<_> {
2404                match item {
2405                    AssignTargetOrSpread::ExprOrSpread(e) => Ok(e),
2406                    _ => syntax_error!(self, item.span(), SyntaxError::InvalidExpr),
2407                }
2408            })
2409            .collect::<Result<Vec<_>, _>>()?;
2410        if let Some(async_span) = async_span {
2411            // It's a call expression
2412            return Ok(CallExpr {
2413                span: self.span(async_span.lo()),
2414                callee: Callee::Expr(Box::new(
2415                    Ident::new_no_ctxt(atom!("async"), async_span).into(),
2416                )),
2417                args: expr_or_spreads,
2418                ..Default::default()
2419            }
2420            .into());
2421        }
2422
2423        // It was not head of arrow function.
2424
2425        if expr_or_spreads.is_empty() {
2426            syntax_error!(
2427                self,
2428                Span::new_with_checked(expr_start, self.last_pos()),
2429                SyntaxError::EmptyParenExpr
2430            );
2431        }
2432
2433        // TODO: Verify that invalid expression like {a = 1} does not exists.
2434
2435        // ParenthesizedExpression cannot contain spread.
2436        if expr_or_spreads.len() == 1 {
2437            let expr = match expr_or_spreads.into_iter().next().unwrap() {
2438                ExprOrSpread {
2439                    spread: Some(..),
2440                    ref expr,
2441                } => syntax_error!(self, expr.span(), SyntaxError::SpreadInParenExpr),
2442                ExprOrSpread { expr, .. } => expr,
2443            };
2444            Ok(ParenExpr {
2445                span: self.span(expr_start),
2446                expr,
2447            }
2448            .into())
2449        } else {
2450            debug_assert!(expr_or_spreads.len() >= 2);
2451
2452            let mut exprs = Vec::with_capacity(expr_or_spreads.len());
2453            for expr in expr_or_spreads {
2454                match expr {
2455                    ExprOrSpread {
2456                        spread: Some(..),
2457                        ref expr,
2458                    } => syntax_error!(self, expr.span(), SyntaxError::SpreadInParenExpr),
2459                    ExprOrSpread { expr, .. } => exprs.push(expr),
2460                }
2461            }
2462            debug_assert!(exprs.len() >= 2);
2463
2464            // span of sequence expression should not include '(', ')'
2465            let seq_expr = SeqExpr {
2466                span: Span::new_with_checked(
2467                    exprs.first().unwrap().span_lo(),
2468                    exprs.last().unwrap().span_hi(),
2469                ),
2470                exprs,
2471            }
2472            .into();
2473            Ok(ParenExpr {
2474                span: self.span(expr_start),
2475                expr: seq_expr,
2476            }
2477            .into())
2478        }
2479    }
2480
2481    fn parse_primary_expr_rest(
2482        &mut self,
2483        start: BytePos,
2484        can_be_arrow: bool,
2485    ) -> PResult<Box<Expr>> {
2486        let decorators = if self.input().is(Token::At) {
2487            Some(self.parse_decorators(false)?)
2488        } else {
2489            None
2490        };
2491
2492        let token_and_span = self.input().get_cur();
2493        let cur = token_and_span.token;
2494
2495        if cur == Token::Class {
2496            return self.parse_class_expr(start, decorators.unwrap_or_default());
2497        }
2498
2499        let try_parse_arrow_expr = |p: &mut Self, id: Ident, id_is_async| -> PResult<Box<Expr>> {
2500            if can_be_arrow && !p.input().had_line_break_before_cur() {
2501                if id_is_async && p.is_ident_ref() {
2502                    // see https://github.com/tc39/ecma262/issues/2034
2503                    // ```js
2504                    // for(async of
2505                    // for(async of x);
2506                    // for(async of =>{};;);
2507                    // ```
2508                    let ctx = p.ctx();
2509                    if ctx.contains(Context::ForLoopInit)
2510                        && p.input().is(Token::Of)
2511                        && !peek!(p).is_some_and(|peek| peek == Token::Arrow)
2512                    {
2513                        // ```spec https://tc39.es/ecma262/#prod-ForInOfStatement
2514                        // for ( [lookahead ∉ { let, async of }] LeftHandSideExpression[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return]
2515                        // [+Await] for await ( [lookahead ≠ let] LeftHandSideExpression[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return]
2516                        // ```
2517
2518                        if !ctx.contains(Context::ForAwaitLoopInit) {
2519                            p.emit_err(p.input().prev_span(), SyntaxError::TS1106);
2520                        }
2521
2522                        return Ok(id.into());
2523                    }
2524
2525                    let token = p.input().cur();
2526                    let ident = p.parse_binding_ident(false)?;
2527                    if p.input().syntax().typescript()
2528                        && token == Token::As
2529                        && !p.input().is(Token::Arrow)
2530                    {
2531                        // async as type
2532                        let type_ann = p.in_type(Self::parse_ts_type)?;
2533                        return Ok(TsAsExpr {
2534                            span: p.span(start),
2535                            expr: Box::new(id.into()),
2536                            type_ann,
2537                        }
2538                        .into());
2539                    }
2540
2541                    // async a => body
2542                    let arg = ident.into();
2543                    let params = vec![arg];
2544                    expect!(p, Token::Arrow);
2545                    let body = p.parse_fn_block_or_expr_body(
2546                        true,
2547                        false,
2548                        true,
2549                        params.is_simple_parameter_list(),
2550                    )?;
2551
2552                    return Ok(ArrowExpr {
2553                        span: p.span(start),
2554                        body,
2555                        params,
2556                        is_async: true,
2557                        is_generator: false,
2558                        ..Default::default()
2559                    }
2560                    .into());
2561                } else if p.input_mut().eat(Token::Arrow) {
2562                    if p.ctx().contains(Context::Strict) && id.is_reserved_in_strict_bind() {
2563                        p.emit_strict_mode_err(id.span, SyntaxError::EvalAndArgumentsInStrict)
2564                    }
2565                    let params = vec![id.into()];
2566                    let body = p.parse_fn_block_or_expr_body(
2567                        false,
2568                        false,
2569                        true,
2570                        params.is_simple_parameter_list(),
2571                    )?;
2572
2573                    return Ok(ArrowExpr {
2574                        span: p.span(start),
2575                        body,
2576                        params,
2577                        is_async: false,
2578                        is_generator: false,
2579                        ..Default::default()
2580                    }
2581                    .into());
2582                }
2583            }
2584
2585            Ok(id.into())
2586        };
2587
2588        let token_start = token_and_span.span.lo;
2589        if cur == Token::Let || (self.input().syntax().typescript() && cur == Token::Await) {
2590            let ctx = self.ctx();
2591            let id = self.parse_ident(
2592                !ctx.contains(Context::InGenerator),
2593                !ctx.contains(Context::InAsync),
2594            )?;
2595            try_parse_arrow_expr(self, id, false)
2596        } else if cur == Token::Hash {
2597            self.bump(); // consume `#`
2598            let id = self.parse_ident_name()?;
2599            Ok(PrivateName {
2600                span: self.span(start),
2601                name: id.sym,
2602            }
2603            .into())
2604        } else if cur == Token::Ident {
2605            let word = self.input_mut().expect_word_token_and_bump();
2606            if self.ctx().contains(Context::InClassField) && word == atom!("arguments") {
2607                self.emit_err(self.input().prev_span(), SyntaxError::ArgumentsInClassField)
2608            };
2609            let id = Ident::new_no_ctxt(word, self.span(token_start));
2610            try_parse_arrow_expr(self, id, false)
2611        } else if self.is_ident_ref() {
2612            let id_is_async = self.input().cur() == Token::Async;
2613            let word = self.input_mut().expect_word_token_and_bump();
2614            let id = Ident::new_no_ctxt(word, self.span(token_start));
2615            try_parse_arrow_expr(self, id, id_is_async)
2616        } else {
2617            syntax_error!(self, self.input().cur_span(), SyntaxError::TS1109)
2618        }
2619    }
2620
2621    fn try_parse_regexp(&mut self, start: BytePos) -> Option<Box<Expr>> {
2622        // Regexp
2623        debug_assert!(self.input().cur() == Token::Slash || self.input().cur() == Token::DivEq);
2624
2625        self.input_mut().set_next_regexp(Some(start));
2626
2627        self.bump(); // `/` or `/=`
2628
2629        let cur = self.input().cur();
2630        if cur == Token::Regex {
2631            self.input_mut().set_next_regexp(None);
2632            let token_span = self.input.cur_span();
2633            let exp_end = self.input_mut().expect_regex_token_value();
2634
2635            let exp_start = token_span.lo + BytePos(1); // +1 to exclude left `/`
2636            let exp = Atom::new(
2637                self.input
2638                    .iter
2639                    .read_string(Span::new_with_checked(exp_start, exp_end)),
2640            );
2641            let flags_start = exp_end + BytePos(1); // +1 to exclude right `/`
2642            let flags = if flags_start <= token_span.hi {
2643                Atom::new(
2644                    self.input
2645                        .iter
2646                        .read_string(Span::new_with_checked(flags_start, token_span.hi)),
2647                )
2648            } else {
2649                Atom::default()
2650            };
2651
2652            self.bump();
2653            let span = self.span(start);
2654            Some(Lit::Regex(Regex { span, exp, flags }).into())
2655        } else {
2656            None
2657        }
2658    }
2659
2660    fn try_parse_async_start(&mut self, can_be_arrow: bool) -> Option<PResult<Box<Expr>>> {
2661        if peek!(self).is_some_and(|peek| peek == Token::Function)
2662            && !self.input_mut().has_linebreak_between_cur_and_peeked()
2663        {
2664            // handle `async function` expression
2665            return Some(self.parse_async_fn_expr());
2666        }
2667
2668        if can_be_arrow
2669            && self.input().syntax().typescript()
2670            && peek!(self).is_some_and(|peek| peek == Token::Lt)
2671        {
2672            // try parsing `async<T>() => {}`
2673            if let Some(res) = self.try_parse_ts(|p| {
2674                let start = p.cur_pos();
2675                p.assert_and_bump(Token::Async);
2676                p.try_parse_ts_generic_async_arrow_fn(start)
2677            }) {
2678                return Some(Ok(res.into()));
2679            }
2680        }
2681
2682        if can_be_arrow
2683            && peek!(self).is_some_and(|peek| peek == Token::LParen)
2684            && !self.input_mut().has_linebreak_between_cur_and_peeked()
2685        {
2686            if let Err(e) = self.expect(Token::Async) {
2687                return Some(Err(e));
2688            }
2689            let async_span = self.input().prev_span();
2690            return Some(self.parse_paren_expr_or_arrow_fn(can_be_arrow, Some(async_span)));
2691        }
2692
2693        None
2694    }
2695
2696    fn parse_this_expr(&mut self, start: BytePos) -> PResult<Box<Expr>> {
2697        debug_assert!(self.input().cur() == Token::This);
2698        self.input_mut().bump();
2699        Ok(ThisExpr {
2700            span: self.span(start),
2701        }
2702        .into())
2703    }
2704
2705    #[cfg(feature = "typescript")]
2706    pub(crate) fn is_start_of_left_hand_side_expr(&mut self) -> bool {
2707        let cur = self.input().cur();
2708        matches!(
2709            cur,
2710            Token::This
2711                | Token::Null
2712                | Token::Super
2713                | Token::True
2714                | Token::False
2715                | Token::Num
2716                | Token::BigInt
2717                | Token::Str
2718                | Token::NoSubstitutionTemplateLiteral
2719                | Token::TemplateHead
2720                | Token::LParen
2721                | Token::LBracket
2722                | Token::Function
2723                | Token::Class
2724                | Token::New
2725                | Token::Regex
2726                | Token::Import
2727        ) || cur.is_ident_ref(self.ctx())
2728            || cur == Token::BackQuote && {
2729                peek!(self)
2730                    .is_some_and(|peek| matches!(peek, Token::LParen | Token::Lt | Token::Dot))
2731            }
2732    }
2733}
2734
2735fn unwrap_ts_non_null(mut expr: &Expr) -> &Expr {
2736    while let Expr::TsNonNull(ts_non_null) = expr {
2737        expr = &ts_non_null.expr;
2738    }
2739
2740    expr
2741}