swc_ecma_minifier/pass/mangle_names/
mangler.rs

1use swc_ecma_ast::*;
2use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith};
3
4use self::{label_manger::LabelMangler, private_name_manger::PrivateNameMangler};
5use crate::util::base54::Base54Chars;
6
7mod label_manger {
8    use rustc_hash::FxHashMap;
9    use swc_atoms::Atom;
10    use swc_ecma_ast::*;
11
12    use crate::util::base54::Base54Chars;
13
14    pub(super) struct LabelMangler {
15        chars: Base54Chars,
16        cache: FxHashMap<Atom, Atom>,
17        n: usize,
18    }
19
20    impl LabelMangler {
21        pub(super) fn new(chars: Base54Chars) -> Self {
22            Self {
23                chars,
24                cache: FxHashMap::with_capacity_and_hasher(64, Default::default()),
25                n: Default::default(),
26            }
27        }
28
29        pub(super) fn mangle(&mut self, label: &mut Ident) {
30            // Avoid cloning the symbol if it's already cached
31            if let Some(cached) = self.cache.get(&label.sym) {
32                label.sym = cached.clone();
33                return;
34            }
35
36            let new_sym = self.chars.encode(&mut self.n, true);
37            self.cache.insert(label.sym.clone(), new_sym.clone());
38            label.sym = new_sym;
39        }
40    }
41}
42
43mod private_name_manger {
44    use rustc_hash::FxHashMap;
45    use swc_atoms::Atom;
46    use swc_ecma_ast::*;
47
48    use crate::util::base54::Base54Chars;
49
50    pub(super) fn private_name_mangler(
51        keep_private_props: bool,
52        chars: Base54Chars,
53    ) -> PrivateNameMangler {
54        PrivateNameMangler {
55            keep_private_props,
56            private_n: Default::default(),
57            renamed_private: Default::default(),
58            chars,
59        }
60    }
61
62    pub(super) struct PrivateNameMangler {
63        chars: Base54Chars,
64        keep_private_props: bool,
65        private_n: usize,
66
67        renamed_private: FxHashMap<Atom, Atom>,
68    }
69
70    impl PrivateNameMangler {
71        pub(super) fn rename_private(&mut self, private_name: &mut PrivateName) {
72            if self.keep_private_props {
73                return;
74            }
75            let new_sym = if let Some(cached) = self.renamed_private.get(&private_name.name) {
76                cached.clone()
77            } else {
78                let sym = self.chars.encode(&mut self.private_n, true);
79
80                self.renamed_private
81                    .insert(private_name.name.clone(), sym.clone());
82
83                sym
84            };
85
86            private_name.name = new_sym;
87        }
88    }
89}
90
91pub(super) struct ManglerVisitor {
92    label_mangler: LabelMangler,
93    private_name_mangler: PrivateNameMangler,
94}
95
96impl ManglerVisitor {
97    pub(super) fn new(keep_private_props: bool, chars: Base54Chars) -> Self {
98        Self {
99            label_mangler: LabelMangler::new(chars),
100            private_name_mangler: self::private_name_manger::private_name_mangler(
101                keep_private_props,
102                chars,
103            ),
104        }
105    }
106}
107
108impl VisitMut for ManglerVisitor {
109    noop_visit_mut_type!(fail);
110
111    fn visit_mut_private_name(&mut self, n: &mut PrivateName) {
112        self.private_name_mangler.rename_private(n);
113    }
114
115    fn visit_mut_labeled_stmt(&mut self, n: &mut LabeledStmt) {
116        self.label_mangler.mangle(&mut n.label);
117
118        n.visit_mut_children_with(self);
119    }
120
121    fn visit_mut_continue_stmt(&mut self, n: &mut ContinueStmt) {
122        if let Some(label) = &mut n.label {
123            self.label_mangler.mangle(label);
124        }
125
126        n.visit_mut_children_with(self);
127    }
128
129    fn visit_mut_break_stmt(&mut self, n: &mut BreakStmt) {
130        if let Some(label) = &mut n.label {
131            self.label_mangler.mangle(label);
132        }
133
134        n.visit_mut_children_with(self);
135    }
136}