swc_bundler/bundler/chunk/plan/
mod.rs

1use anyhow::{bail, Error};
2use rustc_hash::FxHashMap;
3use swc_graph_analyzer::{DepGraph, GraphAnalyzer};
4
5use crate::{
6    bundler::{load::TransformedModule, scope::Scope},
7    dep_graph::ModuleGraph,
8    BundleKind, Bundler, Load, ModuleId, Resolve,
9};
10
11#[cfg(test)]
12mod tests;
13
14#[derive(Debug, Default)]
15struct PlanBuilder {
16    kinds: FxHashMap<ModuleId, BundleKind>,
17}
18
19#[derive(Debug, Default)]
20pub(super) struct Plan {
21    pub entries: FxHashMap<ModuleId, BundleKind>,
22
23    /// Id of all modules.
24    pub all: Vec<ModuleId>,
25}
26
27impl DepGraph for Scope {
28    type ModuleId = ModuleId;
29
30    fn deps_of(&self, module_id: Self::ModuleId) -> Vec<Self::ModuleId> {
31        let m = self.get_module(module_id).expect("failed to get module");
32
33        m.imports
34            .specifiers
35            .iter()
36            .chain(m.exports.reexports.iter())
37            .map(|v| v.0.module_id)
38            .collect()
39    }
40}
41
42impl<L, R> Bundler<'_, L, R>
43where
44    L: Load,
45    R: Resolve,
46{
47    pub(super) fn determine_entries(
48        &self,
49        entries: FxHashMap<String, TransformedModule>,
50    ) -> Result<(Plan, ModuleGraph, Vec<Vec<ModuleId>>), Error> {
51        let mut builder = PlanBuilder::default();
52        let mut analyzer = GraphAnalyzer::new(&self.scope);
53
54        for (name, module) in entries {
55            if let Some(v) = builder.kinds.insert(module.id, BundleKind::Named { name }) {
56                bail!("Multiple entries with same input path detected: {:?}", v)
57            }
58
59            analyzer.load(module.id);
60        }
61        let res = analyzer.into_result();
62
63        // dbg!(&builder.cycles);
64
65        Ok((
66            Plan {
67                entries: builder.kinds,
68                all: res.all,
69            },
70            res.graph,
71            res.cycles,
72        ))
73    }
74}