swc_bundler/bundler/
keywords.rs1use 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 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}