turbopack_core/chunk/
data.rs1use anyhow::Result;
2use turbo_tasks::{ReadRef, ResolvedVc, TryJoinIterExt, ValueToString, Vc};
3use turbo_tasks_fs::FileSystemPath;
4use turbo_tasks_hash::Xxh3Hash64Hasher;
5
6use crate::{
7 chunk::{ModuleId, OutputChunk, OutputChunkRuntimeInfo},
8 output::{OutputAsset, OutputAssets},
9};
10
11#[turbo_tasks::value]
12pub struct ChunkData {
13 pub path: String,
14 pub included: Vec<ReadRef<ModuleId>>,
15 pub excluded: Vec<ReadRef<ModuleId>>,
16 pub module_chunks: Vec<String>,
17 pub references: ResolvedVc<OutputAssets>,
18}
19
20#[turbo_tasks::value(transparent)]
21pub struct ChunkDataOption(Option<ResolvedVc<ChunkData>>);
22
23#[turbo_tasks::value(transparent)]
28pub struct ChunksData(Vec<ResolvedVc<ChunkData>>);
29
30#[turbo_tasks::value_impl]
31impl ChunksData {
32 #[turbo_tasks::function]
33 pub async fn hash(&self) -> Result<Vc<u64>> {
34 let mut hasher = Xxh3Hash64Hasher::new();
35 for chunk in self.0.iter() {
36 hasher.write_value(chunk.await?.path.as_str());
37 }
38 Ok(Vc::cell(hasher.finish()))
39 }
40}
41
42#[turbo_tasks::value_impl]
43impl ChunkData {
44 #[turbo_tasks::function]
45 pub async fn hash(&self) -> Result<Vc<u64>> {
46 let mut hasher = Xxh3Hash64Hasher::new();
47 hasher.write_value(self.path.as_str());
48 for module in &self.included {
49 hasher.write_value(module);
50 }
51 for module in &self.excluded {
52 hasher.write_value(module);
53 }
54 for module_chunk in &self.module_chunks {
55 hasher.write_value(module_chunk.as_str());
56 }
57 for reference in self.references.await?.iter() {
58 hasher.write_value(reference.path().to_string().await?);
59 }
60
61 Ok(Vc::cell(hasher.finish()))
62 }
63
64 #[turbo_tasks::function]
65 pub async fn from_asset(
66 output_root: FileSystemPath,
67 chunk: Vc<Box<dyn OutputAsset>>,
68 ) -> Result<Vc<ChunkDataOption>> {
69 let path = chunk.path().await?;
70 let Some(path) = output_root.get_path_to(&path) else {
74 return Ok(Vc::cell(None));
75 };
76 let path = path.to_string();
77
78 let Some(output_chunk) = Vc::try_resolve_sidecast::<Box<dyn OutputChunk>>(chunk).await?
79 else {
80 return Ok(Vc::cell(Some(
81 ChunkData {
82 path,
83 included: Vec::new(),
84 excluded: Vec::new(),
85 module_chunks: Vec::new(),
86 references: OutputAssets::empty().to_resolved().await?,
87 }
88 .resolved_cell(),
89 )));
90 };
91
92 let runtime_info = output_chunk.runtime_info().await?;
93
94 let OutputChunkRuntimeInfo {
95 included_ids,
96 excluded_ids,
97 module_chunks,
98 placeholder_for_future_extensions: _,
99 } = &*runtime_info;
100
101 let included = if let Some(included_ids) = included_ids {
102 included_ids.await?.iter().copied().try_join().await?
103 } else {
104 Vec::new()
105 };
106 let excluded = if let Some(excluded_ids) = excluded_ids {
107 excluded_ids.await?.iter().copied().try_join().await?
108 } else {
109 Vec::new()
110 };
111 let (module_chunks, module_chunks_references) = if let Some(module_chunks) = module_chunks {
112 module_chunks
113 .await?
114 .iter()
115 .copied()
116 .map(|chunk| {
117 let output_root = output_root.clone();
118
119 async move {
120 let chunk_path = chunk.path().await?;
121 Ok(output_root
122 .get_path_to(&chunk_path)
123 .map(|path| (path.to_owned(), chunk)))
124 }
125 })
126 .try_join()
127 .await?
128 .into_iter()
129 .flatten()
130 .unzip()
131 } else {
132 (Vec::new(), Vec::new())
133 };
134
135 Ok(Vc::cell(Some(
136 ChunkData {
137 path,
138 included,
139 excluded,
140 module_chunks,
141 references: ResolvedVc::cell(module_chunks_references),
142 }
143 .resolved_cell(),
144 )))
145 }
146
147 #[turbo_tasks::function]
148 pub async fn from_assets(
149 output_root: FileSystemPath,
150 chunks: Vc<OutputAssets>,
151 ) -> Result<Vc<ChunksData>> {
152 Ok(Vc::cell(
153 chunks
154 .await?
155 .iter()
156 .map(|&chunk| ChunkData::from_asset(output_root.clone(), *chunk))
157 .try_join()
158 .await?
159 .into_iter()
160 .flat_map(|chunk| *chunk)
161 .collect(),
162 ))
163 }
164
165 #[turbo_tasks::function]
167 pub fn references(&self) -> Vc<OutputAssets> {
168 *self.references
169 }
170}