turbopack_core/chunk/
optimize.rs1use anyhow::Result;
7use turbo_tasks::{ResolvedVc, TryJoinIterExt, Vc};
8use turbo_tasks_fs::{FileSystemPath, FileSystemPathOption};
9
10use crate::chunk::containment_tree::{ContainmentTree, ContainmentTreeKey};
11
12#[derive(Debug, Clone, Eq, PartialEq, Hash)]
13struct FileSystemPathKey(ResolvedVc<FileSystemPath>);
14
15impl FileSystemPathKey {
16 async fn new(path: Vc<FileSystemPath>) -> Result<Self> {
17 Ok(Self(path.to_resolved().await?))
18 }
19}
20
21#[async_trait::async_trait]
22impl ContainmentTreeKey for FileSystemPathKey {
23 async fn parent(&self) -> Result<Self> {
24 Ok(FileSystemPathKey::new(self.0.parent()).await?)
25 }
26}
27
28pub async fn optimize_by_common_parent<T, Acc, GetCommonParent, Optimize>(
29 chunks: &[T],
30 get_common_parent: GetCommonParent,
31 optimize: Optimize,
32) -> Result<Acc>
33where
34 T: Clone,
35 GetCommonParent: Fn(T) -> Vc<FileSystemPathOption> + Clone,
36 Optimize: Fn(Option<Vec<T>>, Vec<Acc>) -> Acc,
37{
38 let tree = ContainmentTree::build(
39 chunks
40 .iter()
41 .map(move |chunk| {
42 let get_common_parent = get_common_parent.clone();
43 async move {
44 let common_parent = get_common_parent(chunk.clone()).await?;
45
46 Ok((
47 if let Some(common_parent) = &*common_parent {
48 Some(FileSystemPathKey::new(**common_parent).await?)
49 } else {
50 None
51 },
52 chunk.clone(),
53 ))
54 }
55 })
56 .try_join()
57 .await?,
58 )
59 .await?;
60
61 fn optimize_tree<K, V, Acc>(
62 tree: ContainmentTree<K, V>,
63 optimize: &impl Fn(Option<Vec<V>>, Vec<Acc>) -> Acc,
64 ) -> Acc {
65 let children = tree
66 .children
67 .into_iter()
68 .map(|tree| optimize_tree(tree, optimize))
69 .collect::<Vec<_>>();
70
71 optimize(tree.values, children)
72 }
73
74 Ok(optimize_tree(tree, &optimize))
75}