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