turbopack_core/module_graph/
export_usage.rs1use anyhow::Result;
4use auto_hash_map::AutoSet;
5use rustc_hash::FxHashMap;
6use turbo_rcstr::RcStr;
7use turbo_tasks::{ResolvedVc, Vc};
8
9use crate::{module::Module, module_graph::ModuleGraph, resolve::ExportUsage};
10
11#[turbo_tasks::function(operation)]
12pub async fn compute_export_usage_info(
13 graph: ResolvedVc<ModuleGraph>,
14) -> Result<Vc<ExportUsageInfo>> {
15 let mut used_exports = FxHashMap::<_, ModuleExportUsageInfo>::default();
16
17 graph
18 .await?
19 .traverse_all_edges_unordered(|(_, ref_data), target| {
20 if let Some(target_module) = ResolvedVc::try_downcast::<Box<dyn Module>>(target.module)
21 {
22 let e = used_exports.entry(target_module).or_default();
23
24 e.add(&ref_data.export);
25 }
26
27 Ok(())
28 })
29 .await?;
30
31 Ok(ExportUsageInfo { used_exports }.cell())
32}
33
34#[turbo_tasks::value(transparent)]
35pub struct OptionExportUsageInfo(Option<ResolvedVc<ExportUsageInfo>>);
36
37#[turbo_tasks::value]
38pub struct ExportUsageInfo {
39 used_exports: FxHashMap<ResolvedVc<Box<dyn Module>>, ModuleExportUsageInfo>,
40}
41
42impl ExportUsageInfo {
43 pub fn used_exports(&self, module: ResolvedVc<Box<dyn Module>>) -> Vc<ModuleExportUsageInfo> {
44 if let Some(exports) = self.used_exports.get(&module) {
45 exports.clone().cell()
46 } else {
47 ModuleExportUsageInfo::all()
50 }
51 }
52}
53
54#[turbo_tasks::value]
55#[derive(Default, Clone)]
56pub enum ModuleExportUsageInfo {
57 #[default]
59 Evaluation,
60 Exports(AutoSet<RcStr>),
61 All,
62}
63
64#[turbo_tasks::value_impl]
65impl ModuleExportUsageInfo {
66 #[turbo_tasks::function]
67 pub fn all() -> Vc<Self> {
68 ModuleExportUsageInfo::All.cell()
69 }
70}
71
72impl ModuleExportUsageInfo {
73 fn add(&mut self, usage: &ExportUsage) {
74 match (&mut *self, usage) {
75 (Self::All, _) => {}
76 (_, ExportUsage::All) => {
77 *self = Self::All;
78 }
79 (Self::Evaluation, ExportUsage::Named(name)) => {
80 *self = Self::Exports(AutoSet::from_iter([name.clone()]));
82 }
83
84 (Self::Exports(l), ExportUsage::Named(r)) => {
85 l.insert(r.clone());
87 }
88
89 (_, ExportUsage::Evaluation) => {
90 }
92 }
93 }
94
95 pub fn is_export_used(&self, export: &RcStr) -> bool {
96 match self {
97 Self::All => true,
98 Self::Evaluation => false,
99 Self::Exports(exports) => exports.contains(export),
100 }
101 }
102}