swc_ecma_lexer/common/parser/
pat.rs

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
25/// argument of arrow is pattern, although idents in pattern is already
26/// checked if is a keyword, it should also be checked if is arguments or
27/// eval
28fn 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
66/// This does not return 'rest' pattern because non-last parameter cannot be
67/// rest.
68pub(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                // It is a Syntax Error if LeftHandSideExpression is either
80                // an ObjectLiteral or an ArrayLiteral
81                // and LeftHandSideExpression cannot
82                // be reparsed as an AssignmentPattern.
83            }
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    // In dts, we do not reparse.
98    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                // It is a Syntax Error if LeftHandSideExpression is either
104                // an ObjectLiteral or an ArrayLiteral
105                // and LeftHandSideExpression cannot
106                // be reparsed as an AssignmentPattern.
107            }
108
109            _ => match *expr {
110                // It is a Syntax Error if the LeftHandSideExpression is
111                // CoverParenthesizedExpressionAndArrowParameterList:(Expression) and
112                // Expression derives a phrase that would produce a Syntax Error according
113                // to these rules if that phrase were substituted for
114                // LeftHandSideExpression. This rule is recursively applied.
115                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    // AssignmentElement:
127    //      DestructuringAssignmentTarget Initializer[+In]?
128    //
129    // DestructuringAssignmentTarget:
130    //      LeftHandSideExpression
131    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            // It's special because of optional initializer
156            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            // {}
194            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            // Trailing comma may exist. We should remove those commas.
284            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            // Comma or other pattern cannot follow a rest pattern.
288            let idx_of_rest_not_allowed = if count_of_trailing_comma == 0 {
289                len - 1
290            } else {
291                // last element is comma, so rest is not allowed for every pattern element.
292                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                    // Rest
312                    Some(ExprOrSpread {
313                        spread: Some(dot3_token),
314                        expr,
315                    }) => {
316                        // TODO: is BindingPat correct?
317                        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                        // TODO: is BindingPat correct?
338                        reparse_expr_as_pat(p, pat_ty.element(), expr).map(Some)?
339                    }
340                    // TODO: syntax error if last element is ellison and ...rest exists.
341                    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        // Invalid patterns.
355        // Note that assignment expression with '=' is valid, and handled above.
356        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
480/// spec: 'FormalParameter'
481///
482/// babel: `parseAssignableListItem`
483fn 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        // `=` cannot follow optional parameter.
564        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, /* eat_colon */ 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, /* eat_colon */ 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                //
733            }
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    // FIXME: This is wrong
760    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        // Rest
797        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}