turbopack_ecmascript/tree_shake/
side_effect_module.rs1use anyhow::Result;
2use turbo_rcstr::RcStr;
3use turbo_tasks::{ResolvedVc, TryJoinIterExt, Value, Vc};
4use turbo_tasks_fs::glob::Glob;
5use turbopack_core::{
6 asset::{Asset, AssetContent},
7 chunk::{ChunkableModule, ChunkingContext, EvaluatableAsset},
8 ident::AssetIdent,
9 module::Module,
10 module_graph::ModuleGraph,
11 reference::{ModuleReferences, SingleChunkableModuleReference},
12 resolve::ModulePart,
13};
14
15use crate::{
16 EcmascriptModuleAsset,
17 chunk::{EcmascriptChunkPlaceable, EcmascriptExports},
18 tree_shake::chunk_item::SideEffectsModuleChunkItem,
19};
20
21#[turbo_tasks::value]
22pub(super) struct SideEffectsModule {
23 pub module: ResolvedVc<EcmascriptModuleAsset>,
25 pub part: ModulePart,
27 pub resolved_as: ResolvedVc<Box<dyn EcmascriptChunkPlaceable>>,
29 pub side_effects: Vec<ResolvedVc<Box<dyn EcmascriptChunkPlaceable>>>,
31}
32
33#[turbo_tasks::value_impl]
34impl SideEffectsModule {
35 #[turbo_tasks::function]
36 pub fn new(
37 module: ResolvedVc<EcmascriptModuleAsset>,
38 part: ModulePart,
39 resolved_as: ResolvedVc<Box<dyn EcmascriptChunkPlaceable>>,
40 side_effects: Vec<ResolvedVc<Box<dyn EcmascriptChunkPlaceable>>>,
41 ) -> Vc<Self> {
42 SideEffectsModule {
43 module,
44 part,
45 resolved_as,
46 side_effects,
47 }
48 .cell()
49 }
50}
51
52#[turbo_tasks::value_impl]
53impl Module for SideEffectsModule {
54 #[turbo_tasks::function]
55 async fn ident(&self) -> Result<Vc<AssetIdent>> {
56 let mut ident = self.module.ident().owned().await?;
57 ident.parts.push(self.part.clone());
58
59 ident.add_asset(
60 ResolvedVc::cell(RcStr::from("resolved")),
61 self.resolved_as.ident().to_resolved().await?,
62 );
63
64 ident.add_modifier(ResolvedVc::cell(RcStr::from("side effects")));
65
66 for (i, side_effect) in self.side_effects.iter().enumerate() {
67 ident.add_asset(
68 ResolvedVc::cell(RcStr::from(format!("side effect {i}"))),
69 side_effect.ident().to_resolved().await?,
70 );
71 }
72
73 Ok(AssetIdent::new(Value::new(ident)))
74 }
75
76 #[turbo_tasks::function]
77 async fn references(&self) -> Result<Vc<ModuleReferences>> {
78 let mut references = vec![];
79
80 references.extend(
81 self.side_effects
82 .iter()
83 .map(|side_effect| async move {
84 Ok(ResolvedVc::upcast(
85 SingleChunkableModuleReference::new(
86 *ResolvedVc::upcast(*side_effect),
87 Vc::cell(RcStr::from("side effect")),
88 )
89 .to_resolved()
90 .await?,
91 ))
92 })
93 .try_join()
94 .await?,
95 );
96
97 references.push(ResolvedVc::upcast(
98 SingleChunkableModuleReference::new(
99 *ResolvedVc::upcast(self.resolved_as),
100 Vc::cell(RcStr::from("resolved as")),
101 )
102 .to_resolved()
103 .await?,
104 ));
105
106 Ok(Vc::cell(references))
107 }
108}
109
110#[turbo_tasks::value_impl]
111impl Asset for SideEffectsModule {
112 #[turbo_tasks::function]
113 fn content(&self) -> Vc<AssetContent> {
114 unreachable!("SideEffectsModule has no content")
115 }
116}
117
118#[turbo_tasks::value_impl]
119impl EcmascriptChunkPlaceable for SideEffectsModule {
120 #[turbo_tasks::function]
121 async fn get_exports(&self) -> Vc<EcmascriptExports> {
122 self.resolved_as.get_exports()
123 }
124
125 #[turbo_tasks::function]
126 async fn is_marked_as_side_effect_free(self: Vc<Self>, _: Vc<Glob>) -> Vc<bool> {
127 Vc::cell(true)
128 }
129}
130
131#[turbo_tasks::value_impl]
132impl ChunkableModule for SideEffectsModule {
133 #[turbo_tasks::function]
134 async fn as_chunk_item(
135 self: Vc<Self>,
136 module_graph: ResolvedVc<ModuleGraph>,
137 chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
138 ) -> Result<Vc<Box<dyn turbopack_core::chunk::ChunkItem>>> {
139 Ok(Vc::upcast(
140 SideEffectsModuleChunkItem {
141 module: self.to_resolved().await?,
142 module_graph,
143 chunking_context,
144 }
145 .cell(),
146 ))
147 }
148}
149
150#[turbo_tasks::value_impl]
151impl EvaluatableAsset for SideEffectsModule {}