swc_bundler/bundler/
keywords.rs

1use rustc_hash::FxHashMap;
2use swc_common::util::take::Take;
3use swc_ecma_ast::*;
4use swc_ecma_utils::private_ident;
5use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith};
6
7use crate::id::Id;
8
9#[derive(Default)]
10pub struct KeywordRenamer {
11    renamed: FxHashMap<Id, Ident>,
12}
13
14impl KeywordRenamer {
15    /// Returns `Some(new_ident)` if it should be renamed.
16    fn renamed(&mut self, id: &Ident) -> Option<Ident> {
17        if id.sym == "import" {
18            return None;
19        }
20
21        if !(id.is_reserved() || id.is_reserved_in_strict_mode(true) || id.is_reserved_in_es3()) {
22            return None;
23        }
24
25        Some(
26            self.renamed
27                .entry(id.into())
28                .or_insert_with(|| private_ident!(id.span, format!("__{}", id.sym)))
29                .clone(),
30        )
31    }
32}
33
34impl VisitMut for KeywordRenamer {
35    noop_visit_mut_type!(fail);
36
37    fn visit_mut_binding_ident(&mut self, n: &mut BindingIdent) {
38        if let Some(new) = self.renamed(&n.id) {
39            n.ctxt = new.ctxt;
40            n.sym = new.sym;
41        }
42    }
43
44    fn visit_mut_class_decl(&mut self, c: &mut ClassDecl) {
45        c.class.visit_mut_with(self);
46        if let Some(renamed) = self.renamed(&c.ident) {
47            c.ident = renamed;
48        }
49    }
50
51    fn visit_mut_class_prop(&mut self, n: &mut ClassProp) {
52        if n.key.is_computed() {
53            n.key.visit_mut_with(self);
54        }
55
56        n.decorators.visit_mut_with(self);
57        n.value.visit_mut_with(self);
58    }
59
60    fn visit_mut_export_named_specifier(&mut self, n: &mut ExportNamedSpecifier) {
61        let orig = match &n.orig {
62            ModuleExportName::Ident(ident) => ident,
63            ModuleExportName::Str(..) => unimplemented!("module string names unimplemented"),
64            #[cfg(swc_ast_unknown)]
65            _ => panic!("unable to access unknown nodes"),
66        };
67        if let Some(renamed) = self.renamed(orig) {
68            n.orig = ModuleExportName::Ident(renamed);
69        }
70    }
71
72    fn visit_mut_expr(&mut self, n: &mut Expr) {
73        if let Expr::Ident(n) = n {
74            if let Some(renamed) = self.renamed(n) {
75                *n = renamed;
76            }
77            return;
78        }
79
80        n.visit_mut_children_with(self);
81    }
82
83    fn visit_mut_fn_decl(&mut self, f: &mut FnDecl) {
84        f.function.visit_mut_with(self);
85        if let Some(renamed) = self.renamed(&f.ident) {
86            f.ident = renamed;
87        }
88    }
89
90    fn visit_mut_object_pat_prop(&mut self, n: &mut ObjectPatProp) {
91        if let ObjectPatProp::Assign(pat) = n {
92            if let Some(renamed) = self.renamed(&pat.key) {
93                match &mut pat.value {
94                    Some(default) => {
95                        *n = ObjectPatProp::KeyValue(KeyValuePatProp {
96                            key: PropName::Ident(pat.key.take().into()),
97                            value: AssignPat {
98                                span: pat.span,
99                                left: Box::new(renamed.into()),
100                                right: default.take(),
101                            }
102                            .into(),
103                        });
104                    }
105                    None => {
106                        *n = ObjectPatProp::KeyValue(KeyValuePatProp {
107                            key: PropName::Ident(pat.key.take().into()),
108                            value: renamed.into(),
109                        })
110                    }
111                }
112            }
113            return;
114        }
115
116        n.visit_mut_children_with(self);
117    }
118
119    fn visit_mut_pat(&mut self, n: &mut Pat) {
120        if let Pat::Ident(n) = n {
121            if let Some(renamed) = self.renamed(&n.id) {
122                *n = renamed.into();
123            }
124
125            return;
126        }
127        n.visit_mut_children_with(self);
128    }
129
130    fn visit_mut_private_prop(&mut self, n: &mut PrivateProp) {
131        n.decorators.visit_mut_with(self);
132        n.value.visit_mut_with(self);
133    }
134
135    fn visit_mut_prop(&mut self, n: &mut Prop) {
136        match n {
137            Prop::Shorthand(i) => {
138                if let Some(renamed) = self.renamed(i) {
139                    *n = Prop::KeyValue(KeyValueProp {
140                        key: PropName::Ident(i.clone().into()),
141                        value: renamed.into(),
142                    });
143                }
144            }
145            _ => {
146                n.visit_mut_children_with(self);
147            }
148        }
149    }
150}