swc_bundler/bundler/
scope.rs

1use std::sync::atomic::{AtomicBool, Ordering};
2
3use swc_atoms::atom;
4use swc_common::{sync::Lrc, FileName};
5
6use super::load::TransformedModule;
7use crate::{
8    id::{Id, ModuleId, ModuleIdGenerator},
9    util::CloneMap,
10};
11
12#[derive(Debug, Default)]
13pub(super) struct Scope {
14    pub module_id_gen: ModuleIdGenerator,
15
16    loaded_modules: CloneMap<ModuleId, ()>,
17
18    /// Cached after applying basic transformations.
19    transformed_modules: CloneMap<ModuleId, TransformedModule>,
20
21    accessed_with_computed_key: CloneMap<ModuleId, Lrc<AtomicBool>>,
22    is_cjs: CloneMap<ModuleId, Lrc<AtomicBool>>,
23}
24
25impl Scope {
26    pub fn mark_as_loaded(&self, id: ModuleId) {
27        self.loaded_modules.insert(id, ());
28    }
29
30    /// Stores module information. The information should contain only
31    /// information gotten from module itself. In other words, it should not
32    /// contains information from a dependency.
33    pub fn store_module(&self, info: TransformedModule) {
34        self.transformed_modules.insert(info.id, info);
35    }
36
37    pub fn get_module_by_path(&self, file_name: &FileName) -> Option<TransformedModule> {
38        let (id, _, _) = self.module_id_gen.gen(file_name);
39        self.get_module(id)
40    }
41
42    pub fn get_module(&self, id: ModuleId) -> Option<TransformedModule> {
43        self.transformed_modules.get(&id)
44    }
45
46    pub fn is_cjs(&self, id: ModuleId) -> bool {
47        if let Some(v) = self.is_cjs.get(&id) {
48            v.load(Ordering::SeqCst)
49        } else {
50            false
51        }
52    }
53
54    /// Set the module as a common js module
55    pub fn mark_as_cjs(&self, id: ModuleId) {
56        if let Some(v) = self.is_cjs.get(&id) {
57            v.store(true, Ordering::SeqCst);
58            return;
59        }
60
61        self.is_cjs.insert(id, Lrc::new(AtomicBool::from(true)));
62    }
63
64    /// Set the module as
65    pub fn mark_as_wrapping_required(&self, id: ModuleId) {
66        if let Some(v) = self.accessed_with_computed_key.get(&id) {
67            v.store(true, Ordering::SeqCst);
68            return;
69        }
70
71        self.accessed_with_computed_key
72            .insert(id, Lrc::new(AtomicBool::from(true)));
73    }
74
75    pub fn should_be_wrapped_with_a_fn(&self, id: ModuleId) -> bool {
76        if let Some(v) = self.accessed_with_computed_key.get(&id) {
77            v.load(Ordering::SeqCst)
78        } else {
79            false
80        }
81    }
82
83    /// Returns `Some(module_ident)` if the module should be wrapped
84    /// with a function.
85    pub fn wrapped_esm_id(&self, id: ModuleId) -> Option<Id> {
86        if !self.should_be_wrapped_with_a_fn(id) {
87            return None;
88        }
89        let info = self.get_module(id)?;
90
91        Some(Id::new(atom!("mod"), info.export_ctxt()))
92    }
93}