turbopack_core/chunk/
data.rs1use anyhow::Result;
2use turbo_tasks::{ReadRef, 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<ReadRef<ModuleId>>,
15 pub excluded: Vec<ReadRef<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) = Vc::try_resolve_sidecast::<Box<dyn OutputChunk>>(chunk).await?
75 else {
76 return Ok(Vc::cell(Some(
77 ChunkData {
78 path,
79 included: Vec::new(),
80 excluded: Vec::new(),
81 module_chunks: Vec::new(),
82 }
83 .resolved_cell(),
84 )));
85 };
86
87 let runtime_info = output_chunk.runtime_info().await?;
88
89 let OutputChunkRuntimeInfo {
90 included_ids,
91 excluded_ids,
92 module_chunks,
93 placeholder_for_future_extensions: _,
94 } = &*runtime_info;
95
96 let included = if let Some(included_ids) = included_ids {
97 included_ids.await?.iter().copied().try_join().await?
98 } else {
99 Vec::new()
100 };
101 let excluded = if let Some(excluded_ids) = excluded_ids {
102 excluded_ids.await?.iter().copied().try_join().await?
103 } else {
104 Vec::new()
105 };
106 let module_chunks = if let Some(module_chunks) = module_chunks {
107 module_chunks
108 .await?
109 .iter()
110 .copied()
111 .map(|chunk| {
112 let output_root = output_root.clone();
113
114 async move {
115 let chunk_path = chunk.path().await?;
116 Ok(output_root
117 .get_path_to(&chunk_path)
118 .map(|path| path.to_owned()))
119 }
120 })
121 .try_flat_join()
122 .await?
123 } else {
124 Vec::new()
125 };
126
127 Ok(Vc::cell(Some(
128 ChunkData {
129 path,
130 included,
131 excluded,
132 module_chunks,
133 }
134 .resolved_cell(),
135 )))
136 }
137
138 #[turbo_tasks::function]
139 pub async fn from_assets(
140 output_root: FileSystemPath,
141 chunks: Vc<OutputAssets>,
142 ) -> Result<Vc<ChunksData>> {
143 Ok(Vc::cell(
144 chunks
145 .await?
146 .iter()
147 .map(|&chunk| ChunkData::from_asset(output_root.clone(), *chunk))
148 .try_join()
149 .await?
150 .into_iter()
151 .flat_map(|chunk| *chunk)
152 .collect(),
153 ))
154 }
155}