|
1 | | -use std::mem; |
2 | | - |
3 | | -use swc_common::{util::take::Take, DUMMY_SP}; |
4 | | -use swc_ecma_ast::*; |
5 | | -use swc_ecma_transforms_base::perf::Parallel; |
6 | | -use swc_ecma_utils::{alias_ident_for, prepend_stmt}; |
7 | | -use swc_ecma_visit::{noop_visit_mut_type, visit_mut_pass, VisitMut, VisitMutWith}; |
8 | | -use swc_trace_macro::swc_trace; |
| 1 | +use swc_ecma_ast::Pass; |
| 2 | +use swc_ecma_compiler::{Compiler, Features}; |
9 | 3 |
|
10 | 4 | pub fn logical_assignments() -> impl Pass { |
11 | | - visit_mut_pass(Operators::default()) |
12 | | -} |
13 | | - |
14 | | -#[derive(Debug, Default)] |
15 | | -struct Operators { |
16 | | - vars: Vec<VarDeclarator>, |
17 | | -} |
18 | | - |
19 | | -impl Operators { |
20 | | - fn memorize_prop(&mut self, c: ComputedPropName) -> (ComputedPropName, ComputedPropName) { |
21 | | - let alias = alias_ident_for(&c.expr, "_ref"); |
22 | | - self.vars.push(VarDeclarator { |
23 | | - span: DUMMY_SP, |
24 | | - name: alias.clone().into(), |
25 | | - init: None, |
26 | | - definite: false, |
27 | | - }); |
28 | | - |
29 | | - ( |
30 | | - ComputedPropName { |
31 | | - span: c.span, |
32 | | - expr: AssignExpr { |
33 | | - span: DUMMY_SP, |
34 | | - left: alias.clone().into(), |
35 | | - op: op!("="), |
36 | | - right: c.expr, |
37 | | - } |
38 | | - .into(), |
39 | | - }, |
40 | | - ComputedPropName { |
41 | | - span: c.span, |
42 | | - expr: Box::new(alias.into()), |
43 | | - }, |
44 | | - ) |
45 | | - } |
46 | | -} |
47 | | - |
48 | | -#[swc_trace] |
49 | | -impl Parallel for Operators { |
50 | | - fn create(&self) -> Self { |
51 | | - Default::default() |
52 | | - } |
53 | | - |
54 | | - fn merge(&mut self, other: Self) { |
55 | | - self.vars.extend(other.vars); |
56 | | - } |
57 | | -} |
58 | | - |
59 | | -#[swc_trace] |
60 | | -impl VisitMut for Operators { |
61 | | - noop_visit_mut_type!(fail); |
62 | | - |
63 | | - fn visit_mut_expr(&mut self, e: &mut Expr) { |
64 | | - e.visit_mut_children_with(self); |
65 | | - |
66 | | - if let Expr::Assign(AssignExpr { |
67 | | - span, |
68 | | - op: op @ (op!("&&=") | op!("||=") | op!("??=")), |
69 | | - left: AssignTarget::Simple(left), |
70 | | - right, |
71 | | - }) = e |
72 | | - { |
73 | | - let (left_expr, r_assign_target) = match &mut *left { |
74 | | - SimpleAssignTarget::SuperProp(SuperPropExpr { |
75 | | - span, |
76 | | - obj, |
77 | | - prop: SuperProp::Computed(c), |
78 | | - }) => { |
79 | | - let (left, right) = self.memorize_prop(c.take()); |
80 | | - |
81 | | - ( |
82 | | - Box::new( |
83 | | - SuperPropExpr { |
84 | | - span: *span, |
85 | | - obj: *obj, |
86 | | - prop: SuperProp::Computed(left), |
87 | | - } |
88 | | - .into(), |
89 | | - ), |
90 | | - Box::new( |
91 | | - SuperPropExpr { |
92 | | - span: *span, |
93 | | - obj: *obj, |
94 | | - prop: SuperProp::Computed(right), |
95 | | - } |
96 | | - .into(), |
97 | | - ), |
98 | | - ) |
99 | | - } |
100 | | - SimpleAssignTarget::Member(m) => { |
101 | | - let (left_obj, right_obj) = match *m.obj.take() { |
102 | | - // TODO: local vars |
103 | | - obj @ Expr::This(_) => (obj.clone().into(), obj.into()), |
104 | | - obj => { |
105 | | - let alias = alias_ident_for(&obj, "_ref"); |
106 | | - self.vars.push(VarDeclarator { |
107 | | - span: DUMMY_SP, |
108 | | - name: alias.clone().into(), |
109 | | - init: None, |
110 | | - definite: false, |
111 | | - }); |
112 | | - |
113 | | - ( |
114 | | - AssignExpr { |
115 | | - span: DUMMY_SP, |
116 | | - op: op!("="), |
117 | | - left: alias.clone().into(), |
118 | | - right: obj.into(), |
119 | | - } |
120 | | - .into(), |
121 | | - alias.into(), |
122 | | - ) |
123 | | - } |
124 | | - }; |
125 | | - |
126 | | - let (left_prop, right_prop) = match m.prop.take() { |
127 | | - MemberProp::Computed(c) => { |
128 | | - let (left, right) = self.memorize_prop(c); |
129 | | - (left.into(), right.into()) |
130 | | - } |
131 | | - prop => (prop.clone(), prop), |
132 | | - }; |
133 | | - |
134 | | - ( |
135 | | - MemberExpr { |
136 | | - span: DUMMY_SP, |
137 | | - obj: left_obj, |
138 | | - prop: left_prop, |
139 | | - } |
140 | | - .into(), |
141 | | - MemberExpr { |
142 | | - span: DUMMY_SP, |
143 | | - obj: right_obj, |
144 | | - prop: right_prop, |
145 | | - } |
146 | | - .into(), |
147 | | - ) |
148 | | - } |
149 | | - _ => { |
150 | | - let expr: Box<Expr> = left.take().into(); |
151 | | - (expr.clone(), expr) |
152 | | - } |
153 | | - }; |
154 | | - |
155 | | - let right = AssignExpr { |
156 | | - span: DUMMY_SP, |
157 | | - op: op!("="), |
158 | | - left: r_assign_target.try_into().unwrap(), |
159 | | - right: right.take(), |
160 | | - } |
161 | | - .into(); |
162 | | - |
163 | | - let op = match *op { |
164 | | - op!("??=") => op!("??"), |
165 | | - op!("&&=") => op!("&&"), |
166 | | - op!("||=") => op!("||"), |
167 | | - _ => unreachable!(), |
168 | | - }; |
169 | | - |
170 | | - *e = BinExpr { |
171 | | - span: *span, |
172 | | - op, |
173 | | - left: left_expr, |
174 | | - right, |
175 | | - } |
176 | | - .into(); |
177 | | - } |
178 | | - } |
179 | | - |
180 | | - /// [swc_ecma_ast::ModuleItem] is the top level Item in the current |
181 | | - /// implementation of JavaScript until the proposal for |
182 | | - /// [module-declarations] and [module-expressions] are officially added. |
183 | | - /// |
184 | | - /// [module declarations]: https://github.com/tc39/proposal-module-declarations. |
185 | | - /// [module-expressions]: https://github.com/tc39/proposal-module-expressions |
186 | | - fn visit_mut_module_items(&mut self, n: &mut Vec<ModuleItem>) { |
187 | | - let vars = self.vars.take(); |
188 | | - n.visit_mut_children_with(self); |
189 | | - |
190 | | - let vars = mem::replace(&mut self.vars, vars); |
191 | | - if !vars.is_empty() { |
192 | | - prepend_stmt( |
193 | | - n, |
194 | | - VarDecl { |
195 | | - kind: VarDeclKind::Var, |
196 | | - decls: vars, |
197 | | - ..Default::default() |
198 | | - } |
199 | | - .into(), |
200 | | - ) |
201 | | - } |
202 | | - } |
203 | | - |
204 | | - fn visit_mut_stmts(&mut self, n: &mut Vec<Stmt>) { |
205 | | - let vars = self.vars.take(); |
206 | | - n.visit_mut_children_with(self); |
207 | | - |
208 | | - let vars = mem::replace(&mut self.vars, vars); |
209 | | - if !vars.is_empty() { |
210 | | - prepend_stmt( |
211 | | - n, |
212 | | - VarDecl { |
213 | | - kind: VarDeclKind::Var, |
214 | | - decls: vars, |
215 | | - ..Default::default() |
216 | | - } |
217 | | - .into(), |
218 | | - ) |
219 | | - } |
220 | | - } |
| 5 | + Compiler::new(swc_ecma_compiler::Config { |
| 6 | + includes: Features::LOGICAL_ASSIGNMENTS, |
| 7 | + excludes: Features::empty(), |
| 8 | + }) |
221 | 9 | } |
0 commit comments