Skip to content

Commit 6d2cb31

Browse files
committed
lookahead decl
1 parent 073a41a commit 6d2cb31

File tree

24 files changed

+886
-470
lines changed

24 files changed

+886
-470
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/conditionals.rs

Lines changed: 3 additions & 3 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

@@ -526,7 +526,7 @@ impl Optimizer<'_> {
526526
}
527527

528528
(Expr::New(cons), Expr::New(alt)) => {
529-
if self.data.contains_unresolved(test) {
529+
if self.data.contains_unresolved(test, self.r) {
530530
return None;
531531
}
532532

@@ -590,7 +590,7 @@ impl Optimizer<'_> {
590590
) if cons.left.eq_ignore_span(&alt.left) && cons.left.as_ident().is_some() => {
591591
if self
592592
.data
593-
.ident_is_unresolved(&cons.left.as_ident().unwrap().id)
593+
.ident_is_unresolved(&cons.left.as_ident().unwrap().id, self.r)
594594
{
595595
return None;
596596
}

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

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -164,35 +164,38 @@ impl Optimizer<'_> {
164164
"NaN" => {
165165
report_change!("evaluate: `Number.NaN` -> `NaN`");
166166
self.changed = true;
167-
*e = Ident::new(
167+
let mut ident = Ident::new(
168168
atom!("NaN"),
169169
*span,
170170
SyntaxContext::empty().apply_mark(self.marks.unresolved_mark),
171-
)
172-
.into();
171+
);
172+
self.r.add_unresolved(&mut ident);
173+
*e = ident.into();
173174
}
174175
"POSITIVE_INFINITY" => {
175176
report_change!("evaluate: `Number.POSITIVE_INFINITY` -> `Infinity`");
176177
self.changed = true;
177-
*e = Ident::new(
178+
let mut ident = Ident::new(
178179
atom!("Infinity"),
179180
*span,
180181
SyntaxContext::empty().apply_mark(self.marks.unresolved_mark),
181-
)
182-
.into();
182+
);
183+
self.r.add_unresolved(&mut ident);
184+
*e = ident.into();
183185
}
184186
"NEGATIVE_INFINITY" => {
185187
report_change!("evaluate: `Number.NEGATIVE_INFINITY` -> `-Infinity`");
186188
self.changed = true;
189+
let mut ident = Ident::new(
190+
atom!("Infinity"),
191+
*span,
192+
SyntaxContext::empty().apply_mark(self.marks.unresolved_mark),
193+
);
194+
self.r.add_unresolved(&mut ident);
187195
*e = UnaryExpr {
188196
span: *span,
189197
op: op!(unary, "-"),
190-
arg: Ident::new(
191-
atom!("Infinity"),
192-
*span,
193-
SyntaxContext::empty().apply_mark(self.marks.unresolved_mark),
194-
)
195-
.into(),
198+
arg: ident.into(),
196199
}
197200
.into();
198201
}
@@ -420,12 +423,13 @@ impl Optimizer<'_> {
420423
report_change!("evaluate: Evaluated an expression as `{}`", value);
421424

422425
if value.is_nan() {
423-
*e = Ident::new(
426+
let mut ident = Ident::new(
424427
atom!("NaN"),
425428
e.span(),
426429
SyntaxContext::empty().apply_mark(self.marks.unresolved_mark),
427-
)
428-
.into();
430+
);
431+
self.r.add_unresolved(&mut ident);
432+
*e = ident.into();
429433
return;
430434
}
431435

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

452456
if l.is_nan() || r.is_nan() {
453-
*e = Ident::new(
457+
let mut ident = Ident::new(
454458
atom!("NaN"),
455459
bin.span,
456460
SyntaxContext::empty().apply_mark(self.marks.unresolved_mark),
457-
)
458-
.into();
461+
);
462+
self.r.add_unresolved(&mut ident);
463+
*e = ident.into();
459464
} else {
460465
*e = Lit::Num(Number {
461466
span: bin.span,
@@ -488,13 +493,15 @@ impl Optimizer<'_> {
488493
report_change!("evaluate: `{} / 0` => `Infinity`", ln);
489494

490495
// Sign does not matter for NaN
496+
let mut ident = Ident::new_no_ctxt(atom!("Infinity"), bin.span);
497+
self.r.add_unresolved(&mut ident);
491498
*e = if ln.is_sign_positive() == rn.is_sign_positive() {
492-
Ident::new_no_ctxt(atom!("Infinity"), bin.span).into()
499+
ident.into()
493500
} else {
494501
UnaryExpr {
495502
span: bin.span,
496503
op: op!(unary, "-"),
497-
arg: Ident::new_no_ctxt(atom!("Infinity"), bin.span).into(),
504+
arg: ident.into(),
498505
}
499506
.into()
500507
};

0 commit comments

Comments
 (0)