swc_ecma_lexer/common/parser/
class_and_fn.rs

1use swc_atoms::atom;
2use swc_common::{BytePos, Span, Spanned};
3use swc_ecma_ast::*;
4
5use super::{
6    buffer::Buffer,
7    expr::{parse_args, parse_assignment_expr},
8    has_use_strict,
9    ident::{parse_binding_ident, parse_opt_binding_ident, parse_private_name},
10    is_constructor,
11    output_type::OutputType,
12    pat::parse_formal_params,
13    stmt::parse_block,
14    typescript::{parse_ts_modifier, parse_ts_type_args, try_parse_ts_type_ann},
15    PResult, Parser,
16};
17use crate::{
18    common::{
19        context::Context,
20        lexer::token::TokenFactory,
21        parser::{
22            expr::parse_subscripts,
23            ident::parse_ident,
24            is_invalid_class_name::IsInvalidClassName,
25            is_not_this,
26            is_simple_param_list::IsSimpleParameterList,
27            pat::{parse_constructor_params, parse_unique_formal_params},
28            typescript::{
29                parse_ts_heritage_clause, parse_ts_type_ann, parse_ts_type_or_type_predicate_ann,
30                parse_ts_type_params, try_parse_ts_index_signature, try_parse_ts_type_params,
31            },
32        },
33    },
34    error::SyntaxError,
35    TokenContext,
36};
37
38struct MakeMethodArgs {
39    start: BytePos,
40    accessibility: Option<Accessibility>,
41    is_abstract: bool,
42    static_token: Option<Span>,
43    decorators: Vec<Decorator>,
44    is_optional: bool,
45    is_override: bool,
46    key: Key,
47    kind: MethodKind,
48    is_async: bool,
49    is_generator: bool,
50}
51
52/// If `required` is `true`, this never returns `None`.
53pub fn parse_maybe_opt_binding_ident<'a>(
54    p: &mut impl Parser<'a>,
55    required: bool,
56    disallow_let: bool,
57) -> PResult<Option<Ident>> {
58    if required {
59        parse_binding_ident(p, disallow_let).map(|v| v.id).map(Some)
60    } else {
61        parse_opt_binding_ident(p, disallow_let).map(|v| v.map(|v| v.id))
62    }
63}
64
65fn parse_maybe_decorator_args<'a, P: Parser<'a>>(p: &mut P, expr: Box<Expr>) -> PResult<Box<Expr>> {
66    let type_args = if p.input().syntax().typescript() && p.input().is(&P::Token::LESS) {
67        let ret = parse_ts_type_args(p)?;
68        p.assert_and_bump(&P::Token::GREATER);
69        Some(ret)
70    } else {
71        None
72    };
73
74    if type_args.is_none() && !p.input().is(&P::Token::LPAREN) {
75        return Ok(expr);
76    }
77
78    let args = parse_args(p, false)?;
79    Ok(CallExpr {
80        span: p.span(expr.span_lo()),
81        callee: Callee::Expr(expr),
82        args,
83        ..Default::default()
84    }
85    .into())
86}
87
88pub fn parse_decorators<'a, P: Parser<'a>>(
89    p: &mut P,
90    allow_export: bool,
91) -> PResult<Vec<Decorator>> {
92    if !p.syntax().decorators() {
93        return Ok(Vec::new());
94    }
95    trace_cur!(p, parse_decorators);
96
97    let mut decorators = Vec::new();
98    let start = p.cur_pos();
99
100    while p.input().is(&P::Token::AT) {
101        decorators.push(parse_decorator(p)?);
102    }
103    if decorators.is_empty() {
104        return Ok(decorators);
105    }
106
107    if p.input().is(&P::Token::EXPORT) {
108        if !p.ctx().contains(Context::InClass)
109            && !p.ctx().contains(Context::InFunction)
110            && !allow_export
111        {
112            syntax_error!(p, p.input().cur_span(), SyntaxError::ExportNotAllowed);
113        }
114
115        if !p.ctx().contains(Context::InClass)
116            && !p.ctx().contains(Context::InFunction)
117            && !p.syntax().decorators_before_export()
118        {
119            syntax_error!(p, p.span(start), SyntaxError::DecoratorOnExport);
120        }
121    } else if !p.input().is(&P::Token::CLASS) {
122        // syntax_error!(p, p.span(start),
123        // SyntaxError::InvalidLeadingDecorator)
124    }
125
126    Ok(decorators)
127}
128
129fn parse_decorator<'a, P: Parser<'a>>(p: &mut P) -> PResult<Decorator> {
130    let start = p.cur_pos();
131    trace_cur!(p, parse_decorator);
132
133    p.assert_and_bump(&P::Token::AT);
134
135    let expr = if p.input_mut().eat(&P::Token::LPAREN) {
136        let expr = p.parse_expr()?;
137        expect!(p, &P::Token::RPAREN);
138        expr
139    } else {
140        let expr = parse_ident(p, false, false).map(Expr::from).map(Box::new)?;
141
142        parse_subscripts(p, Callee::Expr(expr), false, true)?
143    };
144
145    let expr = parse_maybe_decorator_args(p, expr)?;
146
147    Ok(Decorator {
148        span: p.span(start),
149        expr,
150    })
151}
152
153pub fn parse_access_modifier<'a>(p: &mut impl Parser<'a>) -> PResult<Option<Accessibility>> {
154    Ok(
155        parse_ts_modifier(p, &["public", "protected", "private", "in", "out"], false)?.and_then(
156            |s| match s {
157                "public" => Some(Accessibility::Public),
158                "protected" => Some(Accessibility::Protected),
159                "private" => Some(Accessibility::Private),
160                other => {
161                    p.emit_err(p.input().prev_span(), SyntaxError::TS1274(other.into()));
162                    None
163                }
164            },
165        ),
166    )
167}
168
169pub fn parse_super_class<'a, P: Parser<'a>>(
170    p: &mut P,
171) -> PResult<(Box<Expr>, Option<Box<TsTypeParamInstantiation>>)> {
172    let super_class = p.parse_lhs_expr()?;
173    match *super_class {
174        Expr::TsInstantiation(TsInstantiation {
175            expr, type_args, ..
176        }) => Ok((expr, Some(type_args))),
177        _ => {
178            // We still need to parse TS type arguments,
179            // because in some cases "super class" returned by `parse_lhs_expr`
180            // may not include `TsExprWithTypeArgs`
181            // but it's a super class with type params, for example, in JSX.
182            if p.syntax().typescript() && p.input().is(&P::Token::LESS) {
183                let ret = parse_ts_type_args(p)?;
184                p.assert_and_bump(&P::Token::GREATER);
185                Ok((super_class, Some(ret)))
186            } else {
187                Ok((super_class, None))
188            }
189        }
190    }
191}
192
193pub fn is_class_method<'a, P: Parser<'a>>(p: &mut P) -> bool {
194    let cur = p.input().cur();
195    cur == &P::Token::LPAREN
196        || (p.input().syntax().typescript() && (cur.is_less() || cur.is_jsx_tag_start()))
197}
198
199pub fn is_class_property<'a, P: Parser<'a>>(p: &mut P, asi: bool) -> bool {
200    let cur = p.input().cur();
201    (p.input().syntax().typescript() && (cur.is_bang() || cur.is_colon()))
202        || (cur.is_equal() || cur.is_rbrace())
203        || if asi {
204            p.is_general_semi()
205        } else {
206            p.input().is(&P::Token::SEMI)
207        }
208}
209
210pub fn parse_class_prop_name<'a, P: Parser<'a>>(p: &mut P) -> PResult<Key> {
211    if p.input().is(&P::Token::HASH) {
212        let name = parse_private_name(p)?;
213        if name.name == "constructor" {
214            p.emit_err(name.span, SyntaxError::PrivateConstructor);
215        }
216        Ok(Key::Private(name))
217    } else {
218        p.parse_prop_name().map(Key::Public)
219    }
220}
221
222/// `parse_args` closure should not eat '(' or ')'.
223pub fn parse_fn_args_body<'a, P: Parser<'a>, F>(
224    p: &mut P,
225    decorators: Vec<Decorator>,
226    start: BytePos,
227    parse_args: F,
228    is_async: bool,
229    is_generator: bool,
230) -> PResult<Box<Function>>
231where
232    F: FnOnce(&mut P) -> PResult<Vec<Param>>,
233{
234    trace_cur!(p, parse_fn_args_body);
235    let f = |p: &mut P| {
236        let type_params = if p.syntax().typescript() {
237            p.in_type(|p| {
238                trace_cur!(p, parse_fn_args_body__type_params);
239
240                Ok(if p.input().is(&P::Token::LESS) {
241                    Some(parse_ts_type_params(p, false, true)?)
242                } else if p.input().is(&P::Token::JSX_TAG_START) {
243                    debug_assert_eq!(
244                        p.input().token_context().current(),
245                        Some(TokenContext::JSXOpeningTag)
246                    );
247                    p.input_mut().token_context_mut().pop();
248                    debug_assert_eq!(
249                        p.input().token_context().current(),
250                        Some(TokenContext::JSXExpr)
251                    );
252                    p.input_mut().token_context_mut().pop();
253
254                    Some(parse_ts_type_params(p, false, true)?)
255                } else {
256                    None
257                })
258            })?
259        } else {
260            None
261        };
262
263        expect!(p, &P::Token::LPAREN);
264
265        let parse_args_with_generator_ctx = |p: &mut P| {
266            if is_generator {
267                p.do_inside_of_context(Context::InGenerator, parse_args)
268            } else {
269                p.do_outside_of_context(Context::InGenerator, parse_args)
270            }
271        };
272
273        let params = p.do_inside_of_context(Context::InParameters, |p| {
274            p.do_outside_of_context(Context::InFunction, |p| {
275                if is_async {
276                    p.do_inside_of_context(Context::InAsync, parse_args_with_generator_ctx)
277                } else {
278                    p.do_outside_of_context(Context::InAsync, parse_args_with_generator_ctx)
279                }
280            })
281        })?;
282
283        expect!(p, &P::Token::RPAREN);
284
285        // typescript extension
286        let return_type = if p.syntax().typescript() && p.input().is(&P::Token::COLON) {
287            parse_ts_type_or_type_predicate_ann(p, &P::Token::COLON).map(Some)?
288        } else {
289            None
290        };
291
292        let body: Option<_> = parse_fn_block_body(
293            p,
294            is_async,
295            is_generator,
296            false,
297            params.is_simple_parameter_list(),
298        )?;
299
300        if p.syntax().typescript() && body.is_none() {
301            // Declare functions cannot have assignment pattern in parameters
302            for param in &params {
303                // TODO: Search deeply for assignment pattern using a Visitor
304
305                let span = match &param.pat {
306                    Pat::Assign(ref p) => Some(p.span()),
307                    _ => None,
308                };
309
310                if let Some(span) = span {
311                    p.emit_err(span, SyntaxError::TS2371)
312                }
313            }
314        }
315
316        Ok(Box::new(Function {
317            span: p.span(start),
318            decorators,
319            type_params,
320            params,
321            body,
322            is_async,
323            is_generator,
324            return_type,
325            ctxt: Default::default(),
326        }))
327    };
328
329    let f_with_generator_ctx = |p: &mut P| {
330        if is_generator {
331            p.do_inside_of_context(Context::InGenerator, f)
332        } else {
333            p.do_outside_of_context(Context::InGenerator, f)
334        }
335    };
336
337    if is_async {
338        p.do_inside_of_context(Context::InAsync, f_with_generator_ctx)
339    } else {
340        p.do_outside_of_context(Context::InAsync, f_with_generator_ctx)
341    }
342}
343
344pub fn parse_async_fn_expr<'a, P: Parser<'a>>(p: &mut P) -> PResult<Box<Expr>> {
345    let start = p.cur_pos();
346    expect!(p, &P::Token::ASYNC);
347    parse_fn(p, None, Some(start), Vec::new())
348}
349
350/// Parse function expression
351pub fn parse_fn_expr<'a, P: Parser<'a>>(p: &mut P) -> PResult<Box<Expr>> {
352    parse_fn(p, None, None, Vec::new())
353}
354
355pub fn parse_async_fn_decl<'a, P: Parser<'a>>(
356    p: &mut P,
357    decorators: Vec<Decorator>,
358) -> PResult<Decl> {
359    let start = p.cur_pos();
360    expect!(p, &P::Token::ASYNC);
361    parse_fn(p, None, Some(start), decorators)
362}
363
364pub fn parse_fn_decl<'a, P: Parser<'a>>(p: &mut P, decorators: Vec<Decorator>) -> PResult<Decl> {
365    parse_fn(p, None, None, decorators)
366}
367
368pub fn parse_default_async_fn<'a, P: Parser<'a>>(
369    p: &mut P,
370    start: BytePos,
371    decorators: Vec<Decorator>,
372) -> PResult<ExportDefaultDecl> {
373    let start_of_async = p.cur_pos();
374    expect!(p, &P::Token::ASYNC);
375    parse_fn(p, Some(start), Some(start_of_async), decorators)
376}
377
378pub fn parse_default_fn<'a, P: Parser<'a>>(
379    p: &mut P,
380    start: BytePos,
381    decorators: Vec<Decorator>,
382) -> PResult<ExportDefaultDecl> {
383    parse_fn(p, Some(start), None, decorators)
384}
385
386fn parse_fn_inner<'a, P: Parser<'a>>(
387    p: &mut P,
388    _start_of_output_type: Option<BytePos>,
389    start_of_async: Option<BytePos>,
390    decorators: Vec<Decorator>,
391    is_fn_expr: bool,
392    is_ident_required: bool,
393) -> PResult<(Option<Ident>, Box<Function>)> {
394    let start = start_of_async.unwrap_or_else(|| p.cur_pos());
395    p.assert_and_bump(&P::Token::FUNCTION);
396    let is_async = start_of_async.is_some();
397
398    let is_generator = p.input_mut().eat(&P::Token::MUL);
399
400    let ident = if is_fn_expr {
401        let f_with_generator_context = |p: &mut P| {
402            if is_generator {
403                p.do_inside_of_context(Context::InGenerator, |p| {
404                    parse_maybe_opt_binding_ident(p, is_ident_required, false)
405                })
406            } else {
407                p.do_outside_of_context(Context::InGenerator, |p| {
408                    parse_maybe_opt_binding_ident(p, is_ident_required, false)
409                })
410            }
411        };
412
413        p.do_outside_of_context(
414            Context::AllowDirectSuper.union(Context::InClassField),
415            |p| {
416                if is_async {
417                    p.do_inside_of_context(Context::InAsync, f_with_generator_context)
418                } else {
419                    p.do_outside_of_context(Context::InAsync, f_with_generator_context)
420                }
421            },
422        )?
423    } else {
424        // function declaration does not change context for `BindingIdentifier`.
425        p.do_outside_of_context(
426            Context::AllowDirectSuper.union(Context::InClassField),
427            |p| parse_maybe_opt_binding_ident(p, is_ident_required, false),
428        )?
429    };
430
431    p.do_outside_of_context(
432        Context::AllowDirectSuper
433            .union(Context::InClassField)
434            .union(Context::WillExpectColonForCond),
435        |p| {
436            let f = parse_fn_args_body(
437                p,
438                decorators,
439                start,
440                parse_formal_params,
441                is_async,
442                is_generator,
443            )?;
444            if is_fn_expr && f.body.is_none() {
445                unexpected!(p, "{");
446            }
447            Ok((ident, f))
448        },
449    )
450}
451
452fn parse_fn<'a, P: Parser<'a>, T>(
453    p: &mut P,
454    start_of_output_type: Option<BytePos>,
455    start_of_async: Option<BytePos>,
456    decorators: Vec<Decorator>,
457) -> PResult<T>
458where
459    T: OutputType,
460{
461    let start = start_of_async.unwrap_or_else(|| p.cur_pos());
462    let (ident, f) = parse_fn_inner(
463        p,
464        start_of_output_type,
465        start_of_async,
466        decorators,
467        T::is_fn_expr(),
468        T::IS_IDENT_REQUIRED,
469    )?;
470
471    match T::finish_fn(p.span(start_of_output_type.unwrap_or(start)), ident, f) {
472        Ok(v) => Ok(v),
473        Err(kind) => syntax_error!(p, kind),
474    }
475}
476
477pub fn parse_class_decl<'a, P: Parser<'a>>(
478    p: &mut P,
479    start: BytePos,
480    class_start: BytePos,
481    decorators: Vec<Decorator>,
482    is_abstract: bool,
483) -> PResult<Decl> {
484    parse_class(p, start, class_start, decorators, is_abstract)
485}
486
487pub fn parse_class_expr<'a, P: Parser<'a>>(
488    p: &mut P,
489    start: BytePos,
490    decorators: Vec<Decorator>,
491) -> PResult<Box<Expr>> {
492    parse_class(p, start, start, decorators, false)
493}
494
495pub fn parse_default_class<'a, P: Parser<'a>>(
496    p: &mut P,
497    start: BytePos,
498    class_start: BytePos,
499    decorators: Vec<Decorator>,
500    is_abstract: bool,
501) -> PResult<ExportDefaultDecl> {
502    parse_class(p, start, class_start, decorators, is_abstract)
503}
504
505fn make_method<'a, P: Parser<'a>, F>(
506    p: &mut P,
507    parse_args: F,
508    MakeMethodArgs {
509        start,
510        accessibility,
511        is_abstract,
512        static_token,
513        decorators,
514        is_optional,
515        is_override,
516        key,
517        kind,
518        is_async,
519        is_generator,
520    }: MakeMethodArgs,
521) -> PResult<ClassMember>
522where
523    F: FnOnce(&mut P) -> PResult<Vec<Param>>,
524{
525    trace_cur!(p, make_method);
526
527    let is_static = static_token.is_some();
528    let function = p.do_inside_of_context(Context::AllowDirectSuper, |p| {
529        p.do_outside_of_context(Context::InClassField, |p| {
530            parse_fn_args_body(p, decorators, start, parse_args, is_async, is_generator)
531        })
532    })?;
533
534    match kind {
535        MethodKind::Getter | MethodKind::Setter
536            if p.input().syntax().typescript() && p.input().target() == EsVersion::Es3 =>
537        {
538            p.emit_err(key.span(), SyntaxError::TS1056);
539        }
540        _ => {}
541    }
542
543    match key {
544        Key::Private(key) => {
545            let span = p.span(start);
546            if accessibility.is_some() {
547                p.emit_err(span.with_hi(key.span_hi()), SyntaxError::TS18010);
548            }
549
550            Ok(PrivateMethod {
551                span,
552
553                accessibility,
554                is_abstract,
555                is_optional,
556                is_override,
557
558                is_static,
559                key,
560                function,
561                kind,
562            }
563            .into())
564        }
565        Key::Public(key) => {
566            let span = p.span(start);
567            if is_abstract && function.body.is_some() {
568                p.emit_err(span, SyntaxError::TS1245)
569            }
570            Ok(ClassMethod {
571                span,
572
573                accessibility,
574                is_abstract,
575                is_optional,
576                is_override,
577
578                is_static,
579                key,
580                function,
581                kind,
582            }
583            .into())
584        }
585    }
586}
587
588pub fn parse_fn_block_or_expr_body<'a, P: Parser<'a>>(
589    p: &mut P,
590    is_async: bool,
591    is_generator: bool,
592    is_arrow_function: bool,
593    is_simple_parameter_list: bool,
594) -> PResult<Box<BlockStmtOrExpr>> {
595    parse_fn_body(
596        p,
597        is_async,
598        is_generator,
599        is_arrow_function,
600        is_simple_parameter_list,
601        |p, is_simple_parameter_list| {
602            if p.input().is(&P::Token::LBRACE) {
603                parse_block(p, false)
604                    .map(|block_stmt| {
605                        if !is_simple_parameter_list {
606                            if let Some(span) = has_use_strict(&block_stmt) {
607                                p.emit_err(span, SyntaxError::IllegalLanguageModeDirective);
608                            }
609                        }
610                        BlockStmtOrExpr::BlockStmt(block_stmt)
611                    })
612                    .map(Box::new)
613            } else {
614                parse_assignment_expr(p)
615                    .map(BlockStmtOrExpr::Expr)
616                    .map(Box::new)
617            }
618        },
619    )
620}
621
622fn parse_fn_body<'a, P: Parser<'a>, T>(
623    p: &mut P,
624    is_async: bool,
625    is_generator: bool,
626    is_arrow_function: bool,
627    is_simple_parameter_list: bool,
628    f: impl FnOnce(&mut P, bool) -> PResult<T>,
629) -> PResult<T> {
630    if p.ctx().contains(Context::InDeclare)
631        && p.syntax().typescript()
632        && p.input().is(&P::Token::LBRACE)
633    {
634        //            p.emit_err(
635        //                p.ctx().span_of_fn_name.expect("we are not in function"),
636        //                SyntaxError::TS1183,
637        //            );
638        p.emit_err(p.input().cur_span(), SyntaxError::TS1183);
639    }
640
641    let f_with_generator_context = |p: &mut P| {
642        let f_with_inside_non_arrow_fn_scope = |p: &mut P| {
643            let f_with_new_state = |p: &mut P| {
644                let mut p = p.with_state(crate::common::parser::state::State::default());
645                f(&mut p, is_simple_parameter_list)
646            };
647
648            if is_arrow_function && !p.ctx().contains(Context::InsideNonArrowFunctionScope) {
649                p.do_outside_of_context(Context::InsideNonArrowFunctionScope, f_with_new_state)
650            } else {
651                p.do_inside_of_context(Context::InsideNonArrowFunctionScope, f_with_new_state)
652            }
653        };
654
655        if is_generator {
656            p.do_inside_of_context(Context::InGenerator, f_with_inside_non_arrow_fn_scope)
657        } else {
658            p.do_outside_of_context(Context::InGenerator, f_with_inside_non_arrow_fn_scope)
659        }
660    };
661
662    p.do_inside_of_context(Context::InFunction, |p| {
663        p.do_outside_of_context(
664            Context::InStaticBlock
665                .union(Context::IsBreakAllowed)
666                .union(Context::IsContinueAllowed)
667                .union(Context::TopLevel),
668            |p| {
669                if is_async {
670                    p.do_inside_of_context(Context::InAsync, f_with_generator_context)
671                } else {
672                    p.do_outside_of_context(Context::InAsync, f_with_generator_context)
673                }
674            },
675        )
676    })
677}
678
679pub(super) fn parse_fn_block_body<'a, P: Parser<'a>>(
680    p: &mut P,
681    is_async: bool,
682    is_generator: bool,
683    is_arrow_function: bool,
684    is_simple_parameter_list: bool,
685) -> PResult<Option<BlockStmt>> {
686    parse_fn_body(
687        p,
688        is_async,
689        is_generator,
690        is_arrow_function,
691        is_simple_parameter_list,
692        |p, is_simple_parameter_list| {
693            // allow omitting body and allow placing `{` on next line
694            if p.input().syntax().typescript()
695                && !p.input().is(&P::Token::LBRACE)
696                && p.eat_general_semi()
697            {
698                return Ok(None);
699            }
700            p.allow_in_expr(|p| parse_block(p, true)).map(|block_stmt| {
701                if !is_simple_parameter_list {
702                    if let Some(span) = has_use_strict(&block_stmt) {
703                        p.emit_err(span, SyntaxError::IllegalLanguageModeDirective);
704                    }
705                }
706                Some(block_stmt)
707            })
708        },
709    )
710}
711
712fn make_property<'a, P: Parser<'a>>(
713    p: &mut P,
714    start: BytePos,
715    decorators: Vec<Decorator>,
716    accessibility: Option<Accessibility>,
717    key: Key,
718    is_static: bool,
719    accessor_token: Option<Span>,
720    is_optional: bool,
721    readonly: bool,
722    declare: bool,
723    is_abstract: bool,
724    is_override: bool,
725) -> PResult<ClassMember> {
726    if is_constructor(&key) {
727        syntax_error!(p, key.span(), SyntaxError::PropertyNamedConstructor);
728    }
729    if key.is_private() {
730        if declare {
731            p.emit_err(
732                key.span(),
733                SyntaxError::PrivateNameModifier(atom!("declare")),
734            )
735        }
736        if is_abstract {
737            p.emit_err(
738                key.span(),
739                SyntaxError::PrivateNameModifier(atom!("abstract")),
740            )
741        }
742    }
743    let definite =
744        p.input().syntax().typescript() && !is_optional && p.input_mut().eat(&P::Token::BANG);
745
746    let type_ann = try_parse_ts_type_ann(p)?;
747
748    p.do_inside_of_context(Context::IncludeInExpr.union(Context::InClassField), |p| {
749        let value = if p.input().is(&P::Token::EQUAL) {
750            p.assert_and_bump(&P::Token::EQUAL);
751            Some(parse_assignment_expr(p)?)
752        } else {
753            None
754        };
755
756        if !p.eat_general_semi() {
757            p.emit_err(p.input().cur_span(), SyntaxError::TS1005);
758        }
759
760        if accessor_token.is_some() {
761            return Ok(ClassMember::AutoAccessor(AutoAccessor {
762                span: p.span(start),
763                key,
764                value,
765                type_ann,
766                is_static,
767                decorators,
768                accessibility,
769                is_abstract,
770                is_override,
771                definite,
772            }));
773        }
774
775        Ok(match key {
776            Key::Private(key) => {
777                let span = p.span(start);
778                if accessibility.is_some() {
779                    p.emit_err(span.with_hi(key.span_hi()), SyntaxError::TS18010);
780                }
781
782                PrivateProp {
783                    span: p.span(start),
784                    key,
785                    value,
786                    is_static,
787                    decorators,
788                    accessibility,
789                    is_optional,
790                    is_override,
791                    readonly,
792                    type_ann,
793                    definite,
794                    ctxt: Default::default(),
795                }
796                .into()
797            }
798            Key::Public(key) => {
799                let span = p.span(start);
800                if is_abstract && value.is_some() {
801                    p.emit_err(span, SyntaxError::TS1267)
802                }
803                ClassProp {
804                    span,
805                    key,
806                    value,
807                    is_static,
808                    decorators,
809                    accessibility,
810                    is_abstract,
811                    is_optional,
812                    is_override,
813                    readonly,
814                    declare,
815                    definite,
816                    type_ann,
817                }
818                .into()
819            }
820        })
821    })
822}
823
824fn parse_static_block<'a, P: Parser<'a>>(p: &mut P, start: BytePos) -> PResult<ClassMember> {
825    let body = p.do_inside_of_context(
826        Context::InStaticBlock
827            .union(Context::InClassField)
828            .union(Context::AllowUsingDecl),
829        |p| parse_block(p, false),
830    )?;
831
832    let span = p.span(start);
833    Ok(StaticBlock { span, body }.into())
834}
835
836fn parse_class_member_with_is_static<'a, P: Parser<'a>>(
837    p: &mut P,
838    start: BytePos,
839    declare_token: Option<Span>,
840    accessibility: Option<Accessibility>,
841    static_token: Option<Span>,
842    accessor_token: Option<Span>,
843    decorators: Vec<Decorator>,
844) -> PResult<ClassMember> {
845    let mut is_static = static_token.is_some();
846
847    let mut is_abstract = false;
848    let mut is_override = false;
849    let mut readonly = None;
850    let mut modifier_span = None;
851    let declare = declare_token.is_some();
852    while let Some(modifier) = if p.input().syntax().typescript() {
853        parse_ts_modifier(p, &["abstract", "readonly", "override", "static"], true)?
854    } else {
855        None
856    } {
857        modifier_span = Some(p.input().prev_span());
858        match modifier {
859            "abstract" => {
860                if is_abstract {
861                    p.emit_err(
862                        p.input().prev_span(),
863                        SyntaxError::TS1030(atom!("abstract")),
864                    );
865                } else if is_override {
866                    p.emit_err(
867                        p.input().prev_span(),
868                        SyntaxError::TS1029(atom!("abstract"), atom!("override")),
869                    );
870                }
871                is_abstract = true;
872            }
873            "override" => {
874                if is_override {
875                    p.emit_err(
876                        p.input().prev_span(),
877                        SyntaxError::TS1030(atom!("override")),
878                    );
879                } else if readonly.is_some() {
880                    p.emit_err(
881                        p.input().prev_span(),
882                        SyntaxError::TS1029(atom!("override"), atom!("readonly")),
883                    );
884                } else if declare {
885                    p.emit_err(
886                        p.input().prev_span(),
887                        SyntaxError::TS1243(atom!("override"), atom!("declare")),
888                    );
889                } else if !p.ctx().contains(Context::HasSuperClass) {
890                    p.emit_err(p.input().prev_span(), SyntaxError::TS4112);
891                }
892                is_override = true;
893            }
894            "readonly" => {
895                let readonly_span = p.input().prev_span();
896                if readonly.is_some() {
897                    p.emit_err(readonly_span, SyntaxError::TS1030(atom!("readonly")));
898                } else {
899                    readonly = Some(readonly_span);
900                }
901            }
902            "static" => {
903                if is_override {
904                    p.emit_err(
905                        p.input().prev_span(),
906                        SyntaxError::TS1029(atom!("static"), atom!("override")),
907                    );
908                }
909
910                is_static = true;
911            }
912            _ => {}
913        }
914    }
915
916    let accessor_token = accessor_token.or_else(|| {
917        if p.syntax().auto_accessors() && readonly.is_none() {
918            let start = p.cur_pos();
919            if !peek!(p).is_some_and(|cur| cur.is_lparen())
920                && p.input_mut().eat(&P::Token::ACCESSOR)
921            {
922                Some(p.span(start))
923            } else {
924                None
925            }
926        } else {
927            None
928        }
929    });
930
931    if is_static && p.input().is(&P::Token::LBRACE) {
932        if let Some(span) = declare_token {
933            p.emit_err(span, SyntaxError::TS1184);
934        }
935        if accessibility.is_some() {
936            p.emit_err(p.input().cur_span(), SyntaxError::TS1184);
937        }
938        return parse_static_block(p, start);
939    }
940    if p.input().is(&P::Token::STATIC) && peek!(p).is_some_and(|cur| cur.is_lbrace()) {
941        // For "readonly", "abstract" and "override"
942        if let Some(span) = modifier_span {
943            p.emit_err(span, SyntaxError::TS1184);
944        }
945        if let Some(span) = static_token {
946            p.emit_err(span, SyntaxError::TS1184);
947        }
948        p.bump(); // consume "static"
949        return parse_static_block(p, start);
950    }
951
952    if p.input().syntax().typescript() && !is_abstract && !is_override && accessibility.is_none() {
953        let idx = try_parse_ts_index_signature(p, start, readonly.is_some(), is_static)?;
954        if let Some(idx) = idx {
955            return Ok(idx.into());
956        }
957    }
958
959    if p.input_mut().eat(&P::Token::MUL) {
960        // generator method
961        let key = parse_class_prop_name(p)?;
962        if readonly.is_some() {
963            p.emit_err(p.span(start), SyntaxError::ReadOnlyMethod);
964        }
965        if is_constructor(&key) {
966            p.emit_err(p.span(start), SyntaxError::GeneratorConstructor);
967        }
968
969        return make_method(
970            p,
971            parse_unique_formal_params,
972            MakeMethodArgs {
973                start,
974                decorators,
975                is_async: false,
976                is_generator: true,
977                accessibility,
978                is_abstract,
979                is_override,
980                is_optional: false,
981                static_token,
982                key,
983                kind: MethodKind::Method,
984            },
985        );
986    }
987
988    trace_cur!(p, parse_class_member_with_is_static__normal_class_member);
989    let key = if readonly.is_some() && (p.input().cur().is_bang() || p.input().cur().is_colon()) {
990        Key::Public(PropName::Ident(IdentName::new(
991            atom!("readonly"),
992            readonly.unwrap(),
993        )))
994    } else {
995        parse_class_prop_name(p)?
996    };
997    let is_optional = p.input().syntax().typescript() && p.input_mut().eat(&P::Token::QUESTION);
998
999    if is_class_method(p) {
1000        // handle a(){} / get(){} / set(){} / async(){}
1001
1002        trace_cur!(p, parse_class_member_with_is_static__normal_class_method);
1003
1004        if let Some(token) = declare_token {
1005            p.emit_err(token, SyntaxError::TS1031)
1006        }
1007
1008        if readonly.is_some() {
1009            syntax_error!(p, p.span(start), SyntaxError::ReadOnlyMethod);
1010        }
1011        let is_constructor = is_constructor(&key);
1012
1013        if is_constructor {
1014            if p.syntax().typescript() && is_override {
1015                p.emit_err(p.span(start), SyntaxError::TS1089(atom!("override")));
1016            }
1017
1018            if p.syntax().typescript() && p.input().is(&P::Token::LESS) {
1019                let start = p.cur_pos();
1020                if peek!(p).is_some_and(|cur| cur.is_less()) {
1021                    p.assert_and_bump(&P::Token::LESS);
1022                    let start2 = p.cur_pos();
1023                    p.assert_and_bump(&P::Token::GREATER);
1024
1025                    p.emit_err(p.span(start), SyntaxError::TS1098);
1026                    p.emit_err(p.span(start2), SyntaxError::TS1092);
1027                } else {
1028                    let type_params = try_parse_ts_type_params(p, false, true)?;
1029
1030                    if let Some(type_params) = type_params {
1031                        for param in type_params.params {
1032                            p.emit_err(param.span(), SyntaxError::TS1092);
1033                        }
1034                    }
1035                }
1036            }
1037
1038            expect!(p, &P::Token::LPAREN);
1039            let params = parse_constructor_params(p)?;
1040            expect!(p, &P::Token::RPAREN);
1041
1042            if p.syntax().typescript() && p.input().is(&P::Token::COLON) {
1043                let start = p.cur_pos();
1044                let type_ann = parse_ts_type_ann(p, true, start)?;
1045
1046                p.emit_err(type_ann.type_ann.span(), SyntaxError::TS1093);
1047            }
1048
1049            let body: Option<_> =
1050                parse_fn_block_body(p, false, false, false, params.is_simple_parameter_list())?;
1051
1052            if body.is_none() {
1053                for param in params.iter() {
1054                    if param.is_ts_param_prop() {
1055                        p.emit_err(param.span(), SyntaxError::TS2369)
1056                    }
1057                }
1058            }
1059
1060            if p.syntax().typescript() && body.is_none() {
1061                // Declare constructors cannot have assignment pattern in parameters
1062                for param in &params {
1063                    // TODO: Search deeply for assignment pattern using a Visitor
1064
1065                    let span = match *param {
1066                        ParamOrTsParamProp::Param(ref param) => match param.pat {
1067                            Pat::Assign(ref p) => Some(p.span()),
1068                            _ => None,
1069                        },
1070                        ParamOrTsParamProp::TsParamProp(TsParamProp {
1071                            param: TsParamPropParam::Assign(ref p),
1072                            ..
1073                        }) => Some(p.span()),
1074                        _ => None,
1075                    };
1076
1077                    if let Some(span) = span {
1078                        p.emit_err(span, SyntaxError::TS2371)
1079                    }
1080                }
1081            }
1082
1083            if let Some(static_token) = static_token {
1084                p.emit_err(static_token, SyntaxError::TS1089(atom!("static")))
1085            }
1086
1087            if let Some(span) = modifier_span {
1088                if is_abstract {
1089                    p.emit_err(span, SyntaxError::TS1242);
1090                }
1091            }
1092
1093            return Ok(ClassMember::Constructor(Constructor {
1094                span: p.span(start),
1095                accessibility,
1096                key: match key {
1097                    Key::Public(key) => key,
1098                    _ => unreachable!("is_constructor() returns false for PrivateName"),
1099                },
1100                is_optional,
1101                params,
1102                body,
1103                ..Default::default()
1104            }));
1105        } else {
1106            return make_method(
1107                p,
1108                parse_formal_params,
1109                MakeMethodArgs {
1110                    start,
1111                    is_optional,
1112                    accessibility,
1113                    decorators,
1114                    is_abstract,
1115                    is_override,
1116                    static_token,
1117                    kind: MethodKind::Method,
1118                    key,
1119                    is_async: false,
1120                    is_generator: false,
1121                },
1122            );
1123        }
1124    }
1125
1126    let is_next_line_generator =
1127        p.input_mut().had_line_break_before_cur() && p.input().is(&P::Token::MUL);
1128    let getter_or_setter_ident = match key {
1129        // `get\n*` is an uninitialized property named 'get' followed by a generator.
1130        Key::Public(PropName::Ident(ref i))
1131            if (i.sym == "get" || i.sym == "set")
1132                && !is_class_property(p, /* asi */ false)
1133                && !is_next_line_generator =>
1134        {
1135            Some(i)
1136        }
1137        _ => None,
1138    };
1139
1140    if getter_or_setter_ident.is_none() && is_class_property(p, /* asi */ true) {
1141        return make_property(
1142            p,
1143            start,
1144            decorators,
1145            accessibility,
1146            key,
1147            is_static,
1148            accessor_token,
1149            is_optional,
1150            readonly.is_some(),
1151            declare,
1152            is_abstract,
1153            is_override,
1154        );
1155    }
1156
1157    if match key {
1158        Key::Public(PropName::Ident(ref i)) => i.sym == "async",
1159        _ => false,
1160    } && !p.input_mut().had_line_break_before_cur()
1161    {
1162        // handle async foo(){}
1163
1164        if p.input().syntax().typescript() && parse_ts_modifier(p, &["override"], false)?.is_some()
1165        {
1166            is_override = true;
1167            p.emit_err(
1168                p.input().prev_span(),
1169                SyntaxError::TS1029(atom!("override"), atom!("async")),
1170            );
1171        }
1172
1173        let is_generator = p.input_mut().eat(&P::Token::MUL);
1174        let key = parse_class_prop_name(p)?;
1175        if is_constructor(&key) {
1176            syntax_error!(p, key.span(), SyntaxError::AsyncConstructor)
1177        }
1178        if readonly.is_some() {
1179            syntax_error!(p, p.span(start), SyntaxError::ReadOnlyMethod);
1180        }
1181
1182        // handle async foo(){}
1183        let is_optional = is_optional
1184            || p.input().syntax().typescript() && p.input_mut().eat(&P::Token::QUESTION);
1185        return make_method(
1186            p,
1187            parse_unique_formal_params,
1188            MakeMethodArgs {
1189                start,
1190                static_token,
1191                key,
1192                is_abstract,
1193                accessibility,
1194                is_optional,
1195                is_override,
1196                decorators,
1197                kind: MethodKind::Method,
1198                is_async: true,
1199                is_generator,
1200            },
1201        );
1202    }
1203
1204    if let Some(i) = getter_or_setter_ident {
1205        let key_span = key.span();
1206
1207        // handle get foo(){} / set foo(v){}
1208        let key = parse_class_prop_name(p)?;
1209
1210        if readonly.is_some() {
1211            p.emit_err(key_span, SyntaxError::GetterSetterCannotBeReadonly);
1212        }
1213
1214        if is_constructor(&key) {
1215            p.emit_err(key_span, SyntaxError::ConstructorAccessor);
1216        }
1217
1218        return match &*i.sym {
1219            "get" => make_method(
1220                p,
1221                |p| {
1222                    let params = parse_formal_params(p)?;
1223
1224                    if params.iter().any(is_not_this) {
1225                        p.emit_err(key_span, SyntaxError::GetterParam);
1226                    }
1227
1228                    Ok(params)
1229                },
1230                MakeMethodArgs {
1231                    decorators,
1232                    start,
1233                    is_abstract,
1234                    is_async: false,
1235                    is_generator: false,
1236                    is_optional,
1237                    is_override,
1238                    accessibility,
1239                    static_token,
1240                    key,
1241                    kind: MethodKind::Getter,
1242                },
1243            ),
1244            "set" => make_method(
1245                p,
1246                |p| {
1247                    let params = parse_formal_params(p)?;
1248
1249                    if params.iter().filter(|p| is_not_this(p)).count() != 1 {
1250                        p.emit_err(key_span, SyntaxError::SetterParam);
1251                    }
1252
1253                    if !params.is_empty() {
1254                        if let Pat::Rest(..) = params[0].pat {
1255                            p.emit_err(params[0].pat.span(), SyntaxError::RestPatInSetter);
1256                        }
1257                    }
1258
1259                    Ok(params)
1260                },
1261                MakeMethodArgs {
1262                    decorators,
1263                    start,
1264                    is_optional,
1265                    is_abstract,
1266                    is_override,
1267                    is_async: false,
1268                    is_generator: false,
1269                    accessibility,
1270                    static_token,
1271                    key,
1272                    kind: MethodKind::Setter,
1273                },
1274            ),
1275            _ => unreachable!(),
1276        };
1277    }
1278
1279    unexpected!(p, "* for generator, private key, identifier or async")
1280}
1281
1282fn parse_class_member<'a, P: Parser<'a>>(p: &mut P) -> PResult<ClassMember> {
1283    trace_cur!(p, parse_class_member);
1284
1285    let start = p.cur_pos();
1286    let decorators = parse_decorators(p, false)?;
1287    let declare = p.syntax().typescript() && p.input_mut().eat(&P::Token::DECLARE);
1288    let accessibility = if p.input().syntax().typescript() {
1289        parse_access_modifier(p)?
1290    } else {
1291        None
1292    };
1293    // Allow `private declare`.
1294    let declare = declare || p.syntax().typescript() && p.input_mut().eat(&P::Token::DECLARE);
1295
1296    let declare_token = if declare {
1297        // Handle declare(){}
1298        if is_class_method(p) {
1299            let key = Key::Public(PropName::Ident(IdentName::new(
1300                atom!("declare"),
1301                p.span(start),
1302            )));
1303            let is_optional =
1304                p.input().syntax().typescript() && p.input_mut().eat(&P::Token::QUESTION);
1305            return make_method(
1306                p,
1307                parse_unique_formal_params,
1308                MakeMethodArgs {
1309                    start,
1310                    accessibility,
1311                    decorators,
1312                    is_abstract: false,
1313                    is_optional,
1314                    is_override: false,
1315                    is_async: false,
1316                    is_generator: false,
1317                    static_token: None,
1318                    key,
1319                    kind: MethodKind::Method,
1320                },
1321            );
1322        } else if is_class_property(p, /* asi */ true)
1323            || (p.syntax().typescript() && p.input().is(&P::Token::QUESTION))
1324        {
1325            // Property named `declare`
1326
1327            let key = Key::Public(PropName::Ident(IdentName::new(
1328                atom!("declare"),
1329                p.span(start),
1330            )));
1331            let is_optional =
1332                p.input().syntax().typescript() && p.input_mut().eat(&P::Token::QUESTION);
1333            return make_property(
1334                p,
1335                start,
1336                decorators,
1337                accessibility,
1338                key,
1339                false,
1340                None,
1341                is_optional,
1342                false,
1343                false,
1344                false,
1345                false,
1346            );
1347        } else {
1348            Some(p.span(start))
1349        }
1350    } else {
1351        None
1352    };
1353
1354    let static_token = {
1355        let start = p.cur_pos();
1356        if p.input_mut().eat(&P::Token::STATIC) {
1357            Some(p.span(start))
1358        } else {
1359            None
1360        }
1361    };
1362
1363    let accessor_token = if p.syntax().auto_accessors() {
1364        let start = p.cur_pos();
1365        if p.input_mut().eat(&P::Token::ACCESSOR) {
1366            Some(p.span(start))
1367        } else {
1368            None
1369        }
1370    } else {
1371        None
1372    };
1373
1374    if let Some(accessor_token) = accessor_token {
1375        // Handle accessor(){}
1376        if is_class_method(p) {
1377            let key = Key::Public(PropName::Ident(IdentName::new(
1378                atom!("accessor"),
1379                accessor_token,
1380            )));
1381            let is_optional =
1382                p.input().syntax().typescript() && p.input_mut().eat(&P::Token::QUESTION);
1383            return make_method(
1384                p,
1385                parse_unique_formal_params,
1386                MakeMethodArgs {
1387                    start,
1388                    accessibility,
1389                    decorators,
1390                    is_abstract: false,
1391                    is_optional,
1392                    is_override: false,
1393                    is_async: false,
1394                    is_generator: false,
1395                    static_token,
1396                    key,
1397                    kind: MethodKind::Method,
1398                },
1399            );
1400        } else if is_class_property(p, /* asi */ true)
1401            || (p.syntax().typescript() && p.input().is(&P::Token::QUESTION))
1402        {
1403            // Property named `accessor`
1404
1405            let key = Key::Public(PropName::Ident(IdentName::new(
1406                atom!("accessor"),
1407                accessor_token,
1408            )));
1409            let is_optional =
1410                p.input().syntax().typescript() && p.input_mut().eat(&P::Token::QUESTION);
1411            let is_static = static_token.is_some();
1412            return make_property(
1413                p,
1414                start,
1415                decorators,
1416                accessibility,
1417                key,
1418                is_static,
1419                None,
1420                is_optional,
1421                false,
1422                declare,
1423                false,
1424                false,
1425            );
1426        }
1427    }
1428
1429    if let Some(static_token) = static_token {
1430        // Handle static(){}
1431        if is_class_method(p) {
1432            let key = Key::Public(PropName::Ident(IdentName::new(
1433                atom!("static"),
1434                static_token,
1435            )));
1436            let is_optional =
1437                p.input().syntax().typescript() && p.input_mut().eat(&P::Token::QUESTION);
1438            return make_method(
1439                p,
1440                parse_unique_formal_params,
1441                MakeMethodArgs {
1442                    start,
1443                    accessibility,
1444                    decorators,
1445                    is_abstract: false,
1446                    is_optional,
1447                    is_override: false,
1448                    is_async: false,
1449                    is_generator: false,
1450                    static_token: None,
1451                    key,
1452                    kind: MethodKind::Method,
1453                },
1454            );
1455        } else if is_class_property(p, /* asi */ false)
1456            || (p.syntax().typescript() && p.input().is(&P::Token::QUESTION))
1457        {
1458            // Property named `static`
1459
1460            // Avoid to parse
1461            //   static
1462            //   {}
1463            let is_parsing_static_blocks = p.input().is(&P::Token::LBRACE);
1464            if !is_parsing_static_blocks {
1465                let key = Key::Public(PropName::Ident(IdentName::new(
1466                    atom!("static"),
1467                    static_token,
1468                )));
1469                let is_optional =
1470                    p.input().syntax().typescript() && p.input_mut().eat(&P::Token::QUESTION);
1471                return make_property(
1472                    p,
1473                    start,
1474                    decorators,
1475                    accessibility,
1476                    key,
1477                    false,
1478                    accessor_token,
1479                    is_optional,
1480                    false,
1481                    declare,
1482                    false,
1483                    false,
1484                );
1485            }
1486        } else {
1487            // TODO: error if static contains escape
1488        }
1489    }
1490
1491    parse_class_member_with_is_static(
1492        p,
1493        start,
1494        declare_token,
1495        accessibility,
1496        static_token,
1497        accessor_token,
1498        decorators,
1499    )
1500}
1501
1502fn parse_class_body<'a, P: Parser<'a>>(p: &mut P) -> PResult<Vec<ClassMember>> {
1503    let mut elems = Vec::with_capacity(32);
1504    let mut has_constructor_with_body = false;
1505    while !p.input().is(&P::Token::RBRACE) {
1506        if p.input_mut().eat(&P::Token::SEMI) {
1507            let span = p.input().prev_span();
1508            debug_assert!(span.lo <= span.hi);
1509            elems.push(ClassMember::Empty(EmptyStmt { span }));
1510            continue;
1511        }
1512        let elem = p.do_inside_of_context(Context::AllowDirectSuper, parse_class_member)?;
1513
1514        if !p.ctx().contains(Context::InDeclare) {
1515            if let ClassMember::Constructor(Constructor {
1516                body: Some(..),
1517                span,
1518                ..
1519            }) = elem
1520            {
1521                if has_constructor_with_body {
1522                    p.emit_err(span, SyntaxError::DuplicateConstructor);
1523                }
1524                has_constructor_with_body = true;
1525            }
1526        }
1527        elems.push(elem);
1528    }
1529    Ok(elems)
1530}
1531
1532pub fn parse_class<'a, T>(
1533    p: &mut impl Parser<'a>,
1534    start: BytePos,
1535    class_start: BytePos,
1536    decorators: Vec<Decorator>,
1537    is_abstract: bool,
1538) -> PResult<T>
1539where
1540    T: OutputType,
1541{
1542    let (ident, mut class) = p.do_inside_of_context(Context::InClass, |p| {
1543        parse_class_inner(p, start, class_start, decorators, T::IS_IDENT_REQUIRED)
1544    })?;
1545
1546    if is_abstract {
1547        class.is_abstract = true
1548    } else {
1549        for member in class.body.iter() {
1550            match member {
1551                ClassMember::ClassProp(ClassProp {
1552                    is_abstract: true,
1553                    span,
1554                    ..
1555                })
1556                | ClassMember::Method(ClassMethod {
1557                    span,
1558                    is_abstract: true,
1559                    ..
1560                }) => p.emit_err(*span, SyntaxError::TS1244),
1561                _ => (),
1562            }
1563        }
1564    }
1565
1566    match T::finish_class(p.span(start), ident, class) {
1567        Ok(v) => Ok(v),
1568        Err(kind) => syntax_error!(p, kind),
1569    }
1570}
1571
1572/// Not generic
1573fn parse_class_inner<'a, P: Parser<'a>>(
1574    p: &mut P,
1575    _start: BytePos,
1576    class_start: BytePos,
1577    decorators: Vec<Decorator>,
1578    is_ident_required: bool,
1579) -> PResult<(Option<Ident>, Box<Class>)> {
1580    p.strict_mode(|p| {
1581        expect!(p, &P::Token::CLASS);
1582
1583        let ident = parse_maybe_opt_binding_ident(p, is_ident_required, true)?;
1584        if p.input().syntax().typescript() {
1585            if let Some(span) = ident.invalid_class_name() {
1586                p.emit_err(span, SyntaxError::TS2414);
1587            }
1588        }
1589
1590        let type_params = if p.input().syntax().typescript() {
1591            try_parse_ts_type_params(p, true, true)?
1592        } else {
1593            None
1594        };
1595
1596        let (mut super_class, mut super_type_params) = if p.input_mut().eat(&P::Token::EXTENDS) {
1597            let (super_class, super_type_params) = parse_super_class(p)?;
1598
1599            if p.syntax().typescript() && p.input_mut().eat(&P::Token::COMMA) {
1600                let exprs = parse_ts_heritage_clause(p)?;
1601
1602                for e in &exprs {
1603                    p.emit_err(e.span(), SyntaxError::TS1174);
1604                }
1605            }
1606
1607            (Some(super_class), super_type_params)
1608        } else {
1609            (None, None)
1610        };
1611
1612        // Handle TS1172
1613        if p.input_mut().eat(&P::Token::EXTENDS) {
1614            p.emit_err(p.input().prev_span(), SyntaxError::TS1172);
1615
1616            parse_super_class(p)?;
1617        };
1618
1619        let implements =
1620            if p.input().syntax().typescript() && p.input_mut().eat(&P::Token::IMPLEMENTS) {
1621                parse_ts_heritage_clause(p)?
1622            } else {
1623                Vec::with_capacity(4)
1624            };
1625
1626        {
1627            // Handle TS1175
1628            if p.input().syntax().typescript() && p.input_mut().eat(&P::Token::IMPLEMENTS) {
1629                p.emit_err(p.input().prev_span(), SyntaxError::TS1175);
1630
1631                parse_ts_heritage_clause(p)?;
1632            }
1633        }
1634
1635        // Handle TS1173
1636        if p.input().syntax().typescript() && p.input_mut().eat(&P::Token::EXTENDS) {
1637            p.emit_err(p.input().prev_span(), SyntaxError::TS1173);
1638
1639            let (sc, type_params) = parse_super_class(p)?;
1640
1641            if super_class.is_none() {
1642                super_class = Some(sc);
1643                if type_params.is_some() {
1644                    super_type_params = type_params;
1645                }
1646            }
1647        }
1648
1649        expect!(p, &P::Token::LBRACE);
1650
1651        let body = if super_class.is_some() {
1652            p.do_inside_of_context(Context::HasSuperClass, parse_class_body)?
1653        } else {
1654            p.do_outside_of_context(Context::HasSuperClass, parse_class_body)?
1655        };
1656
1657        if p.input().cur().is_eof() {
1658            let eof_text = p.input_mut().dump_cur();
1659            p.emit_err(
1660                p.input().cur_span(),
1661                SyntaxError::Expected(format!("{:?}", P::Token::RBRACE), eof_text),
1662            );
1663        } else {
1664            expect!(p, &P::Token::RBRACE);
1665        }
1666
1667        let span = p.span(class_start);
1668        Ok((
1669            ident,
1670            Box::new(Class {
1671                span,
1672                decorators,
1673                is_abstract: false,
1674                type_params,
1675                super_class,
1676                super_type_params,
1677                body,
1678                implements,
1679                ..Default::default()
1680            }),
1681        ))
1682    })
1683}