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                }
55            }
56        }
57        Pat::Assign(a) => pat_is_valid_argument_in_strict(p, &a.left),
58        Pat::Invalid(_) | Pat::Expr(_) => (),
59    }
60}
61
62/// This does not return 'rest' pattern because non-last parameter cannot be
63/// rest.
64pub(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                // It is a Syntax Error if LeftHandSideExpression is either
76                // an ObjectLiteral or an ArrayLiteral
77                // and LeftHandSideExpression cannot
78                // be reparsed as an AssignmentPattern.
79            }
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    // In dts, we do not reparse.
94    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                // It is a Syntax Error if LeftHandSideExpression is either
100                // an ObjectLiteral or an ArrayLiteral
101                // and LeftHandSideExpression cannot
102                // be reparsed as an AssignmentPattern.
103            }
104
105            _ => match *expr {
106                // It is a Syntax Error if the LeftHandSideExpression is
107                // CoverParenthesizedExpressionAndArrowParameterList:(Expression) and
108                // Expression derives a phrase that would produce a Syntax Error according
109                // to these rules if that phrase were substituted for
110                // LeftHandSideExpression. This rule is recursively applied.
111                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    // AssignmentElement:
123    //      DestructuringAssignmentTarget Initializer[+In]?
124    //
125    // DestructuringAssignmentTarget:
126    //      LeftHandSideExpression
127    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            // It's special because of optional initializer
152            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            // {}
188            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            // Trailing comma may exist. We should remove those commas.
275            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            // Comma or other pattern cannot follow a rest pattern.
279            let idx_of_rest_not_allowed = if count_of_trailing_comma == 0 {
280                len - 1
281            } else {
282                // last element is comma, so rest is not allowed for every pattern element.
283                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                    // Rest
303                    Some(ExprOrSpread {
304                        spread: Some(dot3_token),
305                        expr,
306                    }) => {
307                        // TODO: is BindingPat correct?
308                        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                        // TODO: is BindingPat correct?
329                        reparse_expr_as_pat(p, pat_ty.element(), expr).map(Some)?
330                    }
331                    // TODO: syntax error if last element is ellison and ...rest exists.
332                    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        // Invalid patterns.
346        // Note that assignment expression with '=' is valid, and handled above.
347        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
471/// spec: 'FormalParameter'
472///
473/// babel: `parseAssignableListItem`
474fn 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        // `=` cannot follow optional parameter.
555        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, /* eat_colon */ 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, /* eat_colon */ 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                //
724            }
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    // FIXME: This is wrong
751    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        // Rest
788        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}