swc_ecma_parser/parser/
expr.rs

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