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 pub fn parse_stmt(&mut self) -> PResult<Stmt> {
18 parse_stmt(self)
19 }
20
21 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}