1use swc_common::Spanned;
4
5use super::{util::ExprExt, *};
6use crate::{
7 parser::{class_and_fn::is_not_this, expr::AssignTargetOrSpread},
8 token::{IdentLike, Keyword},
9};
10
11impl<I: Tokens> Parser<I> {
12 pub fn parse_pat(&mut self) -> PResult<Pat> {
13 self.parse_binding_pat_or_ident(false)
14 }
15
16 pub(super) fn parse_opt_binding_ident(
17 &mut self,
18 disallow_let: bool,
19 ) -> PResult<Option<BindingIdent>> {
20 trace_cur!(self, parse_opt_binding_ident);
21
22 if is!(self, BindingIdent) || (self.input.syntax().typescript() && is!(self, "this")) {
23 self.parse_binding_ident(disallow_let).map(Some)
24 } else {
25 Ok(None)
26 }
27 }
28
29 pub(super) fn parse_binding_ident(&mut self, disallow_let: bool) -> PResult<BindingIdent> {
33 trace_cur!(self, parse_binding_ident);
34
35 if disallow_let {
36 if let Some(Token::Word(Word::Keyword(Keyword::Let))) = self.input.cur() {
37 unexpected!(self, "let is reserved in const, let, class declaration")
38 }
39 }
40
41 let ident = self.parse_ident(true, true)?;
43 if ident.is_reserved_in_strict_bind() {
44 self.emit_strict_mode_err(ident.span, SyntaxError::EvalAndArgumentsInStrict);
45 }
46 if (self.ctx().in_async || self.ctx().in_static_block) && ident.sym == "await" {
47 self.emit_err(ident.span, SyntaxError::ExpectedIdent);
48 }
49 if self.ctx().in_generator && ident.sym == "yield" {
50 self.emit_err(ident.span, SyntaxError::ExpectedIdent);
51 }
52
53 Ok(ident.into())
54 }
55
56 pub(super) fn parse_binding_pat_or_ident(&mut self, disallow_let: bool) -> PResult<Pat> {
57 trace_cur!(self, parse_binding_pat_or_ident);
58
59 match *cur!(self, true) {
60 tok!("yield") | Word(..) => self.parse_binding_ident(disallow_let).map(Pat::from),
61 tok!('[') => self.parse_array_binding_pat(),
62 tok!('{') => self.parse_object(),
63 _ => unexpected!(self, "yield, an identifier, [ or {"),
70 }
71 }
72
73 pub(super) fn parse_binding_element(&mut self) -> PResult<Pat> {
75 trace_cur!(self, parse_binding_element);
76
77 let start = cur_pos!(self);
78 let left = self.parse_binding_pat_or_ident(false)?;
79
80 if eat!(self, '=') {
81 let right = self.include_in_expr(true).parse_assignment_expr()?;
82
83 if self.ctx().in_declare {
84 self.emit_err(span!(self, start), SyntaxError::TS2371);
85 }
86
87 return Ok(AssignPat {
88 span: span!(self, start),
89 left: Box::new(left),
90 right,
91 }
92 .into());
93 }
94
95 Ok(left)
96 }
97
98 fn parse_array_binding_pat(&mut self) -> PResult<Pat> {
99 let start = cur_pos!(self);
100
101 assert_and_bump!(self, '[');
102
103 let mut elems = Vec::new();
104
105 let mut rest_span = Span::default();
106
107 while !eof!(self) && !is!(self, ']') {
108 if eat!(self, ',') {
109 elems.push(None);
110 continue;
111 }
112
113 if !rest_span.is_dummy() {
114 self.emit_err(rest_span, SyntaxError::NonLastRestParam);
115 }
116
117 let start = cur_pos!(self);
118
119 let mut is_rest = false;
120 if eat!(self, "...") {
121 is_rest = true;
122 let dot3_token = span!(self, start);
123
124 let pat = self.parse_binding_pat_or_ident(false)?;
125 rest_span = span!(self, start);
126 let pat = RestPat {
127 span: rest_span,
128 dot3_token,
129 arg: Box::new(pat),
130 type_ann: None,
131 }
132 .into();
133 elems.push(Some(pat));
134 } else {
135 elems.push(self.parse_binding_element().map(Some)?);
136 }
137
138 if !is!(self, ']') {
139 expect!(self, ',');
140 if is_rest && is!(self, ']') {
141 self.emit_err(self.input.prev_span(), SyntaxError::CommaAfterRestElement);
142 }
143 }
144 }
145
146 expect!(self, ']');
147 let optional = (self.input.syntax().dts() || self.ctx().in_declare) && eat!(self, '?');
148
149 Ok(ArrayPat {
150 span: span!(self, start),
151 elems,
152 optional,
153 type_ann: None,
154 }
155 .into())
156 }
157
158 pub(super) fn eat_any_ts_modifier(&mut self) -> PResult<bool> {
159 let has_modifier = self.syntax().typescript()
160 && matches!(
161 *cur!(self, false)?,
162 Word(Word::Ident(IdentLike::Known(
163 known_ident!("public")
164 | known_ident!("protected")
165 | known_ident!("private")
166 | known_ident!("readonly")
167 )))
168 )
169 && (peeked_is!(self, IdentName) || peeked_is!(self, '{') || peeked_is!(self, '['));
170 if has_modifier {
171 let _ = self.parse_ts_modifier(&["public", "protected", "private", "readonly"], false);
172 }
173
174 Ok(has_modifier)
175 }
176
177 pub(super) fn parse_formal_param_pat(&mut self) -> PResult<Pat> {
181 let start = cur_pos!(self);
182
183 let has_modifier = self.eat_any_ts_modifier()?;
184
185 let pat_start = cur_pos!(self);
186 let mut pat = self.parse_binding_element()?;
187 let mut opt = false;
188
189 if self.input.syntax().typescript() {
190 if eat!(self, '?') {
191 match pat {
192 Pat::Ident(BindingIdent {
193 id:
194 Ident {
195 ref mut optional, ..
196 },
197 ..
198 })
199 | Pat::Array(ArrayPat {
200 ref mut optional, ..
201 })
202 | Pat::Object(ObjectPat {
203 ref mut optional, ..
204 }) => {
205 *optional = true;
206 opt = true;
207 }
208 _ if self.input.syntax().dts() || self.ctx().in_declare => {}
209 _ => {
210 syntax_error!(
211 self,
212 self.input.prev_span(),
213 SyntaxError::TsBindingPatCannotBeOptional
214 );
215 }
216 }
217 }
218
219 match pat {
220 Pat::Array(ArrayPat {
221 ref mut type_ann,
222 ref mut span,
223 ..
224 })
225 | Pat::Object(ObjectPat {
226 ref mut type_ann,
227 ref mut span,
228 ..
229 })
230 | Pat::Rest(RestPat {
231 ref mut type_ann,
232 ref mut span,
233 ..
234 }) => {
235 let new_type_ann = self.try_parse_ts_type_ann()?;
236 if new_type_ann.is_some() {
237 *span = Span::new(pat_start, self.input.prev_span().hi);
238 }
239 *type_ann = new_type_ann;
240 }
241
242 Pat::Ident(BindingIdent {
243 ref mut type_ann, ..
244 }) => {
245 let new_type_ann = self.try_parse_ts_type_ann()?;
246 *type_ann = new_type_ann;
247 }
248
249 Pat::Assign(AssignPat { ref mut span, .. }) => {
250 if (self.try_parse_ts_type_ann()?).is_some() {
251 *span = Span::new(pat_start, self.input.prev_span().hi);
252 self.emit_err(*span, SyntaxError::TSTypeAnnotationAfterAssign);
253 }
254 }
255 Pat::Invalid(..) => {}
256 _ => unreachable!("invalid syntax: Pat: {:?}", pat),
257 }
258 }
259
260 let pat = if eat!(self, '=') {
261 if opt {
263 self.emit_err(pat.span(), SyntaxError::TS1015);
264 }
265
266 let right = self.parse_assignment_expr()?;
267 if self.ctx().in_declare {
268 self.emit_err(span!(self, start), SyntaxError::TS2371);
269 }
270
271 AssignPat {
272 span: span!(self, start),
273 left: Box::new(pat),
274 right,
275 }
276 .into()
277 } else {
278 pat
279 };
280
281 if has_modifier {
282 self.emit_err(span!(self, start), SyntaxError::TS2369);
283 return Ok(pat);
284 }
285
286 Ok(pat)
287 }
288
289 pub(super) fn parse_constructor_params(&mut self) -> PResult<Vec<ParamOrTsParamProp>> {
290 let mut params = Vec::new();
291 let mut rest_span = Span::default();
292
293 while !eof!(self) && !is!(self, ')') {
294 if !rest_span.is_dummy() {
295 self.emit_err(rest_span, SyntaxError::TS1014);
296 }
297
298 let param_start = cur_pos!(self);
299 let decorators = self.parse_decorators(false)?;
300 let pat_start = cur_pos!(self);
301
302 let mut is_rest = false;
303 if eat!(self, "...") {
304 is_rest = true;
305 let dot3_token = span!(self, pat_start);
306
307 let pat = self.parse_binding_pat_or_ident(false)?;
308 let type_ann = if self.input.syntax().typescript() && is!(self, ':') {
309 let cur_pos = cur_pos!(self);
310 Some(self.parse_ts_type_ann(true, cur_pos)?)
311 } else {
312 None
313 };
314
315 rest_span = span!(self, pat_start);
316 let pat = RestPat {
317 span: rest_span,
318 dot3_token,
319 arg: Box::new(pat),
320 type_ann,
321 }
322 .into();
323 params.push(ParamOrTsParamProp::Param(Param {
324 span: span!(self, param_start),
325 decorators,
326 pat,
327 }));
328 } else {
329 params.push(self.parse_constructor_param(param_start, decorators)?);
330 }
331
332 if !is!(self, ')') {
333 expect!(self, ',');
334 if is!(self, ')') && is_rest {
335 self.emit_err(self.input.prev_span(), SyntaxError::CommaAfterRestElement);
336 }
337 }
338 }
339
340 Ok(params)
341 }
342
343 fn parse_constructor_param(
344 &mut self,
345 param_start: BytePos,
346 decorators: Vec<Decorator>,
347 ) -> PResult<ParamOrTsParamProp> {
348 let (accessibility, is_override, readonly) = if self.input.syntax().typescript() {
349 let accessibility = self.parse_access_modifier()?;
350 (
351 accessibility,
352 self.parse_ts_modifier(&["override"], false)?.is_some(),
353 self.parse_ts_modifier(&["readonly"], false)?.is_some(),
354 )
355 } else {
356 (None, false, false)
357 };
358 if accessibility.is_none() && !is_override && !readonly {
359 let pat = self.parse_formal_param_pat()?;
360 Ok(ParamOrTsParamProp::Param(Param {
361 span: span!(self, param_start),
362 decorators,
363 pat,
364 }))
365 } else {
366 let param = match self.parse_formal_param_pat()? {
367 Pat::Ident(i) => TsParamPropParam::Ident(i),
368 Pat::Assign(a) => TsParamPropParam::Assign(a),
369 node => syntax_error!(self, node.span(), SyntaxError::TsInvalidParamPropPat),
370 };
371 Ok(ParamOrTsParamProp::TsParamProp(TsParamProp {
372 span: span!(self, param_start),
373 accessibility,
374 is_override,
375 readonly,
376 decorators,
377 param,
378 }))
379 }
380 }
381
382 #[allow(dead_code)]
383 pub(super) fn parse_setter_param(&mut self, key_span: Span) -> PResult<Param> {
384 let params = self.parse_formal_params()?;
385 let cnt = params.iter().filter(|p| is_not_this(p)).count();
386
387 if cnt != 1 {
388 self.emit_err(key_span, SyntaxError::SetterParam);
389 }
390
391 if !params.is_empty() {
392 if let Pat::Rest(..) = params[0].pat {
393 self.emit_err(params[0].pat.span(), SyntaxError::RestPatInSetter);
394 }
395 }
396
397 if params.is_empty() {
398 syntax_error!(self, SyntaxError::SetterParamRequired);
399 }
400
401 Ok(params.into_iter().next().unwrap())
402 }
403
404 pub(super) fn parse_formal_params(&mut self) -> PResult<Vec<Param>> {
405 let mut params = Vec::new();
406 let mut rest_span = Span::default();
407
408 while !eof!(self) && !is!(self, ')') {
409 if !rest_span.is_dummy() {
410 self.emit_err(rest_span, SyntaxError::TS1014);
411 }
412
413 let param_start = cur_pos!(self);
414 let decorators = self.parse_decorators(false)?;
415 let pat_start = cur_pos!(self);
416
417 let pat = if eat!(self, "...") {
418 let dot3_token = span!(self, pat_start);
419
420 let mut pat = self.parse_binding_pat_or_ident(false)?;
421
422 if eat!(self, '=') {
423 let right = self.parse_assignment_expr()?;
424 self.emit_err(pat.span(), SyntaxError::TS1048);
425 pat = AssignPat {
426 span: span!(self, pat_start),
427 left: Box::new(pat),
428 right,
429 }
430 .into();
431 }
432
433 let type_ann = if self.input.syntax().typescript() && is!(self, ':') {
434 let cur_pos = cur_pos!(self);
435 let ty = self.parse_ts_type_ann(true, cur_pos)?;
436 Some(ty)
437 } else {
438 None
439 };
440
441 rest_span = span!(self, pat_start);
442 let pat = RestPat {
443 span: rest_span,
444 dot3_token,
445 arg: Box::new(pat),
446 type_ann,
447 }
448 .into();
449
450 if self.syntax().typescript() && eat!(self, '?') {
451 self.emit_err(self.input.prev_span(), SyntaxError::TS1047);
452 }
454
455 pat
456 } else {
457 self.parse_formal_param_pat()?
458 };
459 let is_rest = matches!(pat, Pat::Rest(_));
460
461 params.push(Param {
462 span: span!(self, param_start),
463 decorators,
464 pat,
465 });
466
467 if !is!(self, ')') {
468 expect!(self, ',');
469 if is_rest && is!(self, ')') {
470 self.emit_err(self.input.prev_span(), SyntaxError::CommaAfterRestElement);
471 }
472 }
473 }
474
475 Ok(params)
476 }
477
478 pub(super) fn parse_unique_formal_params(&mut self) -> PResult<Vec<Param>> {
479 self.parse_formal_params()
481 }
482}
483
484#[derive(Debug, Clone, Copy, PartialEq, Eq)]
485pub enum PatType {
486 BindingPat,
487 BindingElement,
488 AssignPat,
490 AssignElement,
491}
492
493impl PatType {
494 pub fn element(self) -> Self {
495 match self {
496 PatType::BindingPat | PatType::BindingElement => PatType::BindingElement,
497 PatType::AssignPat | PatType::AssignElement => PatType::AssignElement,
498 }
499 }
500}
501
502impl<I: Tokens> Parser<I> {
503 pub(super) fn reparse_expr_as_pat(&mut self, pat_ty: PatType, expr: Box<Expr>) -> PResult<Pat> {
506 if let Expr::Invalid(i) = *expr {
507 return Ok(i.into());
508 }
509
510 if pat_ty == PatType::AssignPat {
511 match *expr {
512 Expr::Object(..) | Expr::Array(..) => {
513 }
518
519 _ => {
520 self.check_assign_target(&expr, true);
521 }
522 }
523 }
524
525 self.reparse_expr_as_pat_inner(pat_ty, expr)
526 }
527
528 fn reparse_expr_as_pat_inner(&mut self, pat_ty: PatType, expr: Box<Expr>) -> PResult<Pat> {
529 debug_assert!(!self.input.syntax().dts());
531
532 let span = expr.span();
533
534 if pat_ty == PatType::AssignPat {
535 match *expr {
536 Expr::Object(..) | Expr::Array(..) => {
537 }
542
543 _ => match *expr {
544 Expr::Paren(..) => {
550 return Ok(expr.into());
551 }
552 Expr::Ident(i) => return Ok(i.into()),
553 _ => {
554 return Ok(expr.into());
555 }
556 },
557 }
558 }
559
560 if pat_ty == PatType::AssignElement {
566 match *expr {
567 Expr::Array(..) | Expr::Object(..) => {}
568
569 Expr::Member(..)
570 | Expr::SuperProp(..)
571 | Expr::Call(..)
572 | Expr::New(..)
573 | Expr::Lit(..)
574 | Expr::Ident(..)
575 | Expr::Fn(..)
576 | Expr::Class(..)
577 | Expr::Paren(..)
578 | Expr::Tpl(..)
579 | Expr::TsAs(..) => {
580 if !expr.is_valid_simple_assignment_target(self.ctx().strict) {
581 self.emit_err(span, SyntaxError::NotSimpleAssign)
582 }
583 match *expr {
584 Expr::Ident(i) => return Ok(i.into()),
585 _ => {
586 return Ok(expr.into());
587 }
588 }
589 }
590
591 Expr::Assign(..) => {}
593
594 _ => self.emit_err(span, SyntaxError::InvalidPat),
595 }
596 }
597
598 match *expr {
599 Expr::Paren(..) => {
600 self.emit_err(span, SyntaxError::InvalidPat);
601 Ok(Invalid { span }.into())
602 }
603 Expr::Assign(
604 assign_expr @ AssignExpr {
605 op: AssignOp::Assign,
606 ..
607 },
608 ) => {
609 let AssignExpr {
610 span, left, right, ..
611 } = assign_expr;
612 Ok(AssignPat {
613 span,
614 left: match left {
615 AssignTarget::Simple(left) => {
616 Box::new(self.reparse_expr_as_pat(pat_ty, left.into())?)
617 }
618 AssignTarget::Pat(pat) => pat.into(),
619 },
620 right,
621 }
622 .into())
623 }
624 Expr::Object(ObjectLit {
625 span: object_span,
626 props,
627 }) => {
628 let len = props.len();
630 Ok(ObjectPat {
631 span: object_span,
632 props: props
633 .into_iter()
634 .enumerate()
635 .map(|(idx, prop)| {
636 let span = prop.span();
637 match prop {
638 PropOrSpread::Prop(prop) => match *prop {
639 Prop::Shorthand(id) => {
640 Ok(ObjectPatProp::Assign(AssignPatProp {
641 span: id.span(),
642 key: id.into(),
643 value: None,
644 }))
645 }
646 Prop::KeyValue(kv_prop) => {
647 Ok(ObjectPatProp::KeyValue(KeyValuePatProp {
648 key: kv_prop.key,
649 value: Box::new(self.reparse_expr_as_pat(
650 pat_ty.element(),
651 kv_prop.value,
652 )?),
653 }))
654 }
655 Prop::Assign(assign_prop) => {
656 Ok(ObjectPatProp::Assign(AssignPatProp {
657 span,
658 key: assign_prop.key.into(),
659 value: Some(assign_prop.value),
660 }))
661 }
662 _ => syntax_error!(self, prop.span(), SyntaxError::InvalidPat),
663 },
664
665 PropOrSpread::Spread(SpreadElement { dot3_token, expr }) => {
666 if idx != len - 1 {
667 self.emit_err(span, SyntaxError::NonLastRestParam)
668 } else if let Some(trailing_comma) =
669 self.state.trailing_commas.get(&object_span.lo)
670 {
671 self.emit_err(
672 *trailing_comma,
673 SyntaxError::CommaAfterRestElement,
674 );
675 };
676
677 let element_pat_ty = pat_ty.element();
678 let pat = if let PatType::BindingElement = element_pat_ty {
679 if let Expr::Ident(i) = *expr {
680 i.into()
681 } else {
682 self.emit_err(span, SyntaxError::DotsWithoutIdentifier);
683 Pat::Invalid(Invalid { span })
684 }
685 } else {
686 self.reparse_expr_as_pat(element_pat_ty, expr)?
687 };
688
689 if let Pat::Assign(_) = pat {
690 self.emit_err(span, SyntaxError::TS1048)
691 };
692
693 Ok(ObjectPatProp::Rest(RestPat {
694 span,
695 dot3_token,
696 arg: Box::new(pat),
697 type_ann: None,
698 }))
699 }
700 }
701 })
702 .collect::<PResult<_>>()?,
703 optional: false,
704 type_ann: None,
705 }
706 .into())
707 }
708 Expr::Ident(ident) => Ok(ident.into()),
709 Expr::Array(ArrayLit {
710 elems: mut exprs, ..
711 }) => {
712 if exprs.is_empty() {
713 return Ok(ArrayPat {
714 span,
715 elems: Vec::new(),
716 optional: false,
717 type_ann: None,
718 }
719 .into());
720 }
721
722 let count_of_trailing_comma =
724 exprs.iter().rev().take_while(|e| e.is_none()).count();
725
726 let len = exprs.len();
727 let mut params = Vec::with_capacity(exprs.len() - count_of_trailing_comma);
728
729 let idx_of_rest_not_allowed = if count_of_trailing_comma == 0 {
731 len - 1
732 } else {
733 len - count_of_trailing_comma
735 };
736
737 for expr in exprs.drain(..idx_of_rest_not_allowed) {
738 match expr {
739 Some(
740 expr @ ExprOrSpread {
741 spread: Some(..), ..
742 },
743 ) => self.emit_err(expr.span(), SyntaxError::NonLastRestParam),
744 Some(ExprOrSpread { expr, .. }) => {
745 params.push(self.reparse_expr_as_pat(pat_ty.element(), expr).map(Some)?)
746 }
747 None => params.push(None),
748 }
749 }
750
751 if count_of_trailing_comma == 0 {
752 let expr = exprs.into_iter().next().unwrap();
753 let outer_expr_span = expr.span();
754 let last = match expr {
755 Some(ExprOrSpread {
757 spread: Some(dot3_token),
758 expr,
759 }) => {
760 if let Expr::Assign(_) = *expr {
762 self.emit_err(outer_expr_span, SyntaxError::TS1048);
763 };
764 if let Some(trailing_comma) = self.state.trailing_commas.get(&span.lo) {
765 self.emit_err(*trailing_comma, SyntaxError::CommaAfterRestElement);
766 }
767 let expr_span = expr.span();
768 self.reparse_expr_as_pat(pat_ty.element(), expr)
769 .map(|pat| {
770 RestPat {
771 span: expr_span,
772 dot3_token,
773 arg: Box::new(pat),
774 type_ann: None,
775 }
776 .into()
777 })
778 .map(Some)?
779 }
780 Some(ExprOrSpread { expr, .. }) => {
781 self.reparse_expr_as_pat(pat_ty.element(), expr).map(Some)?
783 }
784 None => None,
786 };
787 params.push(last);
788 }
789 Ok(ArrayPat {
790 span,
791 elems: params,
792 optional: false,
793 type_ann: None,
794 }
795 .into())
796 }
797
798 Expr::Lit(..) | Expr::Assign(..) => {
801 self.emit_err(span, SyntaxError::InvalidPat);
802 Ok(Invalid { span }.into())
803 }
804
805 Expr::Yield(..) if self.ctx().in_generator => {
806 self.emit_err(span, SyntaxError::InvalidPat);
807 Ok(Invalid { span }.into())
808 }
809
810 _ => {
811 self.emit_err(span, SyntaxError::InvalidPat);
812
813 Ok(Invalid { span }.into())
814 }
815 }
816 }
817
818 pub(super) fn parse_paren_items_as_params(
819 &mut self,
820 mut exprs: Vec<AssignTargetOrSpread>,
821 trailing_comma: Option<Span>,
822 ) -> PResult<Vec<Pat>> {
823 let pat_ty = PatType::BindingPat;
824
825 let len = exprs.len();
826 if len == 0 {
827 return Ok(Vec::new());
828 }
829
830 let mut params = Vec::with_capacity(len);
831
832 for expr in exprs.drain(..len - 1) {
833 match expr {
834 AssignTargetOrSpread::ExprOrSpread(ExprOrSpread {
835 spread: Some(..), ..
836 })
837 | AssignTargetOrSpread::Pat(Pat::Rest(..)) => {
838 self.emit_err(expr.span(), SyntaxError::TS1014)
839 }
840 AssignTargetOrSpread::ExprOrSpread(ExprOrSpread {
841 spread: None, expr, ..
842 }) => params.push(self.reparse_expr_as_pat(pat_ty, expr)?),
843 AssignTargetOrSpread::Pat(pat) => params.push(pat),
844 }
845 }
846
847 debug_assert_eq!(exprs.len(), 1);
848 let expr = exprs.into_iter().next().unwrap();
849 let outer_expr_span = expr.span();
850 let last = match expr {
851 AssignTargetOrSpread::ExprOrSpread(ExprOrSpread {
853 spread: Some(dot3_token),
854 expr,
855 }) => {
856 if let Expr::Assign(_) = *expr {
857 self.emit_err(outer_expr_span, SyntaxError::TS1048)
858 };
859 if let Some(trailing_comma) = trailing_comma {
860 self.emit_err(trailing_comma, SyntaxError::CommaAfterRestElement);
861 }
862 let expr_span = expr.span();
863 self.reparse_expr_as_pat(pat_ty, expr).map(|pat| {
864 RestPat {
865 span: expr_span,
866 dot3_token,
867 arg: Box::new(pat),
868 type_ann: None,
869 }
870 .into()
871 })?
872 }
873 AssignTargetOrSpread::ExprOrSpread(ExprOrSpread { expr, .. }) => {
874 self.reparse_expr_as_pat(pat_ty, expr)?
875 }
876 AssignTargetOrSpread::Pat(pat) => {
877 if let Some(trailing_comma) = trailing_comma {
878 if let Pat::Rest(..) = pat {
879 self.emit_err(trailing_comma, SyntaxError::CommaAfterRestElement);
880 }
881 }
882 pat
883 }
884 };
885 params.push(last);
886
887 if self.ctx().strict {
888 for param in params.iter() {
889 self.pat_is_valid_argument_in_strict(param)
890 }
891 }
892
893 Ok(params)
894 }
895
896 fn pat_is_valid_argument_in_strict(&self, pat: &Pat) {
900 match pat {
901 Pat::Ident(i) => {
902 if i.is_reserved_in_strict_bind() {
903 self.emit_strict_mode_err(i.span, SyntaxError::EvalAndArgumentsInStrict)
904 }
905 }
906 Pat::Array(arr) => {
907 for pat in arr.elems.iter().flatten() {
908 self.pat_is_valid_argument_in_strict(pat)
909 }
910 }
911 Pat::Rest(r) => self.pat_is_valid_argument_in_strict(&r.arg),
912 Pat::Object(obj) => {
913 for prop in obj.props.iter() {
914 match prop {
915 ObjectPatProp::KeyValue(KeyValuePatProp { value, .. })
916 | ObjectPatProp::Rest(RestPat { arg: value, .. }) => {
917 self.pat_is_valid_argument_in_strict(value)
918 }
919 ObjectPatProp::Assign(AssignPatProp { key, .. }) => {
920 if key.is_reserved_in_strict_bind() {
921 self.emit_strict_mode_err(
922 key.span,
923 SyntaxError::EvalAndArgumentsInStrict,
924 )
925 }
926 }
927 }
928 }
929 }
930 Pat::Assign(a) => self.pat_is_valid_argument_in_strict(&a.left),
931 Pat::Invalid(_) | Pat::Expr(_) => (),
932 }
933 }
934}
935
936#[cfg(test)]
937mod tests {
938 use swc_common::DUMMY_SP as span;
939 use swc_ecma_visit::assert_eq_ignore_span;
940
941 use super::*;
942
943 fn array_pat(s: &'static str) -> Pat {
944 test_parser(s, Syntax::default(), |p| p.parse_array_binding_pat())
945 }
946
947 fn object_pat(s: &'static str) -> Pat {
948 test_parser(s, Syntax::default(), |p| {
949 p.parse_binding_pat_or_ident(false)
950 })
951 }
952
953 fn ident(s: &str) -> Ident {
954 Ident::new_no_ctxt(s.into(), span)
955 }
956
957 fn ident_name(s: &str) -> IdentName {
958 IdentName::new(s.into(), span)
959 }
960
961 fn rest() -> Option<Pat> {
962 Some(
963 RestPat {
964 span,
965 dot3_token: span,
966 type_ann: None,
967 arg: ident("tail").into(),
968 }
969 .into(),
970 )
971 }
972
973 #[test]
974 fn array_pat_simple() {
975 assert_eq_ignore_span!(
976 array_pat("[a, [b], [c]]"),
977 Pat::Array(ArrayPat {
978 span,
979 optional: false,
980 elems: vec![
981 Some(Pat::Ident(ident("a").into())),
982 Some(Pat::Array(ArrayPat {
983 span,
984 optional: false,
985 elems: vec![Some(Pat::Ident(ident("b").into()))],
986 type_ann: None
987 })),
988 Some(Pat::Array(ArrayPat {
989 span,
990 optional: false,
991 elems: vec![Some(Pat::Ident(ident("c").into()))],
992 type_ann: None
993 }))
994 ],
995 type_ann: None
996 })
997 );
998 }
999
1000 #[test]
1001 fn array_pat_empty_start() {
1002 assert_eq_ignore_span!(
1003 array_pat("[, a, [b], [c]]"),
1004 Pat::Array(ArrayPat {
1005 span,
1006 optional: false,
1007 elems: vec![
1008 None,
1009 Some(Pat::Ident(ident("a").into())),
1010 Some(Pat::Array(ArrayPat {
1011 span,
1012 optional: false,
1013 elems: vec![Some(Pat::Ident(ident("b").into()))],
1014 type_ann: None
1015 })),
1016 Some(Pat::Array(ArrayPat {
1017 span,
1018 optional: false,
1019 elems: vec![Some(Pat::Ident(ident("c").into()))],
1020 type_ann: None
1021 }))
1022 ],
1023 type_ann: None
1024 })
1025 );
1026 }
1027
1028 #[test]
1029 fn array_pat_empty() {
1030 assert_eq_ignore_span!(
1031 array_pat("[a, , [b], [c]]"),
1032 Pat::Array(ArrayPat {
1033 span,
1034 optional: false,
1035 elems: vec![
1036 Some(Pat::Ident(ident("a").into())),
1037 None,
1038 Some(Pat::Array(ArrayPat {
1039 span,
1040 optional: false,
1041 elems: vec![Some(Pat::Ident(ident("b").into()))],
1042 type_ann: None
1043 })),
1044 Some(Pat::Array(ArrayPat {
1045 span,
1046 optional: false,
1047 elems: vec![Some(Pat::Ident(ident("c").into()))],
1048 type_ann: None
1049 }))
1050 ],
1051 type_ann: None
1052 })
1053 );
1054 }
1055
1056 #[test]
1057 fn array_pat_empty_end() {
1058 assert_eq_ignore_span!(
1059 array_pat("[a, ,]"),
1060 Pat::Array(ArrayPat {
1061 span,
1062 optional: false,
1063 elems: vec![Some(Pat::Ident(ident("a").into())), None,],
1064 type_ann: None
1065 })
1066 );
1067 }
1068
1069 #[test]
1070 fn array_binding_pattern_tail() {
1071 assert_eq_ignore_span!(
1072 array_pat("[...tail]"),
1073 Pat::Array(ArrayPat {
1074 span,
1075 optional: false,
1076 elems: vec![rest()],
1077 type_ann: None
1078 })
1079 );
1080 }
1081
1082 #[test]
1083 fn array_binding_pattern_assign() {
1084 assert_eq_ignore_span!(
1085 array_pat("[,a=1,]"),
1086 Pat::Array(ArrayPat {
1087 span,
1088 optional: false,
1089 elems: vec![
1090 None,
1091 Some(Pat::Assign(AssignPat {
1092 span,
1093 left: Box::new(Pat::Ident(ident("a").into())),
1094 right: Box::new(Expr::Lit(Lit::Num(Number {
1095 span,
1096 value: 1.0,
1097 raw: Some("1".into())
1098 })))
1099 }))
1100 ],
1101 type_ann: None
1102 })
1103 );
1104 }
1105
1106 #[test]
1107 fn array_binding_pattern_tail_with_elems() {
1108 assert_eq_ignore_span!(
1109 array_pat("[,,,...tail]"),
1110 Pat::Array(ArrayPat {
1111 span,
1112 optional: false,
1113 elems: vec![None, None, None, rest()],
1114 type_ann: None
1115 })
1116 );
1117 }
1118
1119 #[test]
1120 fn array_binding_pattern_tail_inside_tail() {
1121 assert_eq_ignore_span!(
1122 array_pat("[,,,...[...tail]]"),
1123 Pat::Array(ArrayPat {
1124 span,
1125 optional: false,
1126 elems: vec![
1127 None,
1128 None,
1129 None,
1130 Some(Pat::Rest(RestPat {
1131 span,
1132 dot3_token: span,
1133 type_ann: None,
1134 arg: Box::new(Pat::Array(ArrayPat {
1135 span,
1136 optional: false,
1137 elems: vec![rest()],
1138 type_ann: None
1139 }))
1140 }))
1141 ],
1142 type_ann: None
1143 })
1144 );
1145 }
1146
1147 #[test]
1148 fn object_binding_pattern_tail() {
1149 assert_eq_ignore_span!(
1150 object_pat("{...obj}"),
1151 Pat::Object(ObjectPat {
1152 span,
1153 type_ann: None,
1154 optional: false,
1155 props: vec![ObjectPatProp::Rest(RestPat {
1156 span,
1157 dot3_token: span,
1158 type_ann: None,
1159 arg: Box::new(Pat::Ident(ident("obj").into()))
1160 })]
1161 })
1162 );
1163 }
1164
1165 #[test]
1166 fn object_binding_pattern_with_prop() {
1167 assert_eq_ignore_span!(
1168 object_pat("{prop = 10 }"),
1169 Pat::Object(ObjectPat {
1170 span,
1171 type_ann: None,
1172 optional: false,
1173 props: vec![ObjectPatProp::Assign(AssignPatProp {
1174 span,
1175 key: ident("prop").into(),
1176 value: Some(Box::new(Expr::Lit(Lit::Num(Number {
1177 span,
1178 value: 10.0,
1179 raw: Some("10".into())
1180 }))))
1181 })]
1182 })
1183 );
1184 }
1185
1186 #[test]
1187 fn object_binding_pattern_with_prop_and_label() {
1188 fn prop(key: PropName, assign_name: &str, expr: Expr) -> PropOrSpread {
1189 PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
1190 key,
1191 value: AssignExpr {
1192 span,
1193 op: AssignOp::Assign,
1194 left: ident(assign_name).into(),
1195 right: Box::new(expr),
1196 }
1197 .into(),
1198 })))
1199 }
1200
1201 assert_eq_ignore_span!(
1202 object_pat(
1203 "{obj = {$: num = 10, '': sym = '', \" \": quote = \" \", _: under = [...tail],}}"
1204 ),
1205 Pat::Object(ObjectPat {
1206 span,
1207 type_ann: None,
1208 optional: false,
1209 props: vec![ObjectPatProp::Assign(AssignPatProp {
1210 span,
1211 key: ident("obj").into(),
1212 value: Some(Box::new(Expr::Object(ObjectLit {
1213 span,
1214 props: vec![
1215 prop(
1216 PropName::Ident(ident_name("$")),
1217 "num",
1218 Expr::Lit(Lit::Num(Number {
1219 span,
1220 value: 10.0,
1221 raw: Some("10".into())
1222 }))
1223 ),
1224 prop(
1225 PropName::Str(Str {
1226 span,
1227 value: "".into(),
1228 raw: Some("''".into()),
1229 }),
1230 "sym",
1231 Expr::Lit(Lit::Str(Str {
1232 span,
1233 value: "".into(),
1234 raw: Some("''".into()),
1235 }))
1236 ),
1237 prop(
1238 PropName::Str(Str {
1239 span,
1240 value: " ".into(),
1241 raw: Some("\" \"".into()),
1242 }),
1243 "quote",
1244 Expr::Lit(Lit::Str(Str {
1245 span,
1246 value: " ".into(),
1247 raw: Some("\" \"".into()),
1248 }))
1249 ),
1250 prop(
1251 PropName::Ident(ident_name("_")),
1252 "under",
1253 Expr::Array(ArrayLit {
1254 span,
1255 elems: vec![Some(ExprOrSpread {
1256 spread: Some(span),
1257 expr: Box::new(Expr::Ident(ident("tail")))
1258 })]
1259 })
1260 ),
1261 ]
1262 })))
1263 })]
1264 })
1265 );
1266 }
1267}