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        #[cfg(swc_ast_unknown)]
586        _ => unreachable!(),
587    }
588}
589
590pub fn parse_fn_block_or_expr_body<'a, P: Parser<'a>>(
591    p: &mut P,
592    is_async: bool,
593    is_generator: bool,
594    is_arrow_function: bool,
595    is_simple_parameter_list: bool,
596) -> PResult<Box<BlockStmtOrExpr>> {
597    parse_fn_body(
598        p,
599        is_async,
600        is_generator,
601        is_arrow_function,
602        is_simple_parameter_list,
603        |p, is_simple_parameter_list| {
604            if p.input().is(&P::Token::LBRACE) {
605                parse_block(p, false)
606                    .map(|block_stmt| {
607                        if !is_simple_parameter_list {
608                            if let Some(span) = has_use_strict(&block_stmt) {
609                                p.emit_err(span, SyntaxError::IllegalLanguageModeDirective);
610                            }
611                        }
612                        BlockStmtOrExpr::BlockStmt(block_stmt)
613                    })
614                    .map(Box::new)
615            } else {
616                parse_assignment_expr(p)
617                    .map(BlockStmtOrExpr::Expr)
618                    .map(Box::new)
619            }
620        },
621    )
622}
623
624fn parse_fn_body<'a, P: Parser<'a>, T>(
625    p: &mut P,
626    is_async: bool,
627    is_generator: bool,
628    is_arrow_function: bool,
629    is_simple_parameter_list: bool,
630    f: impl FnOnce(&mut P, bool) -> PResult<T>,
631) -> PResult<T> {
632    if p.ctx().contains(Context::InDeclare)
633        && p.syntax().typescript()
634        && p.input().is(&P::Token::LBRACE)
635    {
636        //            p.emit_err(
637        //                p.ctx().span_of_fn_name.expect("we are not in function"),
638        //                SyntaxError::TS1183,
639        //            );
640        p.emit_err(p.input().cur_span(), SyntaxError::TS1183);
641    }
642
643    let f_with_generator_context = |p: &mut P| {
644        let f_with_inside_non_arrow_fn_scope = |p: &mut P| {
645            let f_with_new_state = |p: &mut P| {
646                let mut p = p.with_state(crate::common::parser::state::State::default());
647                f(&mut p, is_simple_parameter_list)
648            };
649
650            if is_arrow_function && !p.ctx().contains(Context::InsideNonArrowFunctionScope) {
651                p.do_outside_of_context(Context::InsideNonArrowFunctionScope, f_with_new_state)
652            } else {
653                p.do_inside_of_context(Context::InsideNonArrowFunctionScope, f_with_new_state)
654            }
655        };
656
657        if is_generator {
658            p.do_inside_of_context(Context::InGenerator, f_with_inside_non_arrow_fn_scope)
659        } else {
660            p.do_outside_of_context(Context::InGenerator, f_with_inside_non_arrow_fn_scope)
661        }
662    };
663
664    p.do_inside_of_context(Context::InFunction, |p| {
665        p.do_outside_of_context(
666            Context::InStaticBlock
667                .union(Context::IsBreakAllowed)
668                .union(Context::IsContinueAllowed)
669                .union(Context::TopLevel),
670            |p| {
671                if is_async {
672                    p.do_inside_of_context(Context::InAsync, f_with_generator_context)
673                } else {
674                    p.do_outside_of_context(Context::InAsync, f_with_generator_context)
675                }
676            },
677        )
678    })
679}
680
681pub(super) fn parse_fn_block_body<'a, P: Parser<'a>>(
682    p: &mut P,
683    is_async: bool,
684    is_generator: bool,
685    is_arrow_function: bool,
686    is_simple_parameter_list: bool,
687) -> PResult<Option<BlockStmt>> {
688    parse_fn_body(
689        p,
690        is_async,
691        is_generator,
692        is_arrow_function,
693        is_simple_parameter_list,
694        |p, is_simple_parameter_list| {
695            // allow omitting body and allow placing `{` on next line
696            if p.input().syntax().typescript()
697                && !p.input().is(&P::Token::LBRACE)
698                && p.eat_general_semi()
699            {
700                return Ok(None);
701            }
702            p.allow_in_expr(|p| parse_block(p, true)).map(|block_stmt| {
703                if !is_simple_parameter_list {
704                    if let Some(span) = has_use_strict(&block_stmt) {
705                        p.emit_err(span, SyntaxError::IllegalLanguageModeDirective);
706                    }
707                }
708                Some(block_stmt)
709            })
710        },
711    )
712}
713
714fn make_property<'a, P: Parser<'a>>(
715    p: &mut P,
716    start: BytePos,
717    decorators: Vec<Decorator>,
718    accessibility: Option<Accessibility>,
719    key: Key,
720    is_static: bool,
721    accessor_token: Option<Span>,
722    is_optional: bool,
723    readonly: bool,
724    declare: bool,
725    is_abstract: bool,
726    is_override: bool,
727) -> PResult<ClassMember> {
728    if is_constructor(&key) {
729        syntax_error!(p, key.span(), SyntaxError::PropertyNamedConstructor);
730    }
731    if key.is_private() {
732        if declare {
733            p.emit_err(
734                key.span(),
735                SyntaxError::PrivateNameModifier(atom!("declare")),
736            )
737        }
738        if is_abstract {
739            p.emit_err(
740                key.span(),
741                SyntaxError::PrivateNameModifier(atom!("abstract")),
742            )
743        }
744    }
745    let definite =
746        p.input().syntax().typescript() && !is_optional && p.input_mut().eat(&P::Token::BANG);
747
748    let type_ann = try_parse_ts_type_ann(p)?;
749
750    p.do_inside_of_context(Context::IncludeInExpr.union(Context::InClassField), |p| {
751        let value = if p.input().is(&P::Token::EQUAL) {
752            p.assert_and_bump(&P::Token::EQUAL);
753            Some(parse_assignment_expr(p)?)
754        } else {
755            None
756        };
757
758        if !p.eat_general_semi() {
759            p.emit_err(p.input().cur_span(), SyntaxError::TS1005);
760        }
761
762        if accessor_token.is_some() {
763            return Ok(ClassMember::AutoAccessor(AutoAccessor {
764                span: p.span(start),
765                key,
766                value,
767                type_ann,
768                is_static,
769                decorators,
770                accessibility,
771                is_abstract,
772                is_override,
773                definite,
774            }));
775        }
776
777        Ok(match key {
778            Key::Private(key) => {
779                let span = p.span(start);
780                if accessibility.is_some() {
781                    p.emit_err(span.with_hi(key.span_hi()), SyntaxError::TS18010);
782                }
783
784                PrivateProp {
785                    span: p.span(start),
786                    key,
787                    value,
788                    is_static,
789                    decorators,
790                    accessibility,
791                    is_optional,
792                    is_override,
793                    readonly,
794                    type_ann,
795                    definite,
796                    ctxt: Default::default(),
797                }
798                .into()
799            }
800            Key::Public(key) => {
801                let span = p.span(start);
802                if is_abstract && value.is_some() {
803                    p.emit_err(span, SyntaxError::TS1267)
804                }
805                ClassProp {
806                    span,
807                    key,
808                    value,
809                    is_static,
810                    decorators,
811                    accessibility,
812                    is_abstract,
813                    is_optional,
814                    is_override,
815                    readonly,
816                    declare,
817                    definite,
818                    type_ann,
819                }
820                .into()
821            }
822            #[cfg(swc_ast_unknown)]
823            _ => unreachable!(),
824        })
825    })
826}
827
828fn parse_static_block<'a, P: Parser<'a>>(p: &mut P, start: BytePos) -> PResult<ClassMember> {
829    let body = p.do_inside_of_context(
830        Context::InStaticBlock
831            .union(Context::InClassField)
832            .union(Context::AllowUsingDecl),
833        |p| parse_block(p, false),
834    )?;
835
836    let span = p.span(start);
837    Ok(StaticBlock { span, body }.into())
838}
839
840fn parse_class_member_with_is_static<'a, P: Parser<'a>>(
841    p: &mut P,
842    start: BytePos,
843    declare_token: Option<Span>,
844    accessibility: Option<Accessibility>,
845    static_token: Option<Span>,
846    accessor_token: Option<Span>,
847    decorators: Vec<Decorator>,
848) -> PResult<ClassMember> {
849    let mut is_static = static_token.is_some();
850
851    let mut is_abstract = false;
852    let mut is_override = false;
853    let mut readonly = None;
854    let mut modifier_span = None;
855    let declare = declare_token.is_some();
856    while let Some(modifier) = if p.input().syntax().typescript() {
857        parse_ts_modifier(p, &["abstract", "readonly", "override", "static"], true)?
858    } else {
859        None
860    } {
861        modifier_span = Some(p.input().prev_span());
862        match modifier {
863            "abstract" => {
864                if is_abstract {
865                    p.emit_err(
866                        p.input().prev_span(),
867                        SyntaxError::TS1030(atom!("abstract")),
868                    );
869                } else if is_override {
870                    p.emit_err(
871                        p.input().prev_span(),
872                        SyntaxError::TS1029(atom!("abstract"), atom!("override")),
873                    );
874                }
875                is_abstract = true;
876            }
877            "override" => {
878                if is_override {
879                    p.emit_err(
880                        p.input().prev_span(),
881                        SyntaxError::TS1030(atom!("override")),
882                    );
883                } else if readonly.is_some() {
884                    p.emit_err(
885                        p.input().prev_span(),
886                        SyntaxError::TS1029(atom!("override"), atom!("readonly")),
887                    );
888                } else if declare {
889                    p.emit_err(
890                        p.input().prev_span(),
891                        SyntaxError::TS1243(atom!("override"), atom!("declare")),
892                    );
893                } else if !p.ctx().contains(Context::HasSuperClass) {
894                    p.emit_err(p.input().prev_span(), SyntaxError::TS4112);
895                }
896                is_override = true;
897            }
898            "readonly" => {
899                let readonly_span = p.input().prev_span();
900                if readonly.is_some() {
901                    p.emit_err(readonly_span, SyntaxError::TS1030(atom!("readonly")));
902                } else {
903                    readonly = Some(readonly_span);
904                }
905            }
906            "static" => {
907                if is_override {
908                    p.emit_err(
909                        p.input().prev_span(),
910                        SyntaxError::TS1029(atom!("static"), atom!("override")),
911                    );
912                }
913
914                is_static = true;
915            }
916            _ => {}
917        }
918    }
919
920    let accessor_token = accessor_token.or_else(|| {
921        if p.syntax().auto_accessors() && readonly.is_none() {
922            let start = p.cur_pos();
923            if !peek!(p).is_some_and(|cur| cur.is_lparen())
924                && p.input_mut().eat(&P::Token::ACCESSOR)
925            {
926                Some(p.span(start))
927            } else {
928                None
929            }
930        } else {
931            None
932        }
933    });
934
935    if is_static && p.input().is(&P::Token::LBRACE) {
936        if let Some(span) = declare_token {
937            p.emit_err(span, SyntaxError::TS1184);
938        }
939        if accessibility.is_some() {
940            p.emit_err(p.input().cur_span(), SyntaxError::TS1184);
941        }
942        return parse_static_block(p, start);
943    }
944    if p.input().is(&P::Token::STATIC) && peek!(p).is_some_and(|cur| cur.is_lbrace()) {
945        // For "readonly", "abstract" and "override"
946        if let Some(span) = modifier_span {
947            p.emit_err(span, SyntaxError::TS1184);
948        }
949        if let Some(span) = static_token {
950            p.emit_err(span, SyntaxError::TS1184);
951        }
952        p.bump(); // consume "static"
953        return parse_static_block(p, start);
954    }
955
956    if p.input().syntax().typescript() && !is_abstract && !is_override && accessibility.is_none() {
957        let idx = try_parse_ts_index_signature(p, start, readonly.is_some(), is_static)?;
958        if let Some(idx) = idx {
959            return Ok(idx.into());
960        }
961    }
962
963    if p.input_mut().eat(&P::Token::MUL) {
964        // generator method
965        let key = parse_class_prop_name(p)?;
966        if readonly.is_some() {
967            p.emit_err(p.span(start), SyntaxError::ReadOnlyMethod);
968        }
969        if is_constructor(&key) {
970            p.emit_err(p.span(start), SyntaxError::GeneratorConstructor);
971        }
972
973        return make_method(
974            p,
975            parse_unique_formal_params,
976            MakeMethodArgs {
977                start,
978                decorators,
979                is_async: false,
980                is_generator: true,
981                accessibility,
982                is_abstract,
983                is_override,
984                is_optional: false,
985                static_token,
986                key,
987                kind: MethodKind::Method,
988            },
989        );
990    }
991
992    trace_cur!(p, parse_class_member_with_is_static__normal_class_member);
993    let key = if readonly.is_some() && (p.input().cur().is_bang() || p.input().cur().is_colon()) {
994        Key::Public(PropName::Ident(IdentName::new(
995            atom!("readonly"),
996            readonly.unwrap(),
997        )))
998    } else {
999        parse_class_prop_name(p)?
1000    };
1001    let is_optional = p.input().syntax().typescript() && p.input_mut().eat(&P::Token::QUESTION);
1002
1003    if is_class_method(p) {
1004        // handle a(){} / get(){} / set(){} / async(){}
1005
1006        trace_cur!(p, parse_class_member_with_is_static__normal_class_method);
1007
1008        if let Some(token) = declare_token {
1009            p.emit_err(token, SyntaxError::TS1031)
1010        }
1011
1012        if readonly.is_some() {
1013            syntax_error!(p, p.span(start), SyntaxError::ReadOnlyMethod);
1014        }
1015        let is_constructor = is_constructor(&key);
1016
1017        if is_constructor {
1018            if p.syntax().typescript() && is_override {
1019                p.emit_err(p.span(start), SyntaxError::TS1089(atom!("override")));
1020            }
1021
1022            if p.syntax().typescript() && p.input().is(&P::Token::LESS) {
1023                let start = p.cur_pos();
1024                if peek!(p).is_some_and(|cur| cur.is_less()) {
1025                    p.assert_and_bump(&P::Token::LESS);
1026                    let start2 = p.cur_pos();
1027                    p.assert_and_bump(&P::Token::GREATER);
1028
1029                    p.emit_err(p.span(start), SyntaxError::TS1098);
1030                    p.emit_err(p.span(start2), SyntaxError::TS1092);
1031                } else {
1032                    let type_params = try_parse_ts_type_params(p, false, true)?;
1033
1034                    if let Some(type_params) = type_params {
1035                        for param in type_params.params {
1036                            p.emit_err(param.span(), SyntaxError::TS1092);
1037                        }
1038                    }
1039                }
1040            }
1041
1042            expect!(p, &P::Token::LPAREN);
1043            let params = parse_constructor_params(p)?;
1044            expect!(p, &P::Token::RPAREN);
1045
1046            if p.syntax().typescript() && p.input().is(&P::Token::COLON) {
1047                let start = p.cur_pos();
1048                let type_ann = parse_ts_type_ann(p, true, start)?;
1049
1050                p.emit_err(type_ann.type_ann.span(), SyntaxError::TS1093);
1051            }
1052
1053            let body: Option<_> =
1054                parse_fn_block_body(p, false, false, false, params.is_simple_parameter_list())?;
1055
1056            if body.is_none() {
1057                for param in params.iter() {
1058                    if param.is_ts_param_prop() {
1059                        p.emit_err(param.span(), SyntaxError::TS2369)
1060                    }
1061                }
1062            }
1063
1064            if p.syntax().typescript() && body.is_none() {
1065                // Declare constructors cannot have assignment pattern in parameters
1066                for param in &params {
1067                    // TODO: Search deeply for assignment pattern using a Visitor
1068
1069                    let span = match *param {
1070                        ParamOrTsParamProp::Param(ref param) => match param.pat {
1071                            Pat::Assign(ref p) => Some(p.span()),
1072                            _ => None,
1073                        },
1074                        ParamOrTsParamProp::TsParamProp(TsParamProp {
1075                            param: TsParamPropParam::Assign(ref p),
1076                            ..
1077                        }) => Some(p.span()),
1078                        _ => None,
1079                    };
1080
1081                    if let Some(span) = span {
1082                        p.emit_err(span, SyntaxError::TS2371)
1083                    }
1084                }
1085            }
1086
1087            if let Some(static_token) = static_token {
1088                p.emit_err(static_token, SyntaxError::TS1089(atom!("static")))
1089            }
1090
1091            if let Some(span) = modifier_span {
1092                if is_abstract {
1093                    p.emit_err(span, SyntaxError::TS1242);
1094                }
1095            }
1096
1097            return Ok(ClassMember::Constructor(Constructor {
1098                span: p.span(start),
1099                accessibility,
1100                key: match key {
1101                    Key::Public(key) => key,
1102                    _ => unreachable!("is_constructor() returns false for PrivateName"),
1103                },
1104                is_optional,
1105                params,
1106                body,
1107                ..Default::default()
1108            }));
1109        } else {
1110            return make_method(
1111                p,
1112                parse_formal_params,
1113                MakeMethodArgs {
1114                    start,
1115                    is_optional,
1116                    accessibility,
1117                    decorators,
1118                    is_abstract,
1119                    is_override,
1120                    static_token,
1121                    kind: MethodKind::Method,
1122                    key,
1123                    is_async: false,
1124                    is_generator: false,
1125                },
1126            );
1127        }
1128    }
1129
1130    let is_next_line_generator =
1131        p.input_mut().had_line_break_before_cur() && p.input().is(&P::Token::MUL);
1132    let getter_or_setter_ident = match key {
1133        // `get\n*` is an uninitialized property named 'get' followed by a generator.
1134        Key::Public(PropName::Ident(ref i))
1135            if (i.sym == "get" || i.sym == "set")
1136                && !is_class_property(p, /* asi */ false)
1137                && !is_next_line_generator =>
1138        {
1139            Some(i)
1140        }
1141        _ => None,
1142    };
1143
1144    if getter_or_setter_ident.is_none() && is_class_property(p, /* asi */ true) {
1145        return make_property(
1146            p,
1147            start,
1148            decorators,
1149            accessibility,
1150            key,
1151            is_static,
1152            accessor_token,
1153            is_optional,
1154            readonly.is_some(),
1155            declare,
1156            is_abstract,
1157            is_override,
1158        );
1159    }
1160
1161    if match key {
1162        Key::Public(PropName::Ident(ref i)) => i.sym == "async",
1163        _ => false,
1164    } && !p.input_mut().had_line_break_before_cur()
1165    {
1166        // handle async foo(){}
1167
1168        if p.input().syntax().typescript() && parse_ts_modifier(p, &["override"], false)?.is_some()
1169        {
1170            is_override = true;
1171            p.emit_err(
1172                p.input().prev_span(),
1173                SyntaxError::TS1029(atom!("override"), atom!("async")),
1174            );
1175        }
1176
1177        let is_generator = p.input_mut().eat(&P::Token::MUL);
1178        let key = parse_class_prop_name(p)?;
1179        if is_constructor(&key) {
1180            syntax_error!(p, key.span(), SyntaxError::AsyncConstructor)
1181        }
1182        if readonly.is_some() {
1183            syntax_error!(p, p.span(start), SyntaxError::ReadOnlyMethod);
1184        }
1185
1186        // handle async foo(){}
1187        let is_optional = is_optional
1188            || p.input().syntax().typescript() && p.input_mut().eat(&P::Token::QUESTION);
1189        return make_method(
1190            p,
1191            parse_unique_formal_params,
1192            MakeMethodArgs {
1193                start,
1194                static_token,
1195                key,
1196                is_abstract,
1197                accessibility,
1198                is_optional,
1199                is_override,
1200                decorators,
1201                kind: MethodKind::Method,
1202                is_async: true,
1203                is_generator,
1204            },
1205        );
1206    }
1207
1208    if let Some(i) = getter_or_setter_ident {
1209        let key_span = key.span();
1210
1211        // handle get foo(){} / set foo(v){}
1212        let key = parse_class_prop_name(p)?;
1213
1214        if readonly.is_some() {
1215            p.emit_err(key_span, SyntaxError::GetterSetterCannotBeReadonly);
1216        }
1217
1218        if is_constructor(&key) {
1219            p.emit_err(key_span, SyntaxError::ConstructorAccessor);
1220        }
1221
1222        return match &*i.sym {
1223            "get" => make_method(
1224                p,
1225                |p| {
1226                    let params = parse_formal_params(p)?;
1227
1228                    if params.iter().any(is_not_this) {
1229                        p.emit_err(key_span, SyntaxError::GetterParam);
1230                    }
1231
1232                    Ok(params)
1233                },
1234                MakeMethodArgs {
1235                    decorators,
1236                    start,
1237                    is_abstract,
1238                    is_async: false,
1239                    is_generator: false,
1240                    is_optional,
1241                    is_override,
1242                    accessibility,
1243                    static_token,
1244                    key,
1245                    kind: MethodKind::Getter,
1246                },
1247            ),
1248            "set" => make_method(
1249                p,
1250                |p| {
1251                    let params = parse_formal_params(p)?;
1252
1253                    if params.iter().filter(|p| is_not_this(p)).count() != 1 {
1254                        p.emit_err(key_span, SyntaxError::SetterParam);
1255                    }
1256
1257                    if !params.is_empty() {
1258                        if let Pat::Rest(..) = params[0].pat {
1259                            p.emit_err(params[0].pat.span(), SyntaxError::RestPatInSetter);
1260                        }
1261                    }
1262
1263                    Ok(params)
1264                },
1265                MakeMethodArgs {
1266                    decorators,
1267                    start,
1268                    is_optional,
1269                    is_abstract,
1270                    is_override,
1271                    is_async: false,
1272                    is_generator: false,
1273                    accessibility,
1274                    static_token,
1275                    key,
1276                    kind: MethodKind::Setter,
1277                },
1278            ),
1279            _ => unreachable!(),
1280        };
1281    }
1282
1283    unexpected!(p, "* for generator, private key, identifier or async")
1284}
1285
1286fn parse_class_member<'a, P: Parser<'a>>(p: &mut P) -> PResult<ClassMember> {
1287    trace_cur!(p, parse_class_member);
1288
1289    let start = p.cur_pos();
1290    let decorators = parse_decorators(p, false)?;
1291    let declare = p.syntax().typescript() && p.input_mut().eat(&P::Token::DECLARE);
1292    let accessibility = if p.input().syntax().typescript() {
1293        parse_access_modifier(p)?
1294    } else {
1295        None
1296    };
1297    // Allow `private declare`.
1298    let declare = declare || p.syntax().typescript() && p.input_mut().eat(&P::Token::DECLARE);
1299
1300    let declare_token = if declare {
1301        // Handle declare(){}
1302        if is_class_method(p) {
1303            let key = Key::Public(PropName::Ident(IdentName::new(
1304                atom!("declare"),
1305                p.span(start),
1306            )));
1307            let is_optional =
1308                p.input().syntax().typescript() && p.input_mut().eat(&P::Token::QUESTION);
1309            return make_method(
1310                p,
1311                parse_unique_formal_params,
1312                MakeMethodArgs {
1313                    start,
1314                    accessibility,
1315                    decorators,
1316                    is_abstract: false,
1317                    is_optional,
1318                    is_override: false,
1319                    is_async: false,
1320                    is_generator: false,
1321                    static_token: None,
1322                    key,
1323                    kind: MethodKind::Method,
1324                },
1325            );
1326        } else if is_class_property(p, /* asi */ true)
1327            || (p.syntax().typescript() && p.input().is(&P::Token::QUESTION))
1328        {
1329            // Property named `declare`
1330
1331            let key = Key::Public(PropName::Ident(IdentName::new(
1332                atom!("declare"),
1333                p.span(start),
1334            )));
1335            let is_optional =
1336                p.input().syntax().typescript() && p.input_mut().eat(&P::Token::QUESTION);
1337            return make_property(
1338                p,
1339                start,
1340                decorators,
1341                accessibility,
1342                key,
1343                false,
1344                None,
1345                is_optional,
1346                false,
1347                false,
1348                false,
1349                false,
1350            );
1351        } else {
1352            Some(p.span(start))
1353        }
1354    } else {
1355        None
1356    };
1357
1358    let static_token = {
1359        let start = p.cur_pos();
1360        if p.input_mut().eat(&P::Token::STATIC) {
1361            Some(p.span(start))
1362        } else {
1363            None
1364        }
1365    };
1366
1367    let accessor_token = if p.syntax().auto_accessors() {
1368        let start = p.cur_pos();
1369        if p.input_mut().eat(&P::Token::ACCESSOR) {
1370            Some(p.span(start))
1371        } else {
1372            None
1373        }
1374    } else {
1375        None
1376    };
1377
1378    if let Some(accessor_token) = accessor_token {
1379        // Handle accessor(){}
1380        if is_class_method(p) {
1381            let key = Key::Public(PropName::Ident(IdentName::new(
1382                atom!("accessor"),
1383                accessor_token,
1384            )));
1385            let is_optional =
1386                p.input().syntax().typescript() && p.input_mut().eat(&P::Token::QUESTION);
1387            return make_method(
1388                p,
1389                parse_unique_formal_params,
1390                MakeMethodArgs {
1391                    start,
1392                    accessibility,
1393                    decorators,
1394                    is_abstract: false,
1395                    is_optional,
1396                    is_override: false,
1397                    is_async: false,
1398                    is_generator: false,
1399                    static_token,
1400                    key,
1401                    kind: MethodKind::Method,
1402                },
1403            );
1404        } else if is_class_property(p, /* asi */ true)
1405            || (p.syntax().typescript() && p.input().is(&P::Token::QUESTION))
1406        {
1407            // Property named `accessor`
1408
1409            let key = Key::Public(PropName::Ident(IdentName::new(
1410                atom!("accessor"),
1411                accessor_token,
1412            )));
1413            let is_optional =
1414                p.input().syntax().typescript() && p.input_mut().eat(&P::Token::QUESTION);
1415            let is_static = static_token.is_some();
1416            return make_property(
1417                p,
1418                start,
1419                decorators,
1420                accessibility,
1421                key,
1422                is_static,
1423                None,
1424                is_optional,
1425                false,
1426                declare,
1427                false,
1428                false,
1429            );
1430        }
1431    }
1432
1433    if let Some(static_token) = static_token {
1434        // Handle static(){}
1435        if is_class_method(p) {
1436            let key = Key::Public(PropName::Ident(IdentName::new(
1437                atom!("static"),
1438                static_token,
1439            )));
1440            let is_optional =
1441                p.input().syntax().typescript() && p.input_mut().eat(&P::Token::QUESTION);
1442            return make_method(
1443                p,
1444                parse_unique_formal_params,
1445                MakeMethodArgs {
1446                    start,
1447                    accessibility,
1448                    decorators,
1449                    is_abstract: false,
1450                    is_optional,
1451                    is_override: false,
1452                    is_async: false,
1453                    is_generator: false,
1454                    static_token: None,
1455                    key,
1456                    kind: MethodKind::Method,
1457                },
1458            );
1459        } else if is_class_property(p, /* asi */ false)
1460            || (p.syntax().typescript() && p.input().is(&P::Token::QUESTION))
1461        {
1462            // Property named `static`
1463
1464            // Avoid to parse
1465            //   static
1466            //   {}
1467            let is_parsing_static_blocks = p.input().is(&P::Token::LBRACE);
1468            if !is_parsing_static_blocks {
1469                let key = Key::Public(PropName::Ident(IdentName::new(
1470                    atom!("static"),
1471                    static_token,
1472                )));
1473                let is_optional =
1474                    p.input().syntax().typescript() && p.input_mut().eat(&P::Token::QUESTION);
1475                return make_property(
1476                    p,
1477                    start,
1478                    decorators,
1479                    accessibility,
1480                    key,
1481                    false,
1482                    accessor_token,
1483                    is_optional,
1484                    false,
1485                    declare,
1486                    false,
1487                    false,
1488                );
1489            }
1490        } else {
1491            // TODO: error if static contains escape
1492        }
1493    }
1494
1495    parse_class_member_with_is_static(
1496        p,
1497        start,
1498        declare_token,
1499        accessibility,
1500        static_token,
1501        accessor_token,
1502        decorators,
1503    )
1504}
1505
1506fn parse_class_body<'a, P: Parser<'a>>(p: &mut P) -> PResult<Vec<ClassMember>> {
1507    let mut elems = Vec::with_capacity(32);
1508    let mut has_constructor_with_body = false;
1509    while !p.input().is(&P::Token::RBRACE) {
1510        if p.input_mut().eat(&P::Token::SEMI) {
1511            let span = p.input().prev_span();
1512            debug_assert!(span.lo <= span.hi);
1513            elems.push(ClassMember::Empty(EmptyStmt { span }));
1514            continue;
1515        }
1516        let elem = p.do_inside_of_context(Context::AllowDirectSuper, parse_class_member)?;
1517
1518        if !p.ctx().contains(Context::InDeclare) {
1519            if let ClassMember::Constructor(Constructor {
1520                body: Some(..),
1521                span,
1522                ..
1523            }) = elem
1524            {
1525                if has_constructor_with_body {
1526                    p.emit_err(span, SyntaxError::DuplicateConstructor);
1527                }
1528                has_constructor_with_body = true;
1529            }
1530        }
1531        elems.push(elem);
1532    }
1533    Ok(elems)
1534}
1535
1536pub fn parse_class<'a, T>(
1537    p: &mut impl Parser<'a>,
1538    start: BytePos,
1539    class_start: BytePos,
1540    decorators: Vec<Decorator>,
1541    is_abstract: bool,
1542) -> PResult<T>
1543where
1544    T: OutputType,
1545{
1546    let (ident, mut class) = p.do_inside_of_context(Context::InClass, |p| {
1547        parse_class_inner(p, start, class_start, decorators, T::IS_IDENT_REQUIRED)
1548    })?;
1549
1550    if is_abstract {
1551        class.is_abstract = true
1552    } else {
1553        for member in class.body.iter() {
1554            match member {
1555                ClassMember::ClassProp(ClassProp {
1556                    is_abstract: true,
1557                    span,
1558                    ..
1559                })
1560                | ClassMember::Method(ClassMethod {
1561                    span,
1562                    is_abstract: true,
1563                    ..
1564                }) => p.emit_err(*span, SyntaxError::TS1244),
1565                _ => (),
1566            }
1567        }
1568    }
1569
1570    match T::finish_class(p.span(start), ident, class) {
1571        Ok(v) => Ok(v),
1572        Err(kind) => syntax_error!(p, kind),
1573    }
1574}
1575
1576/// Not generic
1577fn parse_class_inner<'a, P: Parser<'a>>(
1578    p: &mut P,
1579    _start: BytePos,
1580    class_start: BytePos,
1581    decorators: Vec<Decorator>,
1582    is_ident_required: bool,
1583) -> PResult<(Option<Ident>, Box<Class>)> {
1584    p.strict_mode(|p| {
1585        expect!(p, &P::Token::CLASS);
1586
1587        let ident = parse_maybe_opt_binding_ident(p, is_ident_required, true)?;
1588        if p.input().syntax().typescript() {
1589            if let Some(span) = ident.invalid_class_name() {
1590                p.emit_err(span, SyntaxError::TS2414);
1591            }
1592        }
1593
1594        let type_params = if p.input().syntax().typescript() {
1595            try_parse_ts_type_params(p, true, true)?
1596        } else {
1597            None
1598        };
1599
1600        let (mut super_class, mut super_type_params) = if p.input_mut().eat(&P::Token::EXTENDS) {
1601            let (super_class, super_type_params) = parse_super_class(p)?;
1602
1603            if p.syntax().typescript() && p.input_mut().eat(&P::Token::COMMA) {
1604                let exprs = parse_ts_heritage_clause(p)?;
1605
1606                for e in &exprs {
1607                    p.emit_err(e.span(), SyntaxError::TS1174);
1608                }
1609            }
1610
1611            (Some(super_class), super_type_params)
1612        } else {
1613            (None, None)
1614        };
1615
1616        // Handle TS1172
1617        if p.input_mut().eat(&P::Token::EXTENDS) {
1618            p.emit_err(p.input().prev_span(), SyntaxError::TS1172);
1619
1620            parse_super_class(p)?;
1621        };
1622
1623        let implements =
1624            if p.input().syntax().typescript() && p.input_mut().eat(&P::Token::IMPLEMENTS) {
1625                parse_ts_heritage_clause(p)?
1626            } else {
1627                Vec::with_capacity(4)
1628            };
1629
1630        {
1631            // Handle TS1175
1632            if p.input().syntax().typescript() && p.input_mut().eat(&P::Token::IMPLEMENTS) {
1633                p.emit_err(p.input().prev_span(), SyntaxError::TS1175);
1634
1635                parse_ts_heritage_clause(p)?;
1636            }
1637        }
1638
1639        // Handle TS1173
1640        if p.input().syntax().typescript() && p.input_mut().eat(&P::Token::EXTENDS) {
1641            p.emit_err(p.input().prev_span(), SyntaxError::TS1173);
1642
1643            let (sc, type_params) = parse_super_class(p)?;
1644
1645            if super_class.is_none() {
1646                super_class = Some(sc);
1647                if type_params.is_some() {
1648                    super_type_params = type_params;
1649                }
1650            }
1651        }
1652
1653        expect!(p, &P::Token::LBRACE);
1654
1655        let body = if super_class.is_some() {
1656            p.do_inside_of_context(Context::HasSuperClass, parse_class_body)?
1657        } else {
1658            p.do_outside_of_context(Context::HasSuperClass, parse_class_body)?
1659        };
1660
1661        if p.input().cur().is_eof() {
1662            let eof_text = p.input_mut().dump_cur();
1663            p.emit_err(
1664                p.input().cur_span(),
1665                SyntaxError::Expected(format!("{:?}", P::Token::RBRACE), eof_text),
1666            );
1667        } else {
1668            expect!(p, &P::Token::RBRACE);
1669        }
1670
1671        let span = p.span(class_start);
1672        Ok((
1673            ident,
1674            Box::new(Class {
1675                span,
1676                decorators,
1677                is_abstract: false,
1678                type_params,
1679                super_class,
1680                super_type_params,
1681                body,
1682                implements,
1683                ..Default::default()
1684            }),
1685        ))
1686    })
1687}