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