Skip to content

Commit b9899df

Browse files
committed
[core][rewriter] dpsc: refactor object assignment target walker into a recursive function
1 parent 235ea13 commit b9899df

File tree

2 files changed

+109
-113
lines changed

2 files changed

+109
-113
lines changed

rewriter/js/src/visitor.rs

Lines changed: 99 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ use oxc::{
77
AssignmentTargetProperty, BindingPattern, BindingPatternKind, BindingProperty,
88
CallExpression, ComputedMemberExpression, DebuggerStatement, ExportAllDeclaration,
99
ExportNamedDeclaration, Expression, FunctionBody, IdentifierReference, ImportDeclaration,
10-
ImportExpression, MemberExpression, MetaProperty, NewExpression, ObjectExpression,
11-
ObjectPattern, ObjectPropertyKind, PrivateIdentifier, PropertyKey, ReturnStatement,
12-
SimpleAssignmentTarget, StringLiteral, ThisExpression, UnaryExpression, UnaryOperator,
13-
UpdateExpression,
10+
ImportExpression, MemberExpression, MetaProperty, NewExpression, ObjectAssignmentTarget,
11+
ObjectExpression, ObjectPattern, ObjectPropertyKind, PrivateIdentifier, PropertyKey,
12+
ReturnStatement, SimpleAssignmentTarget, StringLiteral, ThisExpression, UnaryExpression,
13+
UnaryOperator, UpdateExpression,
1414
},
1515
ast_visit::{Visit, walk},
1616
span::{Atom, GetSpan, Span},
@@ -104,6 +104,79 @@ where
104104
}
105105
}
106106

107+
fn recurse_object_assignment_target(&mut self, s: &ObjectAssignmentTarget<'data>) {
108+
if s.rest.is_some() {
109+
// infeasible to rewrite :(
110+
eprintln!("cannot rewrite rest parameters");
111+
return;
112+
}
113+
for prop in &s.properties {
114+
match prop {
115+
AssignmentTargetProperty::AssignmentTargetPropertyIdentifier(p) => {
116+
// { location } = self;
117+
// correct thing to do here is to change it into an AsignmentTargetPropertyProperty
118+
// { $sj_location: location } = self;
119+
if UNSAFE_GLOBALS.contains(&p.binding.name.to_string().as_str()) {
120+
self.jschanges.add(rewrite!(
121+
p.binding.span(),
122+
RebindProperty {
123+
ident: p.binding.name.clone()
124+
}
125+
));
126+
}
127+
128+
if let Some(d) = &p.init {
129+
// { location = parent } = {};
130+
// we still need to rewrite whatever stuff might be in the default expression
131+
walk::walk_expression(self, &d);
132+
}
133+
}
134+
AssignmentTargetProperty::AssignmentTargetPropertyProperty(p) => {
135+
// { location: x } = self;
136+
// { location: x = "..."} = self;
137+
// { location: { href } } = self;
138+
// { location: { href: x } } = self;
139+
// { ["location"]: x } = self;
140+
141+
match &p.name {
142+
PropertyKey::StaticIdentifier(id) => {
143+
// { location: x } = self;
144+
if UNSAFE_GLOBALS.contains(&id.name.to_string().as_str()) {
145+
self.jschanges.add(rewrite!(
146+
p.name.span(),
147+
RewriteProperty { ident: id.name }
148+
));
149+
}
150+
}
151+
PropertyKey::PrivateIdentifier(_) => {
152+
// doesn't matter
153+
}
154+
// (expression variant)
155+
_ => {
156+
// { ["location"]: x } = self;
157+
158+
// TODO: check literals
159+
self.jschanges.add(rewrite!(p.name.span(), WrapProperty));
160+
}
161+
}
162+
163+
match &p.binding {
164+
AssignmentTargetMaybeDefault::AssignmentTargetWithDefault(d) => {
165+
// { location: x = parent } = {};
166+
167+
// we still need to rewrite whatever stuff might be in the default expression
168+
walk::walk_expression(self, &d.init);
169+
}
170+
AssignmentTargetMaybeDefault::ObjectAssignmentTarget(p) => {
171+
self.recurse_object_assignment_target(p);
172+
}
173+
_ => {}
174+
}
175+
}
176+
}
177+
}
178+
}
179+
107180
fn scramitize(&mut self, span: Span) {
108181
self.jschanges.add(rewrite!(span, Scramitize));
109182
}
@@ -376,106 +449,6 @@ where
376449
}
377450
}
378451

379-
fn visit_assignment_target(&mut self, it: &AssignmentTarget<'data>) {
380-
match &it {
381-
AssignmentTarget::StaticMemberExpression(s) => {
382-
if UNSAFE_GLOBALS.contains(&s.property.name.as_str()) {
383-
self.jschanges.add(rewrite!(
384-
s.property.span(),
385-
RewriteProperty {
386-
ident: s.property.name
387-
}
388-
));
389-
}
390-
391-
// more to walk
392-
walk::walk_expression(self, &s.object);
393-
}
394-
AssignmentTarget::ComputedMemberExpression(s) => {
395-
self.walk_computed_member_expression(s);
396-
walk::walk_expression(self, &s.object);
397-
walk::walk_expression(self, &s.expression);
398-
}
399-
AssignmentTarget::ObjectAssignmentTarget(s) => {
400-
if s.rest.is_some() {
401-
// infeasible to rewrite :(
402-
eprintln!("cannot rewrite rest parameters");
403-
return;
404-
}
405-
for prop in &s.properties {
406-
match prop {
407-
AssignmentTargetProperty::AssignmentTargetPropertyIdentifier(p) => {
408-
// { location } = self;
409-
// correct thing to do here is to change it into an AsignmentTargetPropertyProperty
410-
// { $sj_location: location } = self;
411-
if UNSAFE_GLOBALS.contains(&p.binding.name.to_string().as_str()) {
412-
self.jschanges.add(rewrite!(
413-
p.binding.span(),
414-
RebindProperty {
415-
ident: p.binding.name.clone()
416-
}
417-
));
418-
}
419-
}
420-
AssignmentTargetProperty::AssignmentTargetPropertyProperty(p) => {
421-
// { location: x } = self;
422-
// { location: x = "..."} = self;
423-
// { location: { href } } = self;
424-
// { location: { href: x } } = self;
425-
// { ["location"]: x } = self;
426-
427-
match &p.name {
428-
PropertyKey::StaticIdentifier(id) => {
429-
// { location: x } = self;
430-
if UNSAFE_GLOBALS.contains(&id.name.to_string().as_str()) {
431-
self.jschanges.add(rewrite!(
432-
p.name.span(),
433-
RewriteProperty { ident: id.name }
434-
));
435-
}
436-
}
437-
PropertyKey::PrivateIdentifier(_) => {
438-
// doesn't matter
439-
}
440-
// (expression variant)
441-
_ => {
442-
// { ["location"]: x } = self;
443-
444-
// TODO: check literals
445-
self.jschanges.add(rewrite!(p.name.span(), WrapProperty));
446-
}
447-
}
448-
449-
match &p.binding {
450-
AssignmentTargetMaybeDefault::AssignmentTargetWithDefault(d) => {
451-
// { location: x = parent } = {};
452-
// { location = parent } = {};
453-
454-
// we still need to rewrite whatever stuff might be in the default expression
455-
walk::walk_expression(self, &d.init);
456-
}
457-
_ => {
458-
// { location: { href } } = {};
459-
walk::walk_assignment_target_maybe_default(self, &p.binding);
460-
}
461-
}
462-
}
463-
}
464-
}
465-
}
466-
AssignmentTarget::ArrayAssignmentTarget(_) => {
467-
// [location] = ["https://example.com"]
468-
// this is such a ridiculously specific edge case. just ignore it
469-
return;
470-
}
471-
_ => {
472-
// only walk the left side if it isn't an identifier, we can't replace the
473-
// identifier with a function obviously
474-
walk::walk_assignment_target(self, &it);
475-
}
476-
}
477-
}
478-
479452
fn visit_assignment_expression(&mut self, it: &AssignmentExpression<'data>) {
480453
// location = "https://example.com"
481454
match &it.left {
@@ -495,9 +468,29 @@ where
495468
return;
496469
}
497470
}
498-
_ => {
499-
// gets handled by visit_assignment_target
471+
AssignmentTarget::StaticMemberExpression(s) => {
472+
if UNSAFE_GLOBALS.contains(&s.property.name.as_str()) {
473+
self.jschanges.add(rewrite!(
474+
s.property.span(),
475+
RewriteProperty {
476+
ident: s.property.name
477+
}
478+
));
479+
}
480+
481+
// more to walk
482+
walk::walk_expression(self, &s.object);
483+
}
484+
AssignmentTarget::ComputedMemberExpression(s) => {
485+
self.walk_computed_member_expression(s);
486+
walk::walk_expression(self, &s.object);
487+
walk::walk_expression(self, &s.expression);
500488
}
489+
AssignmentTarget::ObjectAssignmentTarget(o) => {
490+
self.recurse_object_assignment_target(o);
491+
return;
492+
}
493+
_ => {}
501494
}
502495
walk::walk_assignment_expression(self, it);
503496
}

rewriter/native/destructuring.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
({ eval } = self);
2+
({ eval: a } = self);
3+
({ eval = parent } = self);
4+
({ ["eval"]: a } = self);
5+
({ ["eval"]: a = parent } = self);
6+
({ parent: { eval: x } } = self);
7+
({ parent: { eval: x = parent } } = self);
8+
({ parent: { eval} } = self);
9+
10+
111
({ location } = self);
2-
({ location: a } = self);
3-
({ location = parent } = self);
4-
({ ["location"]: a } = self);
5-
({ ["location"]: a = parent } = self);
6-
({ parent: { location: x } } = self);
7-
({ parent: { location: x = parent } } = self);
8-
({ parent: { location } } = self);

0 commit comments

Comments
 (0)