swc_ecma_parser/parser/
stmt.rs

1use swc_common::Spanned;
2use typed_arena::Arena;
3
4use super::{pat::PatType, *};
5use crate::error::SyntaxError;
6
7mod module_item;
8
9impl<'a, I: Tokens> Parser<I> {
10    pub fn parse_module_item(&mut self) -> PResult<ModuleItem> {
11        self.parse_stmt_like(true, true)
12    }
13
14    pub(super) fn parse_block_body<Type>(
15        &mut self,
16        mut allow_directives: bool,
17        top_level: bool,
18        end: Option<&'static Token>,
19    ) -> PResult<Vec<Type>>
20    where
21        Self: StmtLikeParser<'a, Type>,
22        Type: IsDirective + From<Stmt>,
23    {
24        trace_cur!(self, parse_block_body);
25
26        let old_ctx = self.ctx();
27
28        let stmts = Arena::new();
29        while {
30            if self.input.cur().is_none() && end.is_some() {
31                let eof_text = self.input.dump_cur();
32                self.emit_err(
33                    self.input.cur_span(),
34                    SyntaxError::Expected(end.unwrap(), eof_text),
35                );
36                false
37            } else {
38                let c = cur!(self, false).ok();
39                c != end
40            }
41        } {
42            let stmt = self.parse_stmt_like(true, top_level)?;
43            if allow_directives {
44                allow_directives = false;
45                if stmt.is_use_strict() {
46                    let ctx = Context {
47                        strict: true,
48                        ..old_ctx
49                    };
50                    self.set_ctx(ctx);
51
52                    if self.input.knows_cur() && !is!(self, ';') {
53                        unreachable!(
54                            "'use strict'; directive requires parser.input.cur to be empty or \
55                             '}}', but current token was: {:?}",
56                            self.input.cur()
57                        )
58                    }
59                }
60            }
61
62            stmts.alloc(stmt);
63        }
64
65        if self.input.cur().is_some() && end.is_some() {
66            bump!(self);
67        }
68
69        self.set_ctx(old_ctx);
70
71        Ok(stmts.into_vec())
72    }
73
74    /// Parse a statement but not a declaration.
75    pub fn parse_stmt(&mut self, top_level: bool) -> PResult<Stmt> {
76        trace_cur!(self, parse_stmt);
77        self.parse_stmt_like(false, top_level)
78    }
79
80    /// Parse a statement and maybe a declaration.
81    pub fn parse_stmt_list_item(&mut self, top_level: bool) -> PResult<Stmt> {
82        trace_cur!(self, parse_stmt_list_item);
83        self.parse_stmt_like(true, top_level)
84    }
85
86    /// Parse a statement, declaration or module item.
87    fn parse_stmt_like<Type>(&mut self, include_decl: bool, top_level: bool) -> PResult<Type>
88    where
89        Self: StmtLikeParser<'a, Type>,
90        Type: IsDirective + From<Stmt>,
91    {
92        trace_cur!(self, parse_stmt_like);
93
94        let _tracing = debug_tracing!(self, "parse_stmt_like");
95
96        let start = cur_pos!(self);
97        let decorators = self.parse_decorators(true)?;
98
99        if is_one_of!(self, "import", "export") {
100            return self.handle_import_export(top_level, decorators);
101        }
102
103        let ctx = Context {
104            will_expect_colon_for_cond: false,
105            allow_using_decl: true,
106            ..self.ctx()
107        };
108        self.with_ctx(ctx)
109            .parse_stmt_internal(start, include_decl, top_level, decorators)
110            .map(From::from)
111    }
112
113    /// `parseStatementContent`
114    fn parse_stmt_internal(
115        &mut self,
116        start: BytePos,
117        include_decl: bool,
118        top_level: bool,
119        decorators: Vec<Decorator>,
120    ) -> PResult<Stmt> {
121        trace_cur!(self, parse_stmt_internal);
122
123        let is_typescript = self.input.syntax().typescript();
124
125        if is_typescript && is!(self, "const") && peeked_is!(self, "enum") {
126            assert_and_bump!(self, "const");
127            assert_and_bump!(self, "enum");
128            return self
129                .parse_ts_enum_decl(start, true)
130                .map(Decl::from)
131                .map(Stmt::from);
132        }
133
134        match cur!(self, true) {
135            tok!("await") if include_decl || top_level => {
136                if top_level {
137                    self.state.found_module_item = true;
138                    if !self.ctx().can_be_module {
139                        self.emit_err(self.input.cur_span(), SyntaxError::TopLevelAwaitInScript);
140                    }
141                }
142
143                if peeked_is!(self, "using") {
144                    let eaten_await = Some(self.input.cur_pos());
145                    assert_and_bump!(self, "await");
146                    let v = self.parse_using_decl(start, true)?;
147                    if let Some(v) = v {
148                        return Ok(v.into());
149                    }
150
151                    let expr = self.parse_await_expr(eaten_await)?;
152                    let expr = self
153                        .include_in_expr(true)
154                        .parse_bin_op_recursively(expr, 0)?;
155                    eat!(self, ';');
156
157                    let span = span!(self, start);
158                    return Ok(ExprStmt { span, expr }.into());
159                }
160            }
161
162            tok!("break") | tok!("continue") => {
163                let is_break = is!(self, "break");
164                bump!(self);
165
166                let label = if eat!(self, ';') {
167                    None
168                } else {
169                    let i = self.parse_label_ident().map(Some)?;
170                    expect!(self, ';');
171                    i
172                };
173
174                let span = span!(self, start);
175                if is_break {
176                    if label.is_some() && !self.state.labels.contains(&label.as_ref().unwrap().sym)
177                    {
178                        self.emit_err(span, SyntaxError::TS1116);
179                    } else if !self.ctx().is_break_allowed {
180                        self.emit_err(span, SyntaxError::TS1105);
181                    }
182                } else if !self.ctx().is_continue_allowed {
183                    self.emit_err(span, SyntaxError::TS1115);
184                } else if label.is_some()
185                    && !self.state.labels.contains(&label.as_ref().unwrap().sym)
186                {
187                    self.emit_err(span, SyntaxError::TS1107);
188                }
189
190                return Ok(if is_break {
191                    BreakStmt { span, label }.into()
192                } else {
193                    ContinueStmt { span, label }.into()
194                });
195            }
196
197            tok!("debugger") => {
198                bump!(self);
199                expect!(self, ';');
200                return Ok(DebuggerStmt {
201                    span: span!(self, start),
202                }
203                .into());
204            }
205
206            tok!("do") => {
207                return self.parse_do_stmt();
208            }
209
210            tok!("for") => {
211                return self.parse_for_stmt();
212            }
213
214            tok!("function") => {
215                if !include_decl {
216                    self.emit_err(self.input.cur_span(), SyntaxError::DeclNotAllowed);
217                }
218
219                return self.parse_fn_decl(decorators).map(Stmt::from);
220            }
221
222            tok!("class") => {
223                if !include_decl {
224                    self.emit_err(self.input.cur_span(), SyntaxError::DeclNotAllowed);
225                }
226                return self
227                    .parse_class_decl(start, start, decorators, false)
228                    .map(Stmt::from);
229            }
230
231            tok!("if") => {
232                return self.parse_if_stmt().map(Stmt::If);
233            }
234
235            tok!("return") => {
236                return self.parse_return_stmt();
237            }
238
239            tok!("switch") => {
240                return self.parse_switch_stmt();
241            }
242
243            tok!("throw") => {
244                return self.parse_throw_stmt();
245            }
246
247            // Error recovery
248            tok!("catch") => {
249                let span = self.input.cur_span();
250                self.emit_err(span, SyntaxError::TS1005);
251
252                let _ = self.parse_catch_clause();
253                let _ = self.parse_finally_block();
254
255                return Ok(ExprStmt {
256                    span,
257                    expr: Invalid { span }.into(),
258                }
259                .into());
260            }
261
262            // Error recovery
263            tok!("finally") => {
264                let span = self.input.cur_span();
265                self.emit_err(span, SyntaxError::TS1005);
266
267                let _ = self.parse_finally_block();
268
269                return Ok(ExprStmt {
270                    span,
271                    expr: Invalid { span }.into(),
272                }
273                .into());
274            }
275
276            tok!("try") => {
277                return self.parse_try_stmt();
278            }
279
280            tok!("with") => {
281                return self.parse_with_stmt();
282            }
283
284            tok!("while") => {
285                return self.parse_while_stmt();
286            }
287
288            tok!("var") => {
289                let v = self.parse_var_stmt(false)?;
290                return Ok(v.into());
291            }
292
293            tok!("const") if include_decl => {
294                let v = self.parse_var_stmt(false)?;
295                return Ok(v.into());
296            }
297
298            // 'let' can start an identifier reference.
299            tok!("let") if include_decl => {
300                let strict = self.ctx().strict;
301                let is_keyword = match peek!(self) {
302                    Some(t) => t.kind().follows_keyword_let(strict),
303                    _ => false,
304                };
305
306                if is_keyword {
307                    let v = self.parse_var_stmt(false)?;
308                    return Ok(v.into());
309                }
310            }
311
312            tok!("using") if include_decl => {
313                let v = self.parse_using_decl(start, false)?;
314                if let Some(v) = v {
315                    return Ok(v.into());
316                }
317            }
318
319            tok!("interface") => {
320                if is_typescript
321                    && peeked_is!(self, IdentName)
322                    && !self.input.has_linebreak_between_cur_and_peeked()
323                {
324                    let start = self.input.cur_pos();
325                    bump!(self);
326                    return Ok(self.parse_ts_interface_decl(start)?.into());
327                }
328            }
329
330            tok!("type") => {
331                if is_typescript
332                    && peeked_is!(self, IdentName)
333                    && !self.input.has_linebreak_between_cur_and_peeked()
334                {
335                    let start = self.input.cur_pos();
336                    bump!(self);
337                    return Ok(self.parse_ts_type_alias_decl(start)?.into());
338                }
339            }
340
341            tok!("enum") => {
342                if is_typescript
343                    && peeked_is!(self, IdentName)
344                    && !self.input.has_linebreak_between_cur_and_peeked()
345                {
346                    let start = self.input.cur_pos();
347                    bump!(self);
348                    return Ok(self.parse_ts_enum_decl(start, false)?.into());
349                }
350            }
351
352            tok!('{') => {
353                let ctx = Context {
354                    allow_using_decl: true,
355                    ..self.ctx()
356                };
357                return self.with_ctx(ctx).parse_block(false).map(Stmt::Block);
358            }
359
360            _ => {}
361        }
362
363        if eat_exact!(self, ';') {
364            return Ok(EmptyStmt {
365                span: span!(self, start),
366            }
367            .into());
368        }
369
370        // Handle async function foo() {}
371        if is!(self, "async")
372            && peeked_is!(self, "function")
373            && !self.input.has_linebreak_between_cur_and_peeked()
374        {
375            return self.parse_async_fn_decl(decorators).map(From::from);
376        }
377
378        // If the statement does not start with a statement keyword or a
379        // brace, it's an ExpressionStatement or LabeledStatement. We
380        // simply start parsing an expression, and afterwards, if the
381        // next token is a colon and the expression was a simple
382        // Identifier node, we switch to interpreting it as a label.
383        let expr = self.include_in_expr(true).parse_expr()?;
384
385        let expr = match *expr {
386            Expr::Ident(ident) => {
387                if eat!(self, ':') {
388                    return self.parse_labelled_stmt(ident);
389                }
390                ident.into()
391            }
392            _ => self.verify_expr(expr)?,
393        };
394        if let Expr::Ident(ref ident) = *expr {
395            if &*ident.sym == "interface" && self.input.had_line_break_before_cur() {
396                self.emit_strict_mode_err(
397                    ident.span,
398                    SyntaxError::InvalidIdentInStrict(ident.sym.clone()),
399                );
400
401                eat!(self, ';');
402
403                return Ok(ExprStmt {
404                    span: span!(self, start),
405                    expr,
406                }
407                .into());
408            }
409
410            if self.input.syntax().typescript() {
411                if let Some(decl) = self.parse_ts_expr_stmt(decorators, ident.clone())? {
412                    return Ok(decl.into());
413                }
414            }
415        }
416
417        if let Expr::Ident(Ident { ref sym, span, .. }) = *expr {
418            match &**sym {
419                "enum" | "interface" => {
420                    self.emit_strict_mode_err(span, SyntaxError::InvalidIdentInStrict(sym.clone()));
421                }
422                _ => {}
423            }
424        }
425
426        if self.syntax().typescript() {
427            if let Expr::Ident(ref i) = *expr {
428                match &*i.sym {
429                    "public" | "static" | "abstract" => {
430                        if eat!(self, "interface") {
431                            self.emit_err(i.span, SyntaxError::TS2427);
432                            return self
433                                .parse_ts_interface_decl(start)
434                                .map(Decl::from)
435                                .map(Stmt::from);
436                        }
437                    }
438                    _ => {}
439                }
440            }
441        }
442
443        if eat!(self, ';') {
444            Ok(ExprStmt {
445                span: span!(self, start),
446                expr,
447            }
448            .into())
449        } else {
450            if let Token::BinOp(..) = *cur!(self, false)? {
451                self.emit_err(self.input.cur_span(), SyntaxError::TS1005);
452                let expr = self.parse_bin_op_recursively(expr, 0)?;
453                return Ok(ExprStmt {
454                    span: span!(self, start),
455                    expr,
456                }
457                .into());
458            }
459
460            syntax_error!(
461                self,
462                SyntaxError::ExpectedSemiForExprStmt { expr: expr.span() }
463            );
464        }
465    }
466
467    /// Utility function used to parse large if else statements iteratively.
468    ///
469    /// THis function is recursive, but it is very cheap so stack overflow will
470    /// not occur.
471    fn adjust_if_else_clause(&mut self, cur: &mut IfStmt, alt: Box<Stmt>) {
472        cur.span = span!(self, cur.span.lo);
473
474        if let Some(Stmt::If(prev_alt)) = cur.alt.as_deref_mut() {
475            self.adjust_if_else_clause(prev_alt, alt)
476        } else {
477            debug_assert_eq!(cur.alt, None);
478            cur.alt = Some(alt);
479        }
480    }
481
482    fn parse_if_stmt(&mut self) -> PResult<IfStmt> {
483        let start = cur_pos!(self);
484
485        assert_and_bump!(self, "if");
486        let if_token = self.input.prev_span();
487
488        expect!(self, '(');
489        let ctx = Context {
490            ignore_else_clause: false,
491            ..self.ctx()
492        };
493        let test = self
494            .with_ctx(ctx)
495            .include_in_expr(true)
496            .parse_expr()
497            .map_err(|err| {
498                Error::new(
499                    err.span(),
500                    SyntaxError::WithLabel {
501                        inner: Box::new(err),
502                        span: if_token,
503                        note: "Tried to parse the condition for an if statement",
504                    },
505                )
506            })?;
507
508        expect!(self, ')');
509
510        let cons = {
511            // Prevent stack overflow
512            crate::maybe_grow(256 * 1024, 1024 * 1024, || {
513                // Annex B
514                if !self.ctx().strict && is!(self, "function") {
515                    // TODO: report error?
516                }
517                let ctx = Context {
518                    ignore_else_clause: false,
519                    ..self.ctx()
520                };
521                self.with_ctx(ctx).parse_stmt(false).map(Box::new)
522            })?
523        };
524
525        // We parse `else` branch iteratively, to avoid stack overflow
526        // See https://github.com/swc-project/swc/pull/3961
527
528        let alt = if self.ctx().ignore_else_clause {
529            None
530        } else {
531            let mut cur = None;
532
533            let ctx = Context {
534                ignore_else_clause: true,
535                ..self.ctx()
536            };
537
538            let last = loop {
539                if !eat!(self, "else") {
540                    break None;
541                }
542
543                if !is!(self, "if") {
544                    let ctx = Context {
545                        ignore_else_clause: false,
546                        ..self.ctx()
547                    };
548
549                    // As we eat `else` above, we need to parse statement once.
550                    let last = self.with_ctx(ctx).parse_stmt(false)?;
551                    break Some(last);
552                }
553
554                // We encountered `else if`
555
556                let alt = self.with_ctx(ctx).parse_if_stmt()?;
557
558                match &mut cur {
559                    Some(cur) => {
560                        self.adjust_if_else_clause(cur, Box::new(alt.into()));
561                    }
562                    _ => {
563                        cur = Some(alt);
564                    }
565                }
566            };
567
568            match cur {
569                Some(mut cur) => {
570                    if let Some(last) = last {
571                        self.adjust_if_else_clause(&mut cur, Box::new(last));
572                    }
573                    Some(cur.into())
574                }
575                _ => last,
576            }
577        }
578        .map(Box::new);
579
580        let span = span!(self, start);
581        Ok(IfStmt {
582            span,
583            test,
584            cons,
585            alt,
586        })
587    }
588
589    fn parse_return_stmt(&mut self) -> PResult<Stmt> {
590        let start = cur_pos!(self);
591
592        let stmt = self.parse_with(|p| {
593            assert_and_bump!(p, "return");
594
595            let arg = if is!(p, ';') {
596                None
597            } else {
598                p.include_in_expr(true).parse_expr().map(Some)?
599            };
600            expect!(p, ';');
601            Ok(ReturnStmt {
602                span: span!(p, start),
603                arg,
604            }
605            .into())
606        });
607
608        if !self.ctx().in_function && !self.input.syntax().allow_return_outside_function() {
609            self.emit_err(span!(self, start), SyntaxError::ReturnNotAllowed);
610        }
611
612        stmt
613    }
614
615    fn parse_switch_stmt(&mut self) -> PResult<Stmt> {
616        let switch_start = cur_pos!(self);
617
618        assert_and_bump!(self, "switch");
619
620        expect!(self, '(');
621        let discriminant = self.include_in_expr(true).parse_expr()?;
622        expect!(self, ')');
623
624        let mut cases = Vec::new();
625        let mut span_of_previous_default = None;
626
627        expect!(self, '{');
628        let ctx = Context {
629            is_break_allowed: true,
630            ..self.ctx()
631        };
632
633        self.with_ctx(ctx).parse_with(|p| {
634            while is_one_of!(p, "case", "default") {
635                let mut cons = Vec::new();
636                let is_case = is!(p, "case");
637                let case_start = cur_pos!(p);
638                bump!(p);
639                let test = if is_case {
640                    p.include_in_expr(true).parse_expr().map(Some)?
641                } else {
642                    if let Some(previous) = span_of_previous_default {
643                        syntax_error!(p, SyntaxError::MultipleDefault { previous });
644                    }
645                    span_of_previous_default = Some(span!(p, case_start));
646
647                    None
648                };
649                expect!(p, ':');
650
651                while !eof!(p) && !is_one_of!(p, "case", "default", '}') {
652                    cons.push(p.parse_stmt_list_item(false)?);
653                }
654
655                cases.push(SwitchCase {
656                    span: Span::new(case_start, p.input.prev_span().hi),
657                    test,
658                    cons,
659                });
660            }
661
662            Ok(())
663        })?;
664
665        // eof or rbrace
666        expect!(self, '}');
667
668        Ok(SwitchStmt {
669            span: span!(self, switch_start),
670            discriminant,
671            cases,
672        }
673        .into())
674    }
675
676    fn parse_throw_stmt(&mut self) -> PResult<Stmt> {
677        let start = cur_pos!(self);
678
679        assert_and_bump!(self, "throw");
680
681        if self.input.had_line_break_before_cur() {
682            // TODO: Suggest throw arg;
683            syntax_error!(self, SyntaxError::LineBreakInThrow);
684        }
685
686        let arg = self.include_in_expr(true).parse_expr()?;
687        expect!(self, ';');
688
689        let span = span!(self, start);
690        Ok(ThrowStmt { span, arg }.into())
691    }
692
693    fn parse_try_stmt(&mut self) -> PResult<Stmt> {
694        let start = cur_pos!(self);
695        assert_and_bump!(self, "try");
696
697        let block = self.parse_block(false)?;
698
699        let catch_start = cur_pos!(self);
700        let handler = self.parse_catch_clause()?;
701        let finalizer = self.parse_finally_block()?;
702
703        if handler.is_none() && finalizer.is_none() {
704            self.emit_err(Span::new(catch_start, catch_start), SyntaxError::TS1005);
705        }
706
707        let span = span!(self, start);
708        Ok(TryStmt {
709            span,
710            block,
711            handler,
712            finalizer,
713        }
714        .into())
715    }
716
717    fn parse_catch_clause(&mut self) -> PResult<Option<CatchClause>> {
718        let start = cur_pos!(self);
719
720        Ok(if eat!(self, "catch") {
721            let param = self.parse_catch_param()?;
722
723            self.parse_block(false)
724                .map(|body| CatchClause {
725                    span: span!(self, start),
726                    param,
727                    body,
728                })
729                .map(Some)?
730        } else {
731            None
732        })
733    }
734
735    fn parse_finally_block(&mut self) -> PResult<Option<BlockStmt>> {
736        Ok(if eat!(self, "finally") {
737            self.parse_block(false).map(Some)?
738        } else {
739            None
740        })
741    }
742
743    /// It's optional since es2019
744    fn parse_catch_param(&mut self) -> PResult<Option<Pat>> {
745        if eat!(self, '(') {
746            let mut pat = self.parse_binding_pat_or_ident(false)?;
747
748            let type_ann_start = cur_pos!(self);
749
750            if self.syntax().typescript() && eat!(self, ':') {
751                let ctx = Context {
752                    in_type: true,
753                    ..self.ctx()
754                };
755
756                let ty = self.with_ctx(ctx).parse_with(|p| p.parse_ts_type())?;
757                // self.emit_err(ty.span(), SyntaxError::TS1196);
758
759                match &mut pat {
760                    Pat::Ident(BindingIdent { type_ann, .. })
761                    | Pat::Array(ArrayPat { type_ann, .. })
762                    | Pat::Rest(RestPat { type_ann, .. })
763                    | Pat::Object(ObjectPat { type_ann, .. }) => {
764                        *type_ann = Some(Box::new(TsTypeAnn {
765                            span: span!(self, type_ann_start),
766                            type_ann: ty,
767                        }));
768                    }
769                    Pat::Assign(..) => {}
770                    Pat::Invalid(_) => {}
771                    Pat::Expr(_) => {}
772                }
773            }
774            expect!(self, ')');
775            Ok(Some(pat))
776        } else {
777            Ok(None)
778        }
779    }
780
781    pub(super) fn parse_using_decl(
782        &mut self,
783        start: BytePos,
784        is_await: bool,
785    ) -> PResult<Option<Box<UsingDecl>>> {
786        // using
787        // reader = init()
788
789        // is two statements
790        let _ = cur!(self, false);
791        if self.input.has_linebreak_between_cur_and_peeked() {
792            return Ok(None);
793        }
794
795        if !peeked_is!(self, BindingIdent) {
796            return Ok(None);
797        }
798
799        assert_and_bump!(self, "using");
800
801        let mut decls = Vec::new();
802        let mut first = true;
803        while first || eat!(self, ',') {
804            if first {
805                first = false;
806            }
807
808            // Handle
809            //      var a,;
810            //
811            // NewLine is ok
812            if is_exact!(self, ';') || eof!(self) {
813                let span = self.input.prev_span();
814                self.emit_err(span, SyntaxError::TS1009);
815                break;
816            }
817
818            decls.push(self.parse_var_declarator(false, VarDeclKind::Var)?);
819        }
820
821        if !self.syntax().explicit_resource_management() {
822            self.emit_err(span!(self, start), SyntaxError::UsingDeclNotEnabled);
823        }
824
825        if !self.ctx().allow_using_decl {
826            self.emit_err(span!(self, start), SyntaxError::UsingDeclNotAllowed);
827        }
828
829        for decl in &decls {
830            match decl.name {
831                Pat::Ident(..) => {}
832                _ => {
833                    self.emit_err(span!(self, start), SyntaxError::InvalidNameInUsingDecl);
834                }
835            }
836
837            if decl.init.is_none() {
838                self.emit_err(span!(self, start), SyntaxError::InitRequiredForUsingDecl);
839            }
840        }
841
842        eat!(self, ';');
843
844        Ok(Some(Box::new(UsingDecl {
845            span: span!(self, start),
846            is_await,
847            decls,
848        })))
849    }
850
851    pub(super) fn parse_var_stmt(&mut self, for_loop: bool) -> PResult<Box<VarDecl>> {
852        let start = cur_pos!(self);
853        let kind = match bump!(self) {
854            tok!("const") => VarDeclKind::Const,
855            tok!("let") => VarDeclKind::Let,
856            tok!("var") => VarDeclKind::Var,
857            _ => unreachable!(),
858        };
859        let var_span = span!(self, start);
860        let should_include_in = kind != VarDeclKind::Var || !for_loop;
861
862        if self.syntax().typescript() && for_loop {
863            let res = if is_one_of!(self, "in", "of") {
864                self.ts_look_ahead(|p| {
865                    //
866                    if !eat!(p, "of") && !eat!(p, "in") {
867                        return Ok(false);
868                    }
869
870                    p.parse_assignment_expr()?;
871                    expect!(p, ')');
872
873                    Ok(true)
874                })
875            } else {
876                Ok(false)
877            };
878
879            match res {
880                Ok(true) => {
881                    let pos = var_span.hi();
882                    let span = Span::new(pos, pos);
883                    self.emit_err(span, SyntaxError::TS1123);
884
885                    return Ok(Box::new(VarDecl {
886                        span: span!(self, start),
887                        kind,
888                        declare: false,
889                        decls: Vec::new(),
890                        ..Default::default()
891                    }));
892                }
893                Err(..) => {}
894                _ => {}
895            }
896        }
897
898        let mut decls = Vec::new();
899        let mut first = true;
900        while first || eat!(self, ',') {
901            if first {
902                first = false;
903            }
904
905            let ctx = if should_include_in {
906                Context {
907                    include_in_expr: true,
908                    ..self.ctx()
909                }
910            } else {
911                self.ctx()
912            };
913
914            // Handle
915            //      var a,;
916            //
917            // NewLine is ok
918            if is_exact!(self, ';') || eof!(self) {
919                let prev_span = self.input.prev_span();
920                let span = if prev_span == var_span {
921                    Span::new(prev_span.hi, prev_span.hi)
922                } else {
923                    prev_span
924                };
925                self.emit_err(span, SyntaxError::TS1009);
926                break;
927            }
928
929            decls.push(self.with_ctx(ctx).parse_var_declarator(for_loop, kind)?);
930        }
931
932        if !for_loop && !eat!(self, ';') {
933            self.emit_err(self.input.cur_span(), SyntaxError::TS1005);
934
935            let _ = self.parse_expr();
936
937            while !eat!(self, ';') {
938                bump!(self);
939
940                if let Some(Token::Error(_)) = self.input.cur() {
941                    break;
942                }
943            }
944        }
945
946        Ok(Box::new(VarDecl {
947            span: span!(self, start),
948            declare: false,
949            kind,
950            decls,
951            ..Default::default()
952        }))
953    }
954
955    fn parse_var_declarator(
956        &mut self,
957        for_loop: bool,
958        kind: VarDeclKind,
959    ) -> PResult<VarDeclarator> {
960        let start = cur_pos!(self);
961
962        let is_let_or_const = matches!(kind, VarDeclKind::Let | VarDeclKind::Const);
963
964        let mut name = self.parse_binding_pat_or_ident(is_let_or_const)?;
965
966        let definite = if self.input.syntax().typescript() {
967            match name {
968                Pat::Ident(..) => eat!(self, '!'),
969                _ => false,
970            }
971        } else {
972            false
973        };
974
975        // Typescript extension
976        if self.input.syntax().typescript() && is!(self, ':') {
977            let type_annotation = self.try_parse_ts_type_ann()?;
978            match name {
979                Pat::Array(ArrayPat {
980                    ref mut type_ann, ..
981                })
982                | Pat::Ident(BindingIdent {
983                    ref mut type_ann, ..
984                })
985                | Pat::Object(ObjectPat {
986                    ref mut type_ann, ..
987                })
988                | Pat::Rest(RestPat {
989                    ref mut type_ann, ..
990                }) => {
991                    *type_ann = type_annotation;
992                }
993                _ => unreachable!("invalid syntax: Pat: {:?}", name),
994            }
995        }
996
997        //FIXME: This is wrong. Should check in/of only on first loop.
998        let init = if !for_loop || !is_one_of!(self, "in", "of") {
999            if eat!(self, '=') {
1000                let expr = self.parse_assignment_expr()?;
1001                let expr = self.verify_expr(expr)?;
1002
1003                Some(expr)
1004            } else {
1005                // Destructuring bindings require initializers, but
1006                // typescript allows `declare` vars not to have initializers.
1007                if self.ctx().in_declare {
1008                    None
1009                } else if kind == VarDeclKind::Const && !for_loop && !self.ctx().in_declare {
1010                    self.emit_err(
1011                        span!(self, start),
1012                        SyntaxError::ConstDeclarationsRequireInitialization,
1013                    );
1014
1015                    None
1016                } else {
1017                    match name {
1018                        Pat::Ident(..) => None,
1019                        _ => {
1020                            syntax_error!(self, span!(self, start), SyntaxError::PatVarWithoutInit)
1021                        }
1022                    }
1023                }
1024            }
1025        } else {
1026            // e.g. for(let a;;)
1027            None
1028        };
1029
1030        Ok(VarDeclarator {
1031            span: span!(self, start),
1032            name,
1033            init,
1034            definite,
1035        })
1036    }
1037
1038    fn parse_do_stmt(&mut self) -> PResult<Stmt> {
1039        let start = cur_pos!(self);
1040
1041        assert_and_bump!(self, "do");
1042
1043        let ctx = Context {
1044            is_break_allowed: true,
1045            is_continue_allowed: true,
1046            ..self.ctx()
1047        };
1048        let body = self.with_ctx(ctx).parse_stmt(false).map(Box::new)?;
1049        expect!(self, "while");
1050        expect!(self, '(');
1051        let test = self.include_in_expr(true).parse_expr()?;
1052        expect!(self, ')');
1053        // We *may* eat semicolon.
1054        let _ = eat!(self, ';');
1055
1056        let span = span!(self, start);
1057
1058        Ok(DoWhileStmt { span, test, body }.into())
1059    }
1060
1061    fn parse_while_stmt(&mut self) -> PResult<Stmt> {
1062        let start = cur_pos!(self);
1063
1064        assert_and_bump!(self, "while");
1065
1066        expect!(self, '(');
1067        let test = self.include_in_expr(true).parse_expr()?;
1068        expect!(self, ')');
1069
1070        let ctx = Context {
1071            is_break_allowed: true,
1072            is_continue_allowed: true,
1073            ..self.ctx()
1074        };
1075        let body = self.with_ctx(ctx).parse_stmt(false).map(Box::new)?;
1076
1077        let span = span!(self, start);
1078        Ok(WhileStmt { span, test, body }.into())
1079    }
1080
1081    fn parse_with_stmt(&mut self) -> PResult<Stmt> {
1082        if self.syntax().typescript() {
1083            let span = self.input.cur_span();
1084            self.emit_err(span, SyntaxError::TS2410);
1085        }
1086
1087        {
1088            let span = self.input.cur_span();
1089            self.emit_strict_mode_err(span, SyntaxError::WithInStrict);
1090        }
1091
1092        let start = cur_pos!(self);
1093
1094        assert_and_bump!(self, "with");
1095
1096        expect!(self, '(');
1097        let obj = self.include_in_expr(true).parse_expr()?;
1098        expect!(self, ')');
1099
1100        let ctx = Context {
1101            in_function: true,
1102            ..self.ctx()
1103        };
1104        let body = self.with_ctx(ctx).parse_stmt(false).map(Box::new)?;
1105
1106        let span = span!(self, start);
1107        Ok(WithStmt { span, obj, body }.into())
1108    }
1109
1110    pub(super) fn parse_block(&mut self, allow_directives: bool) -> PResult<BlockStmt> {
1111        let start = cur_pos!(self);
1112
1113        expect!(self, '{');
1114
1115        let stmts = self.parse_block_body(allow_directives, false, Some(&tok!('}')))?;
1116
1117        let span = span!(self, start);
1118        Ok(BlockStmt {
1119            span,
1120            stmts,
1121            ctxt: Default::default(),
1122        })
1123    }
1124
1125    fn parse_labelled_stmt(&mut self, l: Ident) -> PResult<Stmt> {
1126        let ctx = Context {
1127            is_break_allowed: true,
1128            allow_using_decl: false,
1129            ..self.ctx()
1130        };
1131        self.with_ctx(ctx).parse_with(|p| {
1132            let start = l.span.lo();
1133
1134            let mut errors = Vec::new();
1135            for lb in &p.state.labels {
1136                if l.sym == *lb {
1137                    errors.push(Error::new(
1138                        l.span,
1139                        SyntaxError::DuplicateLabel(l.sym.clone()),
1140                    ));
1141                }
1142            }
1143            p.state.labels.push(l.sym.clone());
1144
1145            let body = Box::new(if is!(p, "function") {
1146                let f = p.parse_fn_decl(Vec::new())?;
1147                if let Decl::Fn(FnDecl { function, .. }) = &f {
1148                    if p.ctx().strict {
1149                        p.emit_err(function.span, SyntaxError::LabelledFunctionInStrict)
1150                    }
1151                    if function.is_generator || function.is_async {
1152                        p.emit_err(function.span, SyntaxError::LabelledGeneratorOrAsync)
1153                    }
1154                }
1155
1156                f.into()
1157            } else {
1158                p.parse_stmt(false)?
1159            });
1160
1161            for err in errors {
1162                p.emit_error(err);
1163            }
1164
1165            {
1166                let pos = p.state.labels.iter().position(|v| v == &l.sym);
1167                if let Some(pos) = pos {
1168                    p.state.labels.remove(pos);
1169                }
1170            }
1171
1172            Ok(LabeledStmt {
1173                span: span!(p, start),
1174                label: l,
1175                body,
1176            }
1177            .into())
1178        })
1179    }
1180
1181    fn parse_for_stmt(&mut self) -> PResult<Stmt> {
1182        let start = cur_pos!(self);
1183
1184        assert_and_bump!(self, "for");
1185        let await_start = cur_pos!(self);
1186        let await_token = if eat!(self, "await") {
1187            Some(span!(self, await_start))
1188        } else {
1189            None
1190        };
1191        expect!(self, '(');
1192
1193        let mut ctx = self.ctx();
1194        ctx.expr_ctx.for_loop_init = true;
1195        ctx.expr_ctx.for_await_loop_init = await_token.is_some();
1196
1197        let head = self.with_ctx(ctx).parse_for_head()?;
1198        expect!(self, ')');
1199        let ctx = Context {
1200            is_break_allowed: true,
1201            is_continue_allowed: true,
1202            ..self.ctx()
1203        };
1204        let body = self.with_ctx(ctx).parse_stmt(false).map(Box::new)?;
1205
1206        let span = span!(self, start);
1207        Ok(match head {
1208            TempForHead::For { init, test, update } => {
1209                if let Some(await_token) = await_token {
1210                    syntax_error!(self, await_token, SyntaxError::AwaitForStmt);
1211                }
1212
1213                ForStmt {
1214                    span,
1215                    init,
1216                    test,
1217                    update,
1218                    body,
1219                }
1220                .into()
1221            }
1222            TempForHead::ForIn { left, right } => {
1223                if let Some(await_token) = await_token {
1224                    syntax_error!(self, await_token, SyntaxError::AwaitForStmt);
1225                }
1226
1227                ForInStmt {
1228                    span,
1229                    left,
1230                    right,
1231                    body,
1232                }
1233                .into()
1234            }
1235            TempForHead::ForOf { left, right } => ForOfStmt {
1236                span,
1237                is_await: await_token.is_some(),
1238                left,
1239                right,
1240                body,
1241            }
1242            .into(),
1243        })
1244    }
1245
1246    fn parse_for_head(&mut self) -> PResult<TempForHead> {
1247        let strict = self.ctx().strict;
1248
1249        if is_one_of!(self, "const", "var")
1250            || (is!(self, "let")
1251                && peek!(self).map_or(false, |v| v.kind().follows_keyword_let(strict)))
1252        {
1253            let decl = self.parse_var_stmt(true)?;
1254
1255            if is_one_of!(self, "of", "in") {
1256                if decl.decls.len() != 1 {
1257                    for d in decl.decls.iter().skip(1) {
1258                        self.emit_err(d.name.span(), SyntaxError::TooManyVarInForInHead);
1259                    }
1260                } else {
1261                    if (self.ctx().strict || is!(self, "of")) && decl.decls[0].init.is_some() {
1262                        self.emit_err(
1263                            decl.decls[0].name.span(),
1264                            SyntaxError::VarInitializerInForInHead,
1265                        );
1266                    }
1267
1268                    if self.syntax().typescript() {
1269                        let type_ann = match decl.decls[0].name {
1270                            Pat::Ident(ref v) => Some(&v.type_ann),
1271                            Pat::Array(ref v) => Some(&v.type_ann),
1272                            Pat::Rest(ref v) => Some(&v.type_ann),
1273                            Pat::Object(ref v) => Some(&v.type_ann),
1274                            _ => None,
1275                        };
1276
1277                        if let Some(type_ann) = type_ann {
1278                            if type_ann.is_some() {
1279                                self.emit_err(decl.decls[0].name.span(), SyntaxError::TS2483);
1280                            }
1281                        }
1282                    }
1283                }
1284
1285                return self.parse_for_each_head(ForHead::VarDecl(decl));
1286            }
1287
1288            expect_exact!(self, ';');
1289            return self.parse_normal_for_head(Some(VarDeclOrExpr::VarDecl(decl)));
1290        }
1291
1292        if eat_exact!(self, ';') {
1293            return self.parse_normal_for_head(None);
1294        }
1295
1296        let start = cur_pos!(self);
1297        let init = self.include_in_expr(false).parse_for_head_prefix()?;
1298
1299        let mut is_using_decl = false;
1300        let mut is_await_using_decl = false;
1301
1302        if self.input.syntax().explicit_resource_management() {
1303            // using foo
1304            let mut maybe_using_decl = init.is_ident_ref_to("using");
1305            let mut maybe_await_using_decl = false;
1306
1307            // await using foo
1308            if !maybe_using_decl
1309                && init
1310                    .as_await_expr()
1311                    .filter(|e| e.arg.is_ident_ref_to("using"))
1312                    .is_some()
1313            {
1314                maybe_using_decl = true;
1315                maybe_await_using_decl = true;
1316            }
1317
1318            if maybe_using_decl
1319                && !is!(self, "of")
1320                && (peeked_is!(self, "of") || peeked_is!(self, "in"))
1321            {
1322                is_using_decl = maybe_using_decl;
1323                is_await_using_decl = maybe_await_using_decl;
1324            }
1325        }
1326
1327        if is_using_decl {
1328            let name = self.parse_binding_ident(false)?;
1329            let decl = VarDeclarator {
1330                name: name.into(),
1331                span: span!(self, start),
1332                init: None,
1333                definite: false,
1334            };
1335
1336            let pat = Box::new(UsingDecl {
1337                span: span!(self, start),
1338                is_await: is_await_using_decl,
1339                decls: vec![decl],
1340            });
1341
1342            cur!(self, true);
1343
1344            return self.parse_for_each_head(ForHead::UsingDecl(pat));
1345        }
1346
1347        // for (a of b)
1348        if is_one_of!(self, "of", "in") {
1349            let is_in = is!(self, "in");
1350
1351            let pat = self.reparse_expr_as_pat(PatType::AssignPat, init)?;
1352
1353            // for ({} in foo) is invalid
1354            if self.input.syntax().typescript() && is_in {
1355                match pat {
1356                    Pat::Ident(..) => {}
1357                    Pat::Expr(..) => {}
1358                    ref v => self.emit_err(v.span(), SyntaxError::TS2491),
1359                }
1360            }
1361
1362            return self.parse_for_each_head(ForHead::Pat(Box::new(pat)));
1363        }
1364
1365        expect_exact!(self, ';');
1366
1367        let init = self.verify_expr(init)?;
1368        self.parse_normal_for_head(Some(VarDeclOrExpr::Expr(init)))
1369    }
1370
1371    fn parse_for_each_head(&mut self, left: ForHead) -> PResult<TempForHead> {
1372        let is_of = bump!(self) == tok!("of");
1373        if is_of {
1374            let right = self.include_in_expr(true).parse_assignment_expr()?;
1375            Ok(TempForHead::ForOf { left, right })
1376        } else {
1377            if let ForHead::UsingDecl(d) = &left {
1378                self.emit_err(d.span, SyntaxError::UsingDeclNotAllowedForForInLoop)
1379            }
1380
1381            let right = self.include_in_expr(true).parse_expr()?;
1382            Ok(TempForHead::ForIn { left, right })
1383        }
1384    }
1385
1386    fn parse_normal_for_head(&mut self, init: Option<VarDeclOrExpr>) -> PResult<TempForHead> {
1387        let test = if eat_exact!(self, ';') {
1388            None
1389        } else {
1390            let test = self.include_in_expr(true).parse_expr().map(Some)?;
1391            expect_exact!(self, ';');
1392            test
1393        };
1394
1395        let update = if is!(self, ')') {
1396            None
1397        } else {
1398            self.include_in_expr(true).parse_expr().map(Some)?
1399        };
1400
1401        Ok(TempForHead::For { init, test, update })
1402    }
1403}
1404
1405#[allow(clippy::enum_variant_names)]
1406enum TempForHead {
1407    For {
1408        init: Option<VarDeclOrExpr>,
1409        test: Option<Box<Expr>>,
1410        update: Option<Box<Expr>>,
1411    },
1412    ForIn {
1413        left: ForHead,
1414        right: Box<Expr>,
1415    },
1416    ForOf {
1417        left: ForHead,
1418        right: Box<Expr>,
1419    },
1420}
1421
1422pub(super) trait IsDirective {
1423    fn as_ref(&self) -> Option<&Stmt>;
1424    fn is_use_strict(&self) -> bool {
1425        self.as_ref().map_or(false, Stmt::is_use_strict)
1426    }
1427}
1428
1429impl<T> IsDirective for Box<T>
1430where
1431    T: IsDirective,
1432{
1433    fn as_ref(&self) -> Option<&Stmt> {
1434        T::as_ref(&**self)
1435    }
1436}
1437
1438impl IsDirective for Stmt {
1439    fn as_ref(&self) -> Option<&Stmt> {
1440        Some(self)
1441    }
1442}
1443
1444pub(super) trait StmtLikeParser<'a, Type: IsDirective> {
1445    fn handle_import_export(
1446        &mut self,
1447        top_level: bool,
1448        decorators: Vec<Decorator>,
1449    ) -> PResult<Type>;
1450}
1451
1452impl<'a, I: Tokens, T> StmtLikeParser<'a, Box<T>> for Parser<I>
1453where
1454    T: IsDirective,
1455    Self: StmtLikeParser<'a, T>,
1456{
1457    fn handle_import_export(
1458        &mut self,
1459        top_level: bool,
1460        decorators: Vec<Decorator>,
1461    ) -> PResult<Box<T>> {
1462        <Self as StmtLikeParser<T>>::handle_import_export(self, top_level, decorators).map(Box::new)
1463    }
1464}
1465
1466impl<I: Tokens> StmtLikeParser<'_, Stmt> for Parser<I> {
1467    fn handle_import_export(&mut self, _: bool, _: Vec<Decorator>) -> PResult<Stmt> {
1468        let start = cur_pos!(self);
1469        if is!(self, "import") && peeked_is!(self, '(') {
1470            let expr = self.parse_expr()?;
1471
1472            eat!(self, ';');
1473
1474            return Ok(ExprStmt {
1475                span: span!(self, start),
1476                expr,
1477            }
1478            .into());
1479        }
1480
1481        if is!(self, "import") && peeked_is!(self, '.') {
1482            let expr = self.parse_expr()?;
1483
1484            eat!(self, ';');
1485
1486            return Ok(ExprStmt {
1487                span: span!(self, start),
1488                expr,
1489            }
1490            .into());
1491        }
1492
1493        syntax_error!(self, SyntaxError::ImportExportInScript);
1494    }
1495}
1496
1497#[cfg(test)]
1498mod tests {
1499    use swc_common::{comments::SingleThreadedComments, DUMMY_SP as span};
1500    use swc_ecma_visit::assert_eq_ignore_span;
1501
1502    use super::*;
1503    use crate::EsSyntax;
1504
1505    fn stmt(s: &'static str) -> Stmt {
1506        test_parser(s, Syntax::default(), |p| p.parse_stmt(true))
1507    }
1508
1509    fn module_item(s: &'static str) -> ModuleItem {
1510        test_parser(s, Syntax::default(), |p| p.parse_stmt_like(true, true))
1511    }
1512    fn expr(s: &'static str) -> Box<Expr> {
1513        test_parser(s, Syntax::default(), |p| p.parse_expr())
1514    }
1515
1516    #[test]
1517    fn expr_stmt() {
1518        assert_eq_ignore_span!(
1519            stmt("a + b + c"),
1520            Stmt::Expr(ExprStmt {
1521                span,
1522                expr: expr("a + b + c")
1523            })
1524        )
1525    }
1526
1527    #[test]
1528    fn catch_rest_pat() {
1529        assert_eq_ignore_span!(
1530            stmt("try {} catch({ ...a34 }) {}"),
1531            Stmt::Try(Box::new(TryStmt {
1532                span,
1533                block: BlockStmt {
1534                    span,
1535                    ..Default::default()
1536                },
1537                handler: Some(CatchClause {
1538                    span,
1539                    param: Pat::Object(ObjectPat {
1540                        span,
1541                        optional: false,
1542                        props: vec![ObjectPatProp::Rest(RestPat {
1543                            span,
1544                            dot3_token: span,
1545                            arg: Box::new(Pat::Ident(
1546                                Ident::new_no_ctxt("a34".into(), span).into()
1547                            )),
1548                            type_ann: None
1549                        })],
1550                        type_ann: None,
1551                    })
1552                    .into(),
1553                    body: BlockStmt {
1554                        span,
1555                        ..Default::default()
1556                    }
1557                }),
1558                finalizer: None
1559            }))
1560        );
1561    }
1562
1563    #[test]
1564    fn throw_this() {
1565        assert_eq_ignore_span!(
1566            stmt("throw this"),
1567            Stmt::Throw(ThrowStmt {
1568                span,
1569                arg: expr("this"),
1570            })
1571        )
1572    }
1573
1574    #[test]
1575    fn await_for_of() {
1576        assert_eq_ignore_span!(
1577            stmt("for await (const a of b) ;"),
1578            Stmt::ForOf(ForOfStmt {
1579                span,
1580                is_await: true,
1581                left: ForHead::VarDecl(Box::new(VarDecl {
1582                    span,
1583                    kind: VarDeclKind::Const,
1584                    decls: vec![VarDeclarator {
1585                        span,
1586                        init: None,
1587                        name: Pat::Ident(Ident::new_no_ctxt("a".into(), span).into()),
1588                        definite: false,
1589                    }],
1590                    ..Default::default()
1591                })),
1592                right: Box::new(Expr::Ident(Ident::new_no_ctxt("b".into(), span))),
1593
1594                body: Box::new(Stmt::Empty(EmptyStmt { span })),
1595            })
1596        )
1597    }
1598
1599    #[test]
1600    fn no_empty_without_semi() {
1601        assert_eq_ignore_span!(
1602            stmt("(function foo() { return 1 })"),
1603            stmt(
1604                "(function foo () {
1605                return 1
1606            })"
1607            )
1608        );
1609
1610        assert_eq_ignore_span!(
1611            stmt("{ 1; }"),
1612            Stmt::Block(BlockStmt {
1613                span,
1614                stmts: vec![stmt("1")],
1615                ..Default::default()
1616            })
1617        );
1618    }
1619
1620    #[test]
1621    fn if_else() {
1622        assert_eq_ignore_span!(
1623            stmt("if (a) b; else c"),
1624            Stmt::If(IfStmt {
1625                span,
1626                test: expr("a"),
1627                cons: Box::new(stmt("b;")),
1628                alt: Some(Box::new(stmt("c"))),
1629            })
1630        );
1631    }
1632
1633    #[test]
1634    fn class_decorator() {
1635        assert_eq_ignore_span!(
1636            test_parser(
1637                "
1638            @decorator
1639            @dec2
1640            class Foo {}
1641            ",
1642                Syntax::Es(EsSyntax {
1643                    decorators: true,
1644                    ..Default::default()
1645                }),
1646                |p| p.parse_stmt_list_item(true),
1647            ),
1648            Stmt::Decl(Decl::Class(ClassDecl {
1649                ident: Ident::new_no_ctxt("Foo".into(), span),
1650                class: Box::new(Class {
1651                    span,
1652                    decorators: vec![
1653                        Decorator {
1654                            span,
1655                            expr: expr("decorator")
1656                        },
1657                        Decorator {
1658                            span,
1659                            expr: expr("dec2")
1660                        }
1661                    ],
1662                    super_class: None,
1663                    body: Vec::new(),
1664                    is_abstract: false,
1665                    ..Default::default()
1666                }),
1667                declare: false,
1668            }))
1669        );
1670    }
1671
1672    #[test]
1673    fn example() {
1674        let src = r#"
1675import React from 'react'
1676import ReactDOM from 'react-dom'
1677
1678function App() {
1679  return <h1>JSX is working!</h1>
1680}
1681
1682ReactDOM.render(<App />, document.getElementById('root'))
1683
1684"#;
1685        test_parser(
1686            src,
1687            Syntax::Es(EsSyntax {
1688                jsx: true,
1689                ..Default::default()
1690            }),
1691            |p| p.parse_module(),
1692        );
1693    }
1694
1695    #[test]
1696    fn ice() {
1697        let src = r#"import React from "react"
1698
1699function App() {
1700  return <h1>works</h1>
1701}
1702
1703export default App"#;
1704        test_parser(
1705            src,
1706            Syntax::Es(EsSyntax {
1707                jsx: true,
1708                ..Default::default()
1709            }),
1710            |p| p.parse_module(),
1711        );
1712    }
1713
1714    #[test]
1715    fn export_default() {
1716        let src = "export v, { x, y as w } from 'mod';";
1717        test_parser(
1718            src,
1719            Syntax::Es(EsSyntax {
1720                export_default_from: true,
1721                ..Default::default()
1722            }),
1723            |p| p.parse_module(),
1724        );
1725    }
1726
1727    #[test]
1728    fn export_default_2() {
1729        let src = "export foo from 'bar';";
1730        test_parser(
1731            src,
1732            Syntax::Es(EsSyntax {
1733                export_default_from: true,
1734                ..Default::default()
1735            }),
1736            |p| p.parse_module(),
1737        );
1738    }
1739
1740    #[test]
1741    fn export_default_3() {
1742        let src = "export default from 'bar';";
1743        test_parser(
1744            src,
1745            Syntax::Es(EsSyntax {
1746                export_default_from: true,
1747                ..Default::default()
1748            }),
1749            |p| p.parse_module(),
1750        );
1751    }
1752
1753    #[test]
1754    fn export_default_4() {
1755        let src = "export default, {foo} from 'bar';";
1756        test_parser(
1757            src,
1758            Syntax::Es(EsSyntax {
1759                export_default_from: true,
1760                ..Default::default()
1761            }),
1762            |p| p.parse_module(),
1763        );
1764    }
1765
1766    #[test]
1767    fn shebang_01() {
1768        let src = "#!/usr/bin/env node";
1769        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_module());
1770    }
1771
1772    #[test]
1773    fn shebang_02() {
1774        let src = "#!/usr/bin/env node
1775let x = 4";
1776        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_module());
1777    }
1778
1779    #[test]
1780    fn empty() {
1781        test_parser("", Syntax::Es(Default::default()), |p| p.parse_module());
1782    }
1783
1784    #[test]
1785    fn issue_226() {
1786        test_parser(
1787            "export * as Foo from 'bar';",
1788            Syntax::Es(EsSyntax {
1789                export_default_from: true,
1790                ..Default::default()
1791            }),
1792            |p| p.parse_module(),
1793        );
1794    }
1795
1796    #[test]
1797    #[should_panic(expected = "Expected 'from', got ','")]
1798    fn issue_4369_1() {
1799        test_parser(
1800            r#"export * as foo, { bar } from "mod""#,
1801            Syntax::Es(EsSyntax {
1802                export_default_from: false,
1803                ..Default::default()
1804            }),
1805            |p| p.parse_module(),
1806        );
1807    }
1808
1809    #[test]
1810    fn issue_4369_2() {
1811        test_parser(
1812            r#"export foo, * as bar, { baz } from "mod""#,
1813            Syntax::Es(EsSyntax {
1814                export_default_from: true,
1815                ..Default::default()
1816            }),
1817            |p| p.parse_module(),
1818        );
1819    }
1820
1821    #[test]
1822    fn issue_4369_3() {
1823        test_parser(
1824            r#"export foo, * as bar from "mod""#,
1825            Syntax::Es(EsSyntax {
1826                export_default_from: true,
1827                ..Default::default()
1828            }),
1829            |p| p.parse_module(),
1830        );
1831    }
1832
1833    #[test]
1834    fn issue_4369_4() {
1835        test_parser(
1836            r#"export * as bar, { baz } from "mod""#,
1837            Syntax::Es(EsSyntax {
1838                export_default_from: true,
1839                ..Default::default()
1840            }),
1841            |p| p.parse_module(),
1842        );
1843    }
1844
1845    #[test]
1846    fn issue_4369_5() {
1847        test_parser(
1848            r#"export foo, { baz } from "mod""#,
1849            Syntax::Es(EsSyntax {
1850                export_default_from: true,
1851                ..Default::default()
1852            }),
1853            |p| p.parse_module(),
1854        );
1855    }
1856
1857    #[test]
1858    fn issue_257_var() {
1859        test_parser(
1860            "
1861export default function waitUntil(callback, options = {}) {
1862  var timeout = 'timeout' in options ? options.timeout : 1000;
1863}",
1864            Default::default(),
1865            |p| p.parse_module(),
1866        );
1867    }
1868
1869    #[test]
1870    fn issue_257_let() {
1871        test_parser(
1872            "
1873export default function waitUntil(callback, options = {}) {
1874  let timeout = 'timeout' in options ? options.timeout : 1000;
1875}",
1876            Default::default(),
1877            |p| p.parse_module(),
1878        );
1879    }
1880
1881    #[test]
1882    fn issue_269() {
1883        test_parser(
1884            ";(function() {})(window, window.lib || (window.lib = {}))",
1885            Default::default(),
1886            |p| p.parse_module(),
1887        );
1888    }
1889
1890    #[test]
1891    fn issue_319_2() {
1892        module_item(
1893            "export default obj({
1894    async f() {
1895        await g();
1896    }
1897});",
1898        );
1899    }
1900
1901    #[test]
1902    fn issue_340_fn() {
1903        test_parser("export default function(){};", Default::default(), |p| {
1904            p.parse_module()
1905        });
1906    }
1907
1908    #[test]
1909    fn issue_340_async_fn() {
1910        test_parser(
1911            "export default async function(){};",
1912            Default::default(),
1913            |p| p.parse_module(),
1914        );
1915    }
1916
1917    #[test]
1918    fn issue_340_generator_fn() {
1919        test_parser("export default function*(){};", Default::default(), |p| {
1920            p.parse_module()
1921        });
1922    }
1923
1924    #[test]
1925    fn issue_340_class() {
1926        test_parser("export default class {};", Default::default(), |p| {
1927            p.parse_module()
1928        });
1929    }
1930
1931    #[test]
1932    fn issue_360() {
1933        test_parser(
1934            "var IS_IE11 = !global.ActiveXObject && 'ActiveXObject' in global;",
1935            Default::default(),
1936            |p| p.parse_module(),
1937        );
1938    }
1939
1940    #[test]
1941    fn issue_380_1() {
1942        test_parser(
1943            "import(filePath).then(bar => {})",
1944            Syntax::Es(Default::default()),
1945            |p| p.parse_module(),
1946        );
1947    }
1948
1949    #[test]
1950    fn issue_380_2() {
1951        test_parser(
1952            "class Foo {
1953                componentDidMount() {
1954                    const filePath = '../foo/bar'
1955                    import(filePath).then(bar => {})
1956                }
1957            }",
1958            Syntax::Es(Default::default()),
1959            |p| p.parse_module(),
1960        );
1961    }
1962
1963    #[test]
1964    fn issue_411() {
1965        test_parser(
1966            "try {
1967} catch {}",
1968            Syntax::Es(Default::default()),
1969            |p| p.parse_module(),
1970        );
1971    }
1972
1973    #[test]
1974    fn top_level_await() {
1975        test_parser("await foo", Syntax::Es(Default::default()), |p| {
1976            p.parse_module()
1977        });
1978    }
1979
1980    #[test]
1981    fn issue_856() {
1982        let c = SingleThreadedComments::default();
1983        let s = "class Foo {
1984    static _extensions: {
1985        // eslint-disable-next-line @typescript-eslint/no-explicit-any
1986        [key: string]: (module: Module, filename: string) => any;
1987    } = Object.create(null);
1988}
1989";
1990        let _ = test_parser_comment(&c, s, Syntax::Typescript(Default::default()), |p| {
1991            p.parse_typescript_module()
1992        });
1993
1994        let (leading, trailing) = c.take_all();
1995        assert!(trailing.borrow().is_empty());
1996        assert_eq!(leading.borrow().len(), 1);
1997    }
1998
1999    #[test]
2000    fn issue_856_2() {
2001        let c = SingleThreadedComments::default();
2002        let s = "type ConsoleExamineFunc = (
2003  // eslint-disable-next-line @typescript-eslint/no-explicit-any
2004  csl: any,
2005  out: StringBuffer,
2006  err?: StringBuffer,
2007  both?: StringBuffer
2008) => void;";
2009
2010        let _ = test_parser_comment(&c, s, Syntax::Typescript(Default::default()), |p| {
2011            p.parse_typescript_module()
2012        });
2013
2014        let (leading, trailing) = c.take_all();
2015        assert!(trailing.borrow().is_empty());
2016        assert_eq!(leading.borrow().len(), 1);
2017    }
2018
2019    #[test]
2020    fn issue_856_3() {
2021        let c = SingleThreadedComments::default();
2022        let s = "type RequireWrapper = (
2023  // eslint-disable-next-line @typescript-eslint/no-explicit-any
2024  exports: any,
2025  // eslint-disable-next-line @typescript-eslint/no-explicit-any
2026  require: any,
2027  module: Module,
2028  __filename: string,
2029  __dirname: string
2030) => void;";
2031
2032        let _ = test_parser_comment(&c, s, Syntax::Typescript(Default::default()), |p| {
2033            p.parse_typescript_module()
2034        });
2035
2036        let (leading, trailing) = c.take_all();
2037        assert!(trailing.borrow().is_empty());
2038        assert_eq!(leading.borrow().len(), 2);
2039    }
2040
2041    #[test]
2042    fn issue_856_4() {
2043        let c = SingleThreadedComments::default();
2044        let s = "const _extensions: {
2045    // eslint-disable-next-line @typescript-eslint/no-explicit-any
2046    [key: string]: (module: Module, filename: string) => any;
2047  } = Object.create(null);";
2048
2049        let _ = test_parser_comment(&c, s, Syntax::Typescript(Default::default()), |p| {
2050            p.parse_typescript_module()
2051        });
2052
2053        let (leading, trailing) = c.take_all();
2054        assert!(trailing.borrow().is_empty());
2055        assert_eq!(leading.borrow().len(), 1);
2056    }
2057    fn parse_for_head(str: &'static str) -> TempForHead {
2058        test_parser(str, Syntax::default(), |p| p.parse_for_head())
2059    }
2060
2061    #[test]
2062    fn for_array_binding_pattern() {
2063        match parse_for_head("let [, , t] = simple_array; t < 10; t++") {
2064            TempForHead::For { init: Some(v), .. } => assert_eq_ignore_span!(
2065                v,
2066                VarDeclOrExpr::VarDecl(Box::new(VarDecl {
2067                    span,
2068                    declare: false,
2069                    kind: VarDeclKind::Let,
2070                    decls: vec![VarDeclarator {
2071                        span,
2072                        name: Pat::Array(ArrayPat {
2073                            span,
2074                            type_ann: None,
2075                            optional: false,
2076                            elems: vec![
2077                                None,
2078                                None,
2079                                Some(Pat::Ident(Ident::new_no_ctxt("t".into(), span).into()))
2080                            ]
2081                        }),
2082                        init: Some(Box::new(Expr::Ident(Ident::new_no_ctxt(
2083                            "simple_array".into(),
2084                            span
2085                        )))),
2086                        definite: false
2087                    }],
2088                    ..Default::default()
2089                }))
2090            ),
2091            _ => unreachable!(),
2092        }
2093    }
2094    #[test]
2095    fn for_object_binding_pattern() {
2096        match parse_for_head("let {num} = obj; num < 11; num++") {
2097            TempForHead::For { init: Some(v), .. } => assert_eq_ignore_span!(
2098                v,
2099                VarDeclOrExpr::VarDecl(Box::new(VarDecl {
2100                    span,
2101                    kind: VarDeclKind::Let,
2102                    decls: vec![VarDeclarator {
2103                        span,
2104                        name: Pat::Object(ObjectPat {
2105                            optional: false,
2106                            type_ann: None,
2107                            span,
2108                            props: vec![ObjectPatProp::Assign(AssignPatProp {
2109                                span,
2110                                key: Ident::new_no_ctxt("num".into(), span).into(),
2111                                value: None
2112                            })]
2113                        }),
2114                        init: Some(Box::new(Expr::Ident(Ident::new_no_ctxt(
2115                            "obj".into(),
2116                            span
2117                        )))),
2118                        definite: false
2119                    }],
2120                    ..Default::default()
2121                }))
2122            ),
2123            _ => unreachable!(),
2124        }
2125    }
2126
2127    #[test]
2128    #[should_panic(expected = "'import.meta' cannot be used outside of module code.")]
2129    fn import_meta_in_script() {
2130        let src = "const foo = import.meta.url;";
2131        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_script());
2132    }
2133
2134    #[test]
2135    fn import_meta_in_program() {
2136        let src = "const foo = import.meta.url;";
2137        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_program());
2138    }
2139
2140    #[test]
2141    #[should_panic(expected = "'import', and 'export' cannot be used outside of module code")]
2142    fn import_statement_in_script() {
2143        let src = "import 'foo';";
2144        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_script());
2145    }
2146
2147    #[test]
2148    #[should_panic(expected = "top level await is only allowed in module")]
2149    fn top_level_await_in_script() {
2150        let src = "await promise";
2151        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_script());
2152    }
2153
2154    #[test]
2155    fn top_level_await_in_program() {
2156        let src = "await promise";
2157        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_program());
2158    }
2159
2160    #[test]
2161    fn for_of_head_lhs_async_dot() {
2162        let src = "for (async.x of [1]) ;";
2163        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_module());
2164    }
2165
2166    #[test]
2167    fn for_head_init_async_of() {
2168        let src = "for (async of => {}; i < 10; ++i) { ++counter; }";
2169        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_module());
2170    }
2171
2172    #[test]
2173    #[should_panic(expected = "await isn't allowed in non-async function")]
2174    fn await_in_function_in_module() {
2175        let src = "function foo (p) { await p; }";
2176        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_module());
2177    }
2178
2179    #[test]
2180    #[should_panic(expected = "await isn't allowed in non-async function")]
2181    fn await_in_function_in_script() {
2182        let src = "function foo (p) { await p; }";
2183        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_script());
2184    }
2185
2186    #[test]
2187    #[should_panic(expected = "await isn't allowed in non-async function")]
2188    fn await_in_function_in_program() {
2189        let src = "function foo (p) { await p; }";
2190        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_program());
2191    }
2192
2193    #[test]
2194    #[should_panic(expected = "`await` cannot be used as an identifier in an async context")]
2195    fn await_in_nested_async_function_in_module() {
2196        let src = "async function foo () { function bar(x = await) {} }";
2197        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_module());
2198    }
2199
2200    #[test]
2201    fn await_in_nested_async_function_in_script() {
2202        let src = "async function foo () { function bar(x = await) {} }";
2203        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_script());
2204    }
2205
2206    #[test]
2207    fn await_in_nested_async_function_in_program() {
2208        let src = "async function foo () { function bar(x = await) {} }";
2209        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_program());
2210    }
2211
2212    #[test]
2213    #[should_panic(expected = "`await` cannot be used as an identifier in an async context")]
2214    fn await_as_param_ident_in_module() {
2215        let src = "function foo (x = await) { }";
2216        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_module());
2217    }
2218
2219    #[test]
2220    fn await_as_param_ident_in_script() {
2221        let src = "function foo (x = await) { }";
2222        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_script());
2223    }
2224
2225    #[test]
2226    #[should_panic(expected = "`await` cannot be used as an identifier in an async context")]
2227    fn await_as_ident_in_module() {
2228        let src = "let await = 1";
2229        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_module());
2230    }
2231
2232    #[test]
2233    fn await_as_ident_in_script() {
2234        let src = "let await = 1";
2235        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_script());
2236    }
2237
2238    #[test]
2239    #[should_panic(expected = "`await` cannot be used as an identifier in an async context")]
2240    fn await_as_ident_in_async() {
2241        let src = "async function foo() { let await = 1; }";
2242        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_script());
2243    }
2244
2245    #[test]
2246    fn top_level_await_in_block() {
2247        let src = "if (true) { await promise; }";
2248        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_module());
2249    }
2250
2251    #[test]
2252    fn class_static_blocks() {
2253        let src = "class Foo { static { 1 + 1; } }";
2254        assert_eq_ignore_span!(
2255            test_parser(src, Syntax::Es(Default::default()), |p| p.parse_expr()),
2256            Box::new(Expr::Class(ClassExpr {
2257                ident: Some(Ident {
2258                    span,
2259                    sym: "Foo".into(),
2260                    ..Default::default()
2261                }),
2262                class: Box::new(Class {
2263                    span,
2264                    decorators: Vec::new(),
2265                    super_class: None,
2266                    type_params: None,
2267                    super_type_params: None,
2268                    is_abstract: false,
2269                    implements: Vec::new(),
2270                    body: vec!(ClassMember::StaticBlock(StaticBlock {
2271                        span,
2272                        body: BlockStmt {
2273                            span,
2274                            stmts: vec!(stmt("1 + 1;")),
2275                            ..Default::default()
2276                        }
2277                    })),
2278                    ..Default::default()
2279                })
2280            }))
2281        );
2282    }
2283
2284    #[test]
2285    fn multiple_class_static_blocks() {
2286        let src = "class Foo { static { 1 + 1; } static { 1 + 1; } }";
2287        assert_eq_ignore_span!(
2288            test_parser(src, Syntax::Es(Default::default()), |p| p.parse_expr()),
2289            Box::new(Expr::Class(ClassExpr {
2290                ident: Some(Ident {
2291                    span,
2292                    sym: "Foo".into(),
2293                    ..Default::default()
2294                }),
2295                class: Box::new(Class {
2296                    span,
2297                    decorators: Vec::new(),
2298                    super_class: None,
2299                    is_abstract: false,
2300                    body: vec!(
2301                        ClassMember::StaticBlock(StaticBlock {
2302                            span,
2303                            body: BlockStmt {
2304                                span,
2305                                stmts: vec!(stmt("1 + 1;")),
2306                                ..Default::default()
2307                            },
2308                        }),
2309                        ClassMember::StaticBlock(StaticBlock {
2310                            span,
2311                            body: BlockStmt {
2312                                span,
2313                                stmts: vec!(stmt("1 + 1;")),
2314                                ..Default::default()
2315                            },
2316                        })
2317                    ),
2318                    ..Default::default()
2319                })
2320            }))
2321        );
2322    }
2323
2324    #[test]
2325    fn class_static_blocks_with_line_breaks_01() {
2326        let src = "class Foo {
2327            static
2328            {
2329                1 + 1;
2330            }
2331        }";
2332        assert_eq_ignore_span!(
2333            test_parser(src, Syntax::Es(Default::default()), |p| p.parse_expr()),
2334            Box::new(Expr::Class(ClassExpr {
2335                ident: Some(Ident {
2336                    span,
2337                    sym: "Foo".into(),
2338                    ..Default::default()
2339                }),
2340                class: Box::new(Class {
2341                    span,
2342                    is_abstract: false,
2343                    body: vec!(ClassMember::StaticBlock(StaticBlock {
2344                        span,
2345                        body: BlockStmt {
2346                            span,
2347                            stmts: vec!(stmt("1 + 1;")),
2348                            ..Default::default()
2349                        }
2350                    })),
2351                    ..Default::default()
2352                })
2353            }))
2354        );
2355    }
2356
2357    #[test]
2358    fn class_static_blocks_with_line_breaks_02() {
2359        let src = "class Foo {
2360            static
2361            {}
2362        }";
2363        assert_eq_ignore_span!(
2364            test_parser(src, Syntax::Es(Default::default()), |p| p.parse_expr()),
2365            Box::new(Expr::Class(ClassExpr {
2366                ident: Some(Ident {
2367                    span,
2368                    sym: "Foo".into(),
2369                    ..Default::default()
2370                }),
2371                class: Box::new(Class {
2372                    span,
2373                    is_abstract: false,
2374                    body: vec!(ClassMember::StaticBlock(StaticBlock {
2375                        span,
2376                        body: BlockStmt {
2377                            span,
2378                            stmts: Vec::new(),
2379                            ..Default::default()
2380                        }
2381                    })),
2382                    ..Default::default()
2383                })
2384            }))
2385        );
2386    }
2387
2388    #[test]
2389    fn class_static_blocks_in_ts() {
2390        let src = "class Foo { static { 1 + 1 }; }";
2391        test_parser(src, Syntax::Typescript(Default::default()), |p| {
2392            p.parse_expr()
2393        });
2394    }
2395
2396    #[test]
2397    fn class_static_blocks_with_line_breaks_in_ts_01() {
2398        let src = "class Foo {
2399            static
2400            {
2401                1 + 1;
2402            }
2403        }";
2404        test_parser(src, Syntax::Typescript(Default::default()), |p| {
2405            p.parse_expr()
2406        });
2407    }
2408
2409    #[test]
2410    fn class_static_blocks_with_line_breaks_in_ts_02() {
2411        let src = "class Foo {
2412            static
2413            {}
2414        }";
2415        test_parser(src, Syntax::Typescript(Default::default()), |p| {
2416            p.parse_expr()
2417        });
2418    }
2419
2420    #[test]
2421    #[should_panic(expected = "Expected ident")]
2422    fn class_static_blocks_with_await() {
2423        let src = "class Foo{
2424            static {
2425                var await = 'bar';
2426            }
2427        }";
2428        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_expr());
2429    }
2430
2431    #[test]
2432    #[should_panic(expected = "Expected ident")]
2433    fn class_static_blocks_with_await_in_nested_class() {
2434        let src = "class Foo{
2435            static {
2436                function foo() {
2437                    class Foo {
2438                        static {
2439                            var await = 'bar';
2440                        }
2441                    }
2442                }
2443            }
2444        }";
2445        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_expr());
2446    }
2447
2448    #[test]
2449    fn class_static_blocks_with_await_in_fn() {
2450        let src = "class Foo{
2451            static {
2452                function foo() {
2453                    var await = 'bar';
2454                }
2455            }
2456        }";
2457        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_expr());
2458    }
2459
2460    #[test]
2461    #[should_panic(expected = "Modifiers cannot appear here")]
2462    fn class_static_blocks_in_ts_with_invalid_modifier_01() {
2463        let src = "class Foo { abstract static { 1 + 1 }; }";
2464        test_parser(src, Syntax::Typescript(Default::default()), |p| {
2465            p.parse_expr()
2466        });
2467    }
2468
2469    #[test]
2470    #[should_panic(expected = "Modifiers cannot appear here")]
2471    fn class_static_blocks_in_ts_with_invalid_modifier_02() {
2472        let src = "class Foo { static static { 1 + 1 }; }";
2473        test_parser(src, Syntax::Typescript(Default::default()), |p| {
2474            p.parse_expr()
2475        });
2476    }
2477
2478    #[test]
2479    #[should_panic(expected = "Modifiers cannot appear here")]
2480    fn class_static_blocks_in_ts_with_invalid_modifier_03() {
2481        let src = "class Foo { declare static { 1 + 1 }; }";
2482        test_parser(src, Syntax::Typescript(Default::default()), |p| {
2483            p.parse_expr()
2484        });
2485    }
2486
2487    #[test]
2488    #[should_panic(expected = "Modifiers cannot appear here")]
2489    fn class_static_blocks_in_ts_with_invalid_modifier_04() {
2490        let src = "class Foo { private static { 1 + 1 }; }";
2491        test_parser(src, Syntax::Typescript(Default::default()), |p| {
2492            p.parse_expr()
2493        });
2494    }
2495
2496    #[test]
2497    #[should_panic(expected = "Trailing comma is disallowed inside import(...) arguments")]
2498    fn error_for_trailing_comma_inside_dynamic_import() {
2499        let src = "import('foo',)";
2500        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_expr());
2501    }
2502
2503    #[test]
2504    fn no_error_for_trailing_comma_inside_dynamic_import_with_import_assertions() {
2505        let src = "import('foo',)";
2506        test_parser(
2507            src,
2508            Syntax::Es(EsSyntax {
2509                import_attributes: true,
2510                ..Default::default()
2511            }),
2512            |p| p.parse_expr(),
2513        );
2514    }
2515
2516    #[test]
2517    fn type_only_star_exports_with_name() {
2518        let src = "export type * as bar from 'mod'";
2519        test_parser(src, Syntax::Typescript(Default::default()), |p| {
2520            p.parse_module()
2521        });
2522    }
2523
2524    #[test]
2525    fn type_only_star_exports_without_name() {
2526        let src = "export type * from 'mod'";
2527        test_parser(src, Syntax::Typescript(Default::default()), |p| {
2528            p.parse_module()
2529        });
2530    }
2531
2532    #[test]
2533    #[should_panic(expected = "A string literal cannot be used as an imported binding.")]
2534    fn error_for_string_literal_is_import_binding() {
2535        let src = "import { \"str\" } from \"mod\"";
2536        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_module());
2537    }
2538
2539    #[test]
2540    #[should_panic(
2541        expected = "A string literal cannot be used as an exported binding without `from`."
2542    )]
2543    fn error_for_string_literal_is_export_binding() {
2544        let src = "export { 'foo' };";
2545        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_module());
2546    }
2547
2548    #[test]
2549    #[should_panic(expected = "'const' declarations must be initialized")]
2550    fn ts_error_for_const_declaration_not_initialized() {
2551        let src = r#"
2552"use strict";
2553const foo;"#;
2554
2555        test_parser(src, Syntax::Typescript(Default::default()), |p| {
2556            p.parse_script()
2557        });
2558    }
2559
2560    #[test]
2561    #[should_panic(expected = "'const' declarations must be initialized")]
2562    fn es_error_for_const_declaration_not_initialized() {
2563        let src = r#"
2564"use strict";
2565const foo;"#;
2566
2567        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_script());
2568    }
2569
2570    #[test]
2571    fn issue_5557_expr_follow_class() {
2572        let src = "foo * class {} / bar;";
2573
2574        test_parser(src, Default::default(), |p| p.parse_script());
2575    }
2576
2577    #[test]
2578    fn issue_5722_class_keyword_in_tpl() {
2579        let src = "console.log(`${toStr({class: fn})}`)";
2580
2581        test_parser(src, Default::default(), |p| p.parse_script());
2582    }
2583
2584    #[test]
2585    fn issue_6301_await_expr_stmt() {
2586        let src = "try { await; } catch { console.log('caught'); }";
2587
2588        test_parser(src, Default::default(), |p| p.parse_script());
2589    }
2590
2591    #[test]
2592    fn issue_6301_await_expr_stmt_1() {
2593        let src = "try { await, await; } catch { console.log('caught'); }";
2594
2595        test_parser(src, Default::default(), |p| p.parse_script());
2596    }
2597
2598    #[test]
2599    fn issue_6301_await_expr_stmt_2() {
2600        let src = "function test() { await; }";
2601
2602        test_parser(src, Default::default(), |p| p.parse_script());
2603    }
2604
2605    #[test]
2606    fn issue_6301_await_expr_stmt_3() {
2607        let src = "function test() { await, await; }";
2608
2609        test_parser(src, Default::default(), |p| p.parse_script());
2610    }
2611
2612    #[test]
2613    fn issue_6301_await_expr_stmt_4() {
2614        let src = "function test() { [await]; }";
2615
2616        test_parser(src, Default::default(), |p| p.parse_script());
2617    }
2618
2619    #[test]
2620    fn issue_6301_await_expr_stmt_5() {
2621        let src = "function test() { (await); }";
2622
2623        test_parser(src, Default::default(), |p| p.parse_script());
2624    }
2625
2626    #[test]
2627    fn issue_6322() {
2628        let src = "for ( ; { } / 1 ; ) ;";
2629
2630        test_parser(src, Default::default(), |p| p.parse_script());
2631    }
2632
2633    #[test]
2634    fn issue_6323() {
2635        let src = "let x = 0 < { } / 0 ;";
2636
2637        test_parser(src, Default::default(), |p| p.parse_script());
2638    }
2639}