Skip to content

Commit fb3855d

Browse files
committed
deep lookadhead
1 parent 27f359a commit fb3855d

File tree

4 files changed

+159
-80
lines changed
  • crates

4 files changed

+159
-80
lines changed

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

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -204,30 +204,28 @@ impl Optimizer<'_> {
204204
continue;
205205
}
206206
debug_assert!(self.r.is_ref_to_itself(param.node_id));
207-
if let Some(usage) = self.data.vars.get(&param.node_id) {
207+
let node_id = param.node_id;
208+
if let Some(usage) = self.data.vars.get(&node_id) {
208209
if usage.flags.contains(VarUsageInfoFlags::REASSIGNED) {
209210
continue;
210211
}
211212
}
212213

213-
let arg = e.args.get(idx).map(|v| &v.expr);
214-
215-
if let Some(arg) = arg {
214+
if let Some(arg) = e.args.get(idx).map(|v| &v.expr) {
216215
match &**arg {
217216
Expr::Lit(Lit::Regex(..)) => continue,
218217
Expr::Lit(Lit::Str(s)) if s.value.len() > 3 => continue,
219218
Expr::Lit(..) => {}
220219
_ => continue,
221220
}
222221

223-
let should_be_inlined = self.can_be_inlined_for_iife(arg);
224-
if should_be_inlined {
222+
if self.can_be_inlined_for_iife(arg) {
225223
trace_op!(
226224
"iife: Trying to inline argument ({}{:?})",
227225
param.id.sym,
228226
param.id.ctxt
229227
);
230-
vars.insert(param.node_id, arg.clone());
228+
vars.insert(node_id, arg.clone());
231229
} else {
232230
trace_op!(
233231
"iife: Trying to inline argument ({}{:?}) (not inlinable)",
@@ -242,7 +240,7 @@ impl Optimizer<'_> {
242240
param.id.ctxt
243241
);
244242

245-
vars.insert(param.node_id, Expr::undefined(param.span()));
243+
vars.insert(node_id, Expr::undefined(param.span()));
246244
}
247245
}
248246

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -707,10 +707,10 @@ impl Optimizer<'_> {
707707
return;
708708
}
709709

710-
let id = i.node_id;
711-
debug_assert!(self.r.is_ref_to_itself(id));
710+
let node_id = i.node_id;
711+
debug_assert!(self.r.is_ref_to_itself(node_id));
712712

713-
if let Some(usage) = self.data.vars.get(&id) {
713+
if let Some(usage) = self.data.vars.get(&node_id) {
714714
if usage
715715
.flags
716716
.contains(VarUsageInfoFlags::DECLARED_AS_CATCH_PARAM)
@@ -778,7 +778,7 @@ impl Optimizer<'_> {
778778
}
779779

780780
self.vars.simple_functions.insert(
781-
id,
781+
node_id,
782782
FnExpr {
783783
ident: None,
784784
function: f.function.clone(),
@@ -873,7 +873,7 @@ impl Optimizer<'_> {
873873
}
874874
};
875875

876-
self.vars.vars_for_inlining.insert(id, e);
876+
self.vars.vars_for_inlining.insert(node_id, e);
877877
} else {
878878
log_abort!("inline: [x] Usage: {:?}", usage);
879879
}

crates/swc_ecma_transforms_base/src/resolve/mod.rs

Lines changed: 147 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,20 @@ impl Resolver {
217217
for prop in n.props.iter_mut() {
218218
match prop {
219219
ObjectPatProp::KeyValue(p) => {
220+
if let PropName::Computed(key) = &mut p.key {
221+
struct BindingIdent<'r> {
222+
r: &'r mut Resolver,
223+
}
224+
impl<'r> VisitMut for BindingIdent<'r> {
225+
noop_visit_mut_type!();
226+
227+
fn visit_mut_ident(&mut self, ident: &mut Ident) {
228+
self.r.add_binding_for_ident(ident);
229+
}
230+
}
231+
let mut v = BindingIdent { r: self };
232+
key.visit_mut_children_with(&mut v);
233+
};
220234
self.visit_pat_with_binding(&mut p.value, is_var);
221235
}
222236
ObjectPatProp::Assign(p) => {
@@ -247,67 +261,6 @@ impl Resolver {
247261
}
248262
}
249263

250-
fn lookahead_hoist_stmt(&mut self, stmt: &mut Stmt) {
251-
let Stmt::Decl(decl) = stmt else {
252-
return;
253-
};
254-
match decl {
255-
Decl::Fn(n) => {
256-
self.add_binding_for_ident(&mut n.ident);
257-
}
258-
Decl::Class(n) => {
259-
self.add_binding_for_ident(&mut n.ident);
260-
}
261-
_ => {}
262-
}
263-
}
264-
265-
fn lookahead_hoist_stmts(&mut self, stmts: &mut Vec<Stmt>) {
266-
for stmt in stmts {
267-
self.lookahead_hoist_stmt(stmt);
268-
}
269-
}
270-
271-
fn lookahead_hoist_module_items(&mut self, stmts: &mut Vec<ModuleItem>) {
272-
debug_assert!(self.current_scope_id == ScopeId::TOP_LEVEL);
273-
for stmt in stmts {
274-
let decl = match stmt {
275-
ModuleItem::ModuleDecl(m) => m,
276-
ModuleItem::Stmt(stmt) => {
277-
self.lookahead_hoist_stmt(stmt);
278-
continue;
279-
}
280-
};
281-
match decl {
282-
ModuleDecl::Import(n) => {
283-
for spec in &mut n.specifiers {
284-
match spec {
285-
ImportSpecifier::Named(n) => {
286-
self.add_binding_for_ident(&mut n.local);
287-
}
288-
ImportSpecifier::Default(n) => {
289-
self.add_binding_for_ident(&mut n.local);
290-
}
291-
ImportSpecifier::Namespace(n) => {
292-
self.add_binding_for_ident(&mut n.local);
293-
}
294-
}
295-
}
296-
}
297-
ModuleDecl::ExportDecl(n) => match &mut n.decl {
298-
Decl::Fn(n) => {
299-
self.add_binding_for_ident(&mut n.ident);
300-
}
301-
Decl::Class(n) => {
302-
self.add_binding_for_ident(&mut n.ident);
303-
}
304-
_ => {}
305-
},
306-
_ => {}
307-
}
308-
}
309-
}
310-
311264
fn find_binding_or_add_into_global(&mut self, ident: &mut Ident) {
312265
if let Some(to) = self.lookup_binding(&ident.sym, self.current_scope_id) {
313266
self.add_reference(ident, to);
@@ -421,7 +374,9 @@ impl VisitMut for Resolver {
421374

422375
fn visit_mut_var_decl(&mut self, node: &mut VarDecl) {
423376
for decl in &mut node.decls {
424-
self.visit_pat_with_binding(&mut decl.name, node.kind == VarDeclKind::Var);
377+
if node.kind != VarDeclKind::Var {
378+
self.visit_pat_with_binding(&mut decl.name, false);
379+
}
425380
decl.init.visit_mut_children_with(self);
426381
}
427382
}
@@ -436,10 +391,16 @@ impl VisitMut for Resolver {
436391
self.visit_pat_with_binding(&mut node.pat, false);
437392
}
438393

394+
fn visit_mut_function(&mut self, node: &mut Function) {
395+
let mut lookahead = DeepLookahead { r: self };
396+
node.body.visit_mut_with(&mut lookahead);
397+
node.visit_mut_children_with(self);
398+
}
399+
439400
fn visit_mut_fn_decl(&mut self, node: &mut FnDecl) {
440401
debug_assert!(self.is_ref_to_itself(node.ident.node_id));
441402
self.with_new_scope(ScopeKind::Fn, |this| {
442-
node.function.visit_mut_children_with(this);
403+
node.function.visit_mut_with(this);
443404
});
444405
}
445406

@@ -449,7 +410,7 @@ impl VisitMut for Resolver {
449410
this.add_binding_for_ident(ident);
450411
}
451412
this.with_new_scope(ScopeKind::Fn, |this| {
452-
node.function.visit_mut_children_with(this);
413+
node.function.visit_mut_with(this);
453414
});
454415
});
455416
}
@@ -459,6 +420,10 @@ impl VisitMut for Resolver {
459420
for param in &mut node.params {
460421
this.visit_pat_with_binding(param, false);
461422
}
423+
if let Some(block_stmt) = node.body.as_mut_block_stmt() {
424+
let mut lookahead = DeepLookahead { r: this };
425+
block_stmt.visit_mut_children_with(&mut lookahead);
426+
}
462427
node.body.visit_mut_children_with(this);
463428
});
464429
}
@@ -480,12 +445,16 @@ impl VisitMut for Resolver {
480445
}
481446

482447
fn visit_mut_stmts(&mut self, node: &mut Vec<Stmt>) {
483-
self.lookahead_hoist_stmts(node);
448+
let mut lookahead = ShadowLookahead { r: self };
449+
lookahead.lookahead_hoist_stmts(node);
484450
node.visit_mut_children_with(self);
485451
}
486452

487453
fn visit_mut_module_items(&mut self, node: &mut Vec<ModuleItem>) {
488-
self.lookahead_hoist_module_items(node);
454+
let mut lookahead = ShadowLookahead { r: self };
455+
lookahead.lookahead_hoist_module_items(node);
456+
let mut lookahead = DeepLookahead { r: self };
457+
node.visit_mut_children_with(&mut lookahead);
489458
node.visit_mut_children_with(self);
490459
}
491460

@@ -552,7 +521,119 @@ impl VisitMut for Resolver {
552521

553522
fn visit_mut_script(&mut self, node: &mut Script) {
554523
self.start_visit_with(|this| {
524+
let mut lookahead = DeepLookahead { r: this };
525+
node.body.visit_mut_children_with(&mut lookahead);
555526
this.visit_mut_stmts(&mut node.body);
556527
});
557528
}
558529
}
530+
531+
/// only lookahead current block
532+
struct ShadowLookahead<'r> {
533+
r: &'r mut Resolver,
534+
}
535+
536+
impl<'r> ShadowLookahead<'r> {
537+
fn lookahead_hoist_stmt(&mut self, stmt: &mut Stmt) {
538+
let Stmt::Decl(decl) = stmt else {
539+
return;
540+
};
541+
match decl {
542+
Decl::Fn(n) => {
543+
self.r.add_binding_for_ident(&mut n.ident);
544+
}
545+
Decl::Class(n) => {
546+
self.r.add_binding_for_ident(&mut n.ident);
547+
}
548+
_ => {}
549+
}
550+
}
551+
552+
fn lookahead_hoist_stmts(&mut self, stmts: &mut Vec<Stmt>) {
553+
for stmt in stmts {
554+
self.lookahead_hoist_stmt(stmt);
555+
}
556+
}
557+
558+
fn lookahead_hoist_module_items(&mut self, stmts: &mut Vec<ModuleItem>) {
559+
debug_assert!(self.r.current_scope_id == ScopeId::TOP_LEVEL);
560+
for stmt in stmts {
561+
let decl = match stmt {
562+
ModuleItem::ModuleDecl(m) => m,
563+
ModuleItem::Stmt(stmt) => {
564+
self.lookahead_hoist_stmt(stmt);
565+
continue;
566+
}
567+
};
568+
match decl {
569+
ModuleDecl::Import(n) => {
570+
for spec in &mut n.specifiers {
571+
match spec {
572+
ImportSpecifier::Named(n) => {
573+
self.r.add_binding_for_ident(&mut n.local);
574+
}
575+
ImportSpecifier::Default(n) => {
576+
self.r.add_binding_for_ident(&mut n.local);
577+
}
578+
ImportSpecifier::Namespace(n) => {
579+
self.r.add_binding_for_ident(&mut n.local);
580+
}
581+
}
582+
}
583+
}
584+
ModuleDecl::ExportDecl(n) => match &mut n.decl {
585+
Decl::Fn(n) => {
586+
self.r.add_binding_for_ident(&mut n.ident);
587+
}
588+
Decl::Class(n) => {
589+
self.r.add_binding_for_ident(&mut n.ident);
590+
}
591+
_ => {}
592+
},
593+
_ => {}
594+
}
595+
}
596+
}
597+
}
598+
599+
/// lookahead current block and its child blocks(exclude function, class...)
600+
struct DeepLookahead<'r> {
601+
r: &'r mut Resolver,
602+
}
603+
604+
impl<'r> VisitMut for DeepLookahead<'r> {
605+
noop_visit_mut_type!();
606+
607+
fn visit_mut_arrow_expr(&mut self, _: &mut ArrowExpr) {}
608+
609+
fn visit_mut_constructor(&mut self, _: &mut Constructor) {}
610+
611+
fn visit_mut_expr(&mut self, _: &mut Expr) {}
612+
613+
fn visit_mut_function(&mut self, _: &mut Function) {}
614+
615+
fn visit_mut_param(&mut self, _: &mut Param) {}
616+
617+
fn visit_mut_assign_target(&mut self, _: &mut AssignTarget) {}
618+
619+
fn visit_mut_setter_prop(&mut self, _: &mut SetterProp) {}
620+
621+
fn visit_mut_tagged_tpl(&mut self, _: &mut TaggedTpl) {}
622+
623+
fn visit_mut_tpl(&mut self, _: &mut Tpl) {}
624+
625+
fn visit_mut_fn_decl(&mut self, _: &mut FnDecl) {}
626+
627+
fn visit_mut_class_decl(&mut self, _: &mut ClassDecl) {}
628+
629+
fn visit_mut_import_decl(&mut self, _: &mut ImportDecl) {}
630+
631+
fn visit_mut_var_decl(&mut self, node: &mut VarDecl) {
632+
if node.kind != VarDeclKind::Var {
633+
return;
634+
}
635+
for decl in &mut node.decls {
636+
self.r.visit_pat_with_binding(&mut decl.name, true);
637+
}
638+
}
639+
}

crates/swc_ecma_usage_analyzer/src/analyzer/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ where
176176

177177
fn report_assign_pat(&mut self, p: &Pat, is_read_modify: bool) {
178178
for id in find_pat_ids(p) {
179-
debug_assert!(!self.r.is_ref_to_unresolved(id));
179+
debug_assert!(!self.r.is_ref_to_unresolved(id), "p: {p:#?}, id: {id:#?}");
180180
let id = self.r.find_binding_by_node_id(id);
181181
// It's hard to determined the type of pat assignment
182182
self.data

0 commit comments

Comments
 (0)