Skip to content

Commit 5417dd5

Browse files
committed
lookahead decl
1 parent 073a41a commit 5417dd5

File tree

30 files changed

+1033
-526
lines changed

30 files changed

+1033
-526
lines changed

crates/swc_ecma_minifier/src/compress/hoist_decls.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use par_iter::prelude::*;
22
use rustc_hash::FxHashSet;
33
use swc_common::{pass::Repeated, util::take::Take, NodeId, DUMMY_SP};
44
use swc_ecma_ast::*;
5+
use swc_ecma_transforms_base::resolve::Resolver;
56
use swc_ecma_usage_analyzer::analyzer::UsageAnalyzer;
67
use swc_ecma_utils::{find_pat_ids, StmtLike};
78
use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith, VisitWith};
@@ -18,18 +19,24 @@ pub(super) struct DeclHoisterConfig {
1819
pub _top_level: bool,
1920
}
2021

21-
pub(super) fn decl_hoister(config: DeclHoisterConfig, data: &ProgramData) -> Hoister {
22+
pub(super) fn decl_hoister<'a>(
23+
config: DeclHoisterConfig,
24+
data: &'a ProgramData,
25+
r: &'a mut Resolver,
26+
) -> Hoister<'a> {
2227
Hoister {
2328
config,
2429
changed: false,
2530
data,
31+
r,
2632
}
2733
}
2834

2935
pub(super) struct Hoister<'a> {
3036
config: DeclHoisterConfig,
3137
changed: bool,
3238
data: &'a ProgramData,
39+
r: &'a mut Resolver,
3340
}
3441

3542
impl Repeated for Hoister<'_> {
@@ -123,14 +130,16 @@ impl Hoister<'_> {
123130
let ids: Vec<Ident> = find_pat_ids(&decl.name);
124131

125132
for id in ids {
126-
if done.insert(id.node_id) {
133+
debug_assert!(self.r.is_ref_to_binding(id.node_id));
134+
let node_id = self.r.find_binding_by_ident(&id);
135+
if done.insert(node_id) {
127136
// If the enclosing function declares parameter with same
128137
// name, we can drop a varaible.
129138
if decl.init.is_none()
130139
&& self
131140
.data
132141
.vars
133-
.get(&id.node_id)
142+
.get(&node_id)
134143
.map(|v| {
135144
v.flags.contains(
136145
VarUsageInfoFlags::DECLARED_AS_FN_PARAM,
@@ -210,13 +219,15 @@ impl Hoister<'_> {
210219

211220
let preserve = match &decl.name {
212221
Pat::Ident(name) => {
222+
debug_assert!(self.r.is_ref_to_binding(name.id.node_id));
223+
let node_id = self.r.find_binding_by_ident(&name.id);
213224
// If the enclosing function declares parameter with same
214225
// name, we can drop a varaible. (If it's side-effect free).
215226
if decl.init.is_none()
216227
&& self
217228
.data
218229
.vars
219-
.get(&name.node_id)
230+
.get(&node_id)
220231
.map(|v| {
221232
v.flags.contains(
222233
VarUsageInfoFlags::DECLARED_AS_FN_PARAM,
@@ -227,7 +238,7 @@ impl Hoister<'_> {
227238
return false;
228239
}
229240

230-
done.insert(name.node_id)
241+
done.insert(node_id)
231242
}
232243
_ => true,
233244
};

crates/swc_ecma_minifier/src/compress/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ impl Compressor<'_> {
9393
_top_level: self.options.top_level(),
9494
},
9595
&data,
96+
self.r,
9697
);
9798
n.visit_mut_with(&mut v);
9899
self.changed |= v.changed();
@@ -149,6 +150,7 @@ impl Compressor<'_> {
149150

150151
let mut visitor = pure_optimizer(
151152
self.options,
153+
self.r,
152154
self.marks,
153155
PureOptimizerConfig {
154156
enable_join_vars: self.pass > 1,

crates/swc_ecma_minifier/src/compress/optimize/arguments.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,14 @@ impl Optimizer<'_> {
7474
id: Ident { sym, .. },
7575
..
7676
}) if &**sym == "arguments" => true,
77-
Pat::Ident(i) => self
78-
.data
79-
.vars
80-
.get(&i.node_id)
81-
.map(|v| v.declared_count >= 2)
82-
.unwrap_or(false),
77+
Pat::Ident(i) => {
78+
debug_assert!(self.r.is_ref_to_itself(i.id.node_id));
79+
self.data
80+
.vars
81+
.get(&i.node_id)
82+
.map(|v| v.declared_count >= 2)
83+
.unwrap_or(false)
84+
}
8385
_ => true,
8486
}) {
8587
return;

crates/swc_ecma_minifier/src/compress/optimize/bools.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ impl Optimizer<'_> {
2222
) if &**l_v == "undefined" => {
2323
// TODO?
2424
if let Expr::Ident(arg) = &**arg {
25-
if let Some(usage) = o.data.vars.get(&arg.node_id) {
25+
let node_id = o.r.find_binding_by_ident(arg);
26+
if let Some(usage) = o.data.vars.get(&node_id) {
2627
if !usage.flags.contains(VarUsageInfoFlags::DECLARED) {
2728
return false;
2829
}

crates/swc_ecma_minifier/src/compress/optimize/conditionals.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ impl Optimizer<'_> {
387387
// to f(a, a = 1 ? true : false)
388388
let side_effects_in_test = test.may_have_side_effects(self.ctx.expr_ctx);
389389

390-
if self.data.contains_unresolved(test) {
390+
if self.data.contains_unresolved(test, self.r) {
391391
return None;
392392
}
393393

@@ -401,10 +401,11 @@ impl Optimizer<'_> {
401401
return None;
402402
}
403403

404+
let node_id = self.r.find_binding_by_ident(cons_callee);
404405
let side_effect_free = self
405406
.data
406407
.vars
407-
.get(&cons_callee.node_id)
408+
.get(&node_id)
408409
.map(|v| {
409410
v.flags.contains(
410411
VarUsageInfoFlags::IS_FN_LOCAL.union(VarUsageInfoFlags::DECLARED),
@@ -526,7 +527,7 @@ impl Optimizer<'_> {
526527
}
527528

528529
(Expr::New(cons), Expr::New(alt)) => {
529-
if self.data.contains_unresolved(test) {
530+
if self.data.contains_unresolved(test, self.r) {
530531
return None;
531532
}
532533

@@ -590,7 +591,7 @@ impl Optimizer<'_> {
590591
) if cons.left.eq_ignore_span(&alt.left) && cons.left.as_ident().is_some() => {
591592
if self
592593
.data
593-
.ident_is_unresolved(&cons.left.as_ident().unwrap().id)
594+
.ident_is_unresolved(&cons.left.as_ident().unwrap().id, self.r)
594595
{
595596
return None;
596597
}

crates/swc_ecma_minifier/src/compress/optimize/dead_code.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,12 @@ impl Optimizer<'_> {
5555
.map(|s| s.contains(ScopeData::USED_ARGUMENTS))
5656
.unwrap_or(false);
5757

58+
let node_id = self.r.find_binding_by_ident(lhs);
59+
5860
if self
5961
.data
6062
.vars
61-
.get(&lhs.node_id)
63+
.get(&node_id)
6264
.map(|var| {
6365
var.flags.contains(
6466
VarUsageInfoFlags::DECLARED.union(VarUsageInfoFlags::IS_FN_LOCAL),
@@ -94,10 +96,12 @@ impl Optimizer<'_> {
9496
.map(|s| s.contains(ScopeData::USED_ARGUMENTS))
9597
.unwrap_or(false);
9698

99+
let node_id = self.r.find_binding_by_ident(lhs);
100+
97101
if self
98102
.data
99103
.vars
100-
.get(&lhs.node_id)
104+
.get(&node_id)
101105
.map(|var| {
102106
var.flags.contains(
103107
VarUsageInfoFlags::DECLARED.union(VarUsageInfoFlags::IS_FN_LOCAL),

crates/swc_ecma_minifier/src/compress/optimize/evaluate.rs

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ impl Optimizer<'_> {
4444
if let Expr::Ident(obj) = &**obj {
4545
let metadata = *self.functions.get(&obj.to_id())?;
4646

47-
let usage = self.data.vars.get(&obj.node_id)?;
47+
let node_id = self.r.find_binding_by_ident(obj);
48+
let usage = self.data.vars.get(&node_id)?;
4849

4950
if usage.flags.contains(VarUsageInfoFlags::REASSIGNED) {
5051
return None;
@@ -98,10 +99,11 @@ impl Optimizer<'_> {
9899

99100
// We should not convert used-defined `undefined` to `void 0`.
100101
if let Expr::Ident(i) = e {
102+
let node_id = self.r.find_binding_by_ident(i);
101103
if self
102104
.data
103105
.vars
104-
.get(&i.node_id)
106+
.get(&node_id)
105107
.map(|var| var.flags.contains(VarUsageInfoFlags::DECLARED))
106108
.unwrap_or(false)
107109
{
@@ -164,35 +166,38 @@ impl Optimizer<'_> {
164166
"NaN" => {
165167
report_change!("evaluate: `Number.NaN` -> `NaN`");
166168
self.changed = true;
167-
*e = Ident::new(
169+
let mut ident = Ident::new(
168170
atom!("NaN"),
169171
*span,
170172
SyntaxContext::empty().apply_mark(self.marks.unresolved_mark),
171-
)
172-
.into();
173+
);
174+
self.r.add_unresolved(&mut ident);
175+
*e = ident.into();
173176
}
174177
"POSITIVE_INFINITY" => {
175178
report_change!("evaluate: `Number.POSITIVE_INFINITY` -> `Infinity`");
176179
self.changed = true;
177-
*e = Ident::new(
180+
let mut ident = Ident::new(
178181
atom!("Infinity"),
179182
*span,
180183
SyntaxContext::empty().apply_mark(self.marks.unresolved_mark),
181-
)
182-
.into();
184+
);
185+
self.r.add_unresolved(&mut ident);
186+
*e = ident.into();
183187
}
184188
"NEGATIVE_INFINITY" => {
185189
report_change!("evaluate: `Number.NEGATIVE_INFINITY` -> `-Infinity`");
186190
self.changed = true;
191+
let mut ident = Ident::new(
192+
atom!("Infinity"),
193+
*span,
194+
SyntaxContext::empty().apply_mark(self.marks.unresolved_mark),
195+
);
196+
self.r.add_unresolved(&mut ident);
187197
*e = UnaryExpr {
188198
span: *span,
189199
op: op!(unary, "-"),
190-
arg: Ident::new(
191-
atom!("Infinity"),
192-
*span,
193-
SyntaxContext::empty().apply_mark(self.marks.unresolved_mark),
194-
)
195-
.into(),
200+
arg: ident.into(),
196201
}
197202
.into();
198203
}
@@ -420,12 +425,13 @@ impl Optimizer<'_> {
420425
report_change!("evaluate: Evaluated an expression as `{}`", value);
421426

422427
if value.is_nan() {
423-
*e = Ident::new(
428+
let mut ident = Ident::new(
424429
atom!("NaN"),
425430
e.span(),
426431
SyntaxContext::empty().apply_mark(self.marks.unresolved_mark),
427-
)
428-
.into();
432+
);
433+
self.r.add_unresolved(&mut ident);
434+
*e = ident.into();
429435
return;
430436
}
431437

@@ -450,12 +456,13 @@ impl Optimizer<'_> {
450456
report_change!("evaluate: Evaluated `{:?} ** {:?}`", l, r);
451457

452458
if l.is_nan() || r.is_nan() {
453-
*e = Ident::new(
459+
let mut ident = Ident::new(
454460
atom!("NaN"),
455461
bin.span,
456462
SyntaxContext::empty().apply_mark(self.marks.unresolved_mark),
457-
)
458-
.into();
463+
);
464+
self.r.add_unresolved(&mut ident);
465+
*e = ident.into();
459466
} else {
460467
*e = Lit::Num(Number {
461468
span: bin.span,
@@ -488,13 +495,15 @@ impl Optimizer<'_> {
488495
report_change!("evaluate: `{} / 0` => `Infinity`", ln);
489496

490497
// Sign does not matter for NaN
498+
let mut ident = Ident::new_no_ctxt(atom!("Infinity"), bin.span);
499+
self.r.add_unresolved(&mut ident);
491500
*e = if ln.is_sign_positive() == rn.is_sign_positive() {
492-
Ident::new_no_ctxt(atom!("Infinity"), bin.span).into()
501+
ident.into()
493502
} else {
494503
UnaryExpr {
495504
span: bin.span,
496505
op: op!(unary, "-"),
497-
arg: Ident::new_no_ctxt(atom!("Infinity"), bin.span).into(),
506+
arg: ident.into(),
498507
}
499508
.into()
500509
};

0 commit comments

Comments
 (0)