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