1use swc_common::{BytePos, Span, Spanned};
2use swc_ecma_ast::*;
3
4use super::{
5 assign_target_or_spread::AssignTargetOrSpread,
6 class_and_fn::{parse_access_modifier, parse_decorators},
7 pat_type::PatType,
8 typescript::{
9 eat_any_ts_modifier, parse_ts_modifier, parse_ts_type_ann, try_parse_ts_type_ann,
10 },
11 PResult, Parser,
12};
13use crate::{
14 common::{
15 context::Context,
16 lexer::token::TokenFactory,
17 parser::{
18 buffer::Buffer, expr::parse_assignment_expr, expr_ext::ExprExt,
19 ident::parse_binding_ident, object::parse_object_pat,
20 },
21 },
22 error::SyntaxError,
23};
24
25fn pat_is_valid_argument_in_strict<'a>(p: &mut impl Parser<'a>, pat: &Pat) {
29 debug_assert!(p.ctx().contains(Context::Strict));
30 match pat {
31 Pat::Ident(i) => {
32 if i.is_reserved_in_strict_bind() {
33 p.emit_strict_mode_err(i.span, SyntaxError::EvalAndArgumentsInStrict)
34 }
35 }
36 Pat::Array(arr) => {
37 for pat in arr.elems.iter().flatten() {
38 pat_is_valid_argument_in_strict(p, pat)
39 }
40 }
41 Pat::Rest(r) => pat_is_valid_argument_in_strict(p, &r.arg),
42 Pat::Object(obj) => {
43 for prop in obj.props.iter() {
44 match prop {
45 ObjectPatProp::KeyValue(KeyValuePatProp { value, .. })
46 | ObjectPatProp::Rest(RestPat { arg: value, .. }) => {
47 pat_is_valid_argument_in_strict(p, value)
48 }
49 ObjectPatProp::Assign(AssignPatProp { key, .. }) => {
50 if key.is_reserved_in_strict_bind() {
51 p.emit_strict_mode_err(key.span, SyntaxError::EvalAndArgumentsInStrict)
52 }
53 }
54 #[cfg(swc_ast_unknown)]
55 _ => (),
56 }
57 }
58 }
59 Pat::Assign(a) => pat_is_valid_argument_in_strict(p, &a.left),
60 Pat::Invalid(_) | Pat::Expr(_) => (),
61 #[cfg(swc_ast_unknown)]
62 _ => (),
63 }
64}
65
66pub(super) fn reparse_expr_as_pat<'a>(
69 p: &mut impl Parser<'a>,
70 pat_ty: PatType,
71 expr: Box<Expr>,
72) -> PResult<Pat> {
73 if let Expr::Invalid(i) = *expr {
74 return Ok(i.into());
75 }
76 if pat_ty == PatType::AssignPat {
77 match *expr {
78 Expr::Object(..) | Expr::Array(..) => {
79 }
84 _ => {
85 p.check_assign_target(&expr, true);
86 }
87 }
88 }
89 reparse_expr_as_pat_inner(p, pat_ty, expr)
90}
91
92fn reparse_expr_as_pat_inner<'a>(
93 p: &mut impl Parser<'a>,
94 pat_ty: PatType,
95 expr: Box<Expr>,
96) -> PResult<Pat> {
97 debug_assert!(!p.input().syntax().dts());
99 let span = expr.span();
100 if pat_ty == PatType::AssignPat {
101 match *expr {
102 Expr::Object(..) | Expr::Array(..) => {
103 }
108
109 _ => match *expr {
110 Expr::Paren(..) => {
116 return Ok(expr.into());
117 }
118 Expr::Ident(i) => return Ok(i.into()),
119 _ => {
120 return Ok(expr.into());
121 }
122 },
123 }
124 }
125
126 if pat_ty == PatType::AssignElement {
132 match *expr {
133 Expr::Array(..) | Expr::Object(..) => {}
134 Expr::Member(..)
135 | Expr::SuperProp(..)
136 | Expr::Call(..)
137 | Expr::New(..)
138 | Expr::Lit(..)
139 | Expr::Ident(..)
140 | Expr::Fn(..)
141 | Expr::Class(..)
142 | Expr::Paren(..)
143 | Expr::Tpl(..)
144 | Expr::TsAs(..) => {
145 if !expr.is_valid_simple_assignment_target(p.ctx().contains(Context::Strict)) {
146 p.emit_err(span, SyntaxError::NotSimpleAssign)
147 }
148 match *expr {
149 Expr::Ident(i) => return Ok(i.into()),
150 _ => {
151 return Ok(expr.into());
152 }
153 }
154 }
155 Expr::Assign(..) => {}
157 _ => p.emit_err(span, SyntaxError::InvalidPat),
158 }
159 }
160
161 match *expr {
162 Expr::Paren(..) => {
163 p.emit_err(span, SyntaxError::InvalidPat);
164 Ok(Invalid { span }.into())
165 }
166 Expr::Assign(
167 assign_expr @ AssignExpr {
168 op: AssignOp::Assign,
169 ..
170 },
171 ) => {
172 let AssignExpr {
173 span, left, right, ..
174 } = assign_expr;
175 Ok(AssignPat {
176 span,
177 left: match left {
178 AssignTarget::Simple(left) => {
179 Box::new(reparse_expr_as_pat(p, pat_ty, left.into())?)
180 }
181 AssignTarget::Pat(pat) => pat.into(),
182 #[cfg(swc_ast_unknown)]
183 _ => unreachable!(),
184 },
185 right,
186 }
187 .into())
188 }
189 Expr::Object(ObjectLit {
190 span: object_span,
191 props,
192 }) => {
193 let len = props.len();
195 Ok(ObjectPat {
196 span: object_span,
197 props: props
198 .into_iter()
199 .enumerate()
200 .map(|(idx, prop)| {
201 let span = prop.span();
202 match prop {
203 PropOrSpread::Prop(prop) => match *prop {
204 Prop::Shorthand(id) => Ok(ObjectPatProp::Assign(AssignPatProp {
205 span: id.span(),
206 key: id.into(),
207 value: None,
208 })),
209 Prop::KeyValue(kv_prop) => {
210 Ok(ObjectPatProp::KeyValue(KeyValuePatProp {
211 key: kv_prop.key,
212 value: Box::new(reparse_expr_as_pat(
213 p,
214 pat_ty.element(),
215 kv_prop.value,
216 )?),
217 }))
218 }
219 Prop::Assign(assign_prop) => {
220 Ok(ObjectPatProp::Assign(AssignPatProp {
221 span,
222 key: assign_prop.key.into(),
223 value: Some(assign_prop.value),
224 }))
225 }
226 _ => syntax_error!(p, prop.span(), SyntaxError::InvalidPat),
227 },
228
229 PropOrSpread::Spread(SpreadElement { dot3_token, expr }) => {
230 if idx != len - 1 {
231 p.emit_err(span, SyntaxError::NonLastRestParam)
232 } else if let Some(trailing_comma) =
233 p.state().trailing_commas.get(&object_span.lo)
234 {
235 p.emit_err(*trailing_comma, SyntaxError::CommaAfterRestElement);
236 };
237
238 let element_pat_ty = pat_ty.element();
239 let pat = if let PatType::BindingElement = element_pat_ty {
240 if let Expr::Ident(i) = *expr {
241 i.into()
242 } else {
243 p.emit_err(span, SyntaxError::DotsWithoutIdentifier);
244 Pat::Invalid(Invalid { span })
245 }
246 } else {
247 reparse_expr_as_pat(p, element_pat_ty, expr)?
248 };
249 if let Pat::Assign(_) = pat {
250 p.emit_err(span, SyntaxError::TS1048)
251 };
252 Ok(ObjectPatProp::Rest(RestPat {
253 span,
254 dot3_token,
255 arg: Box::new(pat),
256 type_ann: None,
257 }))
258 }
259
260 #[cfg(swc_ast_unknown)]
261 _ => unreachable!(),
262 }
263 })
264 .collect::<PResult<_>>()?,
265 optional: false,
266 type_ann: None,
267 }
268 .into())
269 }
270 Expr::Ident(ident) => Ok(ident.into()),
271 Expr::Array(ArrayLit {
272 elems: mut exprs, ..
273 }) => {
274 if exprs.is_empty() {
275 return Ok(ArrayPat {
276 span,
277 elems: Vec::new(),
278 optional: false,
279 type_ann: None,
280 }
281 .into());
282 }
283 let count_of_trailing_comma = exprs.iter().rev().take_while(|e| e.is_none()).count();
285 let len = exprs.len();
286 let mut params = Vec::with_capacity(exprs.len() - count_of_trailing_comma);
287 let idx_of_rest_not_allowed = if count_of_trailing_comma == 0 {
289 len - 1
290 } else {
291 len - count_of_trailing_comma
293 };
294 for expr in exprs.drain(..idx_of_rest_not_allowed) {
295 match expr {
296 Some(
297 expr @ ExprOrSpread {
298 spread: Some(..), ..
299 },
300 ) => p.emit_err(expr.span(), SyntaxError::NonLastRestParam),
301 Some(ExprOrSpread { expr, .. }) => {
302 params.push(reparse_expr_as_pat(p, pat_ty.element(), expr).map(Some)?)
303 }
304 None => params.push(None),
305 }
306 }
307 if count_of_trailing_comma == 0 {
308 let expr = exprs.into_iter().next().unwrap();
309 let outer_expr_span = expr.span();
310 let last = match expr {
311 Some(ExprOrSpread {
313 spread: Some(dot3_token),
314 expr,
315 }) => {
316 if let Expr::Assign(_) = *expr {
318 p.emit_err(outer_expr_span, SyntaxError::TS1048);
319 };
320 if let Some(trailing_comma) = p.state().trailing_commas.get(&span.lo) {
321 p.emit_err(*trailing_comma, SyntaxError::CommaAfterRestElement);
322 }
323 let expr_span = expr.span();
324 reparse_expr_as_pat(p, pat_ty.element(), expr)
325 .map(|pat| {
326 RestPat {
327 span: expr_span,
328 dot3_token,
329 arg: Box::new(pat),
330 type_ann: None,
331 }
332 .into()
333 })
334 .map(Some)?
335 }
336 Some(ExprOrSpread { expr, .. }) => {
337 reparse_expr_as_pat(p, pat_ty.element(), expr).map(Some)?
339 }
340 None => None,
342 };
343 params.push(last);
344 }
345 Ok(ArrayPat {
346 span,
347 elems: params,
348 optional: false,
349 type_ann: None,
350 }
351 .into())
352 }
353
354 Expr::Lit(..) | Expr::Assign(..) => {
357 p.emit_err(span, SyntaxError::InvalidPat);
358 Ok(Invalid { span }.into())
359 }
360
361 Expr::Yield(..) if p.ctx().contains(Context::InGenerator) => {
362 p.emit_err(span, SyntaxError::InvalidPat);
363 Ok(Invalid { span }.into())
364 }
365
366 _ => {
367 p.emit_err(span, SyntaxError::InvalidPat);
368
369 Ok(Invalid { span }.into())
370 }
371 }
372}
373
374pub(super) fn parse_binding_element<'a, P: Parser<'a>>(p: &mut P) -> PResult<Pat> {
375 trace_cur!(p, parse_binding_element);
376
377 let start = p.cur_pos();
378 let left = parse_binding_pat_or_ident(p, false)?;
379
380 if p.input_mut().eat(&P::Token::EQUAL) {
381 let right = p.allow_in_expr(parse_assignment_expr)?;
382
383 if p.ctx().contains(Context::InDeclare) {
384 p.emit_err(p.span(start), SyntaxError::TS2371);
385 }
386
387 return Ok(AssignPat {
388 span: p.span(start),
389 left: Box::new(left),
390 right,
391 }
392 .into());
393 }
394
395 Ok(left)
396}
397
398pub fn parse_binding_pat_or_ident<'a, P: Parser<'a>>(
399 p: &mut P,
400 disallow_let: bool,
401) -> PResult<Pat> {
402 trace_cur!(p, parse_binding_pat_or_ident);
403
404 let cur = p.input().cur();
405 if cur.is_word() {
406 parse_binding_ident(p, disallow_let).map(Pat::from)
407 } else if cur.is_lbracket() {
408 parse_array_binding_pat(p)
409 } else if cur.is_lbrace() {
410 parse_object_pat(p)
411 } else if cur.is_error() {
412 let err = p.input_mut().expect_error_token_and_bump();
413 Err(err)
414 } else {
415 unexpected!(p, "yield, an identifier, [ or {")
416 }
417}
418
419pub fn parse_array_binding_pat<'a, P: Parser<'a>>(p: &mut P) -> PResult<Pat> {
420 let start = p.cur_pos();
421
422 p.assert_and_bump(&P::Token::LBRACKET);
423
424 let mut elems = Vec::new();
425
426 let mut rest_span = Span::default();
427
428 while !p.input().is(&P::Token::RBRACKET) {
429 if p.input_mut().eat(&P::Token::COMMA) {
430 elems.push(None);
431 continue;
432 }
433
434 if !rest_span.is_dummy() {
435 p.emit_err(rest_span, SyntaxError::NonLastRestParam);
436 }
437
438 let start = p.cur_pos();
439
440 let mut is_rest = false;
441 if p.input_mut().eat(&P::Token::DOTDOTDOT) {
442 is_rest = true;
443 let dot3_token = p.span(start);
444
445 let pat = parse_binding_pat_or_ident(p, false)?;
446 rest_span = p.span(start);
447 let pat = RestPat {
448 span: rest_span,
449 dot3_token,
450 arg: Box::new(pat),
451 type_ann: None,
452 }
453 .into();
454 elems.push(Some(pat));
455 } else {
456 elems.push(parse_binding_element(p).map(Some)?);
457 }
458
459 if !p.input().is(&P::Token::RBRACKET) {
460 expect!(p, &P::Token::COMMA);
461 if is_rest && p.input().is(&P::Token::RBRACKET) {
462 p.emit_err(p.input().prev_span(), SyntaxError::CommaAfterRestElement);
463 }
464 }
465 }
466
467 expect!(p, &P::Token::RBRACKET);
468 let optional = (p.input().syntax().dts() || p.ctx().contains(Context::InDeclare))
469 && p.input_mut().eat(&P::Token::QUESTION);
470
471 Ok(ArrayPat {
472 span: p.span(start),
473 elems,
474 optional,
475 type_ann: None,
476 }
477 .into())
478}
479
480fn parse_formal_param_pat<'a, P: Parser<'a>>(p: &mut P) -> PResult<Pat> {
484 let start = p.cur_pos();
485
486 let has_modifier = eat_any_ts_modifier(p)?;
487
488 let pat_start = p.cur_pos();
489 let mut pat = parse_binding_element(p)?;
490 let mut opt = false;
491
492 if p.input().syntax().typescript() {
493 if p.input_mut().eat(&P::Token::QUESTION) {
494 match pat {
495 Pat::Ident(BindingIdent {
496 id: Ident {
497 ref mut optional, ..
498 },
499 ..
500 })
501 | Pat::Array(ArrayPat {
502 ref mut optional, ..
503 })
504 | Pat::Object(ObjectPat {
505 ref mut optional, ..
506 }) => {
507 *optional = true;
508 opt = true;
509 }
510 _ if p.input().syntax().dts() || p.ctx().contains(Context::InDeclare) => {}
511 _ => {
512 syntax_error!(
513 p,
514 p.input().prev_span(),
515 SyntaxError::TsBindingPatCannotBeOptional
516 );
517 }
518 }
519 }
520
521 match pat {
522 Pat::Array(ArrayPat {
523 ref mut type_ann,
524 ref mut span,
525 ..
526 })
527 | Pat::Object(ObjectPat {
528 ref mut type_ann,
529 ref mut span,
530 ..
531 })
532 | Pat::Rest(RestPat {
533 ref mut type_ann,
534 ref mut span,
535 ..
536 }) => {
537 let new_type_ann = try_parse_ts_type_ann(p)?;
538 if new_type_ann.is_some() {
539 *span = Span::new_with_checked(pat_start, p.input().prev_span().hi);
540 }
541 *type_ann = new_type_ann;
542 }
543
544 Pat::Ident(BindingIdent {
545 ref mut type_ann, ..
546 }) => {
547 let new_type_ann = try_parse_ts_type_ann(p)?;
548 *type_ann = new_type_ann;
549 }
550
551 Pat::Assign(AssignPat { ref mut span, .. }) => {
552 if (try_parse_ts_type_ann(p)?).is_some() {
553 *span = Span::new_with_checked(pat_start, p.input().prev_span().hi);
554 p.emit_err(*span, SyntaxError::TSTypeAnnotationAfterAssign);
555 }
556 }
557 Pat::Invalid(..) => {}
558 _ => unreachable!("invalid syntax: Pat: {:?}", pat),
559 }
560 }
561
562 let pat = if p.input_mut().eat(&P::Token::EQUAL) {
563 if opt {
565 p.emit_err(pat.span(), SyntaxError::TS1015);
566 }
567
568 let right = parse_assignment_expr(p)?;
569 if p.ctx().contains(Context::InDeclare) {
570 p.emit_err(p.span(start), SyntaxError::TS2371);
571 }
572
573 AssignPat {
574 span: p.span(start),
575 left: Box::new(pat),
576 right,
577 }
578 .into()
579 } else {
580 pat
581 };
582
583 if has_modifier {
584 p.emit_err(p.span(start), SyntaxError::TS2369);
585 return Ok(pat);
586 }
587
588 Ok(pat)
589}
590
591fn parse_constructor_param<'a, P: Parser<'a>>(
592 p: &mut P,
593 param_start: BytePos,
594 decorators: Vec<Decorator>,
595) -> PResult<ParamOrTsParamProp> {
596 let (accessibility, is_override, readonly) = if p.input().syntax().typescript() {
597 let accessibility = parse_access_modifier(p)?;
598 (
599 accessibility,
600 parse_ts_modifier(p, &["override"], false)?.is_some(),
601 parse_ts_modifier(p, &["readonly"], false)?.is_some(),
602 )
603 } else {
604 (None, false, false)
605 };
606 if accessibility.is_none() && !is_override && !readonly {
607 let pat = parse_formal_param_pat(p)?;
608 Ok(ParamOrTsParamProp::Param(Param {
609 span: p.span(param_start),
610 decorators,
611 pat,
612 }))
613 } else {
614 let param = match parse_formal_param_pat(p)? {
615 Pat::Ident(i) => TsParamPropParam::Ident(i),
616 Pat::Assign(a) => TsParamPropParam::Assign(a),
617 node => syntax_error!(p, node.span(), SyntaxError::TsInvalidParamPropPat),
618 };
619 Ok(ParamOrTsParamProp::TsParamProp(TsParamProp {
620 span: p.span(param_start),
621 accessibility,
622 is_override,
623 readonly,
624 decorators,
625 param,
626 }))
627 }
628}
629
630pub fn parse_constructor_params<'a, P: Parser<'a>>(p: &mut P) -> PResult<Vec<ParamOrTsParamProp>> {
631 let mut params = Vec::new();
632 let mut rest_span = Span::default();
633
634 while !p.input().is(&P::Token::RPAREN) {
635 if !rest_span.is_dummy() {
636 p.emit_err(rest_span, SyntaxError::TS1014);
637 }
638
639 let param_start = p.cur_pos();
640 let decorators = parse_decorators(p, false)?;
641 let pat_start = p.cur_pos();
642
643 let mut is_rest = false;
644 if p.input_mut().eat(&P::Token::DOTDOTDOT) {
645 is_rest = true;
646 let dot3_token = p.span(pat_start);
647
648 let pat = parse_binding_pat_or_ident(p, false)?;
649 let type_ann = if p.input().syntax().typescript() && p.input().is(&P::Token::COLON) {
650 let cur_pos = p.cur_pos();
651 Some(parse_ts_type_ann(p, true, cur_pos)?)
652 } else {
653 None
654 };
655
656 rest_span = p.span(pat_start);
657 let pat = RestPat {
658 span: rest_span,
659 dot3_token,
660 arg: Box::new(pat),
661 type_ann,
662 }
663 .into();
664 params.push(ParamOrTsParamProp::Param(Param {
665 span: p.span(param_start),
666 decorators,
667 pat,
668 }));
669 } else {
670 params.push(parse_constructor_param(p, param_start, decorators)?);
671 }
672
673 if !p.input().is(&P::Token::RPAREN) {
674 expect!(p, &P::Token::COMMA);
675 if p.input().is(&P::Token::RPAREN) && is_rest {
676 p.emit_err(p.input().prev_span(), SyntaxError::CommaAfterRestElement);
677 }
678 }
679 }
680
681 Ok(params)
682}
683
684pub fn parse_formal_params<'a, P: Parser<'a>>(p: &mut P) -> PResult<Vec<Param>> {
685 let mut params = Vec::new();
686 let mut rest_span = Span::default();
687
688 while !p.input().is(&P::Token::RPAREN) {
689 if !rest_span.is_dummy() {
690 p.emit_err(rest_span, SyntaxError::TS1014);
691 }
692
693 let param_start = p.cur_pos();
694 let decorators = parse_decorators(p, false)?;
695 let pat_start = p.cur_pos();
696
697 let pat = if p.input_mut().eat(&P::Token::DOTDOTDOT) {
698 let dot3_token = p.span(pat_start);
699
700 let mut pat = parse_binding_pat_or_ident(p, false)?;
701
702 if p.input_mut().eat(&P::Token::EQUAL) {
703 let right = parse_assignment_expr(p)?;
704 p.emit_err(pat.span(), SyntaxError::TS1048);
705 pat = AssignPat {
706 span: p.span(pat_start),
707 left: Box::new(pat),
708 right,
709 }
710 .into();
711 }
712
713 let type_ann = if p.input().syntax().typescript() && p.input().is(&P::Token::COLON) {
714 let cur_pos = p.cur_pos();
715 let ty = parse_ts_type_ann(p, true, cur_pos)?;
716 Some(ty)
717 } else {
718 None
719 };
720
721 rest_span = p.span(pat_start);
722 let pat = RestPat {
723 span: rest_span,
724 dot3_token,
725 arg: Box::new(pat),
726 type_ann,
727 }
728 .into();
729
730 if p.syntax().typescript() && p.input_mut().eat(&P::Token::QUESTION) {
731 p.emit_err(p.input().prev_span(), SyntaxError::TS1047);
732 }
734
735 pat
736 } else {
737 parse_formal_param_pat(p)?
738 };
739 let is_rest = matches!(pat, Pat::Rest(_));
740
741 params.push(Param {
742 span: p.span(param_start),
743 decorators,
744 pat,
745 });
746
747 if !p.input().is(&P::Token::RPAREN) {
748 expect!(p, &P::Token::COMMA);
749 if is_rest && p.input().is(&P::Token::RPAREN) {
750 p.emit_err(p.input().prev_span(), SyntaxError::CommaAfterRestElement);
751 }
752 }
753 }
754
755 Ok(params)
756}
757
758pub fn parse_unique_formal_params<'a>(p: &mut impl Parser<'a>) -> PResult<Vec<Param>> {
759 parse_formal_params(p)
761}
762
763pub(super) fn parse_paren_items_as_params<'a, P: Parser<'a>>(
764 p: &mut P,
765 mut exprs: Vec<AssignTargetOrSpread>,
766 trailing_comma: Option<Span>,
767) -> PResult<Vec<Pat>> {
768 let pat_ty = PatType::BindingPat;
769
770 let len = exprs.len();
771 if len == 0 {
772 return Ok(Vec::new());
773 }
774
775 let mut params = Vec::with_capacity(len);
776
777 for expr in exprs.drain(..len - 1) {
778 match expr {
779 AssignTargetOrSpread::ExprOrSpread(ExprOrSpread {
780 spread: Some(..), ..
781 })
782 | AssignTargetOrSpread::Pat(Pat::Rest(..)) => {
783 p.emit_err(expr.span(), SyntaxError::TS1014)
784 }
785 AssignTargetOrSpread::ExprOrSpread(ExprOrSpread {
786 spread: None, expr, ..
787 }) => params.push(reparse_expr_as_pat(p, pat_ty, expr)?),
788 AssignTargetOrSpread::Pat(pat) => params.push(pat),
789 }
790 }
791
792 debug_assert_eq!(exprs.len(), 1);
793 let expr = exprs.pop().unwrap();
794 let outer_expr_span = expr.span();
795 let last = match expr {
796 AssignTargetOrSpread::ExprOrSpread(ExprOrSpread {
798 spread: Some(dot3_token),
799 expr,
800 }) => {
801 if let Expr::Assign(_) = *expr {
802 p.emit_err(outer_expr_span, SyntaxError::TS1048)
803 };
804 if let Some(trailing_comma) = trailing_comma {
805 p.emit_err(trailing_comma, SyntaxError::CommaAfterRestElement);
806 }
807 let expr_span = expr.span();
808 reparse_expr_as_pat(p, pat_ty, expr).map(|pat| {
809 RestPat {
810 span: expr_span,
811 dot3_token,
812 arg: Box::new(pat),
813 type_ann: None,
814 }
815 .into()
816 })?
817 }
818 AssignTargetOrSpread::ExprOrSpread(ExprOrSpread { expr, .. }) => {
819 reparse_expr_as_pat(p, pat_ty, expr)?
820 }
821 AssignTargetOrSpread::Pat(pat) => {
822 if let Some(trailing_comma) = trailing_comma {
823 if let Pat::Rest(..) = pat {
824 p.emit_err(trailing_comma, SyntaxError::CommaAfterRestElement);
825 }
826 }
827 pat
828 }
829 };
830 params.push(last);
831
832 if p.ctx().contains(Context::Strict) {
833 for param in params.iter() {
834 pat_is_valid_argument_in_strict(p, param)
835 }
836 }
837 Ok(params)
838}