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, module_graph::ModuleGraph};
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 _module_graph: Vc<ModuleGraph>,
38 _chunking_context: Vc<Box<dyn ChunkingContext>>,
39 ) -> Result<CodeGeneration> {
40 let mut visitors = Vec::new();
41
42 visitors.push(
43 create_visitor!(self.path, visit_mut_module_item(module_item: &mut ModuleItem) {
44 let item = replace(module_item, ModuleItem::Stmt(quote!(";" as Stmt)));
45 if let ModuleItem::ModuleDecl(module_decl) = item {
46 match module_decl {
47 ModuleDecl::ExportDefaultExpr(ExportDefaultExpr { box expr, .. }) => {
48 let stmt = quote!("const $name = $expr;" as Stmt,
49 name = Ident::new(magic_identifier::mangle("default export").into(), DUMMY_SP, Default::default()),
50 expr: Expr = expr
51 );
52 *module_item = ModuleItem::Stmt(stmt);
53 }
54 ModuleDecl::ExportDefaultDecl(ExportDefaultDecl { decl, span }) => {
55 match decl {
56 DefaultDecl::Class(class) => {
57 *module_item = ModuleItem::Stmt(Stmt::Decl(Decl::Class(ClassDecl {
58 ident: class.ident.unwrap_or_else(|| Ident::new(magic_identifier::mangle("default export").into(), DUMMY_SP, Default::default())),
59 declare: false,
60 class: class.class
61 })))
62 }
63 DefaultDecl::Fn(fn_expr) => {
64 *module_item = ModuleItem::Stmt(Stmt::Decl(Decl::Fn(FnDecl {
65 ident: fn_expr.ident.unwrap_or_else(|| Ident::new(magic_identifier::mangle("default export").into(), DUMMY_SP, Default::default())),
66 declare: false,
67 function: fn_expr.function
68 })))
69 }
70 DefaultDecl::TsInterfaceDecl(_) => {
71 *module_item = ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultDecl(ExportDefaultDecl { decl, span }));
73 }
74 }
75 }
76 ModuleDecl::ExportDecl(ExportDecl { decl, .. }) => {
77 *module_item = ModuleItem::Stmt(Stmt::Decl(decl));
78 }
79 ModuleDecl::ExportNamed(_) => {
80 }
82 ModuleDecl::ExportAll(_) => {
83 }
85 ModuleDecl::Import(_) => {
86 }
88 _ => {
89 *module_item = ModuleItem::ModuleDecl(module_decl);
91 }
92 }
93 } else {
94 *module_item = item;
96 }
97 }),
98 );
99
100 Ok(CodeGeneration::visitors(visitors))
101 }
102}
103
104impl From<EsmModuleItem> for CodeGen {
105 fn from(val: EsmModuleItem) -> Self {
106 CodeGen::EsmModuleItem(val)
107 }
108}