1use react_compiler_ast::common::BaseNode;
13use react_compiler_ast::common::Comment as BabelComment;
14use react_compiler_ast::declarations::ExportAllDeclaration;
15use react_compiler_ast::declarations::ExportDefaultDecl as BabelExportDefaultDecl;
16use react_compiler_ast::declarations::ExportDefaultDeclaration;
17use react_compiler_ast::declarations::ExportKind;
18use react_compiler_ast::declarations::ExportNamedDeclaration;
19use react_compiler_ast::declarations::ImportDeclaration;
20use react_compiler_ast::declarations::ImportKind;
21use react_compiler_ast::expressions::Expression as BabelExpr;
22use react_compiler_ast::expressions::{self as babel_expr};
23use react_compiler_ast::operators::*;
24use react_compiler_ast::patterns::*;
25use react_compiler_ast::statements::Statement as BabelStmt;
26use react_compiler_ast::statements::{self as babel_stmt};
27use swc_atoms::Atom;
28use swc_atoms::Wtf8Atom;
29use swc_common::BytePos;
30use swc_common::DUMMY_SP;
31use swc_common::Span;
32use swc_common::Spanned;
33use swc_common::SyntaxContext;
34use swc_common::comments::Comment as SwcComment;
35use swc_common::comments::CommentKind;
36use swc_common::comments::Comments;
37use swc_common::comments::SingleThreadedComments;
38use swc_ecma_ast::*;
39
40pub struct SwcConversionResult {
42 pub module: Module,
43 pub comments: SingleThreadedComments,
44}
45
46pub fn convert_program_to_swc(file: &react_compiler_ast::File) -> SwcConversionResult {
48 convert_program_to_swc_with_source(file, None)
49}
50
51pub fn convert_program_to_swc_with_source(
55 file: &react_compiler_ast::File,
56 source_text: Option<&str>,
57) -> SwcConversionResult {
58 let ctx = ReverseCtx {
59 comments: SingleThreadedComments::default(),
60 source_text: source_text.map(|s| s.to_string()),
61 };
62 let module = ctx.convert_program(&file.program);
63 SwcConversionResult {
64 module,
65 comments: ctx.comments,
66 }
67}
68
69struct ReverseCtx {
70 comments: SingleThreadedComments,
71 source_text: Option<String>,
72}
73
74impl ReverseCtx {
75 fn span(&self, base: &BaseNode) -> Span {
77 let span = match (base.start, base.end) {
78 (Some(start), Some(end)) => Span::new(BytePos(start), BytePos(end)),
79 _ => DUMMY_SP,
80 };
81 self.extract_comments(base, span);
82 span
83 }
84
85 fn span_no_comments(&self, base: &BaseNode) -> Span {
88 match (base.start, base.end) {
89 (Some(start), Some(end)) => Span::new(BytePos(start), BytePos(end)),
90 _ => DUMMY_SP,
91 }
92 }
93
94 fn convert_babel_comment(babel_comment: &BabelComment) -> SwcComment {
96 let (kind, text) = match babel_comment {
97 BabelComment::CommentBlock(data) => (CommentKind::Block, &data.value),
98 BabelComment::CommentLine(data) => (CommentKind::Line, &data.value),
99 };
100 SwcComment {
101 kind,
102 span: DUMMY_SP,
103 text: Atom::from(text.as_str()),
104 }
105 }
106
107 fn extract_comments(&self, base: &BaseNode, span: Span) {
109 if let Some(ref leading) = base.leading_comments {
110 let pos = span.lo;
111 for c in leading {
112 self.comments
113 .add_leading(pos, Self::convert_babel_comment(c));
114 }
115 }
116 if let Some(ref trailing) = base.trailing_comments {
117 let pos = span.hi;
118 for c in trailing {
119 self.comments
120 .add_trailing(pos, Self::convert_babel_comment(c));
121 }
122 }
123 if let Some(ref inner) = base.inner_comments {
124 let pos = span.lo;
126 for c in inner {
127 self.comments
128 .add_leading(pos, Self::convert_babel_comment(c));
129 }
130 }
131 }
132
133 fn atom(&self, s: &str) -> Atom {
134 Atom::from(s)
135 }
136
137 fn wtf8(&self, s: &str) -> Wtf8Atom {
138 Wtf8Atom::from(s)
139 }
140
141 fn escape_string_raw(&self, value: &str) -> Option<Atom> {
145 let mut needs_escape = false;
146 for ch in value.chars() {
147 if !ch.is_ascii() || ch == '\t' || ch == '\'' || ch == '"' || ch == '\\' {
148 needs_escape = true;
149 break;
150 }
151 }
152 if !needs_escape {
153 return None;
154 }
155 let mut escaped = String::with_capacity(value.len() + 16);
156 escaped.push('"');
157 for ch in value.chars() {
158 match ch {
159 '"' => escaped.push_str("\\\""),
160 '\\' => escaped.push_str("\\\\"),
161 '\n' => escaped.push_str("\\n"),
162 '\r' => escaped.push_str("\\r"),
163 '\t' => escaped.push_str("\\t"),
164 c if !c.is_ascii() => {
165 let mut buf = [0u16; 2];
167 let encoded = c.encode_utf16(&mut buf);
168 for unit in encoded {
169 escaped.push_str(&format!("\\u{:04X}", unit));
170 }
171 }
172 c => escaped.push(c),
173 }
174 }
175 escaped.push('"');
176 Some(Atom::from(escaped.as_str()))
177 }
178
179 fn extract_source_stmt(&self, base: &react_compiler_ast::common::BaseNode) -> Option<Stmt> {
184 let source = self.source_text.as_deref()?;
185 let start = base.start? as usize;
186 let end = base.end? as usize;
187 let start_idx = start.saturating_sub(1);
189 let end_idx = end.saturating_sub(1);
190 if start_idx >= source.len() || end_idx > source.len() || start_idx >= end_idx {
191 return None;
192 }
193 let text = &source[start_idx..end_idx];
194 self.parse_ts_stmt(text, base)
195 }
196
197 fn parse_ts_stmt(
199 &self,
200 text: &str,
201 base: &react_compiler_ast::common::BaseNode,
202 ) -> Option<Stmt> {
203 let cm = swc_common::sync::Lrc::new(swc_common::SourceMap::default());
204 let fm = cm.new_source_file(
205 swc_common::sync::Lrc::new(swc_common::FileName::Anon),
206 text.to_string(),
207 );
208 let mut errors = vec![];
209 let module = swc_ecma_parser::parse_file_as_module(
210 &fm,
211 swc_ecma_parser::Syntax::Typescript(swc_ecma_parser::TsSyntax {
212 tsx: true,
213 ..Default::default()
214 }),
215 swc_ecma_ast::EsVersion::latest(),
216 None,
217 &mut errors,
218 )
219 .ok()?;
220
221 if let Some(item) = module.body.into_iter().next() {
222 match item {
223 ModuleItem::Stmt(stmt) => {
224 let span = self.span(base);
226 return Some(self.assign_span_to_stmt(stmt, span));
227 }
228 ModuleItem::ModuleDecl(_) => {}
229 }
230 }
231 None
232 }
233
234 fn assign_span_to_stmt(&self, stmt: Stmt, span: Span) -> Stmt {
236 match stmt {
237 Stmt::Decl(Decl::TsTypeAlias(mut d)) => {
238 d.span = span;
239 Stmt::Decl(Decl::TsTypeAlias(d))
240 }
241 Stmt::Decl(Decl::TsInterface(mut d)) => {
242 d.span = span;
243 Stmt::Decl(Decl::TsInterface(d))
244 }
245 Stmt::Decl(Decl::TsEnum(mut d)) => {
246 d.span = span;
247 Stmt::Decl(Decl::TsEnum(d))
248 }
249 other => other,
250 }
251 }
252
253 fn ident(&self, name: &str, span: Span) -> Ident {
254 Ident {
255 sym: self.atom(name),
256 span,
257 ctxt: SyntaxContext::empty(),
258 optional: false,
259 }
260 }
261
262 fn ident_name(&self, name: &str, span: Span) -> IdentName {
263 IdentName {
264 sym: self.atom(name),
265 span,
266 }
267 }
268
269 fn binding_ident(&self, name: &str, span: Span) -> BindingIdent {
270 BindingIdent {
271 id: self.ident(name, span),
272 type_ann: None,
273 }
274 }
275
276 fn convert_program(&self, program: &react_compiler_ast::Program) -> Module {
279 let mut body: Vec<ModuleItem> = Vec::new();
280
281 for dir in &program.directives {
283 let span = self.span(&dir.base);
284 let str_span = self.span(&dir.value.base);
285 body.push(ModuleItem::Stmt(Stmt::Expr(ExprStmt {
286 span,
287 expr: Box::new(Expr::Lit(Lit::Str(Str {
288 span: str_span,
289 value: self.wtf8(&dir.value.value),
290 raw: None,
291 }))),
292 })));
293 }
294
295 for s in &program.body {
296 body.push(self.convert_statement_to_module_item(s));
297 }
298
299 Module {
300 span: DUMMY_SP,
301 body,
302 shebang: None,
303 }
304 }
305
306 fn convert_statement_to_module_item(&self, stmt: &BabelStmt) -> ModuleItem {
307 match stmt {
308 BabelStmt::ImportDeclaration(d) => {
309 ModuleItem::ModuleDecl(ModuleDecl::Import(self.convert_import_declaration(d)))
310 }
311 BabelStmt::ExportNamedDeclaration(d) => self.convert_export_named_to_module_item(d),
312 BabelStmt::ExportDefaultDeclaration(d) => self.convert_export_default_to_module_item(d),
313 BabelStmt::ExportAllDeclaration(d) => ModuleItem::ModuleDecl(ModuleDecl::ExportAll(
314 self.convert_export_all_declaration(d),
315 )),
316 BabelStmt::Unknown(unknown) => match self.convert_unknown_to_module_decl(unknown) {
320 Some(decl) => ModuleItem::ModuleDecl(decl),
321 None => ModuleItem::Stmt(self.convert_statement(stmt)),
322 },
323 _ => ModuleItem::Stmt(self.convert_statement(stmt)),
324 }
325 }
326
327 fn convert_unknown_to_module_decl(
332 &self,
333 unknown: &babel_stmt::UnknownStatement,
334 ) -> Option<ModuleDecl> {
335 let raw = unknown.raw().parse_value();
336 let raw = &raw;
337 match unknown.node_type() {
338 "TSImportEqualsDeclaration" => {
339 let id = self.ident_from_raw(raw.get("id")?)?;
340 let module_ref = self.ts_module_ref_from_raw(raw.get("moduleReference")?)?;
341 let is_type_only = match raw.get("importKind") {
344 None => false,
345 Some(kind) => match kind.as_str() {
346 Some("type") => true,
347 Some("value") => false,
348 _ => return None,
349 },
350 };
351 let is_export = match raw.get("isExport") {
352 None => false,
353 Some(value) => value.as_bool()?,
354 };
355 Some(ModuleDecl::TsImportEquals(Box::new(TsImportEqualsDecl {
356 span: self.span(unknown.base()),
357 is_export,
358 is_type_only,
359 id,
360 module_ref,
361 })))
362 }
363 "TSExportAssignment" => {
364 let expr: BabelExpr =
365 serde_json::from_value(raw.get("expression")?.clone()).ok()?;
366 Some(ModuleDecl::TsExportAssignment(TsExportAssignment {
367 span: self.span(unknown.base()),
368 expr: Box::new(self.convert_expression(&expr)),
369 }))
370 }
371 "TSNamespaceExportDeclaration" => {
372 let id = self.ident_from_raw(raw.get("id")?)?;
373 Some(ModuleDecl::TsNamespaceExport(TsNamespaceExportDecl {
374 span: self.span(unknown.base()),
375 id,
376 }))
377 }
378 _ => None,
379 }
380 }
381
382 fn ident_from_raw(&self, raw: &serde_json::Value) -> Option<Ident> {
383 if raw.get("type").and_then(serde_json::Value::as_str) != Some("Identifier") {
384 return None;
385 }
386 let id: babel_expr::Identifier = serde_json::from_value(raw.clone()).ok()?;
387 Some(self.ident(&id.name, self.span_no_comments(&id.base)))
388 }
389
390 fn ts_module_ref_from_raw(&self, raw: &serde_json::Value) -> Option<TsModuleRef> {
391 match raw.get("type").and_then(serde_json::Value::as_str)? {
392 "TSExternalModuleReference" => {
393 let expr = raw.get("expression")?;
394 if expr.get("type").and_then(serde_json::Value::as_str) != Some("StringLiteral") {
395 return None;
396 }
397 let lit: react_compiler_ast::literals::StringLiteral =
398 serde_json::from_value(expr.clone()).ok()?;
399 let ref_base: BaseNode = serde_json::from_value(raw.clone()).ok()?;
400 Some(TsModuleRef::TsExternalModuleRef(TsExternalModuleRef {
401 span: self.span_no_comments(&ref_base),
402 expr: Str {
403 span: self.span_no_comments(&lit.base),
404 value: self.wtf8(&lit.value),
405 raw: None,
406 },
407 }))
408 }
409 "TSQualifiedName" | "Identifier" => self
410 .ts_entity_name_from_raw(raw)
411 .map(TsModuleRef::TsEntityName),
412 _ => None,
413 }
414 }
415
416 fn ts_entity_name_from_raw(&self, raw: &serde_json::Value) -> Option<TsEntityName> {
417 match raw.get("type").and_then(serde_json::Value::as_str)? {
418 "Identifier" => self.ident_from_raw(raw).map(TsEntityName::Ident),
419 "TSQualifiedName" => {
420 let base: BaseNode = serde_json::from_value(raw.clone()).ok()?;
421 let left = self.ts_entity_name_from_raw(raw.get("left")?)?;
422 let right: babel_expr::Identifier =
423 serde_json::from_value(raw.get("right")?.clone()).ok()?;
424 Some(TsEntityName::TsQualifiedName(Box::new(TsQualifiedName {
425 span: self.span_no_comments(&base),
426 left,
427 right: self.ident_name(&right.name, self.span_no_comments(&right.base)),
428 })))
429 }
430 _ => None,
431 }
432 }
433
434 fn convert_statement(&self, stmt: &BabelStmt) -> Stmt {
437 match stmt {
438 BabelStmt::BlockStatement(s) => Stmt::Block(self.convert_block_statement(s)),
439 BabelStmt::ReturnStatement(s) => Stmt::Return(ReturnStmt {
440 span: self.span(&s.base),
441 arg: s
442 .argument
443 .as_ref()
444 .map(|a| Box::new(self.convert_expression(a))),
445 }),
446 BabelStmt::ExpressionStatement(s) => {
447 let expr = self.convert_expression(&s.expression);
448 let needs_paren = match &expr {
452 Expr::Assign(a) => {
453 matches!(&a.left, AssignTarget::Pat(AssignTargetPat::Object(_)))
454 }
455 Expr::Call(c) => match &c.callee {
456 Callee::Expr(e) => matches!(e.as_ref(), Expr::Fn(_)),
457 _ => false,
458 },
459 _ => false,
460 };
461 let expr = if needs_paren {
462 Expr::Paren(ParenExpr {
463 span: self.span_no_comments(&s.base),
464 expr: Box::new(expr),
465 })
466 } else {
467 expr
468 };
469 Stmt::Expr(ExprStmt {
470 span: self.span(&s.base),
471 expr: Box::new(expr),
472 })
473 }
474 BabelStmt::IfStatement(s) => Stmt::If(IfStmt {
475 span: self.span(&s.base),
476 test: Box::new(self.convert_expression(&s.test)),
477 cons: Box::new(self.convert_statement(&s.consequent)),
478 alt: s
479 .alternate
480 .as_ref()
481 .map(|a| Box::new(self.convert_statement(a))),
482 }),
483 BabelStmt::ForStatement(s) => {
484 let init = s.init.as_ref().map(|i| self.convert_for_init(i));
485 let test = s
486 .test
487 .as_ref()
488 .map(|t| Box::new(self.convert_expression(t)));
489 let update = s
490 .update
491 .as_ref()
492 .map(|u| Box::new(self.convert_expression(u)));
493 let body = Box::new(self.convert_statement(&s.body));
494 Stmt::For(ForStmt {
495 span: self.span(&s.base),
496 init,
497 test,
498 update,
499 body,
500 })
501 }
502 BabelStmt::WhileStatement(s) => Stmt::While(WhileStmt {
503 span: self.span(&s.base),
504 test: Box::new(self.convert_expression(&s.test)),
505 body: Box::new(self.convert_statement(&s.body)),
506 }),
507 BabelStmt::DoWhileStatement(s) => Stmt::DoWhile(DoWhileStmt {
508 span: self.span(&s.base),
509 test: Box::new(self.convert_expression(&s.test)),
510 body: Box::new(self.convert_statement(&s.body)),
511 }),
512 BabelStmt::ForInStatement(s) => Stmt::ForIn(ForInStmt {
513 span: self.span(&s.base),
514 left: self.convert_for_in_of_left(&s.left),
515 right: Box::new(self.convert_expression(&s.right)),
516 body: Box::new(self.convert_statement(&s.body)),
517 }),
518 BabelStmt::ForOfStatement(s) => Stmt::ForOf(ForOfStmt {
519 span: self.span(&s.base),
520 is_await: s.is_await,
521 left: self.convert_for_in_of_left(&s.left),
522 right: Box::new(self.convert_expression(&s.right)),
523 body: Box::new(self.convert_statement(&s.body)),
524 }),
525 BabelStmt::SwitchStatement(s) => {
526 let cases = s
527 .cases
528 .iter()
529 .map(|c| SwitchCase {
530 span: self.span(&c.base),
531 test: c
532 .test
533 .as_ref()
534 .map(|t| Box::new(self.convert_expression(t))),
535 cons: c
536 .consequent
537 .iter()
538 .map(|s| self.convert_statement(s))
539 .collect(),
540 })
541 .collect();
542 Stmt::Switch(SwitchStmt {
543 span: self.span(&s.base),
544 discriminant: Box::new(self.convert_expression(&s.discriminant)),
545 cases,
546 })
547 }
548 BabelStmt::ThrowStatement(s) => Stmt::Throw(ThrowStmt {
549 span: self.span(&s.base),
550 arg: Box::new(self.convert_expression(&s.argument)),
551 }),
552 BabelStmt::TryStatement(s) => {
553 let block = self.convert_block_statement(&s.block);
554 let handler = s.handler.as_ref().map(|h| self.convert_catch_clause(h));
555 let finalizer = s
556 .finalizer
557 .as_ref()
558 .map(|f| self.convert_block_statement(f));
559 Stmt::Try(Box::new(TryStmt {
560 span: self.span(&s.base),
561 block,
562 handler,
563 finalizer,
564 }))
565 }
566 BabelStmt::BreakStatement(s) => Stmt::Break(BreakStmt {
567 span: self.span(&s.base),
568 label: s.label.as_ref().map(|l| self.ident(&l.name, DUMMY_SP)),
569 }),
570 BabelStmt::ContinueStatement(s) => Stmt::Continue(ContinueStmt {
571 span: self.span(&s.base),
572 label: s.label.as_ref().map(|l| self.ident(&l.name, DUMMY_SP)),
573 }),
574 BabelStmt::LabeledStatement(s) => Stmt::Labeled(LabeledStmt {
575 span: self.span(&s.base),
576 label: self.ident(&s.label.name, DUMMY_SP),
577 body: Box::new(self.convert_statement(&s.body)),
578 }),
579 BabelStmt::EmptyStatement(s) => Stmt::Empty(EmptyStmt {
580 span: self.span(&s.base),
581 }),
582 BabelStmt::DebuggerStatement(s) => Stmt::Debugger(DebuggerStmt {
583 span: self.span(&s.base),
584 }),
585 BabelStmt::WithStatement(s) => Stmt::With(WithStmt {
586 span: self.span(&s.base),
587 obj: Box::new(self.convert_expression(&s.object)),
588 body: Box::new(self.convert_statement(&s.body)),
589 }),
590 BabelStmt::VariableDeclaration(d) => {
591 Stmt::Decl(Decl::Var(Box::new(self.convert_variable_declaration(d))))
592 }
593 BabelStmt::FunctionDeclaration(f) => {
594 Stmt::Decl(Decl::Fn(self.convert_function_declaration(f)))
595 }
596 BabelStmt::ClassDeclaration(c) => {
597 let ident =
598 c.id.as_ref()
599 .map(|id| self.ident(&id.name, self.span(&id.base)))
600 .unwrap_or_else(|| self.ident("_anonymous", DUMMY_SP));
601 let super_class = c
602 .super_class
603 .as_ref()
604 .map(|s| Box::new(self.convert_expression(s)));
605 Stmt::Decl(Decl::Class(ClassDecl {
606 ident,
607 declare: c.declare.unwrap_or(false),
608 class: Box::new(Class {
609 span: self.span(&c.base),
610 ctxt: SyntaxContext::empty(),
611 decorators: vec![],
612 body: vec![],
613 super_class,
614 is_abstract: false,
615 type_params: None,
616 super_type_params: None,
617 implements: vec![],
618 }),
619 }))
620 }
621 BabelStmt::ImportDeclaration(_)
623 | BabelStmt::ExportNamedDeclaration(_)
624 | BabelStmt::ExportDefaultDeclaration(_)
625 | BabelStmt::ExportAllDeclaration(_) => Stmt::Empty(EmptyStmt { span: DUMMY_SP }),
626 BabelStmt::TSTypeAliasDeclaration(d) => self
628 .extract_source_stmt(&d.base)
629 .unwrap_or(Stmt::Empty(EmptyStmt { span: DUMMY_SP })),
630 BabelStmt::TSInterfaceDeclaration(d) => self
631 .extract_source_stmt(&d.base)
632 .unwrap_or(Stmt::Empty(EmptyStmt { span: DUMMY_SP })),
633 BabelStmt::TSEnumDeclaration(d) => self
634 .extract_source_stmt(&d.base)
635 .unwrap_or(Stmt::Empty(EmptyStmt { span: DUMMY_SP })),
636 BabelStmt::TypeAlias(d) => self
638 .extract_source_stmt(&d.base)
639 .unwrap_or(Stmt::Empty(EmptyStmt { span: DUMMY_SP })),
640 BabelStmt::OpaqueType(d) => self
641 .extract_source_stmt(&d.base)
642 .unwrap_or(Stmt::Empty(EmptyStmt { span: DUMMY_SP })),
643 BabelStmt::InterfaceDeclaration(d) => self
644 .extract_source_stmt(&d.base)
645 .unwrap_or(Stmt::Empty(EmptyStmt { span: DUMMY_SP })),
646 BabelStmt::EnumDeclaration(d) => self
647 .extract_source_stmt(&d.base)
648 .unwrap_or(Stmt::Empty(EmptyStmt { span: DUMMY_SP })),
649 BabelStmt::TSModuleDeclaration(_)
651 | BabelStmt::TSDeclareFunction(_)
652 | BabelStmt::DeclareVariable(_)
653 | BabelStmt::DeclareFunction(_)
654 | BabelStmt::DeclareClass(_)
655 | BabelStmt::DeclareModule(_)
656 | BabelStmt::DeclareModuleExports(_)
657 | BabelStmt::DeclareExportDeclaration(_)
658 | BabelStmt::DeclareExportAllDeclaration(_)
659 | BabelStmt::DeclareInterface(_)
660 | BabelStmt::DeclareTypeAlias(_)
661 | BabelStmt::DeclareOpaqueType(_) => Stmt::Empty(EmptyStmt { span: DUMMY_SP }),
662 BabelStmt::Unknown(unknown) => {
667 let message = format!(
668 "[react-compiler] internal error: unmodeled statement `{}` reached the SWC reverse converter",
669 unknown.node_type()
670 );
671 Stmt::Throw(ThrowStmt {
672 span: DUMMY_SP,
673 arg: Box::new(Expr::Lit(Lit::Str(Str {
674 span: DUMMY_SP,
675 value: self.wtf8(&message),
676 raw: None,
677 }))),
678 })
679 }
680 }
681 }
682
683 fn convert_block_statement(&self, block: &babel_stmt::BlockStatement) -> BlockStmt {
684 let mut stmts: Vec<Stmt> = Vec::new();
685
686 for dir in &block.directives {
688 let span = self.span(&dir.base);
689 let str_span = self.span(&dir.value.base);
690 stmts.push(Stmt::Expr(ExprStmt {
691 span,
692 expr: Box::new(Expr::Lit(Lit::Str(Str {
693 span: str_span,
694 value: self.wtf8(&dir.value.value),
695 raw: None,
696 }))),
697 }));
698 }
699
700 for s in &block.body {
701 stmts.push(self.convert_statement(s));
702 }
703
704 BlockStmt {
705 span: self.span(&block.base),
706 ctxt: SyntaxContext::empty(),
707 stmts,
708 }
709 }
710
711 fn convert_catch_clause(&self, clause: &babel_stmt::CatchClause) -> CatchClause {
712 let param = clause.param.as_ref().map(|p| self.convert_pattern(p));
713 CatchClause {
714 span: self.span(&clause.base),
715 param,
716 body: self.convert_block_statement(&clause.body),
717 }
718 }
719
720 fn convert_for_init(&self, init: &babel_stmt::ForInit) -> VarDeclOrExpr {
721 match init {
722 babel_stmt::ForInit::VariableDeclaration(v) => {
723 VarDeclOrExpr::VarDecl(Box::new(self.convert_variable_declaration(v)))
724 }
725 babel_stmt::ForInit::Expression(e) => {
726 VarDeclOrExpr::Expr(Box::new(self.convert_expression(e)))
727 }
728 }
729 }
730
731 fn convert_for_in_of_left(&self, left: &babel_stmt::ForInOfLeft) -> ForHead {
732 match left {
733 babel_stmt::ForInOfLeft::VariableDeclaration(v) => {
734 ForHead::VarDecl(Box::new(self.convert_variable_declaration(v)))
735 }
736 babel_stmt::ForInOfLeft::Pattern(p) => ForHead::Pat(Box::new(self.convert_pattern(p))),
737 }
738 }
739
740 fn convert_variable_declaration(&self, decl: &babel_stmt::VariableDeclaration) -> VarDecl {
741 let kind = match decl.kind {
742 babel_stmt::VariableDeclarationKind::Var => VarDeclKind::Var,
743 babel_stmt::VariableDeclarationKind::Let => VarDeclKind::Let,
744 babel_stmt::VariableDeclarationKind::Const => VarDeclKind::Const,
745 babel_stmt::VariableDeclarationKind::Using => VarDeclKind::Var, };
747 let decls = decl
748 .declarations
749 .iter()
750 .map(|d| self.convert_variable_declarator(d))
751 .collect();
752 let declare = decl.declare.unwrap_or(false);
753 VarDecl {
754 span: self.span(&decl.base),
755 ctxt: SyntaxContext::empty(),
756 kind,
757 declare,
758 decls,
759 }
760 }
761
762 fn convert_variable_declarator(&self, d: &babel_stmt::VariableDeclarator) -> VarDeclarator {
763 let name = self.convert_pattern(&d.id);
764 let init = d
765 .init
766 .as_ref()
767 .map(|e| Box::new(self.convert_expression(e)));
768 let definite = d.definite.unwrap_or(false);
769 VarDeclarator {
770 span: self.span(&d.base),
771 name,
772 init,
773 definite,
774 }
775 }
776
777 fn convert_expression(&self, expr: &BabelExpr) -> Expr {
780 match expr {
781 BabelExpr::Identifier(id) => {
782 let span = self.span(&id.base);
783 Expr::Ident(self.ident(&id.name, span))
784 }
785 BabelExpr::StringLiteral(lit) => Expr::Lit(Lit::Str(Str {
786 span: self.span(&lit.base),
787 value: self.wtf8(&lit.value),
788 raw: self.escape_string_raw(&lit.value),
789 })),
790 BabelExpr::NumericLiteral(lit) => {
791 let value = if lit.value == 0.0 && lit.value.is_sign_negative() {
794 0.0
795 } else {
796 lit.value
797 };
798 Expr::Lit(Lit::Num(Number {
799 span: self.span(&lit.base),
800 value,
801 raw: None,
802 }))
803 }
804 BabelExpr::BooleanLiteral(lit) => Expr::Lit(Lit::Bool(Bool {
805 span: self.span(&lit.base),
806 value: lit.value,
807 })),
808 BabelExpr::NullLiteral(lit) => Expr::Lit(Lit::Null(Null {
809 span: self.span(&lit.base),
810 })),
811 BabelExpr::BigIntLiteral(lit) => Expr::Lit(Lit::BigInt(BigInt {
812 span: self.span(&lit.base),
813 value: Box::new(lit.value.parse().unwrap_or_default()),
814 raw: None,
815 })),
816 BabelExpr::RegExpLiteral(lit) => Expr::Lit(Lit::Regex(Regex {
817 span: self.span(&lit.base),
818 exp: self.atom(&lit.pattern),
819 flags: self.atom(&lit.flags),
820 })),
821 BabelExpr::CallExpression(call) => {
822 let callee = self.convert_expression(&call.callee);
823 let args = self.convert_arguments(&call.arguments);
824 let callee = match &callee {
828 Expr::Arrow(_) | Expr::Fn(_) => Expr::Paren(ParenExpr {
829 span: callee.span(),
830 expr: Box::new(callee),
831 }),
832 _ => callee,
833 };
834 Expr::Call(CallExpr {
835 span: self.span(&call.base),
836 ctxt: SyntaxContext::empty(),
837 callee: Callee::Expr(Box::new(callee)),
838 args,
839 type_args: None,
840 })
841 }
842 BabelExpr::MemberExpression(m) => self.convert_member_expression(m),
843 BabelExpr::OptionalCallExpression(call) => {
844 let callee = self.convert_expression_for_chain(&call.callee);
845 let args = self.convert_arguments(&call.arguments);
846 let base = OptChainBase::Call(OptCall {
847 span: self.span(&call.base),
848 ctxt: SyntaxContext::empty(),
849 callee: Box::new(callee),
850 args,
851 type_args: None,
852 });
853 Expr::OptChain(OptChainExpr {
854 span: self.span(&call.base),
855 optional: call.optional,
856 base: Box::new(base),
857 })
858 }
859 BabelExpr::OptionalMemberExpression(m) => {
860 let base = self.convert_optional_member_to_chain_base(m);
861 Expr::OptChain(OptChainExpr {
862 span: self.span(&m.base),
863 optional: m.optional,
864 base: Box::new(base),
865 })
866 }
867 BabelExpr::BinaryExpression(bin) => {
868 let op = self.convert_binary_operator(&bin.operator);
869 Expr::Bin(BinExpr {
870 span: self.span(&bin.base),
871 op,
872 left: Box::new(self.convert_expression(&bin.left)),
873 right: Box::new(self.convert_expression(&bin.right)),
874 })
875 }
876 BabelExpr::LogicalExpression(log) => {
877 let op = self.convert_logical_operator(&log.operator);
878 let span = self.span(&log.base);
879 let bin = Expr::Bin(BinExpr {
880 span,
881 op,
882 left: Box::new(self.convert_expression(&log.left)),
883 right: Box::new(self.convert_expression(&log.right)),
884 });
885 Expr::Paren(ParenExpr {
891 span,
892 expr: Box::new(bin),
893 })
894 }
895 BabelExpr::UnaryExpression(un) => {
896 let op = self.convert_unary_operator(&un.operator);
897 Expr::Unary(UnaryExpr {
898 span: self.span(&un.base),
899 op,
900 arg: Box::new(self.convert_expression(&un.argument)),
901 })
902 }
903 BabelExpr::UpdateExpression(up) => {
904 let op = self.convert_update_operator(&up.operator);
905 Expr::Update(UpdateExpr {
906 span: self.span(&up.base),
907 op,
908 prefix: up.prefix,
909 arg: Box::new(self.convert_expression(&up.argument)),
910 })
911 }
912 BabelExpr::ConditionalExpression(cond) => {
913 let span = self.span(&cond.base);
914 Expr::Paren(ParenExpr {
919 span,
920 expr: Box::new(Expr::Cond(CondExpr {
921 span,
922 test: Box::new(self.convert_expression(&cond.test)),
923 cons: Box::new(self.convert_expression(&cond.consequent)),
924 alt: Box::new(self.convert_expression(&cond.alternate)),
925 })),
926 })
927 }
928 BabelExpr::AssignmentExpression(assign) => {
929 let op = self.convert_assignment_operator(&assign.operator);
930 let left = self.convert_pattern_to_assign_target(&assign.left);
931 let span = self.span(&assign.base);
932 let assign_expr = Expr::Assign(AssignExpr {
933 span,
934 op,
935 left,
936 right: Box::new(self.convert_expression(&assign.right)),
937 });
938 Expr::Paren(ParenExpr {
943 span,
944 expr: Box::new(assign_expr),
945 })
946 }
947 BabelExpr::SequenceExpression(seq) => {
948 let exprs = seq
949 .expressions
950 .iter()
951 .map(|e| Box::new(self.convert_expression(e)))
952 .collect();
953 let span = self.span(&seq.base);
954 Expr::Paren(ParenExpr {
959 span,
960 expr: Box::new(Expr::Seq(SeqExpr { span, exprs })),
961 })
962 }
963 BabelExpr::ArrowFunctionExpression(arrow) => self.convert_arrow_function(arrow),
964 BabelExpr::FunctionExpression(func) => {
965 let ident = func
966 .id
967 .as_ref()
968 .map(|id| self.ident(&id.name, self.span(&id.base)));
969 let params = self.convert_params(&func.params);
970 let body = Some(self.convert_block_statement(&func.body));
971 Expr::Fn(FnExpr {
972 ident,
973 function: Box::new(Function {
974 params,
975 decorators: vec![],
976 span: self.span(&func.base),
977 ctxt: SyntaxContext::empty(),
978 body,
979 is_generator: func.generator,
980 is_async: func.is_async,
981 type_params: None,
982 return_type: None,
983 }),
984 })
985 }
986 BabelExpr::ObjectExpression(obj) => {
987 let props = obj
988 .properties
989 .iter()
990 .map(|p| self.convert_object_expression_property(p))
991 .collect();
992 Expr::Object(ObjectLit {
993 span: self.span(&obj.base),
994 props,
995 })
996 }
997 BabelExpr::ArrayExpression(arr) => {
998 let elems = arr
999 .elements
1000 .iter()
1001 .map(|e| self.convert_array_element(e))
1002 .collect();
1003 Expr::Array(ArrayLit {
1004 span: self.span(&arr.base),
1005 elems,
1006 })
1007 }
1008 BabelExpr::NewExpression(n) => {
1009 let callee = Box::new(self.convert_expression(&n.callee));
1010 let args = Some(self.convert_arguments(&n.arguments));
1011 Expr::New(NewExpr {
1012 span: self.span(&n.base),
1013 ctxt: SyntaxContext::empty(),
1014 callee,
1015 args,
1016 type_args: None,
1017 })
1018 }
1019 BabelExpr::TemplateLiteral(tl) => {
1020 let template = self.convert_template_literal(tl);
1021 Expr::Tpl(template)
1022 }
1023 BabelExpr::TaggedTemplateExpression(tag) => {
1024 let t = Box::new(self.convert_expression(&tag.tag));
1025 let tpl = Box::new(self.convert_template_literal(&tag.quasi));
1026 Expr::TaggedTpl(TaggedTpl {
1027 span: self.span(&tag.base),
1028 ctxt: SyntaxContext::empty(),
1029 tag: t,
1030 type_params: None,
1031 tpl,
1032 })
1033 }
1034 BabelExpr::AwaitExpression(a) => Expr::Await(AwaitExpr {
1035 span: self.span(&a.base),
1036 arg: Box::new(self.convert_expression(&a.argument)),
1037 }),
1038 BabelExpr::YieldExpression(y) => Expr::Yield(YieldExpr {
1039 span: self.span(&y.base),
1040 delegate: y.delegate,
1041 arg: y
1042 .argument
1043 .as_ref()
1044 .map(|a| Box::new(self.convert_expression(a))),
1045 }),
1046 BabelExpr::SpreadElement(s) => {
1047 self.convert_expression(&s.argument)
1050 }
1051 BabelExpr::MetaProperty(mp) => Expr::MetaProp(MetaPropExpr {
1052 span: self.span(&mp.base),
1053 kind: match (mp.meta.name.as_str(), mp.property.name.as_str()) {
1054 ("new", "target") => MetaPropKind::NewTarget,
1055 ("import", "meta") => MetaPropKind::ImportMeta,
1056 _ => MetaPropKind::NewTarget,
1057 },
1058 }),
1059 BabelExpr::ClassExpression(c) => {
1060 let ident =
1061 c.id.as_ref()
1062 .map(|id| self.ident(&id.name, self.span(&id.base)));
1063 let super_class = c
1064 .super_class
1065 .as_ref()
1066 .map(|s| Box::new(self.convert_expression(s)));
1067 Expr::Class(ClassExpr {
1068 ident,
1069 class: Box::new(Class {
1070 span: self.span(&c.base),
1071 ctxt: SyntaxContext::empty(),
1072 decorators: vec![],
1073 body: vec![],
1074 super_class,
1075 is_abstract: false,
1076 type_params: None,
1077 super_type_params: None,
1078 implements: vec![],
1079 }),
1080 })
1081 }
1082 BabelExpr::PrivateName(p) => Expr::PrivateName(PrivateName {
1083 span: self.span(&p.base),
1084 name: self.atom(&p.id.name),
1085 }),
1086 BabelExpr::Super(s) => Expr::Ident(self.ident("super", self.span(&s.base))),
1087 BabelExpr::Import(i) => Expr::Ident(self.ident("import", self.span(&i.base))),
1088 BabelExpr::ThisExpression(t) => Expr::This(ThisExpr {
1089 span: self.span(&t.base),
1090 }),
1091 BabelExpr::ParenthesizedExpression(p) => Expr::Paren(ParenExpr {
1092 span: self.span(&p.base),
1093 expr: Box::new(self.convert_expression(&p.expression)),
1094 }),
1095 BabelExpr::JSXElement(el) => {
1096 let element = self.convert_jsx_element(el.as_ref());
1097 Expr::JSXElement(Box::new(element))
1098 }
1099 BabelExpr::JSXFragment(frag) => {
1100 let fragment = self.convert_jsx_fragment(frag);
1101 Expr::JSXFragment(fragment)
1102 }
1103 BabelExpr::TSAsExpression(e) => {
1105 let expr = Box::new(self.convert_expression(&e.expression));
1106 let span = self.span(&e.base);
1107 let annotation = e.type_annotation.parse_value();
1108 let is_as_const = annotation.get("type").and_then(|v| v.as_str())
1111 == Some("TSTypeReference")
1112 && annotation
1113 .get("typeName")
1114 .and_then(|tn| tn.get("name"))
1115 .and_then(|n| n.as_str())
1116 == Some("const");
1117
1118 if is_as_const {
1119 Expr::TsConstAssertion(TsConstAssertion { span, expr })
1120 } else {
1121 let type_ann = self.convert_ts_type_from_json(&annotation, span);
1122 Expr::TsAs(TsAsExpr {
1123 span,
1124 expr,
1125 type_ann: Box::new(type_ann),
1126 })
1127 }
1128 }
1129 BabelExpr::TSSatisfiesExpression(e) => self.convert_expression(&e.expression),
1130 BabelExpr::TSNonNullExpression(e) => Expr::TsNonNull(TsNonNullExpr {
1131 span: self.span(&e.base),
1132 expr: Box::new(self.convert_expression(&e.expression)),
1133 }),
1134 BabelExpr::TSTypeAssertion(e) => self.convert_expression(&e.expression),
1135 BabelExpr::TSInstantiationExpression(e) => self.convert_expression(&e.expression),
1136 BabelExpr::TypeCastExpression(e) => self.convert_expression(&e.expression),
1137 BabelExpr::AssignmentPattern(p) => {
1138 let left = self.convert_pattern_to_assign_target(&p.left);
1139 Expr::Assign(AssignExpr {
1140 span: self.span(&p.base),
1141 op: AssignOp::Assign,
1142 left,
1143 right: Box::new(self.convert_expression(&p.right)),
1144 })
1145 }
1146 }
1147 }
1148
1149 fn convert_expression_for_chain(&self, expr: &BabelExpr) -> Expr {
1161 match expr {
1162 BabelExpr::OptionalMemberExpression(m) => {
1163 if m.optional {
1164 let base = self.convert_optional_member_to_chain_base(m);
1166 Expr::OptChain(OptChainExpr {
1167 span: self.span(&m.base),
1168 optional: true,
1169 base: Box::new(base),
1170 })
1171 } else {
1172 self.convert_optional_member_to_member_expr(m)
1174 }
1175 }
1176 BabelExpr::OptionalCallExpression(call) => {
1177 let callee = self.convert_expression_for_chain(&call.callee);
1178 let args = self.convert_arguments(&call.arguments);
1179 if call.optional {
1180 let base = OptChainBase::Call(OptCall {
1182 span: self.span(&call.base),
1183 ctxt: SyntaxContext::empty(),
1184 callee: Box::new(callee),
1185 args,
1186 type_args: None,
1187 });
1188 Expr::OptChain(OptChainExpr {
1189 span: self.span(&call.base),
1190 optional: true,
1191 base: Box::new(base),
1192 })
1193 } else {
1194 Expr::Call(CallExpr {
1196 span: self.span(&call.base),
1197 ctxt: SyntaxContext::empty(),
1198 callee: Callee::Expr(Box::new(callee)),
1199 args,
1200 type_args: None,
1201 })
1202 }
1203 }
1204 _ => self.convert_expression(expr),
1205 }
1206 }
1207
1208 fn convert_member_expression(&self, m: &babel_expr::MemberExpression) -> Expr {
1209 let object = self.convert_expression(&m.object);
1210 let object = match &object {
1215 Expr::OptChain(_) => Box::new(Expr::Paren(ParenExpr {
1216 span: object.span(),
1217 expr: Box::new(object),
1218 })),
1219 _ => Box::new(object),
1220 };
1221 if m.computed {
1222 let property = self.convert_expression(&m.property);
1223 Expr::Member(MemberExpr {
1224 span: self.span(&m.base),
1225 obj: object,
1226 prop: MemberProp::Computed(ComputedPropName {
1227 span: DUMMY_SP,
1228 expr: Box::new(property),
1229 }),
1230 })
1231 } else {
1232 let prop_name = self.expression_to_ident_name(&m.property);
1233 Expr::Member(MemberExpr {
1234 span: self.span(&m.base),
1235 obj: object,
1236 prop: MemberProp::Ident(prop_name),
1237 })
1238 }
1239 }
1240
1241 fn convert_optional_member_to_chain_base(
1242 &self,
1243 m: &babel_expr::OptionalMemberExpression,
1244 ) -> OptChainBase {
1245 let object = Box::new(self.convert_expression_for_chain(&m.object));
1246 if m.computed {
1247 let property = self.convert_expression(&m.property);
1248 OptChainBase::Member(MemberExpr {
1249 span: self.span(&m.base),
1250 obj: object,
1251 prop: MemberProp::Computed(ComputedPropName {
1252 span: DUMMY_SP,
1253 expr: Box::new(property),
1254 }),
1255 })
1256 } else {
1257 let prop_name = self.expression_to_ident_name(&m.property);
1258 OptChainBase::Member(MemberExpr {
1259 span: self.span(&m.base),
1260 obj: object,
1261 prop: MemberProp::Ident(prop_name),
1262 })
1263 }
1264 }
1265
1266 fn convert_optional_member_to_member_expr(
1267 &self,
1268 m: &babel_expr::OptionalMemberExpression,
1269 ) -> Expr {
1270 let object = Box::new(self.convert_expression_for_chain(&m.object));
1271 if m.computed {
1272 let property = self.convert_expression(&m.property);
1273 Expr::Member(MemberExpr {
1274 span: self.span(&m.base),
1275 obj: object,
1276 prop: MemberProp::Computed(ComputedPropName {
1277 span: DUMMY_SP,
1278 expr: Box::new(property),
1279 }),
1280 })
1281 } else {
1282 let prop_name = self.expression_to_ident_name(&m.property);
1283 Expr::Member(MemberExpr {
1284 span: self.span(&m.base),
1285 obj: object,
1286 prop: MemberProp::Ident(prop_name),
1287 })
1288 }
1289 }
1290
1291 fn expression_to_ident_name(&self, expr: &BabelExpr) -> IdentName {
1292 match expr {
1293 BabelExpr::Identifier(id) => self.ident_name(&id.name, self.span(&id.base)),
1294 _ => self.ident_name("__unknown__", DUMMY_SP),
1295 }
1296 }
1297
1298 fn convert_arguments(&self, args: &[BabelExpr]) -> Vec<ExprOrSpread> {
1299 args.iter().map(|a| self.convert_argument(a)).collect()
1300 }
1301
1302 fn convert_argument(&self, arg: &BabelExpr) -> ExprOrSpread {
1303 match arg {
1304 BabelExpr::SpreadElement(s) => ExprOrSpread {
1305 spread: Some(self.span(&s.base)),
1306 expr: Box::new(self.convert_expression(&s.argument)),
1307 },
1308 _ => ExprOrSpread {
1309 spread: None,
1310 expr: Box::new(self.convert_expression(arg)),
1311 },
1312 }
1313 }
1314
1315 fn convert_array_element(&self, elem: &Option<BabelExpr>) -> Option<ExprOrSpread> {
1316 match elem {
1317 None => None,
1318 Some(BabelExpr::SpreadElement(s)) => Some(ExprOrSpread {
1319 spread: Some(self.span(&s.base)),
1320 expr: Box::new(self.convert_expression(&s.argument)),
1321 }),
1322 Some(e) => Some(ExprOrSpread {
1323 spread: None,
1324 expr: Box::new(self.convert_expression(e)),
1325 }),
1326 }
1327 }
1328
1329 fn convert_object_expression_property(
1330 &self,
1331 prop: &babel_expr::ObjectExpressionProperty,
1332 ) -> PropOrSpread {
1333 match prop {
1334 babel_expr::ObjectExpressionProperty::ObjectProperty(p) => {
1335 let key = if p.computed {
1336 PropName::Computed(ComputedPropName {
1338 span: DUMMY_SP,
1339 expr: Box::new(self.convert_expression(&p.key)),
1340 })
1341 } else {
1342 self.convert_expression_to_prop_name(&p.key)
1343 };
1344 let value = self.convert_expression(&p.value);
1345 let method = p.method.unwrap_or(false);
1346
1347 if p.shorthand {
1348 PropOrSpread::Prop(Box::new(Prop::Shorthand(match &*p.key {
1349 BabelExpr::Identifier(id) => self.ident(&id.name, self.span(&id.base)),
1350 _ => self.ident("__unknown__", DUMMY_SP),
1351 })))
1352 } else if method {
1353 let func = match value {
1356 Expr::Fn(fn_expr) => *fn_expr.function,
1357 _ => {
1358 return PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
1360 key,
1361 value: Box::new(value),
1362 })));
1363 }
1364 };
1365 PropOrSpread::Prop(Box::new(Prop::Method(MethodProp {
1366 key,
1367 function: Box::new(func),
1368 })))
1369 } else {
1370 PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
1371 key,
1372 value: Box::new(value),
1373 })))
1374 }
1375 }
1376 babel_expr::ObjectExpressionProperty::ObjectMethod(m) => {
1377 let key = if m.computed {
1378 PropName::Computed(ComputedPropName {
1379 span: DUMMY_SP,
1380 expr: Box::new(self.convert_expression(&m.key)),
1381 })
1382 } else {
1383 self.convert_expression_to_prop_name(&m.key)
1384 };
1385 let func = self.convert_object_method_to_function(m);
1386 match m.kind {
1387 babel_expr::ObjectMethodKind::Get => {
1388 PropOrSpread::Prop(Box::new(Prop::Getter(GetterProp {
1389 span: self.span(&m.base),
1390 key,
1391 type_ann: None,
1392 body: func.body,
1393 })))
1394 }
1395 babel_expr::ObjectMethodKind::Set => {
1396 let param = func
1397 .params
1398 .into_iter()
1399 .next()
1400 .map(|p| Box::new(p.pat))
1401 .unwrap_or_else(|| {
1402 Box::new(Pat::Ident(self.binding_ident("_", DUMMY_SP)))
1403 });
1404 PropOrSpread::Prop(Box::new(Prop::Setter(SetterProp {
1405 span: self.span(&m.base),
1406 key,
1407 this_param: None,
1408 param,
1409 body: func.body,
1410 })))
1411 }
1412 babel_expr::ObjectMethodKind::Method => {
1413 PropOrSpread::Prop(Box::new(Prop::Method(MethodProp {
1414 key,
1415 function: Box::new(func),
1416 })))
1417 }
1418 }
1419 }
1420 babel_expr::ObjectExpressionProperty::SpreadElement(s) => {
1421 PropOrSpread::Spread(SpreadElement {
1422 dot3_token: self.span(&s.base),
1423 expr: Box::new(self.convert_expression(&s.argument)),
1424 })
1425 }
1426 }
1427 }
1428
1429 fn convert_expression_to_prop_name(&self, expr: &BabelExpr) -> PropName {
1430 match expr {
1431 BabelExpr::Identifier(id) => {
1432 PropName::Ident(self.ident_name(&id.name, self.span(&id.base)))
1433 }
1434 BabelExpr::StringLiteral(s) => PropName::Str(Str {
1435 span: self.span(&s.base),
1436 value: self.wtf8(&s.value),
1437 raw: None,
1438 }),
1439 BabelExpr::NumericLiteral(n) => PropName::Num(Number {
1440 span: self.span(&n.base),
1441 value: n.value,
1442 raw: None,
1443 }),
1444 _ => PropName::Computed(ComputedPropName {
1445 span: DUMMY_SP,
1446 expr: Box::new(self.convert_expression(expr)),
1447 }),
1448 }
1449 }
1450
1451 fn convert_template_literal(&self, tl: &babel_expr::TemplateLiteral) -> Tpl {
1452 let quasis = tl
1453 .quasis
1454 .iter()
1455 .map(|q| {
1456 let cooked = q.value.cooked.as_ref().map(|c| self.wtf8(c));
1457 TplElement {
1458 span: self.span(&q.base),
1459 tail: q.tail,
1460 cooked,
1461 raw: self.atom(&q.value.raw),
1462 }
1463 })
1464 .collect();
1465 let exprs = tl
1466 .expressions
1467 .iter()
1468 .map(|e| Box::new(self.convert_expression(e)))
1469 .collect();
1470 Tpl {
1471 span: self.span(&tl.base),
1472 exprs,
1473 quasis,
1474 }
1475 }
1476
1477 fn convert_function_declaration(&self, f: &babel_stmt::FunctionDeclaration) -> FnDecl {
1480 let ident =
1481 f.id.as_ref()
1482 .map(|id| self.ident(&id.name, self.span(&id.base)))
1483 .unwrap_or_else(|| self.ident("_anonymous", DUMMY_SP));
1484 let params = self.convert_params(&f.params);
1485 let body = Some(self.convert_block_statement(&f.body));
1486 let declare = f.declare.unwrap_or(false);
1487 FnDecl {
1488 ident,
1489 declare,
1490 function: Box::new(Function {
1491 params,
1492 decorators: vec![],
1493 span: self.span(&f.base),
1494 ctxt: SyntaxContext::empty(),
1495 body,
1496 is_generator: f.generator,
1497 is_async: f.is_async,
1498 type_params: None,
1499 return_type: None,
1500 }),
1501 }
1502 }
1503
1504 fn convert_object_method_to_function(&self, m: &babel_expr::ObjectMethod) -> Function {
1505 let params = self.convert_params(&m.params);
1506 let body = Some(self.convert_block_statement(&m.body));
1507 Function {
1508 params,
1509 decorators: vec![],
1510 span: self.span(&m.base),
1511 ctxt: SyntaxContext::empty(),
1512 body,
1513 is_generator: m.generator,
1514 is_async: m.is_async,
1515 type_params: None,
1516 return_type: None,
1517 }
1518 }
1519
1520 fn convert_arrow_function(&self, arrow: &babel_expr::ArrowFunctionExpression) -> Expr {
1521 let is_expression = arrow.expression.unwrap_or(false);
1522 let params = arrow
1523 .params
1524 .iter()
1525 .map(|p| self.convert_pattern(p))
1526 .collect();
1527
1528 let body: Box<BlockStmtOrExpr> = match &*arrow.body {
1529 babel_expr::ArrowFunctionBody::BlockStatement(block) => Box::new(
1530 BlockStmtOrExpr::BlockStmt(self.convert_block_statement(block)),
1531 ),
1532 babel_expr::ArrowFunctionBody::Expression(expr) => {
1533 if is_expression {
1534 let converted = self.convert_expression(expr);
1535 let converted = if matches!(&converted, Expr::Object(_)) {
1538 Expr::Paren(ParenExpr {
1539 span: converted.span(),
1540 expr: Box::new(converted),
1541 })
1542 } else {
1543 converted
1544 };
1545 Box::new(BlockStmtOrExpr::Expr(Box::new(converted)))
1546 } else {
1547 let ret_stmt = Stmt::Return(ReturnStmt {
1549 span: DUMMY_SP,
1550 arg: Some(Box::new(self.convert_expression(expr))),
1551 });
1552 Box::new(BlockStmtOrExpr::BlockStmt(BlockStmt {
1553 span: DUMMY_SP,
1554 ctxt: SyntaxContext::empty(),
1555 stmts: vec![ret_stmt],
1556 }))
1557 }
1558 }
1559 };
1560
1561 Expr::Arrow(ArrowExpr {
1562 span: self.span(&arrow.base),
1563 ctxt: SyntaxContext::empty(),
1564 params,
1565 body,
1566 is_async: arrow.is_async,
1567 is_generator: arrow.generator,
1568 return_type: None,
1569 type_params: None,
1570 })
1571 }
1572
1573 fn convert_params(&self, params: &[PatternLike]) -> Vec<Param> {
1574 params
1575 .iter()
1576 .map(|p| Param {
1577 span: DUMMY_SP,
1578 decorators: vec![],
1579 pat: self.convert_pattern(p),
1580 })
1581 .collect()
1582 }
1583
1584 fn convert_pattern(&self, pattern: &PatternLike) -> Pat {
1587 match pattern {
1588 PatternLike::Identifier(id) => {
1589 let mut bi = self.binding_ident(&id.name, self.span(&id.base));
1590 bi.id.optional = id.optional.unwrap_or(false);
1591 if let Some(ref type_ann) = id.type_annotation {
1593 bi.type_ann =
1594 self.convert_ts_type_annotation_from_json(&type_ann.parse_value());
1595 }
1596 Pat::Ident(bi)
1597 }
1598 PatternLike::ObjectPattern(obj) => {
1599 let mut props: Vec<ObjectPatProp> = Vec::new();
1600
1601 for prop in &obj.properties {
1602 match prop {
1603 ObjectPatternProperty::ObjectProperty(p) => {
1604 if p.shorthand {
1605 let value = self.convert_pattern(&p.value);
1607 match &*p.key {
1608 BabelExpr::Identifier(id) => {
1609 let key_ident =
1610 self.binding_ident(&id.name, self.span(&id.base));
1611 match value {
1612 Pat::Assign(assign_pat) => {
1613 props.push(ObjectPatProp::Assign(AssignPatProp {
1614 span: self.span(&p.base),
1615 key: key_ident,
1616 value: Some(assign_pat.right),
1617 }));
1618 }
1619 _ => {
1620 props.push(ObjectPatProp::Assign(AssignPatProp {
1621 span: self.span(&p.base),
1622 key: key_ident,
1623 value: None,
1624 }));
1625 }
1626 }
1627 }
1628 _ => {
1629 let key = self.convert_expression_to_prop_name(&p.key);
1631 props.push(ObjectPatProp::KeyValue(KeyValuePatProp {
1632 key,
1633 value: Box::new(value),
1634 }));
1635 }
1636 }
1637 } else {
1638 let key = self.convert_expression_to_prop_name(&p.key);
1639 let value = self.convert_pattern(&p.value);
1640 props.push(ObjectPatProp::KeyValue(KeyValuePatProp {
1641 key,
1642 value: Box::new(value),
1643 }));
1644 }
1645 }
1646 ObjectPatternProperty::RestElement(r) => {
1647 let arg = Box::new(self.convert_pattern(&r.argument));
1648 props.push(ObjectPatProp::Rest(RestPat {
1649 span: self.span(&r.base),
1650 dot3_token: self.span(&r.base),
1651 arg,
1652 type_ann: None,
1653 }));
1654 }
1655 }
1656 }
1657
1658 Pat::Object(ObjectPat {
1659 span: self.span(&obj.base),
1660 props,
1661 optional: false,
1662 type_ann: None,
1663 })
1664 }
1665 PatternLike::ArrayPattern(arr) => {
1666 let elems = arr
1667 .elements
1668 .iter()
1669 .map(|e| e.as_ref().map(|p| self.convert_pattern(p)))
1670 .collect();
1671 Pat::Array(ArrayPat {
1672 span: self.span(&arr.base),
1673 elems,
1674 optional: false,
1675 type_ann: None,
1676 })
1677 }
1678 PatternLike::AssignmentPattern(ap) => {
1679 let left = Box::new(self.convert_pattern(&ap.left));
1680 let right = Box::new(self.convert_expression(&ap.right));
1681 Pat::Assign(AssignPat {
1682 span: self.span(&ap.base),
1683 left,
1684 right,
1685 })
1686 }
1687 PatternLike::RestElement(r) => {
1688 let arg = Box::new(self.convert_pattern(&r.argument));
1689 Pat::Rest(RestPat {
1690 span: self.span(&r.base),
1691 dot3_token: self.span(&r.base),
1692 arg,
1693 type_ann: None,
1694 })
1695 }
1696 PatternLike::MemberExpression(m) => {
1697 Pat::Expr(Box::new(self.convert_member_expression(m)))
1699 }
1700 PatternLike::TSAsExpression(e) => {
1703 Pat::Expr(Box::new(self.convert_expression(&e.expression)))
1704 }
1705 PatternLike::TSSatisfiesExpression(e) => {
1706 Pat::Expr(Box::new(self.convert_expression(&e.expression)))
1707 }
1708 PatternLike::TSNonNullExpression(e) => {
1709 Pat::Expr(Box::new(self.convert_expression(&e.expression)))
1710 }
1711 PatternLike::TSTypeAssertion(e) => {
1712 Pat::Expr(Box::new(self.convert_expression(&e.expression)))
1713 }
1714 PatternLike::TypeCastExpression(e) => {
1715 Pat::Expr(Box::new(self.convert_expression(&e.expression)))
1716 }
1717 }
1718 }
1719
1720 fn convert_pattern_to_assign_target(&self, pattern: &PatternLike) -> AssignTarget {
1723 match pattern {
1724 PatternLike::Identifier(id) => AssignTarget::Simple(SimpleAssignTarget::Ident(
1725 self.binding_ident(&id.name, self.span(&id.base)),
1726 )),
1727 PatternLike::MemberExpression(m) => {
1728 let expr = self.convert_member_expression(m);
1729 match expr {
1730 Expr::Member(member) => {
1731 AssignTarget::Simple(SimpleAssignTarget::Member(member))
1732 }
1733 _ => AssignTarget::Simple(SimpleAssignTarget::Ident(
1734 self.binding_ident("__unknown__", DUMMY_SP),
1735 )),
1736 }
1737 }
1738 PatternLike::ObjectPattern(_obj) => {
1739 let pat = self.convert_pattern(pattern);
1740 match pat {
1741 Pat::Object(obj_pat) => AssignTarget::Pat(AssignTargetPat::Object(obj_pat)),
1742 _ => AssignTarget::Simple(SimpleAssignTarget::Ident(
1743 self.binding_ident("__unknown__", DUMMY_SP),
1744 )),
1745 }
1746 }
1747 PatternLike::ArrayPattern(_arr) => {
1748 let pat = self.convert_pattern(pattern);
1749 match pat {
1750 Pat::Array(arr_pat) => AssignTarget::Pat(AssignTargetPat::Array(arr_pat)),
1751 _ => AssignTarget::Simple(SimpleAssignTarget::Ident(
1752 self.binding_ident("__unknown__", DUMMY_SP),
1753 )),
1754 }
1755 }
1756 PatternLike::AssignmentPattern(ap) => {
1757 self.convert_pattern_to_assign_target(&ap.left)
1759 }
1760 PatternLike::RestElement(r) => self.convert_pattern_to_assign_target(&r.argument),
1761 PatternLike::TSAsExpression(_)
1762 | PatternLike::TSSatisfiesExpression(_)
1763 | PatternLike::TSNonNullExpression(_)
1764 | PatternLike::TSTypeAssertion(_)
1765 | PatternLike::TypeCastExpression(_) => AssignTarget::Simple(
1766 SimpleAssignTarget::Ident(self.binding_ident("__unknown__", DUMMY_SP)),
1767 ),
1768 }
1769 }
1770
1771 fn convert_jsx_element(
1774 &self,
1775 el: &react_compiler_ast::jsx::JSXElement,
1776 ) -> swc_ecma_ast::JSXElement {
1777 let opening = self.convert_jsx_opening_element(&el.opening_element);
1778 let children: Vec<swc_ecma_ast::JSXElementChild> = el
1779 .children
1780 .iter()
1781 .map(|c| self.convert_jsx_child(c))
1782 .collect();
1783 let closing = el
1784 .closing_element
1785 .as_ref()
1786 .map(|c| self.convert_jsx_closing_element(c));
1787 swc_ecma_ast::JSXElement {
1788 span: self.span(&el.base),
1789 opening,
1790 children,
1791 closing,
1792 }
1793 }
1794
1795 fn convert_jsx_opening_element(
1796 &self,
1797 el: &react_compiler_ast::jsx::JSXOpeningElement,
1798 ) -> swc_ecma_ast::JSXOpeningElement {
1799 let name = self.convert_jsx_element_name(&el.name);
1800 let attrs = el
1801 .attributes
1802 .iter()
1803 .map(|a| self.convert_jsx_attribute_item(a))
1804 .collect();
1805 swc_ecma_ast::JSXOpeningElement {
1806 span: self.span(&el.base),
1807 name,
1808 attrs,
1809 self_closing: el.self_closing,
1810 type_args: None,
1811 }
1812 }
1813
1814 fn convert_jsx_closing_element(
1815 &self,
1816 el: &react_compiler_ast::jsx::JSXClosingElement,
1817 ) -> swc_ecma_ast::JSXClosingElement {
1818 let name = self.convert_jsx_element_name(&el.name);
1819 swc_ecma_ast::JSXClosingElement {
1820 span: self.span(&el.base),
1821 name,
1822 }
1823 }
1824
1825 fn convert_jsx_element_name(
1826 &self,
1827 name: &react_compiler_ast::jsx::JSXElementName,
1828 ) -> swc_ecma_ast::JSXElementName {
1829 match name {
1830 react_compiler_ast::jsx::JSXElementName::JSXIdentifier(id) => {
1831 swc_ecma_ast::JSXElementName::Ident(self.ident(&id.name, self.span(&id.base)))
1832 }
1833 react_compiler_ast::jsx::JSXElementName::JSXMemberExpression(m) => {
1834 let member = self.convert_jsx_member_expression(m);
1835 swc_ecma_ast::JSXElementName::JSXMemberExpr(member)
1836 }
1837 react_compiler_ast::jsx::JSXElementName::JSXNamespacedName(ns) => {
1838 let namespace = self.ident_name(&ns.namespace.name, self.span(&ns.namespace.base));
1839 let name = self.ident_name(&ns.name.name, self.span(&ns.name.base));
1840 swc_ecma_ast::JSXElementName::JSXNamespacedName(swc_ecma_ast::JSXNamespacedName {
1841 span: DUMMY_SP,
1842 ns: namespace,
1843 name,
1844 })
1845 }
1846 }
1847 }
1848
1849 fn convert_jsx_member_expression(
1850 &self,
1851 m: &react_compiler_ast::jsx::JSXMemberExpression,
1852 ) -> swc_ecma_ast::JSXMemberExpr {
1853 let obj = self.convert_jsx_member_expression_object(&m.object);
1854 let prop = self.ident_name(&m.property.name, self.span(&m.property.base));
1855 swc_ecma_ast::JSXMemberExpr {
1856 span: DUMMY_SP,
1857 obj,
1858 prop,
1859 }
1860 }
1861
1862 fn convert_jsx_member_expression_object(
1863 &self,
1864 obj: &react_compiler_ast::jsx::JSXMemberExprObject,
1865 ) -> swc_ecma_ast::JSXObject {
1866 match obj {
1867 react_compiler_ast::jsx::JSXMemberExprObject::JSXIdentifier(id) => {
1868 swc_ecma_ast::JSXObject::Ident(self.ident(&id.name, self.span(&id.base)))
1869 }
1870 react_compiler_ast::jsx::JSXMemberExprObject::JSXMemberExpression(m) => {
1871 let member = self.convert_jsx_member_expression(m);
1872 swc_ecma_ast::JSXObject::JSXMemberExpr(Box::new(member))
1873 }
1874 }
1875 }
1876
1877 fn convert_jsx_attribute_item(
1878 &self,
1879 item: &react_compiler_ast::jsx::JSXAttributeItem,
1880 ) -> swc_ecma_ast::JSXAttrOrSpread {
1881 match item {
1882 react_compiler_ast::jsx::JSXAttributeItem::JSXAttribute(attr) => {
1883 let name = self.convert_jsx_attribute_name(&attr.name);
1884 let value = attr
1885 .value
1886 .as_ref()
1887 .map(|v| self.convert_jsx_attribute_value(v));
1888 swc_ecma_ast::JSXAttrOrSpread::JSXAttr(swc_ecma_ast::JSXAttr {
1889 span: self.span(&attr.base),
1890 name,
1891 value,
1892 })
1893 }
1894 react_compiler_ast::jsx::JSXAttributeItem::JSXSpreadAttribute(s) => {
1895 swc_ecma_ast::JSXAttrOrSpread::SpreadElement(SpreadElement {
1896 dot3_token: self.span(&s.base),
1897 expr: Box::new(self.convert_expression(&s.argument)),
1898 })
1899 }
1900 }
1901 }
1902
1903 fn convert_jsx_attribute_name(
1904 &self,
1905 name: &react_compiler_ast::jsx::JSXAttributeName,
1906 ) -> swc_ecma_ast::JSXAttrName {
1907 match name {
1908 react_compiler_ast::jsx::JSXAttributeName::JSXIdentifier(id) => {
1909 swc_ecma_ast::JSXAttrName::Ident(self.ident_name(&id.name, self.span(&id.base)))
1910 }
1911 react_compiler_ast::jsx::JSXAttributeName::JSXNamespacedName(ns) => {
1912 let namespace = self.ident_name(&ns.namespace.name, self.span(&ns.namespace.base));
1913 let name = self.ident_name(&ns.name.name, self.span(&ns.name.base));
1914 swc_ecma_ast::JSXAttrName::JSXNamespacedName(swc_ecma_ast::JSXNamespacedName {
1915 span: DUMMY_SP,
1916 ns: namespace,
1917 name,
1918 })
1919 }
1920 }
1921 }
1922
1923 fn convert_jsx_attribute_value(
1924 &self,
1925 value: &react_compiler_ast::jsx::JSXAttributeValue,
1926 ) -> swc_ecma_ast::JSXAttrValue {
1927 match value {
1928 react_compiler_ast::jsx::JSXAttributeValue::StringLiteral(s) => {
1929 let raw = if s.value.contains('"') {
1933 Some(Atom::from(format!(
1934 "'{}'",
1935 s.value.replace('\\', "\\\\").replace('\'', "\\'")
1936 )))
1937 } else {
1938 self.escape_string_raw(&s.value)
1939 };
1940 swc_ecma_ast::JSXAttrValue::Str(Str {
1941 span: self.span(&s.base),
1942 value: self.wtf8(&s.value),
1943 raw,
1944 })
1945 }
1946 react_compiler_ast::jsx::JSXAttributeValue::JSXExpressionContainer(ec) => {
1947 let expr = self.convert_jsx_expression_container_expr(&ec.expression);
1948 swc_ecma_ast::JSXAttrValue::JSXExprContainer(swc_ecma_ast::JSXExprContainer {
1949 span: self.span(&ec.base),
1950 expr,
1951 })
1952 }
1953 react_compiler_ast::jsx::JSXAttributeValue::JSXElement(el) => {
1954 let element = self.convert_jsx_element(el.as_ref());
1955 swc_ecma_ast::JSXAttrValue::JSXElement(Box::new(element))
1956 }
1957 react_compiler_ast::jsx::JSXAttributeValue::JSXFragment(frag) => {
1958 let fragment = self.convert_jsx_fragment(frag);
1959 swc_ecma_ast::JSXAttrValue::JSXFragment(fragment)
1960 }
1961 }
1962 }
1963
1964 fn convert_jsx_expression_container_expr(
1965 &self,
1966 expr: &react_compiler_ast::jsx::JSXExpressionContainerExpr,
1967 ) -> swc_ecma_ast::JSXExpr {
1968 match expr {
1969 react_compiler_ast::jsx::JSXExpressionContainerExpr::JSXEmptyExpression(e) => {
1970 swc_ecma_ast::JSXExpr::JSXEmptyExpr(swc_ecma_ast::JSXEmptyExpr {
1971 span: self.span(&e.base),
1972 })
1973 }
1974 react_compiler_ast::jsx::JSXExpressionContainerExpr::Expression(e) => {
1975 swc_ecma_ast::JSXExpr::Expr(Box::new(self.convert_expression(e)))
1976 }
1977 }
1978 }
1979
1980 fn convert_jsx_child(
1981 &self,
1982 child: &react_compiler_ast::jsx::JSXChild,
1983 ) -> swc_ecma_ast::JSXElementChild {
1984 match child {
1985 react_compiler_ast::jsx::JSXChild::JSXText(t) => {
1986 swc_ecma_ast::JSXElementChild::JSXText(swc_ecma_ast::JSXText {
1987 span: self.span(&t.base),
1988 value: self.atom(&t.value),
1989 raw: self.atom(&t.value),
1990 })
1991 }
1992 react_compiler_ast::jsx::JSXChild::JSXElement(el) => {
1993 let element = self.convert_jsx_element(el.as_ref());
1994 swc_ecma_ast::JSXElementChild::JSXElement(Box::new(element))
1995 }
1996 react_compiler_ast::jsx::JSXChild::JSXFragment(frag) => {
1997 let fragment = self.convert_jsx_fragment(frag);
1998 swc_ecma_ast::JSXElementChild::JSXFragment(fragment)
1999 }
2000 react_compiler_ast::jsx::JSXChild::JSXExpressionContainer(ec) => {
2001 let expr = self.convert_jsx_expression_container_expr(&ec.expression);
2002 swc_ecma_ast::JSXElementChild::JSXExprContainer(swc_ecma_ast::JSXExprContainer {
2003 span: self.span(&ec.base),
2004 expr,
2005 })
2006 }
2007 react_compiler_ast::jsx::JSXChild::JSXSpreadChild(s) => {
2008 swc_ecma_ast::JSXElementChild::JSXSpreadChild(swc_ecma_ast::JSXSpreadChild {
2009 span: self.span(&s.base),
2010 expr: Box::new(self.convert_expression(&s.expression)),
2011 })
2012 }
2013 }
2014 }
2015
2016 fn convert_jsx_fragment(
2017 &self,
2018 frag: &react_compiler_ast::jsx::JSXFragment,
2019 ) -> swc_ecma_ast::JSXFragment {
2020 let children = frag
2021 .children
2022 .iter()
2023 .map(|c| self.convert_jsx_child(c))
2024 .collect();
2025 swc_ecma_ast::JSXFragment {
2026 span: self.span(&frag.base),
2027 opening: swc_ecma_ast::JSXOpeningFragment {
2028 span: self.span(&frag.opening_fragment.base),
2029 },
2030 children,
2031 closing: swc_ecma_ast::JSXClosingFragment {
2032 span: self.span(&frag.closing_fragment.base),
2033 },
2034 }
2035 }
2036
2037 fn convert_import_declaration(&self, decl: &ImportDeclaration) -> swc_ecma_ast::ImportDecl {
2040 let specifiers = decl
2041 .specifiers
2042 .iter()
2043 .map(|s| self.convert_import_specifier(s))
2044 .collect();
2045 let src = Box::new(Str {
2046 span: self.span(&decl.source.base),
2047 value: self.wtf8(&decl.source.value),
2048 raw: None,
2049 });
2050 let type_only = matches!(decl.import_kind.as_ref(), Some(ImportKind::Type));
2051 swc_ecma_ast::ImportDecl {
2052 span: self.span(&decl.base),
2053 specifiers,
2054 src,
2055 type_only,
2056 with: None,
2057 phase: Default::default(),
2058 }
2059 }
2060
2061 fn convert_import_specifier(
2062 &self,
2063 spec: &react_compiler_ast::declarations::ImportSpecifier,
2064 ) -> swc_ecma_ast::ImportSpecifier {
2065 match spec {
2066 react_compiler_ast::declarations::ImportSpecifier::ImportSpecifier(s) => {
2067 let local = self.ident(&s.local.name, self.span(&s.local.base));
2068 let imported_name = match &s.imported {
2071 react_compiler_ast::declarations::ModuleExportName::Identifier(id) => {
2072 Some(&id.name)
2073 }
2074 react_compiler_ast::declarations::ModuleExportName::StringLiteral(_) => None,
2075 };
2076 let imported = if imported_name == Some(&s.local.name) {
2077 None
2078 } else {
2079 Some(self.convert_module_export_name(&s.imported))
2080 };
2081 let is_type_only = matches!(s.import_kind.as_ref(), Some(ImportKind::Type));
2082 swc_ecma_ast::ImportSpecifier::Named(ImportNamedSpecifier {
2083 span: self.span(&s.base),
2084 local,
2085 imported,
2086 is_type_only,
2087 })
2088 }
2089 react_compiler_ast::declarations::ImportSpecifier::ImportDefaultSpecifier(s) => {
2090 let local = self.ident(&s.local.name, self.span(&s.local.base));
2091 swc_ecma_ast::ImportSpecifier::Default(ImportDefaultSpecifier {
2092 span: self.span(&s.base),
2093 local,
2094 })
2095 }
2096 react_compiler_ast::declarations::ImportSpecifier::ImportNamespaceSpecifier(s) => {
2097 let local = self.ident(&s.local.name, self.span(&s.local.base));
2098 swc_ecma_ast::ImportSpecifier::Namespace(ImportStarAsSpecifier {
2099 span: self.span(&s.base),
2100 local,
2101 })
2102 }
2103 }
2104 }
2105
2106 fn convert_module_export_name(
2107 &self,
2108 name: &react_compiler_ast::declarations::ModuleExportName,
2109 ) -> swc_ecma_ast::ModuleExportName {
2110 match name {
2111 react_compiler_ast::declarations::ModuleExportName::Identifier(id) => {
2112 swc_ecma_ast::ModuleExportName::Ident(self.ident(&id.name, self.span(&id.base)))
2113 }
2114 react_compiler_ast::declarations::ModuleExportName::StringLiteral(s) => {
2115 swc_ecma_ast::ModuleExportName::Str(Str {
2116 span: self.span(&s.base),
2117 value: self.wtf8(&s.value),
2118 raw: None,
2119 })
2120 }
2121 }
2122 }
2123
2124 fn convert_export_named_to_module_item(&self, decl: &ExportNamedDeclaration) -> ModuleItem {
2125 if let Some(declaration) = &decl.declaration {
2127 let swc_decl = self.convert_declaration(declaration);
2128 return ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
2129 span: self.span(&decl.base),
2130 decl: swc_decl,
2131 }));
2132 }
2133 self.convert_export_named_specifiers(decl)
2134 }
2135
2136 fn convert_declaration(&self, decl: &react_compiler_ast::declarations::Declaration) -> Decl {
2137 match decl {
2138 react_compiler_ast::declarations::Declaration::FunctionDeclaration(f) => {
2139 Decl::Fn(self.convert_function_declaration(f))
2140 }
2141 react_compiler_ast::declarations::Declaration::VariableDeclaration(v) => {
2142 Decl::Var(Box::new(self.convert_variable_declaration(v)))
2143 }
2144 react_compiler_ast::declarations::Declaration::ClassDeclaration(c) => {
2145 let ident =
2146 c.id.as_ref()
2147 .map(|id| self.ident(&id.name, self.span(&id.base)))
2148 .unwrap_or_else(|| self.ident("_anonymous", DUMMY_SP));
2149 let super_class = c
2150 .super_class
2151 .as_ref()
2152 .map(|s| Box::new(self.convert_expression(s)));
2153 Decl::Class(ClassDecl {
2154 ident,
2155 declare: c.declare.unwrap_or(false),
2156 class: Box::new(Class {
2157 span: self.span(&c.base),
2158 ctxt: SyntaxContext::empty(),
2159 decorators: vec![],
2160 body: vec![],
2161 super_class,
2162 is_abstract: false,
2163 type_params: None,
2164 super_type_params: None,
2165 implements: vec![],
2166 }),
2167 })
2168 }
2169 _ => Decl::Var(Box::new(VarDecl {
2170 span: DUMMY_SP,
2171 ctxt: SyntaxContext::empty(),
2172 kind: VarDeclKind::Const,
2173 declare: true,
2174 decls: vec![],
2175 })),
2176 }
2177 }
2178
2179 fn convert_export_named_specifiers(&self, decl: &ExportNamedDeclaration) -> ModuleItem {
2180 let specifiers = decl
2181 .specifiers
2182 .iter()
2183 .map(|s| self.convert_export_specifier(s))
2184 .collect();
2185 let src = decl.source.as_ref().map(|s| {
2186 Box::new(Str {
2187 span: self.span(&s.base),
2188 value: self.wtf8(&s.value),
2189 raw: None,
2190 })
2191 });
2192 let type_only = matches!(decl.export_kind.as_ref(), Some(ExportKind::Type));
2193
2194 ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(NamedExport {
2195 span: self.span(&decl.base),
2196 specifiers,
2197 src,
2198 type_only,
2199 with: None,
2200 }))
2201 }
2202
2203 fn convert_export_specifier(
2204 &self,
2205 spec: &react_compiler_ast::declarations::ExportSpecifier,
2206 ) -> swc_ecma_ast::ExportSpecifier {
2207 match spec {
2208 react_compiler_ast::declarations::ExportSpecifier::ExportSpecifier(s) => {
2209 let orig = self.convert_module_export_name(&s.local);
2210 let local_name = match &s.local {
2212 react_compiler_ast::declarations::ModuleExportName::Identifier(id) => {
2213 Some(&id.name)
2214 }
2215 _ => None,
2216 };
2217 let exported_name = match &s.exported {
2218 react_compiler_ast::declarations::ModuleExportName::Identifier(id) => {
2219 Some(&id.name)
2220 }
2221 _ => None,
2222 };
2223 let exported = if local_name.is_some() && local_name == exported_name {
2224 None
2225 } else {
2226 Some(self.convert_module_export_name(&s.exported))
2227 };
2228 let is_type_only = matches!(s.export_kind.as_ref(), Some(ExportKind::Type));
2229 swc_ecma_ast::ExportSpecifier::Named(ExportNamedSpecifier {
2230 span: self.span(&s.base),
2231 orig,
2232 exported,
2233 is_type_only,
2234 })
2235 }
2236 react_compiler_ast::declarations::ExportSpecifier::ExportDefaultSpecifier(s) => {
2237 swc_ecma_ast::ExportSpecifier::Default(swc_ecma_ast::ExportDefaultSpecifier {
2238 exported: self.ident(&s.exported.name, self.span(&s.exported.base)),
2239 })
2240 }
2241 react_compiler_ast::declarations::ExportSpecifier::ExportNamespaceSpecifier(s) => {
2242 let name = self.convert_module_export_name(&s.exported);
2243 swc_ecma_ast::ExportSpecifier::Namespace(ExportNamespaceSpecifier {
2244 span: self.span(&s.base),
2245 name,
2246 })
2247 }
2248 }
2249 }
2250
2251 fn convert_export_default_to_module_item(&self, decl: &ExportDefaultDeclaration) -> ModuleItem {
2252 let span = self.span(&decl.base);
2253 match &*decl.declaration {
2254 BabelExportDefaultDecl::FunctionDeclaration(f) => {
2255 let fd = self.convert_function_declaration(f);
2256 ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultDecl(
2257 swc_ecma_ast::ExportDefaultDecl {
2258 span,
2259 decl: swc_ecma_ast::DefaultDecl::Fn(FnExpr {
2260 ident: Some(fd.ident),
2261 function: fd.function,
2262 }),
2263 },
2264 ))
2265 }
2266 BabelExportDefaultDecl::ClassDeclaration(c) => {
2267 let ident =
2268 c.id.as_ref()
2269 .map(|id| self.ident(&id.name, self.span(&id.base)));
2270 let super_class = c
2271 .super_class
2272 .as_ref()
2273 .map(|s| Box::new(self.convert_expression(s)));
2274 ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultDecl(
2275 swc_ecma_ast::ExportDefaultDecl {
2276 span,
2277 decl: swc_ecma_ast::DefaultDecl::Class(ClassExpr {
2278 ident,
2279 class: Box::new(Class {
2280 span,
2281 ctxt: SyntaxContext::empty(),
2282 decorators: vec![],
2283 body: vec![],
2284 super_class,
2285 is_abstract: false,
2286 type_params: None,
2287 super_type_params: None,
2288 implements: vec![],
2289 }),
2290 }),
2291 },
2292 ))
2293 }
2294 BabelExportDefaultDecl::EnumDeclaration(_) => {
2295 ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultExpr(ExportDefaultExpr {
2298 span,
2299 expr: Box::new(swc_ecma_ast::Expr::Lit(swc_ecma_ast::Lit::Null(
2300 swc_ecma_ast::Null { span },
2301 ))),
2302 }))
2303 }
2304 BabelExportDefaultDecl::Expression(e) => {
2305 ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultExpr(ExportDefaultExpr {
2306 span,
2307 expr: Box::new(self.convert_expression(e)),
2308 }))
2309 }
2310 }
2311 }
2312
2313 fn convert_export_all_declaration(
2314 &self,
2315 decl: &ExportAllDeclaration,
2316 ) -> swc_ecma_ast::ExportAll {
2317 let src = Box::new(Str {
2318 span: self.span(&decl.source.base),
2319 value: self.wtf8(&decl.source.value),
2320 raw: None,
2321 });
2322 let type_only = matches!(decl.export_kind.as_ref(), Some(ExportKind::Type));
2323 swc_ecma_ast::ExportAll {
2324 span: self.span(&decl.base),
2325 src,
2326 type_only,
2327 with: None,
2328 }
2329 }
2330
2331 fn convert_ts_type_annotation_from_json(
2336 &self,
2337 json: &serde_json::Value,
2338 ) -> Option<Box<TsTypeAnn>> {
2339 let type_name = json.get("type")?.as_str()?;
2340 if type_name != "TSTypeAnnotation" && type_name != "TypeAnnotation" {
2341 return None;
2342 }
2343 let type_annotation = json.get("typeAnnotation")?;
2344 let ts_type = self.convert_ts_type_from_json(type_annotation, DUMMY_SP);
2345 Some(Box::new(TsTypeAnn {
2346 span: DUMMY_SP,
2347 type_ann: Box::new(ts_type),
2348 }))
2349 }
2350
2351 fn convert_ts_type_from_json(&self, json: &serde_json::Value, span: Span) -> TsType {
2355 let type_name = json.get("type").and_then(|v| v.as_str()).unwrap_or("");
2356 match type_name {
2357 "TSTypeReference" => {
2358 let name = json
2359 .get("typeName")
2360 .and_then(|tn| tn.get("name"))
2361 .and_then(|n| n.as_str())
2362 .unwrap_or("unknown");
2363 if name == "const" {
2364 TsType::TsTypeRef(TsTypeRef {
2365 span,
2366 type_name: TsEntityName::Ident(self.ident("const", span)),
2367 type_params: None,
2368 })
2369 } else {
2370 TsType::TsTypeRef(TsTypeRef {
2371 span,
2372 type_name: TsEntityName::Ident(self.ident(name, span)),
2373 type_params: None,
2374 })
2375 }
2376 }
2377 "TSNumberKeyword" => TsType::TsKeywordType(TsKeywordType {
2378 span,
2379 kind: TsKeywordTypeKind::TsNumberKeyword,
2380 }),
2381 "TSStringKeyword" => TsType::TsKeywordType(TsKeywordType {
2382 span,
2383 kind: TsKeywordTypeKind::TsStringKeyword,
2384 }),
2385 "TSBooleanKeyword" => TsType::TsKeywordType(TsKeywordType {
2386 span,
2387 kind: TsKeywordTypeKind::TsBooleanKeyword,
2388 }),
2389 "TSVoidKeyword" => TsType::TsKeywordType(TsKeywordType {
2390 span,
2391 kind: TsKeywordTypeKind::TsVoidKeyword,
2392 }),
2393 "TSNullKeyword" => TsType::TsKeywordType(TsKeywordType {
2394 span,
2395 kind: TsKeywordTypeKind::TsNullKeyword,
2396 }),
2397 "TSUndefinedKeyword" => TsType::TsKeywordType(TsKeywordType {
2398 span,
2399 kind: TsKeywordTypeKind::TsUndefinedKeyword,
2400 }),
2401 "TSAnyKeyword" => TsType::TsKeywordType(TsKeywordType {
2402 span,
2403 kind: TsKeywordTypeKind::TsAnyKeyword,
2404 }),
2405 "TSNeverKeyword" => TsType::TsKeywordType(TsKeywordType {
2406 span,
2407 kind: TsKeywordTypeKind::TsNeverKeyword,
2408 }),
2409 "TSUnionType" => {
2410 let types = json
2411 .get("types")
2412 .and_then(|t| t.as_array())
2413 .map(|arr| {
2414 arr.iter()
2415 .map(|t| Box::new(self.convert_ts_type_from_json(t, span)))
2416 .collect::<Vec<_>>()
2417 })
2418 .unwrap_or_default();
2419 TsType::TsUnionOrIntersectionType(TsUnionOrIntersectionType::TsUnionType(
2420 TsUnionType { span, types },
2421 ))
2422 }
2423 "TSIntersectionType" => {
2424 let types = json
2425 .get("types")
2426 .and_then(|t| t.as_array())
2427 .map(|arr| {
2428 arr.iter()
2429 .map(|t| Box::new(self.convert_ts_type_from_json(t, span)))
2430 .collect::<Vec<_>>()
2431 })
2432 .unwrap_or_default();
2433 TsType::TsUnionOrIntersectionType(TsUnionOrIntersectionType::TsIntersectionType(
2434 TsIntersectionType { span, types },
2435 ))
2436 }
2437 "TSLiteralType" => {
2438 if let Some(literal) = json.get("literal") {
2439 let lit_type = literal.get("type").and_then(|t| t.as_str()).unwrap_or("");
2440 match lit_type {
2441 "StringLiteral" => {
2442 let value = literal.get("value").and_then(|v| v.as_str()).unwrap_or("");
2443 TsType::TsLitType(TsLitType {
2444 span,
2445 lit: TsLit::Str(Str {
2446 span,
2447 value: self.wtf8(value),
2448 raw: None,
2449 }),
2450 })
2451 }
2452 "NumericLiteral" => {
2453 let value =
2454 literal.get("value").and_then(|v| v.as_f64()).unwrap_or(0.0);
2455 TsType::TsLitType(TsLitType {
2456 span,
2457 lit: TsLit::Number(Number {
2458 span,
2459 value,
2460 raw: None,
2461 }),
2462 })
2463 }
2464 "BooleanLiteral" => {
2465 let value = literal
2466 .get("value")
2467 .and_then(|v| v.as_bool())
2468 .unwrap_or(false);
2469 TsType::TsLitType(TsLitType {
2470 span,
2471 lit: TsLit::Bool(Bool { span, value }),
2472 })
2473 }
2474 _ => TsType::TsKeywordType(TsKeywordType {
2475 span,
2476 kind: TsKeywordTypeKind::TsAnyKeyword,
2477 }),
2478 }
2479 } else {
2480 TsType::TsKeywordType(TsKeywordType {
2481 span,
2482 kind: TsKeywordTypeKind::TsAnyKeyword,
2483 })
2484 }
2485 }
2486 "TSArrayType" => {
2487 let elem = json
2488 .get("elementType")
2489 .map(|t| self.convert_ts_type_from_json(t, span))
2490 .unwrap_or(TsType::TsKeywordType(TsKeywordType {
2491 span,
2492 kind: TsKeywordTypeKind::TsAnyKeyword,
2493 }));
2494 TsType::TsArrayType(TsArrayType {
2495 span,
2496 elem_type: Box::new(elem),
2497 })
2498 }
2499 "TSFunctionType"
2500 | "TSTypeLiteral"
2501 | "TSParenthesizedType"
2502 | "TSTupleType"
2503 | "TSOptionalType"
2504 | "TSRestType"
2505 | "TSConditionalType"
2506 | "TSInferType"
2507 | "TSMappedType"
2508 | "TSIndexedAccessType"
2509 | "TSTypeOperator"
2510 | "TSTypePredicate"
2511 | "TSImportType"
2512 | "TSQualifiedName" => {
2513 if let (Some(source), Some(start), Some(end)) = (
2515 self.source_text.as_deref(),
2516 json.get("start").and_then(|v| v.as_u64()),
2517 json.get("end").and_then(|v| v.as_u64()),
2518 ) {
2519 let start_idx = (start as usize).saturating_sub(1);
2520 let end_idx = (end as usize).saturating_sub(1);
2521 if start_idx < source.len() && end_idx <= source.len() && start_idx < end_idx {
2522 let text = &source[start_idx..end_idx];
2523 let wrapper = format!("type __T = {};", text);
2525 let cm = swc_common::sync::Lrc::new(swc_common::SourceMap::default());
2526 let fm = cm.new_source_file(
2527 swc_common::sync::Lrc::new(swc_common::FileName::Anon),
2528 wrapper,
2529 );
2530 let mut errors = vec![];
2531 if let Ok(module) = swc_ecma_parser::parse_file_as_module(
2532 &fm,
2533 swc_ecma_parser::Syntax::Typescript(swc_ecma_parser::TsSyntax {
2534 tsx: true,
2535 ..Default::default()
2536 }),
2537 swc_ecma_ast::EsVersion::latest(),
2538 None,
2539 &mut errors,
2540 ) {
2541 if let Some(ModuleItem::Stmt(Stmt::Decl(Decl::TsTypeAlias(alias)))) =
2542 module.body.into_iter().next()
2543 {
2544 return *alias.type_ann;
2545 }
2546 }
2547 }
2548 }
2549 TsType::TsKeywordType(TsKeywordType {
2551 span,
2552 kind: TsKeywordTypeKind::TsAnyKeyword,
2553 })
2554 }
2555 "NumberTypeAnnotation"
2557 | "StringTypeAnnotation"
2558 | "BooleanTypeAnnotation"
2559 | "VoidTypeAnnotation"
2560 | "NullLiteralTypeAnnotation"
2561 | "AnyTypeAnnotation"
2562 | "GenericTypeAnnotation"
2563 | "UnionTypeAnnotation"
2564 | "IntersectionTypeAnnotation"
2565 | "NullableTypeAnnotation"
2566 | "FunctionTypeAnnotation"
2567 | "ObjectTypeAnnotation"
2568 | "ArrayTypeAnnotation"
2569 | "TupleTypeAnnotation"
2570 | "TypeofTypeAnnotation"
2571 | "NumberLiteralTypeAnnotation"
2572 | "StringLiteralTypeAnnotation"
2573 | "BooleanLiteralTypeAnnotation" => {
2574 if let (Some(source), Some(start), Some(end)) = (
2576 self.source_text.as_deref(),
2577 json.get("start").and_then(|v| v.as_u64()),
2578 json.get("end").and_then(|v| v.as_u64()),
2579 ) {
2580 let start_idx = (start as usize).saturating_sub(1);
2581 let end_idx = (end as usize).saturating_sub(1);
2582 if start_idx < source.len() && end_idx <= source.len() && start_idx < end_idx {
2583 let text = &source[start_idx..end_idx];
2584 let wrapper = format!("type __T = {};", text);
2587 let cm = swc_common::sync::Lrc::new(swc_common::SourceMap::default());
2588 let fm = cm.new_source_file(
2589 swc_common::sync::Lrc::new(swc_common::FileName::Anon),
2590 wrapper,
2591 );
2592 let mut errors = vec![];
2593 if let Ok(module) = swc_ecma_parser::parse_file_as_module(
2594 &fm,
2595 swc_ecma_parser::Syntax::Typescript(swc_ecma_parser::TsSyntax {
2596 tsx: true,
2597 ..Default::default()
2598 }),
2599 swc_ecma_ast::EsVersion::latest(),
2600 None,
2601 &mut errors,
2602 ) {
2603 if let Some(ModuleItem::Stmt(Stmt::Decl(Decl::TsTypeAlias(alias)))) =
2604 module.body.into_iter().next()
2605 {
2606 return *alias.type_ann;
2607 }
2608 }
2609 }
2610 }
2611 TsType::TsKeywordType(TsKeywordType {
2613 span,
2614 kind: TsKeywordTypeKind::TsAnyKeyword,
2615 })
2616 }
2617 _ => {
2618 TsType::TsKeywordType(TsKeywordType {
2620 span,
2621 kind: TsKeywordTypeKind::TsAnyKeyword,
2622 })
2623 }
2624 }
2625 }
2626
2627 fn convert_binary_operator(&self, op: &BinaryOperator) -> BinaryOp {
2630 match op {
2631 BinaryOperator::Add => BinaryOp::Add,
2632 BinaryOperator::Sub => BinaryOp::Sub,
2633 BinaryOperator::Mul => BinaryOp::Mul,
2634 BinaryOperator::Div => BinaryOp::Div,
2635 BinaryOperator::Rem => BinaryOp::Mod,
2636 BinaryOperator::Exp => BinaryOp::Exp,
2637 BinaryOperator::Eq => BinaryOp::EqEq,
2638 BinaryOperator::StrictEq => BinaryOp::EqEqEq,
2639 BinaryOperator::Neq => BinaryOp::NotEq,
2640 BinaryOperator::StrictNeq => BinaryOp::NotEqEq,
2641 BinaryOperator::Lt => BinaryOp::Lt,
2642 BinaryOperator::Lte => BinaryOp::LtEq,
2643 BinaryOperator::Gt => BinaryOp::Gt,
2644 BinaryOperator::Gte => BinaryOp::GtEq,
2645 BinaryOperator::Shl => BinaryOp::LShift,
2646 BinaryOperator::Shr => BinaryOp::RShift,
2647 BinaryOperator::UShr => BinaryOp::ZeroFillRShift,
2648 BinaryOperator::BitOr => BinaryOp::BitOr,
2649 BinaryOperator::BitXor => BinaryOp::BitXor,
2650 BinaryOperator::BitAnd => BinaryOp::BitAnd,
2651 BinaryOperator::In => BinaryOp::In,
2652 BinaryOperator::Instanceof => BinaryOp::InstanceOf,
2653 BinaryOperator::Pipeline => BinaryOp::BitOr, }
2655 }
2656
2657 fn convert_logical_operator(&self, op: &LogicalOperator) -> BinaryOp {
2658 match op {
2659 LogicalOperator::Or => BinaryOp::LogicalOr,
2660 LogicalOperator::And => BinaryOp::LogicalAnd,
2661 LogicalOperator::NullishCoalescing => BinaryOp::NullishCoalescing,
2662 }
2663 }
2664
2665 fn convert_unary_operator(&self, op: &UnaryOperator) -> UnaryOp {
2666 match op {
2667 UnaryOperator::Neg => UnaryOp::Minus,
2668 UnaryOperator::Plus => UnaryOp::Plus,
2669 UnaryOperator::Not => UnaryOp::Bang,
2670 UnaryOperator::BitNot => UnaryOp::Tilde,
2671 UnaryOperator::TypeOf => UnaryOp::TypeOf,
2672 UnaryOperator::Void => UnaryOp::Void,
2673 UnaryOperator::Delete => UnaryOp::Delete,
2674 UnaryOperator::Throw => UnaryOp::Void, }
2676 }
2677
2678 fn convert_update_operator(&self, op: &UpdateOperator) -> UpdateOp {
2679 match op {
2680 UpdateOperator::Increment => UpdateOp::PlusPlus,
2681 UpdateOperator::Decrement => UpdateOp::MinusMinus,
2682 }
2683 }
2684
2685 fn convert_assignment_operator(&self, op: &AssignmentOperator) -> AssignOp {
2686 match op {
2687 AssignmentOperator::Assign => AssignOp::Assign,
2688 AssignmentOperator::AddAssign => AssignOp::AddAssign,
2689 AssignmentOperator::SubAssign => AssignOp::SubAssign,
2690 AssignmentOperator::MulAssign => AssignOp::MulAssign,
2691 AssignmentOperator::DivAssign => AssignOp::DivAssign,
2692 AssignmentOperator::RemAssign => AssignOp::ModAssign,
2693 AssignmentOperator::ExpAssign => AssignOp::ExpAssign,
2694 AssignmentOperator::ShlAssign => AssignOp::LShiftAssign,
2695 AssignmentOperator::ShrAssign => AssignOp::RShiftAssign,
2696 AssignmentOperator::UShrAssign => AssignOp::ZeroFillRShiftAssign,
2697 AssignmentOperator::BitOrAssign => AssignOp::BitOrAssign,
2698 AssignmentOperator::BitXorAssign => AssignOp::BitXorAssign,
2699 AssignmentOperator::BitAndAssign => AssignOp::BitAndAssign,
2700 AssignmentOperator::OrAssign => AssignOp::OrAssign,
2701 AssignmentOperator::AndAssign => AssignOp::AndAssign,
2702 AssignmentOperator::NullishAssign => AssignOp::NullishAssign,
2703 }
2704 }
2705}