turbopack_ecmascript/analyzer/jsvalue/
traverse.rs1use crate::analyzer::{JsValue, ObjectPart};
2
3impl<'a> JsValue<'a> {
5 pub fn for_each_children_mut(
8 &mut self,
9 visitor: &mut impl FnMut(&mut JsValue<'a>) -> bool,
10 ) -> bool {
11 match self {
12 JsValue::Alternatives {
13 total_nodes: _,
14 values: list,
15 logical_property: _,
16 }
17 | JsValue::Concat(_, list)
18 | JsValue::Add(_, list)
19 | JsValue::Logical(_, _, list)
20 | JsValue::Array { items: list, .. } => {
21 let mut modified = false;
22 for item in list.iter_mut() {
23 if visitor(item) {
24 modified = true
25 }
26 }
27 if modified {
28 self.update_total_nodes();
29 }
30 modified
31 }
32 JsValue::Not(_, value) => {
33 let modified = visitor(value);
34 if modified {
35 self.update_total_nodes();
36 }
37 modified
38 }
39 JsValue::Object { parts, .. } => {
40 let mut modified = false;
41 for item in parts.iter_mut() {
42 match item {
43 ObjectPart::KeyValue(key, value) => {
44 if visitor(key) {
45 modified = true
46 }
47 if visitor(value) {
48 modified = true
49 }
50 }
51 ObjectPart::Spread(value) => {
52 if visitor(value) {
53 modified = true
54 }
55 }
56 }
57 }
58 if modified {
59 self.update_total_nodes();
60 }
61 modified
62 }
63 JsValue::New(_, call) => {
64 let modified = call.for_each_children_mut(visitor);
65 if modified {
66 self.update_total_nodes();
67 }
68 modified
69 }
70 JsValue::Call(_, call) => {
71 let modified = call.for_each_children_mut(visitor);
72 if modified {
73 self.update_total_nodes();
74 }
75 modified
76 }
77 JsValue::SuperCall(_, args) => {
78 let mut modified = false;
79 for item in args.iter_mut() {
80 if visitor(item) {
81 modified = true
82 }
83 }
84 if modified {
85 self.update_total_nodes();
86 }
87 modified
88 }
89 JsValue::MemberCall(_, call) => {
90 let modified = call.for_each_children_mut(visitor);
91
92 if modified {
93 self.update_total_nodes();
94 }
95 modified
96 }
97 JsValue::Function(_, _, return_value) => {
98 let modified = visitor(return_value);
99
100 if modified {
101 self.update_total_nodes();
102 }
103 modified
104 }
105 JsValue::Binary(_, a, _, b) => {
106 let m1 = visitor(a);
107 let m2 = visitor(b);
108 let modified = m1 || m2;
109 if modified {
110 self.update_total_nodes();
111 }
112 modified
113 }
114 JsValue::Tenary(_, test, cons, alt) => {
115 let m1 = visitor(test);
116 let m2 = visitor(cons);
117 let m3 = visitor(alt);
118 let modified = m1 || m2 || m3;
119 if modified {
120 self.update_total_nodes();
121 }
122 modified
123 }
124 JsValue::Member(_, obj, prop) | JsValue::In(_, obj, prop) => {
125 let m1 = visitor(obj);
126 let m2 = visitor(prop);
127 let modified = m1 || m2;
128 if modified {
129 self.update_total_nodes();
130 }
131 modified
132 }
133 JsValue::Iterated(_, operand)
134 | JsValue::TypeOf(_, operand)
135 | JsValue::Promise(_, operand)
136 | JsValue::Awaited(_, operand) => {
137 let modified = visitor(operand);
138 if modified {
139 self.update_total_nodes();
140 }
141 modified
142 }
143
144 JsValue::Constant(_)
145 | JsValue::FreeVar(_)
146 | JsValue::Variable(_)
147 | JsValue::Module(..)
148 | JsValue::Url(_, _)
149 | JsValue::WellKnownObject(_)
150 | JsValue::WellKnownFunction(_)
151 | JsValue::Unknown { .. }
152 | JsValue::Argument(..) => false,
153 }
154 }
155
156 pub fn for_each_early_children_mut(
159 &mut self,
160 visitor: &mut impl FnMut(&mut JsValue<'a>) -> bool,
161 ) -> bool {
162 match self {
163 JsValue::New(_, call) if !call.args().is_empty() => {
164 let m = visitor(call.callee_mut());
165 if m {
166 self.update_total_nodes();
167 }
168 m
169 }
170 JsValue::Call(_, call) if !call.args().is_empty() => {
171 let m = visitor(call.callee_mut());
172 if m {
173 self.update_total_nodes();
174 }
175 m
176 }
177 JsValue::MemberCall(_, call) if !call.args().is_empty() => {
178 let m1 = visitor(call.prop_mut());
179 let m2 = visitor(call.obj_mut());
180 let modified = m1 || m2;
181 if modified {
182 self.update_total_nodes();
183 }
184 modified
185 }
186 JsValue::Member(_, obj, _) => {
187 let m = visitor(obj);
188 if m {
189 self.update_total_nodes();
190 }
191 m
192 }
193 _ => false,
194 }
195 }
196
197 pub fn for_each_late_children_mut(
200 &mut self,
201 visitor: &mut impl FnMut(&mut JsValue<'a>) -> bool,
202 ) -> bool {
203 match self {
204 JsValue::New(_, call) if !call.args().is_empty() => {
205 let mut modified = false;
206 for item in call.args_mut().iter_mut() {
207 if visitor(item) {
208 modified = true
209 }
210 }
211 if modified {
212 self.update_total_nodes();
213 }
214 modified
215 }
216 JsValue::Call(_, call) if !call.args().is_empty() => {
217 let mut modified = false;
218 for item in call.args_mut().iter_mut() {
219 if visitor(item) {
220 modified = true
221 }
222 }
223 if modified {
224 self.update_total_nodes();
225 }
226 modified
227 }
228 JsValue::MemberCall(_, call) if !call.args().is_empty() => {
229 let mut modified = false;
230 for item in call.args_mut().iter_mut() {
231 if visitor(item) {
232 modified = true
233 }
234 }
235 if modified {
236 self.update_total_nodes();
237 }
238 modified
239 }
240 JsValue::Member(_, _, prop) => {
241 let m = visitor(prop);
242 if m {
243 self.update_total_nodes();
244 }
245 m
246 }
247 _ => self.for_each_children_mut(visitor),
248 }
249 }
250
251 pub fn visit(&self, visitor: &mut impl FnMut(&JsValue<'a>)) {
253 self.for_each_children(&mut |value| value.visit(visitor));
254 visitor(self);
255 }
256
257 pub fn for_each_children(&self, visitor: &mut impl FnMut(&JsValue<'a>)) {
259 match self {
260 JsValue::Alternatives {
261 total_nodes: _,
262 values: list,
263 logical_property: _,
264 }
265 | JsValue::Concat(_, list)
266 | JsValue::Add(_, list)
267 | JsValue::Logical(_, _, list)
268 | JsValue::Array { items: list, .. } => {
269 for item in list.iter() {
270 visitor(item);
271 }
272 }
273 JsValue::Not(_, value) => {
274 visitor(value);
275 }
276 JsValue::Object { parts, .. } => {
277 for item in parts.iter() {
278 match item {
279 ObjectPart::KeyValue(key, value) => {
280 visitor(key);
281 visitor(value);
282 }
283 ObjectPart::Spread(value) => {
284 visitor(value);
285 }
286 }
287 }
288 }
289 JsValue::New(_, call) => {
290 call.for_each_children(visitor);
291 }
292 JsValue::Call(_, call) => {
293 call.for_each_children(visitor);
294 }
295 JsValue::SuperCall(_, args) => {
296 for item in args.iter() {
297 visitor(item);
298 }
299 }
300 JsValue::MemberCall(_, call) => {
301 call.for_each_children(visitor);
302 }
303 JsValue::Function(_, _, return_value) => {
304 visitor(return_value);
305 }
306 JsValue::Member(_, obj, prop) | JsValue::In(_, obj, prop) => {
307 visitor(obj);
308 visitor(prop);
309 }
310 JsValue::Binary(_, a, _, b) => {
311 visitor(a);
312 visitor(b);
313 }
314 JsValue::Tenary(_, test, cons, alt) => {
315 visitor(test);
316 visitor(cons);
317 visitor(alt);
318 }
319
320 JsValue::Iterated(_, operand)
321 | JsValue::TypeOf(_, operand)
322 | JsValue::Promise(_, operand)
323 | JsValue::Awaited(_, operand) => {
324 visitor(operand);
325 }
326
327 JsValue::Constant(_)
328 | JsValue::FreeVar(_)
329 | JsValue::Variable(_)
330 | JsValue::Module(..)
331 | JsValue::Url(_, _)
332 | JsValue::WellKnownObject(_)
333 | JsValue::WellKnownFunction(_)
334 | JsValue::Unknown { .. }
335 | JsValue::Argument(..) => {}
336 }
337 }
338}