Skip to content

Commit

Permalink
fix(es/minifier): Don't invoke IIFE containing reserved words (#8939)
Browse files Browse the repository at this point in the history
**Description:**

`inline` and `seq inline` should apply this change too.

**Related issue:**

 - Closes #8622
  • Loading branch information
Austaras authored May 9, 2024
1 parent 1f01cd4 commit 5a3456c
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 60 deletions.
142 changes: 82 additions & 60 deletions crates/swc_ecma_minifier/src/compress/optimize/iife.rs
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,16 @@ impl Optimizer<'_> {
}
}

for pid in param_ids {
if self.ident_reserved(&pid.sym) {
log_abort!(
"iife: [x] Cannot inline because of reservation of `{}`",
pid
);
return false;
}
}

true
}

Expand Down Expand Up @@ -751,83 +761,95 @@ impl Optimizer<'_> {
}
}

if !body.stmts.iter().all(|stmt| match stmt {
Stmt::Decl(Decl::Var(var))
if matches!(
&**var,
VarDecl {
kind: VarDeclKind::Var | VarDeclKind::Let,
..
if !body.stmts.iter().all(|stmt| {
if let Stmt::Decl(Decl::Var(var)) = stmt {
for decl in &var.decls {
for id in find_pat_ids::<_, Id>(&decl.name) {
if self.ident_reserved(&id.0) {
log_abort!("iife: [x] Cannot inline because reservation of `{}`", id.0);
return false;
}
}
) =>
{
if var.decls.iter().any(|decl| match &decl.name {
Pat::Ident(BindingIdent {
id: Ident { sym, .. },
..
}) if &**sym == "arguments" => true,
Pat::Ident(id) => {
if self.vars.has_pending_inline_for(&id.to_id()) {
log_abort!(
"iife: [x] Cannot inline because pending inline of `{}`",
id.id
);
return true;
}
}

match stmt {
Stmt::Decl(Decl::Var(var))
if matches!(
&**var,
VarDecl {
kind: VarDeclKind::Var | VarDeclKind::Let,
..
}
) =>
{
for decl in &var.decls {
match &decl.name {
Pat::Ident(BindingIdent {
id: Ident { sym, .. },
..
}) if &**sym == "arguments" => return false,
Pat::Ident(id) => {
if self.vars.has_pending_inline_for(&id.to_id()) {
log_abort!(
"iife: [x] Cannot inline because pending inline of `{}`",
id.id
);
return false;
}
}

false
_ => return false,
}
}

_ => true,
}) {
return false;
}
if self.ctx.executed_multiple_time {
return false;
}

if self.ctx.executed_multiple_time {
return false;
}
if !self.may_add_ident() {
return false;
}

if !self.may_add_ident() {
return false;
true
}

true
}
Stmt::Expr(e) => match &*e.expr {
Expr::Await(..) => false,

Stmt::Expr(e) => match &*e.expr {
Expr::Await(..) => false,
// TODO: Check if parameter is used and inline if call is not related to
// parameters.
Expr::Call(e) => {
if e.callee.as_expr().and_then(|e| e.as_ident()).is_some() {
return true;
}

// TODO: Check if parameter is used and inline if call is not related to parameters.
Expr::Call(e) => {
if e.callee.as_expr().and_then(|e| e.as_ident()).is_some() {
return true;
}
let used = idents_used_by(&e.callee);

let used = idents_used_by(&e.callee);
if used.iter().all(|id| {
self.data
.vars
.get(id)
.map(|usage| usage.ref_count == 1 && usage.callee_count > 0)
.unwrap_or(false)
}) {
return true;
}

if used.iter().all(|id| {
self.data
.vars
.get(id)
.map(|usage| usage.ref_count == 1 && usage.callee_count > 0)
.unwrap_or(false)
}) {
return true;
param_ids.iter().all(|param| !used.contains(&param.to_id()))
}

param_ids.iter().all(|param| !used.contains(&param.to_id()))
}

_ => true,
},
_ => true,
},

Stmt::Return(ReturnStmt { arg, .. }) => match arg.as_deref() {
Some(Expr::Await(..)) => false,
Stmt::Return(ReturnStmt { arg, .. }) => match arg.as_deref() {
Some(Expr::Await(..)) => false,

Some(Expr::Lit(Lit::Num(..))) => !self.ctx.in_obj_of_non_computed_member,
_ => true,
},
_ => false,
Some(Expr::Lit(Lit::Num(..))) => !self.ctx.in_obj_of_non_computed_member,
_ => true,
},
_ => false,
}
}) {
return false;
}
Expand Down
8 changes: 8 additions & 0 deletions crates/swc_ecma_minifier/src/compress/optimize/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,14 @@ impl Optimizer<'_> {
self.options.top_level()
}

fn ident_reserved(&self, sym: &JsWord) -> bool {
if let Some(MangleOptions { reserved, .. }) = self.mangle_options {
reserved.contains(sym)
} else {
false
}
}

fn handle_stmts(&mut self, stmts: &mut Vec<Stmt>, will_terminate: bool) {
// Skip if `use asm` exists.
if maybe_par!(
Expand Down
15 changes: 15 additions & 0 deletions crates/swc_ecma_minifier/tests/fixture/issues/8622/input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export function foo(cond) {
let reserved = 1;
if (cond) {
reserved = 2;
}
return [reserved, bar(cond)];
}

function bar(cond) {
let reserved = 1;
if (cond) {
reserved = 2;
}
return reserved;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"reserved": ["reserved"]
}
10 changes: 10 additions & 0 deletions crates/swc_ecma_minifier/tests/fixture/issues/8622/output.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export function foo(e) {
let reserved = 1;
return e && (reserved = 2), [
reserved,
function(e) {
let reserved = 1;
return e && (reserved = 2), reserved;
}(e)
];
}

0 comments on commit 5a3456c

Please sign in to comment.