turbopack_core/chunk/
availability_info.rs1use anyhow::Result;
2use bincode::{Decode, Encode};
3use bitfield::bitfield;
4use turbo_rcstr::RcStr;
5use turbo_tasks::ResolvedVc;
6
7use crate::{
8 chunk::available_chunk_groups::AvailableChunkGroups,
9 module::Modules,
10 module_graph::{
11 ModuleGraph, chunk_group_info::ChunkGroupKey, module_batch::ChunkableModuleOrBatch,
12 },
13};
14
15bitfield! {
16 #[turbo_tasks::task_input]
17 #[derive(Clone, Copy, Default, PartialEq, Eq, Hash, Encode, Decode)]
18 pub struct AvailabilityFlags(u8);
19 impl Debug;
20 pub is_in_async_module, set_is_in_async_module: 0;
21}
22
23#[turbo_tasks::task_input]
24#[derive(Eq, PartialEq, Hash, Clone, Copy, Debug, Encode, Decode)]
25pub struct AvailabilityInfo {
26 flags: AvailabilityFlags,
27 available_chunk_groups: Option<ResolvedVc<AvailableChunkGroups>>,
29 entry_group: Option<ResolvedVc<Modules>>,
31}
32
33impl AvailabilityInfo {
34 pub fn root() -> Self {
35 Self {
36 flags: AvailabilityFlags::default(),
37 available_chunk_groups: None,
38 entry_group: None,
39 }
40 }
41
42 pub fn available_chunk_groups(&self) -> Option<ResolvedVc<AvailableChunkGroups>> {
43 self.available_chunk_groups
44 }
45
46 pub async fn with_chunk_group(
47 self,
48 module_graph: ResolvedVc<ModuleGraph>,
49 chunk_group: ChunkGroupKey,
50 ) -> Result<Self> {
51 let chunk_group = module_graph
52 .chunk_group_info()
53 .get_index_of(chunk_group)
54 .await? as u32;
55 Ok(Self {
56 flags: self.flags,
57 available_chunk_groups: Some(
58 if let Some(available_chunk_groups) = self.available_chunk_groups {
59 available_chunk_groups
60 .with_chunk_group(*module_graph, chunk_group)
61 .to_resolved()
62 .await?
63 } else {
64 AvailableChunkGroups::new(*module_graph, chunk_group)
65 .to_resolved()
66 .await?
67 },
68 ),
69 entry_group: self.entry_group,
70 })
71 }
72
73 pub async fn is_available(
75 &self,
76 module_graph: ResolvedVc<ModuleGraph>,
77 item: ChunkableModuleOrBatch,
78 ) -> Result<bool> {
79 let Some(available_chunk_groups) = self.available_chunk_groups else {
80 return Ok(false);
81 };
82 let available_chunk_groups = available_chunk_groups.await?;
83 let chunk_group_info = module_graph.chunk_group_info().await?;
84 let module = match item {
85 ChunkableModuleOrBatch::Module(module) => ResolvedVc::upcast(module),
86 ChunkableModuleOrBatch::Batch(batch) => match batch.await?.modules.first() {
89 Some(&module) => ResolvedVc::upcast(module),
90 None => return Ok(false),
91 },
92 ChunkableModuleOrBatch::None(_) => return Ok(false),
93 };
94 Ok(chunk_group_info
95 .module_chunk_groups
96 .await?
97 .get(&module)
98 .is_some_and(|groups| {
99 !groups.is_disjoint(available_chunk_groups.chunk_groups(module_graph))
100 }))
101 }
102
103 pub fn in_async_module(self) -> Self {
104 let mut flags = self.flags;
105 flags.set_is_in_async_module(true);
106 Self {
107 flags,
108 available_chunk_groups: self.available_chunk_groups,
109 entry_group: self.entry_group,
110 }
111 }
112
113 pub fn is_in_async_module(&self) -> bool {
114 self.flags.is_in_async_module()
115 }
116
117 pub fn with_entry_group(self, entry_group: ResolvedVc<Modules>) -> Self {
118 Self {
119 flags: self.flags,
120 available_chunk_groups: self.available_chunk_groups,
121 entry_group: Some(entry_group),
122 }
123 }
124
125 pub fn entry_group(&self) -> Option<ResolvedVc<Modules>> {
126 self.entry_group
127 }
128
129 pub async fn ident(&self) -> Result<Option<RcStr>> {
130 Ok(
131 if let Some(available_chunk_groups) = self.available_chunk_groups {
132 Some(available_chunk_groups.hash().await?.to_string().into())
133 } else {
134 None
135 },
136 )
137 }
138}