turbopack_ecmascript/references/esm/
module_item.rs1use std::mem::replace;
2
3use anyhow::Result;
4use serde::{Deserialize, Serialize};
5use swc_core::{
6 common::DUMMY_SP,
7 ecma::ast::{
8 ClassDecl, Decl, DefaultDecl, ExportDecl, ExportDefaultDecl, ExportDefaultExpr, FnDecl,
9 Ident, ModuleDecl, ModuleItem, Stmt,
10 },
11 quote,
12};
13use turbo_tasks::{NonLocalValue, Vc, debug::ValueDebugFormat, trace::TraceRawVcs};
14use turbopack_core::chunk::ChunkingContext;
15
16use crate::{
17 code_gen::{CodeGen, CodeGeneration},
18 create_visitor, magic_identifier,
19 references::AstPath,
20};
21
22#[derive(PartialEq, Eq, Serialize, Deserialize, TraceRawVcs, ValueDebugFormat, NonLocalValue)]
26pub struct EsmModuleItem {
27 pub path: AstPath,
28}
29
30impl EsmModuleItem {
31 pub fn new(path: AstPath) -> Self {
32 EsmModuleItem { path }
33 }
34
35 pub async fn code_generation(
36 &self,
37 _chunking_context: Vc<Box<dyn ChunkingContext>>,
38 ) -> Result<CodeGeneration> {
39 let mut visitors = Vec::new();
40
41 visitors.push(
42 create_visitor!(self.path, visit_mut_module_item, |module_item: &mut ModuleItem| {
43 let item = replace(module_item, ModuleItem::Stmt(quote!(";" as Stmt)));
44 if let ModuleItem::ModuleDecl(module_decl) = item {
45 match module_decl {
46 ModuleDecl::ExportDefaultExpr(ExportDefaultExpr { box expr, .. }) => {
47 let stmt = quote!("const $name = $expr;" as Stmt,
48 name = Ident::new(magic_identifier::mangle("default export").into(), DUMMY_SP, Default::default()),
49 expr: Expr = expr
50 );
51 *module_item = ModuleItem::Stmt(stmt);
52 }
53 ModuleDecl::ExportDefaultDecl(ExportDefaultDecl { decl, span }) => {
54 match decl {
55 DefaultDecl::Class(class) => {
56 *module_item = ModuleItem::Stmt(Stmt::Decl(Decl::Class(ClassDecl {
57 ident: class.ident.unwrap_or_else(|| Ident::new(magic_identifier::mangle("default export").into(), DUMMY_SP, Default::default())),
58 declare: false,
59 class: class.class
60 })))
61 }
62 DefaultDecl::Fn(fn_expr) => {
63 *module_item = ModuleItem::Stmt(Stmt::Decl(Decl::Fn(FnDecl {
64 ident: fn_expr.ident.unwrap_or_else(|| Ident::new(magic_identifier::mangle("default export").into(), DUMMY_SP, Default::default())),
65 declare: false,
66 function: fn_expr.function
67 })))
68 }
69 DefaultDecl::TsInterfaceDecl(_) => {
70 *module_item = ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultDecl(ExportDefaultDecl { decl, span }));
72 }
73 }
74 }
75 ModuleDecl::ExportDecl(ExportDecl { decl, .. }) => {
76 *module_item = ModuleItem::Stmt(Stmt::Decl(decl));
77 }
78 ModuleDecl::ExportNamed(_) => {
79 }
81 ModuleDecl::ExportAll(_) => {
82 }
84 ModuleDecl::Import(_) => {
85 }
87 _ => {
88 *module_item = ModuleItem::ModuleDecl(module_decl);
90 }
91 }
92 } else {
93 *module_item = item;
95 }
96 }),
97 );
98
99 Ok(CodeGeneration::visitors(visitors))
100 }
101}
102
103impl From<EsmModuleItem> for CodeGen {
104 fn from(val: EsmModuleItem) -> Self {
105 CodeGen::EsmModuleItem(val)
106 }
107}