swc_ecma_parser/parser/
stmt.rs

1use swc_ecma_lexer::common::parser::{
2    module_item::parse_module_item,
3    stmt::{parse_stmt, parse_stmt_list_item},
4};
5
6use super::*;
7use crate::parser::Parser;
8
9mod module_item;
10
11impl<I: Tokens> Parser<I> {
12    pub fn parse_module_item(&mut self) -> PResult<ModuleItem> {
13        parse_module_item(self)
14    }
15
16    /// Parse a statement but not a declaration.
17    pub fn parse_stmt(&mut self) -> PResult<Stmt> {
18        parse_stmt(self)
19    }
20
21    /// Parse a statement and maybe a declaration.
22    pub fn parse_stmt_list_item(&mut self) -> PResult<Stmt> {
23        parse_stmt_list_item(self)
24    }
25}
26
27#[cfg(test)]
28mod tests {
29    use swc_atoms::atom;
30    use swc_common::{comments::SingleThreadedComments, DUMMY_SP as span};
31    use swc_ecma_lexer::{common::parser::stmt::TempForHead, TsSyntax};
32    use swc_ecma_visit::assert_eq_ignore_span;
33
34    use super::*;
35    use crate::EsSyntax;
36
37    fn stmt(s: &'static str) -> Stmt {
38        test_parser(s, Syntax::default(), |p| p.parse_stmt())
39    }
40
41    fn module_item(s: &'static str) -> ModuleItem {
42        test_parser(s, Syntax::default(), |p| p.parse_module_item())
43    }
44    fn expr(s: &'static str) -> Box<Expr> {
45        test_parser(s, Syntax::default(), |p| p.parse_expr())
46    }
47
48    #[test]
49    fn expr_stmt() {
50        assert_eq_ignore_span!(
51            stmt("a + b + c"),
52            Stmt::Expr(ExprStmt {
53                span,
54                expr: expr("a + b + c")
55            })
56        )
57    }
58
59    #[test]
60    fn catch_rest_pat() {
61        assert_eq_ignore_span!(
62            stmt("try {} catch({ ...a34 }) {}"),
63            Stmt::Try(Box::new(TryStmt {
64                span,
65                block: BlockStmt {
66                    span,
67                    ..Default::default()
68                },
69                handler: Some(CatchClause {
70                    span,
71                    param: Pat::Object(ObjectPat {
72                        span,
73                        optional: false,
74                        props: vec![ObjectPatProp::Rest(RestPat {
75                            span,
76                            dot3_token: span,
77                            arg: Box::new(Pat::Ident(
78                                Ident::new_no_ctxt(atom!("a34"), span).into()
79                            )),
80                            type_ann: None
81                        })],
82                        type_ann: None,
83                    })
84                    .into(),
85                    body: BlockStmt {
86                        span,
87                        ..Default::default()
88                    }
89                }),
90                finalizer: None
91            }))
92        );
93    }
94
95    #[test]
96    fn throw_this() {
97        assert_eq_ignore_span!(
98            stmt("throw this"),
99            Stmt::Throw(ThrowStmt {
100                span,
101                arg: expr("this"),
102            })
103        )
104    }
105
106    #[test]
107    fn await_for_of() {
108        assert_eq_ignore_span!(
109            stmt("for await (const a of b) ;"),
110            Stmt::ForOf(ForOfStmt {
111                span,
112                is_await: true,
113                left: ForHead::VarDecl(Box::new(VarDecl {
114                    span,
115                    kind: VarDeclKind::Const,
116                    decls: vec![VarDeclarator {
117                        span,
118                        init: None,
119                        name: Pat::Ident(Ident::new_no_ctxt(atom!("a"), span).into()),
120                        definite: false,
121                    }],
122                    ..Default::default()
123                })),
124                right: Box::new(Expr::Ident(Ident::new_no_ctxt(atom!("b"), span))),
125
126                body: Box::new(Stmt::Empty(EmptyStmt { span })),
127            })
128        )
129    }
130
131    #[test]
132    fn no_empty_without_semi() {
133        assert_eq_ignore_span!(
134            stmt("(function foo() { return 1 })"),
135            stmt(
136                "(function foo () {
137                return 1
138            })"
139            )
140        );
141
142        assert_eq_ignore_span!(
143            stmt("{ 1; }"),
144            Stmt::Block(BlockStmt {
145                span,
146                stmts: vec![stmt("1")],
147                ..Default::default()
148            })
149        );
150    }
151
152    #[test]
153    fn if_else() {
154        assert_eq_ignore_span!(
155            stmt("if (a) b; else c"),
156            Stmt::If(IfStmt {
157                span,
158                test: expr("a"),
159                cons: Box::new(stmt("b;")),
160                alt: Some(Box::new(stmt("c"))),
161            })
162        );
163    }
164
165    #[test]
166    fn class_decorator() {
167        assert_eq_ignore_span!(
168            test_parser(
169                "
170            @decorator
171            @dec2
172            class Foo {}
173            ",
174                Syntax::Es(EsSyntax {
175                    decorators: true,
176                    ..Default::default()
177                }),
178                |p| p.parse_stmt_list_item(),
179            ),
180            Stmt::Decl(Decl::Class(ClassDecl {
181                ident: Ident::new_no_ctxt(atom!("Foo"), span),
182                class: Box::new(Class {
183                    span,
184                    decorators: vec![
185                        Decorator {
186                            span,
187                            expr: expr("decorator")
188                        },
189                        Decorator {
190                            span,
191                            expr: expr("dec2")
192                        }
193                    ],
194                    super_class: None,
195                    body: Vec::new(),
196                    is_abstract: false,
197                    ..Default::default()
198                }),
199                declare: false,
200            }))
201        );
202    }
203
204    #[test]
205    fn example() {
206        let src = r#"
207import React from 'react'
208import ReactDOM from 'react-dom'
209
210function App() {
211  return <h1>JSX is working!</h1>
212}
213
214ReactDOM.render(<App />, document.getElementById('root'))
215
216"#;
217        test_parser(
218            src,
219            Syntax::Es(EsSyntax {
220                jsx: true,
221                ..Default::default()
222            }),
223            |p| p.parse_module(),
224        );
225    }
226
227    #[test]
228    fn ice() {
229        let src = r#"import React from "react"
230
231function App() {
232  return <h1>works</h1>
233}
234
235export default App"#;
236        test_parser(
237            src,
238            Syntax::Es(EsSyntax {
239                jsx: true,
240                ..Default::default()
241            }),
242            |p| p.parse_module(),
243        );
244    }
245
246    #[test]
247    fn export_default() {
248        let src = "export v, { x, y as w } from 'mod';";
249        test_parser(
250            src,
251            Syntax::Es(EsSyntax {
252                export_default_from: true,
253                ..Default::default()
254            }),
255            |p| p.parse_module(),
256        );
257    }
258
259    #[test]
260    fn export_default_2() {
261        let src = "export foo from 'bar';";
262        test_parser(
263            src,
264            Syntax::Es(EsSyntax {
265                export_default_from: true,
266                ..Default::default()
267            }),
268            |p| p.parse_module(),
269        );
270    }
271
272    #[test]
273    fn export_default_3() {
274        let src = "export default from 'bar';";
275        test_parser(
276            src,
277            Syntax::Es(EsSyntax {
278                export_default_from: true,
279                ..Default::default()
280            }),
281            |p| p.parse_module(),
282        );
283    }
284
285    #[test]
286    fn export_default_4() {
287        let src = "export default, {foo} from 'bar';";
288        test_parser(
289            src,
290            Syntax::Es(EsSyntax {
291                export_default_from: true,
292                ..Default::default()
293            }),
294            |p| p.parse_module(),
295        );
296    }
297
298    #[test]
299    fn shebang_01() {
300        let src = "#!/usr/bin/env node";
301        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_module());
302    }
303
304    #[test]
305    fn shebang_02() {
306        let src = "#!/usr/bin/env node
307let x = 4";
308        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_module());
309    }
310
311    #[test]
312    fn empty() {
313        test_parser("", Syntax::Es(Default::default()), |p| p.parse_module());
314    }
315
316    #[test]
317    fn issue_226() {
318        test_parser(
319            "export * as Foo from 'bar';",
320            Syntax::Es(EsSyntax {
321                export_default_from: true,
322                ..Default::default()
323            }),
324            |p| p.parse_module(),
325        );
326    }
327
328    #[test]
329    #[should_panic(expected = "Expected 'from', got ','")]
330    fn issue_4369_1() {
331        test_parser(
332            r#"export * as foo, { bar } from "mod""#,
333            Syntax::Es(EsSyntax {
334                export_default_from: false,
335                ..Default::default()
336            }),
337            |p| p.parse_module(),
338        );
339    }
340
341    #[test]
342    fn issue_4369_2() {
343        test_parser(
344            r#"export foo, * as bar, { baz } from "mod""#,
345            Syntax::Es(EsSyntax {
346                export_default_from: true,
347                ..Default::default()
348            }),
349            |p| p.parse_module(),
350        );
351    }
352
353    #[test]
354    fn issue_4369_3() {
355        test_parser(
356            r#"export foo, * as bar from "mod""#,
357            Syntax::Es(EsSyntax {
358                export_default_from: true,
359                ..Default::default()
360            }),
361            |p| p.parse_module(),
362        );
363    }
364
365    #[test]
366    fn issue_4369_4() {
367        test_parser(
368            r#"export * as bar, { baz } from "mod""#,
369            Syntax::Es(EsSyntax {
370                export_default_from: true,
371                ..Default::default()
372            }),
373            |p| p.parse_module(),
374        );
375    }
376
377    #[test]
378    fn issue_4369_5() {
379        test_parser(
380            r#"export foo, { baz } from "mod""#,
381            Syntax::Es(EsSyntax {
382                export_default_from: true,
383                ..Default::default()
384            }),
385            |p| p.parse_module(),
386        );
387    }
388
389    #[test]
390    fn issue_257_var() {
391        test_parser(
392            "
393export default function waitUntil(callback, options = {}) {
394  var timeout = 'timeout' in options ? options.timeout : 1000;
395}",
396            Default::default(),
397            |p| p.parse_module(),
398        );
399    }
400
401    #[test]
402    fn issue_257_let() {
403        test_parser(
404            "
405export default function waitUntil(callback, options = {}) {
406  let timeout = 'timeout' in options ? options.timeout : 1000;
407}",
408            Default::default(),
409            |p| p.parse_module(),
410        );
411    }
412
413    #[test]
414    fn issue_269() {
415        test_parser(
416            ";(function() {})(window, window.lib || (window.lib = {}))",
417            Default::default(),
418            |p| p.parse_module(),
419        );
420    }
421
422    #[test]
423    fn issue_319_2() {
424        module_item(
425            "export default obj({
426    async f() {
427        await g();
428    }
429});",
430        );
431    }
432
433    #[test]
434    fn issue_340_fn() {
435        test_parser("export default function(){};", Default::default(), |p| {
436            p.parse_module()
437        });
438    }
439
440    #[test]
441    fn issue_340_async_fn() {
442        test_parser(
443            "export default async function(){};",
444            Default::default(),
445            |p| p.parse_module(),
446        );
447    }
448
449    #[test]
450    fn issue_340_generator_fn() {
451        test_parser("export default function*(){};", Default::default(), |p| {
452            p.parse_module()
453        });
454    }
455
456    #[test]
457    fn issue_340_class() {
458        test_parser("export default class {};", Default::default(), |p| {
459            p.parse_module()
460        });
461    }
462
463    #[test]
464    fn issue_360() {
465        test_parser(
466            "var IS_IE11 = !global.ActiveXObject && 'ActiveXObject' in global;",
467            Default::default(),
468            |p| p.parse_module(),
469        );
470    }
471
472    #[test]
473    fn issue_380_1() {
474        test_parser(
475            "import(filePath).then(bar => {})",
476            Syntax::Es(Default::default()),
477            |p| p.parse_module(),
478        );
479    }
480
481    #[test]
482    fn issue_380_2() {
483        test_parser(
484            "class Foo {
485                componentDidMount() {
486                    const filePath = '../foo/bar'
487                    import(filePath).then(bar => {})
488                }
489            }",
490            Syntax::Es(Default::default()),
491            |p| p.parse_module(),
492        );
493    }
494
495    #[test]
496    fn issue_411() {
497        test_parser(
498            "try {
499} catch {}",
500            Syntax::Es(Default::default()),
501            |p| p.parse_module(),
502        );
503    }
504
505    #[test]
506    fn top_level_await() {
507        test_parser("await foo", Syntax::Es(Default::default()), |p| {
508            p.parse_module()
509        });
510    }
511
512    #[test]
513    fn issue_856() {
514        let c = SingleThreadedComments::default();
515        let s = "class Foo {
516    static _extensions: {
517        // eslint-disable-next-line @typescript-eslint/no-explicit-any
518        [key: string]: (module: Module, filename: string) => any;
519    } = Object.create(null);
520}
521";
522        let _ = test_parser_comment(&c, s, Syntax::Typescript(Default::default()), |p| {
523            p.parse_typescript_module()
524        });
525
526        let (leading, trailing) = c.take_all();
527        assert!(trailing.borrow().is_empty());
528        assert_eq!(leading.borrow().len(), 1);
529    }
530
531    #[test]
532    fn issue_856_2() {
533        let c = SingleThreadedComments::default();
534        let s = "type ConsoleExamineFunc = (
535  // eslint-disable-next-line @typescript-eslint/no-explicit-any
536  csl: any,
537  out: StringBuffer,
538  err?: StringBuffer,
539  both?: StringBuffer
540) => void;";
541
542        let _ = test_parser_comment(&c, s, Syntax::Typescript(Default::default()), |p| {
543            p.parse_typescript_module()
544        });
545
546        let (leading, trailing) = c.take_all();
547        assert!(trailing.borrow().is_empty());
548        assert_eq!(leading.borrow().len(), 1);
549    }
550
551    #[test]
552    fn issue_856_3() {
553        let c = SingleThreadedComments::default();
554        let s = "type RequireWrapper = (
555  // eslint-disable-next-line @typescript-eslint/no-explicit-any
556  exports: any,
557  // eslint-disable-next-line @typescript-eslint/no-explicit-any
558  require: any,
559  module: Module,
560  __filename: string,
561  __dirname: string
562) => void;";
563
564        let _ = test_parser_comment(&c, s, Syntax::Typescript(Default::default()), |p| {
565            p.parse_typescript_module()
566        });
567
568        let (leading, trailing) = c.take_all();
569        assert!(trailing.borrow().is_empty());
570        assert_eq!(leading.borrow().len(), 2);
571    }
572
573    #[test]
574    fn issue_856_4() {
575        let c = SingleThreadedComments::default();
576        let s = "const _extensions: {
577    // eslint-disable-next-line @typescript-eslint/no-explicit-any
578    [key: string]: (module: Module, filename: string) => any;
579  } = Object.create(null);";
580
581        let _ = test_parser_comment(&c, s, Syntax::Typescript(Default::default()), |p| {
582            p.parse_typescript_module()
583        });
584
585        let (leading, trailing) = c.take_all();
586        assert!(trailing.borrow().is_empty());
587        assert_eq!(leading.borrow().len(), 1);
588    }
589
590    fn parse_for_head(str: &'static str) -> TempForHead {
591        test_parser(str, Syntax::default(), |p| {
592            swc_ecma_lexer::common::parser::stmt::parse_for_head(p)
593        })
594    }
595
596    #[test]
597    fn for_array_binding_pattern() {
598        match parse_for_head("let [, , t] = simple_array; t < 10; t++") {
599            TempForHead::For { init: Some(v), .. } => assert_eq_ignore_span!(
600                v,
601                VarDeclOrExpr::VarDecl(Box::new(VarDecl {
602                    span,
603                    declare: false,
604                    kind: VarDeclKind::Let,
605                    decls: vec![VarDeclarator {
606                        span,
607                        name: Pat::Array(ArrayPat {
608                            span,
609                            type_ann: None,
610                            optional: false,
611                            elems: vec![
612                                None,
613                                None,
614                                Some(Pat::Ident(Ident::new_no_ctxt(atom!("t"), span).into()))
615                            ]
616                        }),
617                        init: Some(Box::new(Expr::Ident(Ident::new_no_ctxt(
618                            atom!("simple_array"),
619                            span
620                        )))),
621                        definite: false
622                    }],
623                    ..Default::default()
624                }))
625            ),
626            _ => unreachable!(),
627        }
628    }
629    #[test]
630    fn for_object_binding_pattern() {
631        match parse_for_head("let {num} = obj; num < 11; num++") {
632            TempForHead::For { init: Some(v), .. } => assert_eq_ignore_span!(
633                v,
634                VarDeclOrExpr::VarDecl(Box::new(VarDecl {
635                    span,
636                    kind: VarDeclKind::Let,
637                    decls: vec![VarDeclarator {
638                        span,
639                        name: Pat::Object(ObjectPat {
640                            optional: false,
641                            type_ann: None,
642                            span,
643                            props: vec![ObjectPatProp::Assign(AssignPatProp {
644                                span,
645                                key: Ident::new_no_ctxt(atom!("num"), span).into(),
646                                value: None
647                            })]
648                        }),
649                        init: Some(Box::new(Expr::Ident(Ident::new_no_ctxt(
650                            atom!("obj"),
651                            span
652                        )))),
653                        definite: false
654                    }],
655                    ..Default::default()
656                }))
657            ),
658            _ => unreachable!(),
659        }
660    }
661
662    #[test]
663    #[should_panic(expected = "'import.meta' cannot be used outside of module code.")]
664    fn import_meta_in_script() {
665        let src = "const foo = import.meta.url;";
666        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_script());
667    }
668
669    #[test]
670    fn import_meta_in_program() {
671        let src = "const foo = import.meta.url;";
672        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_program());
673    }
674
675    #[test]
676    #[should_panic(expected = "'import', and 'export' cannot be used outside of module code")]
677    fn import_statement_in_script() {
678        let src = "import 'foo';";
679        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_script());
680    }
681
682    #[test]
683    #[should_panic(expected = "top level await is only allowed in module")]
684    fn top_level_await_in_script() {
685        let src = "await promise";
686        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_script());
687    }
688
689    #[test]
690    fn top_level_await_in_program() {
691        let src = "await promise";
692        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_program());
693    }
694
695    #[test]
696    fn for_of_head_lhs_async_dot() {
697        let src = "for (async.x of [1]) ;";
698        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_module());
699    }
700
701    #[test]
702    fn for_head_init_async_of() {
703        let src = "for (async of => {}; i < 10; ++i) { ++counter; }";
704        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_module());
705    }
706
707    #[test]
708    #[should_panic(expected = "await isn't allowed in non-async function")]
709    fn await_in_function_in_module() {
710        let src = "function foo (p) { await p; }";
711        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_module());
712    }
713
714    #[test]
715    #[should_panic(expected = "await isn't allowed in non-async function")]
716    fn await_in_function_in_script() {
717        let src = "function foo (p) { await p; }";
718        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_script());
719    }
720
721    #[test]
722    #[should_panic(expected = "await isn't allowed in non-async function")]
723    fn await_in_function_in_program() {
724        let src = "function foo (p) { await p; }";
725        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_program());
726    }
727
728    #[test]
729    #[should_panic(expected = "`await` cannot be used as an identifier in an async context")]
730    fn await_in_nested_async_function_in_module() {
731        let src = "async function foo () { function bar(x = await) {} }";
732        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_module());
733    }
734
735    #[test]
736    fn await_in_nested_async_function_in_script() {
737        let src = "async function foo () { function bar(x = await) {} }";
738        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_script());
739    }
740
741    #[test]
742    fn await_in_nested_async_function_in_program() {
743        let src = "async function foo () { function bar(x = await) {} }";
744        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_program());
745    }
746
747    #[test]
748    #[should_panic(expected = "`await` cannot be used as an identifier in an async context")]
749    fn await_as_param_ident_in_module() {
750        let src = "function foo (x = await) { }";
751        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_module());
752    }
753
754    #[test]
755    fn await_as_param_ident_in_script() {
756        let src = "function foo (x = await) { }";
757        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_script());
758    }
759
760    #[test]
761    #[should_panic(expected = "`await` cannot be used as an identifier in an async context")]
762    fn await_as_ident_in_module() {
763        let src = "let await = 1";
764        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_module());
765    }
766
767    #[test]
768    fn await_as_ident_in_script() {
769        let src = "let await = 1";
770        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_script());
771    }
772
773    #[test]
774    #[should_panic(expected = "`await` cannot be used as an identifier in an async context")]
775    fn await_as_ident_in_async() {
776        let src = "async function foo() { let await = 1; }";
777        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_script());
778    }
779
780    #[test]
781    fn top_level_await_in_block() {
782        let src = "if (true) { await promise; }";
783        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_module());
784    }
785
786    #[test]
787    fn top_level_await_in_decl() {
788        test_parser(r#"const t = await test();"#, Default::default(), |p| {
789            let program = p.parse_program()?;
790            assert!(program.is_module());
791            Ok(program)
792        });
793    }
794
795    #[test]
796    fn class_static_blocks() {
797        let src = "class Foo { static { 1 + 1; } }";
798        assert_eq_ignore_span!(
799            test_parser(src, Syntax::Es(Default::default()), |p| p.parse_expr()),
800            Box::new(Expr::Class(ClassExpr {
801                ident: Some(Ident {
802                    span,
803                    sym: atom!("Foo"),
804                    ..Default::default()
805                }),
806                class: Box::new(Class {
807                    span,
808                    decorators: Vec::new(),
809                    super_class: None,
810                    type_params: None,
811                    super_type_params: None,
812                    is_abstract: false,
813                    implements: Vec::new(),
814                    body: vec!(ClassMember::StaticBlock(StaticBlock {
815                        span,
816                        body: BlockStmt {
817                            span,
818                            stmts: vec!(stmt("1 + 1;")),
819                            ..Default::default()
820                        }
821                    })),
822                    ..Default::default()
823                })
824            }))
825        );
826    }
827
828    #[test]
829    fn multiple_class_static_blocks() {
830        let src = "class Foo { static { 1 + 1; } static { 1 + 1; } }";
831        assert_eq_ignore_span!(
832            test_parser(src, Syntax::Es(Default::default()), |p| p.parse_expr()),
833            Box::new(Expr::Class(ClassExpr {
834                ident: Some(Ident {
835                    span,
836                    sym: atom!("Foo"),
837                    ..Default::default()
838                }),
839                class: Box::new(Class {
840                    span,
841                    decorators: Vec::new(),
842                    super_class: None,
843                    is_abstract: false,
844                    body: vec!(
845                        ClassMember::StaticBlock(StaticBlock {
846                            span,
847                            body: BlockStmt {
848                                span,
849                                stmts: vec!(stmt("1 + 1;")),
850                                ..Default::default()
851                            },
852                        }),
853                        ClassMember::StaticBlock(StaticBlock {
854                            span,
855                            body: BlockStmt {
856                                span,
857                                stmts: vec!(stmt("1 + 1;")),
858                                ..Default::default()
859                            },
860                        })
861                    ),
862                    ..Default::default()
863                })
864            }))
865        );
866    }
867
868    #[test]
869    fn class_static_blocks_with_line_breaks_01() {
870        let src = "class Foo {
871            static
872            {
873                1 + 1;
874            }
875        }";
876        assert_eq_ignore_span!(
877            test_parser(src, Syntax::Es(Default::default()), |p| p.parse_expr()),
878            Box::new(Expr::Class(ClassExpr {
879                ident: Some(Ident {
880                    span,
881                    sym: atom!("Foo"),
882                    ..Default::default()
883                }),
884                class: Box::new(Class {
885                    span,
886                    is_abstract: false,
887                    body: vec!(ClassMember::StaticBlock(StaticBlock {
888                        span,
889                        body: BlockStmt {
890                            span,
891                            stmts: vec!(stmt("1 + 1;")),
892                            ..Default::default()
893                        }
894                    })),
895                    ..Default::default()
896                })
897            }))
898        );
899    }
900
901    #[test]
902    fn class_static_blocks_with_line_breaks_02() {
903        let src = "class Foo {
904            static
905            {}
906        }";
907        assert_eq_ignore_span!(
908            test_parser(src, Syntax::Es(Default::default()), |p| p.parse_expr()),
909            Box::new(Expr::Class(ClassExpr {
910                ident: Some(Ident {
911                    span,
912                    sym: atom!("Foo"),
913                    ..Default::default()
914                }),
915                class: Box::new(Class {
916                    span,
917                    is_abstract: false,
918                    body: vec!(ClassMember::StaticBlock(StaticBlock {
919                        span,
920                        body: BlockStmt {
921                            span,
922                            stmts: Vec::new(),
923                            ..Default::default()
924                        }
925                    })),
926                    ..Default::default()
927                })
928            }))
929        );
930    }
931
932    #[test]
933    fn class_static_blocks_in_ts() {
934        let src = "class Foo { static { 1 + 1 }; }";
935        test_parser(src, Syntax::Typescript(Default::default()), |p| {
936            p.parse_expr()
937        });
938    }
939
940    #[test]
941    fn class_static_blocks_with_line_breaks_in_ts_01() {
942        let src = "class Foo {
943            static
944            {
945                1 + 1;
946            }
947        }";
948        test_parser(src, Syntax::Typescript(Default::default()), |p| {
949            p.parse_expr()
950        });
951    }
952
953    #[test]
954    fn class_static_blocks_with_line_breaks_in_ts_02() {
955        let src = "class Foo {
956            static
957            {}
958        }";
959        test_parser(src, Syntax::Typescript(Default::default()), |p| {
960            p.parse_expr()
961        });
962    }
963
964    #[test]
965    #[should_panic(expected = "Expected ident")]
966    fn class_static_blocks_with_await() {
967        let src = "class Foo{
968            static {
969                var await = 'bar';
970            }
971        }";
972        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_expr());
973    }
974
975    #[test]
976    #[should_panic(expected = "Expected ident")]
977    fn class_static_blocks_with_await_in_nested_class() {
978        let src = "class Foo{
979            static {
980                function foo() {
981                    class Foo {
982                        static {
983                            var await = 'bar';
984                        }
985                    }
986                }
987            }
988        }";
989        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_expr());
990    }
991
992    #[test]
993    fn class_static_blocks_with_await_in_fn() {
994        let src = "class Foo{
995            static {
996                function foo() {
997                    var await = 'bar';
998                }
999            }
1000        }";
1001        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_expr());
1002    }
1003
1004    #[test]
1005    #[should_panic(expected = "Modifiers cannot appear here")]
1006    fn class_static_blocks_in_ts_with_invalid_modifier_01() {
1007        let src = "class Foo { abstract static { 1 + 1 }; }";
1008        test_parser(src, Syntax::Typescript(Default::default()), |p| {
1009            p.parse_expr()
1010        });
1011    }
1012
1013    #[test]
1014    #[should_panic(expected = "Modifiers cannot appear here")]
1015    fn class_static_blocks_in_ts_with_invalid_modifier_02() {
1016        let src = "class Foo { static static { 1 + 1 }; }";
1017        test_parser(src, Syntax::Typescript(Default::default()), |p| {
1018            p.parse_expr()
1019        });
1020    }
1021
1022    #[test]
1023    #[should_panic(expected = "Modifiers cannot appear here")]
1024    fn class_static_blocks_in_ts_with_invalid_modifier_03() {
1025        let src = "class Foo { declare static { 1 + 1 }; }";
1026        test_parser(src, Syntax::Typescript(Default::default()), |p| {
1027            p.parse_expr()
1028        });
1029    }
1030
1031    #[test]
1032    #[should_panic(expected = "Modifiers cannot appear here")]
1033    fn class_static_blocks_in_ts_with_invalid_modifier_04() {
1034        let src = "class Foo { private static { 1 + 1 }; }";
1035        test_parser(src, Syntax::Typescript(Default::default()), |p| {
1036            p.parse_expr()
1037        });
1038    }
1039
1040    #[ignore = "see https://github.com/swc-project/swc/pull/3018#issuecomment-991947907"]
1041    #[test]
1042    #[should_panic(expected = "Trailing comma is disallowed inside import(...) arguments")]
1043    fn error_for_trailing_comma_inside_dynamic_import() {
1044        let src = "import('foo',)";
1045        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_expr());
1046    }
1047
1048    #[test]
1049    fn no_error_for_trailing_comma_inside_dynamic_import_with_import_assertions() {
1050        let src = "import('foo',)";
1051        test_parser(
1052            src,
1053            Syntax::Es(EsSyntax {
1054                import_attributes: true,
1055                ..Default::default()
1056            }),
1057            |p| p.parse_expr(),
1058        );
1059    }
1060
1061    #[test]
1062    fn type_only_star_exports_with_name() {
1063        let src = "export type * as bar from 'mod'";
1064        test_parser(src, Syntax::Typescript(Default::default()), |p| {
1065            p.parse_module()
1066        });
1067    }
1068
1069    #[test]
1070    fn type_only_star_exports_without_name() {
1071        let src = "export type * from 'mod'";
1072        test_parser(src, Syntax::Typescript(Default::default()), |p| {
1073            p.parse_module()
1074        });
1075    }
1076
1077    #[test]
1078    #[should_panic(expected = "A string literal cannot be used as an imported binding.")]
1079    fn error_for_string_literal_is_import_binding() {
1080        let src = "import { \"str\" } from \"mod\"";
1081        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_module());
1082    }
1083
1084    #[test]
1085    #[should_panic(
1086        expected = "A string literal cannot be used as an exported binding without `from`."
1087    )]
1088    fn error_for_string_literal_is_export_binding() {
1089        let src = "export { 'foo' };";
1090        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_module());
1091    }
1092
1093    #[test]
1094    #[should_panic(expected = "'const' declarations must be initialized")]
1095    fn ts_error_for_const_declaration_not_initialized() {
1096        let src = r#"
1097"use strict";
1098const foo;"#;
1099
1100        test_parser(src, Syntax::Typescript(Default::default()), |p| {
1101            p.parse_script()
1102        });
1103    }
1104
1105    #[test]
1106    #[should_panic(expected = "'const' declarations must be initialized")]
1107    fn es_error_for_const_declaration_not_initialized() {
1108        let src = r#"
1109"use strict";
1110const foo;"#;
1111
1112        test_parser(src, Syntax::Es(Default::default()), |p| p.parse_script());
1113    }
1114
1115    #[test]
1116    fn issue_5557_expr_follow_class() {
1117        let src = "foo * class {} / bar;";
1118
1119        test_parser(src, Default::default(), |p| p.parse_script());
1120    }
1121
1122    #[test]
1123    fn issue_5722_class_keyword_in_tpl() {
1124        let src = "console.log(`${toStr({class: fn})}`)";
1125
1126        test_parser(src, Default::default(), |p| p.parse_script());
1127    }
1128
1129    #[test]
1130    fn issue_6301_await_expr_stmt() {
1131        let src = "try { await; } catch { console.log('caught'); }";
1132
1133        test_parser(src, Default::default(), |p| p.parse_script());
1134    }
1135
1136    #[test]
1137    fn issue_6301_await_expr_stmt_1() {
1138        let src = "try { await, await; } catch { console.log('caught'); }";
1139
1140        test_parser(src, Default::default(), |p| p.parse_script());
1141    }
1142
1143    #[test]
1144    fn issue_6301_await_expr_stmt_2() {
1145        let src = "function test() { await; }";
1146
1147        test_parser(src, Default::default(), |p| p.parse_script());
1148    }
1149
1150    #[test]
1151    fn issue_6301_await_expr_stmt_3() {
1152        let src = "function test() { await, await; }";
1153
1154        test_parser(src, Default::default(), |p| p.parse_script());
1155    }
1156
1157    #[test]
1158    fn issue_6301_await_expr_stmt_4() {
1159        let src = "function test() { [await]; }";
1160
1161        test_parser(src, Default::default(), |p| p.parse_script());
1162    }
1163
1164    #[test]
1165    fn issue_6301_await_expr_stmt_5() {
1166        let src = "function test() { (await); }";
1167
1168        test_parser(src, Default::default(), |p| p.parse_script());
1169    }
1170
1171    #[test]
1172    fn issue_6322() {
1173        let src = "for ( ; { } / 1 ; ) ;";
1174
1175        test_parser(src, Default::default(), |p| p.parse_script());
1176    }
1177
1178    #[test]
1179    fn issue_6323() {
1180        let src = "let x = 0 < { } / 0 ;";
1181
1182        test_parser(src, Default::default(), |p| p.parse_script());
1183    }
1184
1185    #[test]
1186    fn issue_10797_0() {
1187        let src = "
1188// var b = delete ANY1;
1189
1190module A {
1191    export const a = 1
1192}";
1193        test_parser(src, Syntax::Typescript(TsSyntax::default()), |p| {
1194            p.parse_script()
1195        });
1196    }
1197
1198    #[test]
1199    fn issue_10797_1() {
1200        let src = "
1201module A {
1202    export const a = 1
1203}
1204
1205var b = delete ANY1;";
1206        test_parser(src, Syntax::Typescript(TsSyntax::default()), |p| {
1207            p.parse_script()
1208        });
1209    }
1210}