turbopack_ecmascript/tree_shake/
side_effect_module.rs1use anyhow::Result;
2use turbo_rcstr::{RcStr, rcstr};
3use turbo_tasks::{ResolvedVc, TryJoinIterExt, Vc};
4use turbopack_core::{
5 chunk::{ChunkableModule, ChunkingContext, EvaluatableAsset},
6 ident::AssetIdent,
7 module::{Module, ModuleSideEffects},
8 module_graph::ModuleGraph,
9 reference::{ModuleReferences, SingleChunkableModuleReference},
10 resolve::{ExportUsage, ModulePart},
11};
12
13use crate::{
14 EcmascriptModuleAsset,
15 chunk::{EcmascriptChunkPlaceable, EcmascriptExports},
16 tree_shake::chunk_item::SideEffectsModuleChunkItem,
17};
18
19#[turbo_tasks::value]
20pub(super) struct SideEffectsModule {
21 pub module: ResolvedVc<EcmascriptModuleAsset>,
23 pub part: ModulePart,
25 pub resolved_as: ResolvedVc<Box<dyn EcmascriptChunkPlaceable>>,
27 pub side_effects: Vec<ResolvedVc<Box<dyn EcmascriptChunkPlaceable>>>,
29}
30
31#[turbo_tasks::value_impl]
32impl SideEffectsModule {
33 #[turbo_tasks::function]
34 pub fn new(
35 module: ResolvedVc<EcmascriptModuleAsset>,
36 part: ModulePart,
37 resolved_as: ResolvedVc<Box<dyn EcmascriptChunkPlaceable>>,
38 side_effects: Vec<ResolvedVc<Box<dyn EcmascriptChunkPlaceable>>>,
39 ) -> Vc<Self> {
40 SideEffectsModule {
41 module,
42 part,
43 resolved_as,
44 side_effects,
45 }
46 .cell()
47 }
48}
49
50#[turbo_tasks::value_impl]
51impl Module for SideEffectsModule {
52 #[turbo_tasks::function]
53 async fn ident(&self) -> Result<Vc<AssetIdent>> {
54 let mut ident = self.module.ident().owned().await?;
55 ident.parts.push(self.part.clone());
56
57 ident.add_asset(
58 rcstr!("resolved"),
59 self.resolved_as.ident().to_resolved().await?,
60 );
61
62 ident.add_modifier(rcstr!("side effects"));
63
64 for (i, side_effect) in self.side_effects.iter().enumerate() {
65 ident.add_asset(
66 RcStr::from(format!("side effect {i}")),
67 side_effect.ident().to_resolved().await?,
68 );
69 }
70
71 Ok(AssetIdent::new(ident))
72 }
73
74 #[turbo_tasks::function]
75 fn source(&self) -> Vc<turbopack_core::source::OptionSource> {
76 Vc::cell(None)
77 }
78
79 #[turbo_tasks::function]
80 async fn references(&self) -> Result<Vc<ModuleReferences>> {
81 let mut references = vec![];
82
83 references.extend(
84 self.side_effects
85 .iter()
86 .map(|side_effect| async move {
87 Ok(ResolvedVc::upcast(
88 SingleChunkableModuleReference::new(
89 *ResolvedVc::upcast(*side_effect),
90 rcstr!("side effect"),
91 ExportUsage::evaluation(),
92 )
93 .to_resolved()
94 .await?,
95 ))
96 })
97 .try_join()
98 .await?,
99 );
100
101 references.push(ResolvedVc::upcast(
102 SingleChunkableModuleReference::new(
103 *ResolvedVc::upcast(self.resolved_as),
104 rcstr!("resolved as"),
105 ExportUsage::all(),
106 )
107 .to_resolved()
108 .await?,
109 ));
110
111 Ok(Vc::cell(references))
112 }
113
114 #[turbo_tasks::function]
115 fn side_effects(self: Vc<Self>) -> Vc<ModuleSideEffects> {
116 ModuleSideEffects::ModuleEvaluationIsSideEffectFree.cell()
120 }
121}
122
123#[turbo_tasks::value_impl]
124impl EcmascriptChunkPlaceable for SideEffectsModule {
125 #[turbo_tasks::function]
126 fn get_exports(&self) -> Vc<EcmascriptExports> {
127 self.resolved_as.get_exports()
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 {}