turbopack_core/module_graph/
async_module_info.rs1use anyhow::Result;
2use rustc_hash::FxHashSet;
3use turbo_tasks::{ResolvedVc, TryFlatJoinIterExt, Vc};
4
5use crate::{
6 module::{Module, Modules},
7 module_graph::{GraphTraversalAction, ModuleGraph, SingleModuleGraphWithBindingUsage},
8};
9
10#[turbo_tasks::value(transparent)]
11pub struct ModulesSet(FxHashSet<ResolvedVc<Box<dyn Module>>>);
12
13#[turbo_tasks::value(transparent)]
16pub struct AsyncModulesInfo(FxHashSet<ResolvedVc<Box<dyn Module>>>);
17
18#[turbo_tasks::value_impl]
19impl AsyncModulesInfo {
20 #[turbo_tasks::function]
21 pub fn is_async(&self, module: ResolvedVc<Box<dyn Module>>) -> Vc<bool> {
22 Vc::cell(self.0.contains(&module))
23 }
24
25 #[turbo_tasks::function]
26 pub async fn is_async_multiple(&self, modules: ResolvedVc<Modules>) -> Result<Vc<ModulesSet>> {
27 Ok(Vc::cell(
28 modules
29 .await?
30 .iter()
31 .copied()
32 .filter(|m| self.0.contains(m))
33 .collect(),
34 ))
35 }
36}
37
38#[turbo_tasks::function(operation)]
39pub async fn compute_async_module_info(
40 graphs: ResolvedVc<ModuleGraph>,
41) -> Result<Vc<AsyncModulesInfo>> {
42 let mut result: Vc<AsyncModulesInfo> = Vc::cell(Default::default());
44 let graphs = graphs.await?;
45 for graph in graphs.iter_graphs() {
46 result = compute_async_module_info_single(graph, result);
47 }
48 Ok(result)
49}
50
51#[turbo_tasks::function]
52async fn compute_async_module_info_single(
53 graph: SingleModuleGraphWithBindingUsage,
54 parent_async_modules: Vc<AsyncModulesInfo>,
55) -> Result<Vc<AsyncModulesInfo>> {
56 let parent_async_modules = parent_async_modules.await?;
57 let graph = graph.read().await?;
58
59 let self_async_modules = graph
60 .enumerate_nodes()
61 .map(async |(_, node)| {
62 Ok(match node {
63 super::SingleModuleGraphNode::Module(node) => {
64 node.is_self_async().await?.then_some(*node)
65 }
66 super::SingleModuleGraphNode::VisitedModule { idx: _, module } => {
67 parent_async_modules.contains(module).then_some(*module)
70 }
71 })
72 })
73 .try_flat_join()
74 .await?;
75
76 let mut async_modules = FxHashSet::default();
81 async_modules.extend(self_async_modules.iter());
82
83 graph.traverse_edges_from_entries_dfs_reversed(
84 self_async_modules,
85 &mut (),
86 |child, parent, _state| {
89 Ok(if let Some((_, edge)) = child {
90 if edge.chunking_type.is_inherit_async() {
91 async_modules.insert(parent);
92 GraphTraversalAction::Continue
93 } else {
94 GraphTraversalAction::Exclude
96 }
97 } else {
98 GraphTraversalAction::Continue
100 })
101 },
102 |_, _, _| Ok(()),
103 )?;
104
105 async_modules.extend(parent_async_modules);
107
108 Ok(Vc::cell(async_modules))
109}