swc_ecma_minifier/pass/mangle_names/
mod.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use rustc_hash::{FxHashMap, FxHashSet};
use swc_atoms::JsWord;
use swc_common::chain;
use swc_ecma_ast::{Module, *};
use swc_ecma_transforms_base::rename::{renamer, Renamer};
use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith};

pub(crate) use self::preserver::idents_to_preserve;
use crate::{option::MangleOptions, util::base54::Base54Chars};

mod preserver;
mod private_name;

pub(crate) fn name_mangler(
    options: MangleOptions,
    preserved: FxHashSet<Id>,
    chars: Base54Chars,
) -> impl VisitMut {
    chain!(
        LabelMangler {
            chars,
            cache: Default::default(),
            n: Default::default(),
        },
        self::private_name::private_name_mangler(options.keep_private_props, chars),
        renamer(Default::default(), ManglingRenamer { chars, preserved })
    )
}

struct ManglingRenamer {
    chars: Base54Chars,
    preserved: FxHashSet<Id>,
}

impl Renamer for ManglingRenamer {
    const MANGLE: bool = true;
    const RESET_N: bool = false;

    fn preserved_ids_for_module(&mut self, _: &Module) -> FxHashSet<Id> {
        self.preserved.clone()
    }

    fn preserved_ids_for_script(&mut self, _: &Script) -> FxHashSet<Id> {
        self.preserved.clone()
    }

    fn new_name_for(&self, _: &Id, n: &mut usize) -> JsWord {
        self.chars.encode(n, true)
    }
}

struct LabelMangler {
    chars: Base54Chars,
    cache: FxHashMap<JsWord, JsWord>,
    n: usize,
}

impl LabelMangler {
    fn mangle(&mut self, label: &mut Ident) {
        let v = self
            .cache
            .entry(label.sym.clone())
            .or_insert_with(|| self.chars.encode(&mut self.n, true))
            .clone();

        label.sym = v;
    }
}

impl VisitMut for LabelMangler {
    noop_visit_mut_type!();

    fn visit_mut_labeled_stmt(&mut self, s: &mut LabeledStmt) {
        self.mangle(&mut s.label);

        s.visit_mut_children_with(self);
    }

    fn visit_mut_continue_stmt(&mut self, s: &mut ContinueStmt) {
        if let Some(label) = &mut s.label {
            self.mangle(label);
        }
    }

    fn visit_mut_break_stmt(&mut self, s: &mut BreakStmt) {
        if let Some(label) = &mut s.label {
            self.mangle(label);
        }
    }
}