Skip to content

Commit ccbfcd1

Browse files
authored
feat(es/compiler): Merge logical assignments (#10914)
**Related issue:** - This PR is a part of #10913
1 parent a44d329 commit ccbfcd1

File tree

8 files changed

+232
-227
lines changed

8 files changed

+232
-227
lines changed

.changeset/wet-feet-press.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
swc_ecma_compat_es2021: patch
3+
swc_ecma_compiler: patch
4+
swc_core: patch
5+
---
6+
7+
feat(es/compiler): Merge logical assignments

Cargo.lock

Lines changed: 1 addition & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/swc_ecma_compat_es2021/Cargo.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,8 @@ version = "22.0.0"
1414

1515
[dependencies]
1616
tracing = { workspace = true }
17-
swc_common = { version = "14.0.1", path = "../swc_common" }
17+
1818
swc_ecma_ast = { version = "14.0.0", path = "../swc_ecma_ast" }
19+
swc_ecma_compiler = { version = "0.1.1", path = "../swc_ecma_compiler" }
1920
swc_ecma_transforms_base = { version = "22.0.0", path = "../swc_ecma_transforms_base" }
2021
swc_ecma_utils = { version = "19.0.0", path = "../swc_ecma_utils" }
21-
swc_ecma_visit = { version = "14.0.0", path = "../swc_ecma_visit" }
22-
swc_trace_macro = { version = "2.0.2", path = "../swc_trace_macro" }
Lines changed: 6 additions & 218 deletions
Original file line numberDiff line numberDiff line change
@@ -1,221 +1,9 @@
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};
93

104
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+
})
2219
}

0 commit comments

Comments
 (0)