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
91
92
93
94
95
96
97
98
use crate::ext::MapWithMut;
use fxhash::FxHashMap;
use swc_ecma_ast::*;
use swc_ecma_utils::{ident::IdentLike, Id};
use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith};
pub fn constant_propagation() -> impl 'static + Fold {
as_folder(ConstPropagation::default())
}
#[derive(Default)]
struct ConstPropagation<'a> {
scope: Scope<'a>,
}
#[derive(Default)]
struct Scope<'a> {
parent: Option<&'a Scope<'a>>,
vars: FxHashMap<Id, Box<Expr>>,
}
impl Scope<'_> {
fn find_var(&self, id: &Id) -> Option<&Box<Expr>> {
if let Some(v) = self.vars.get(id) {
return Some(v);
}
self.parent.and_then(|parent| parent.find_var(id))
}
}
impl VisitMut for ConstPropagation<'_> {
noop_visit_mut_type!();
fn visit_mut_var_decl(&mut self, var: &mut VarDecl) {
var.decls.visit_mut_with(self);
if let VarDeclKind::Const = var.kind {
for decl in &var.decls {
match &decl.name {
Pat::Ident(name) => match &decl.init {
Some(init) => match &**init {
Expr::Lit(Lit::Bool(..))
| Expr::Lit(Lit::Num(..))
| Expr::Lit(Lit::Null(..))
| Expr::Ident(..) => {
self.scope.vars.insert(name.to_id(), init.clone());
}
_ => {}
},
None => {}
},
_ => {}
}
}
}
}
fn visit_mut_prop(&mut self, p: &mut Prop) {
p.visit_mut_children_with(self);
match p {
Prop::Shorthand(i) => {
if let Some(expr) = self.scope.find_var(&i.to_id()) {
*p = Prop::KeyValue(KeyValueProp {
key: PropName::Ident(i.take()),
value: expr.clone(),
});
return;
}
}
_ => {}
}
}
fn visit_mut_expr(&mut self, e: &mut Expr) {
match e {
Expr::Ident(i) => {
if let Some(expr) = self.scope.find_var(&i.to_id()) {
*e = *expr.clone();
return;
}
}
_ => {}
}
e.visit_mut_children_with(self);
}
fn visit_mut_member_expr(&mut self, e: &mut MemberExpr) {
e.obj.visit_mut_with(self);
if e.computed {
e.prop.visit_mut_with(self);
}
}
}