swc_ecma_compat_es2015/
arrow.rs1use std::mem;
2
3use swc_common::{util::take::Take, Mark, SyntaxContext, DUMMY_SP};
4use swc_ecma_ast::*;
5use swc_ecma_utils::{
6 function::{init_this, FnEnvHoister},
7 prepend_stmt,
8};
9use swc_ecma_visit::{noop_visit_mut_type, visit_mut_pass, InjectVars, VisitMut, VisitMutWith};
10use swc_trace_macro::swc_trace;
11
12pub fn arrow(unresolved_mark: Mark) -> impl Pass + VisitMut + InjectVars {
61 visit_mut_pass(Arrow {
62 in_subclass: false,
63 hoister: FnEnvHoister::new(SyntaxContext::empty().apply_mark(unresolved_mark)),
64 })
65}
66
67#[derive(Default)]
68struct Arrow {
69 in_subclass: bool,
70 hoister: FnEnvHoister,
71}
72
73#[swc_trace]
74impl VisitMut for Arrow {
75 noop_visit_mut_type!(fail);
76
77 fn visit_mut_class(&mut self, c: &mut Class) {
78 let old = self.in_subclass;
79
80 if c.super_class.is_some() {
81 self.in_subclass = true;
82 }
83 c.visit_mut_children_with(self);
84 self.in_subclass = old;
85 }
86
87 fn visit_mut_constructor(&mut self, c: &mut Constructor) {
88 c.params.visit_mut_children_with(self);
89
90 if let Some(BlockStmt { span: _, stmts, .. }) = &mut c.body {
91 let old_rep = self.hoister.take();
92
93 stmts.visit_mut_children_with(self);
94
95 if self.in_subclass {
96 let (decl, this_id) =
97 mem::replace(&mut self.hoister, old_rep).to_stmt_in_subclass();
98
99 if let Some(stmt) = decl {
100 if let Some(this_id) = this_id {
101 init_this(stmts, &this_id)
102 }
103 prepend_stmt(stmts, stmt);
104 }
105 } else {
106 let decl = mem::replace(&mut self.hoister, old_rep).to_stmt();
107
108 if let Some(stmt) = decl {
109 prepend_stmt(stmts, stmt);
110 }
111 }
112 }
113 }
114
115 fn visit_mut_expr(&mut self, expr: &mut Expr) {
116 match expr {
117 Expr::Arrow(ArrowExpr {
118 span,
119 params,
120 body,
121 is_async,
122 is_generator,
123 ..
124 }) => {
125 params.visit_mut_with(self);
126 params.visit_mut_with(&mut self.hoister);
127
128 let params: Vec<Param> = params
129 .take()
130 .into_iter()
131 .map(|pat| Param {
132 span: DUMMY_SP,
133 decorators: Default::default(),
134 pat,
135 })
136 .collect();
137
138 body.visit_mut_with(self);
139
140 body.visit_mut_with(&mut self.hoister);
141
142 let fn_expr = Function {
143 decorators: Vec::new(),
144 span: *span,
145 params,
146 is_async: *is_async,
147 is_generator: *is_generator,
148 body: Some(match &mut **body {
149 BlockStmtOrExpr::BlockStmt(block) => block.take(),
150 BlockStmtOrExpr::Expr(expr) => BlockStmt {
151 span: DUMMY_SP,
152 stmts: vec![Stmt::Return(ReturnStmt {
153 span: DUMMY_SP,
157 arg: Some(expr.take()),
158 })],
159 ..Default::default()
160 },
161 #[cfg(swc_ast_unknown)]
162 _ => panic!("unable to access unknown nodes"),
163 }),
164 ..Default::default()
165 }
166 .into();
167
168 *expr = fn_expr;
169 }
170 _ => {
171 expr.visit_mut_children_with(self);
172 }
173 }
174 }
175
176 fn visit_mut_function(&mut self, f: &mut Function) {
177 let old_rep = self.hoister.take();
178
179 f.visit_mut_children_with(self);
180
181 let decl = mem::replace(&mut self.hoister, old_rep).to_stmt();
182
183 if let (Some(body), Some(stmt)) = (&mut f.body, decl) {
184 prepend_stmt(&mut body.stmts, stmt);
185 }
186 }
187
188 fn visit_mut_getter_prop(&mut self, f: &mut GetterProp) {
189 f.key.visit_mut_with(self);
190
191 if let Some(body) = &mut f.body {
192 let old_rep = self.hoister.take();
193
194 body.visit_mut_with(self);
195
196 let decl = mem::replace(&mut self.hoister, old_rep).to_stmt();
197
198 if let Some(stmt) = decl {
199 prepend_stmt(&mut body.stmts, stmt);
200 }
201 }
202 }
203
204 fn visit_mut_module_items(&mut self, stmts: &mut Vec<ModuleItem>) {
205 stmts.visit_mut_children_with(self);
206
207 let decl = self.hoister.take().to_stmt();
208
209 if let Some(stmt) = decl {
210 prepend_stmt(stmts, stmt.into());
211 }
212 }
213
214 fn visit_mut_script(&mut self, script: &mut Script) {
215 script.visit_mut_children_with(self);
216
217 let decl = self.hoister.take().to_stmt();
218
219 if let Some(stmt) = decl {
220 prepend_stmt(&mut script.body, stmt);
221 }
222 }
223
224 fn visit_mut_setter_prop(&mut self, f: &mut SetterProp) {
225 f.key.visit_mut_with(self);
226 f.param.visit_mut_with(self);
227
228 if let Some(body) = &mut f.body {
229 let old_rep = self.hoister.take();
230
231 body.visit_mut_with(self);
232
233 let decl = mem::replace(&mut self.hoister, old_rep).to_stmt();
234
235 if let Some(stmt) = decl {
236 prepend_stmt(&mut body.stmts, stmt);
237 }
238 }
239 }
240}
241
242impl InjectVars for Arrow {
243 fn take_vars(&mut self) -> Vec<VarDeclarator> {
244 self.hoister.take().to_decl()
245 }
246}