turbopack_ecmascript/references/esm/
module_item.rs1use std::mem::replace;
2
3use anyhow::Result;
4use bincode::{Decode, Encode};
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(
26 PartialEq, Eq, TraceRawVcs, ValueDebugFormat, NonLocalValue, Debug, Hash, Encode, Decode,
27)]
28pub struct EsmModuleItem {
29 pub path: AstPath,
30}
31
32impl EsmModuleItem {
33 pub fn new(path: AstPath) -> Self {
34 EsmModuleItem { path }
35 }
36
37 pub async fn code_generation(
38 &self,
39 _chunking_context: Vc<Box<dyn ChunkingContext>>,
40 ) -> Result<CodeGeneration> {
41 let mut visitors = Vec::new();
42
43 visitors.push(
44 create_visitor!(self.path, visit_mut_module_item, |module_item: &mut ModuleItem| {
45 let item = replace(module_item, ModuleItem::Stmt(quote!(";" as Stmt)));
46 if let ModuleItem::ModuleDecl(module_decl) = item {
47 match module_decl {
48 ModuleDecl::ExportDefaultExpr(ExportDefaultExpr { box expr, .. }) => {
49 let stmt = quote!("const $name = $expr;" as Stmt,
50 name = Ident::new(magic_identifier::mangle("default export").into(), DUMMY_SP, Default::default()),
51 expr: Expr = expr
52 );
53 *module_item = ModuleItem::Stmt(stmt);
54 }
55 ModuleDecl::ExportDefaultDecl(ExportDefaultDecl { decl, span }) => {
56 match decl {
57 DefaultDecl::Class(class) => {
58 *module_item = ModuleItem::Stmt(Stmt::Decl(Decl::Class(ClassDecl {
59 ident: class.ident.unwrap_or_else(|| Ident::new(magic_identifier::mangle("default export").into(), DUMMY_SP, Default::default())),
60 declare: false,
61 class: class.class
62 })))
63 }
64 DefaultDecl::Fn(fn_expr) => {
65 *module_item = ModuleItem::Stmt(Stmt::Decl(Decl::Fn(FnDecl {
66 ident: fn_expr.ident.unwrap_or_else(|| Ident::new(magic_identifier::mangle("default export").into(), DUMMY_SP, Default::default())),
67 declare: false,
68 function: fn_expr.function
69 })))
70 }
71 DefaultDecl::TsInterfaceDecl(_) => {
72 *module_item = ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultDecl(ExportDefaultDecl { decl, span }));
74 }
75 }
76 }
77 ModuleDecl::ExportDecl(ExportDecl { decl, .. }) => {
78 *module_item = ModuleItem::Stmt(Stmt::Decl(decl));
79 }
80 ModuleDecl::ExportNamed(_) => {
81 }
83 ModuleDecl::ExportAll(_) => {
84 }
86 ModuleDecl::Import(_) => {
87 }
89 _ => {
90 *module_item = ModuleItem::ModuleDecl(module_decl);
92 }
93 }
94 } else {
95 *module_item = item;
97 }
98 }),
99 );
100
101 Ok(CodeGeneration::visitors(visitors))
102 }
103}
104
105impl From<EsmModuleItem> for CodeGen {
106 fn from(val: EsmModuleItem) -> Self {
107 CodeGen::EsmModuleItem(val)
108 }
109}