Skip to content

Commit 72a53a0

Browse files
authored
fix(es/minifier): Inline block stmt into expr (#11107)
**Related issue:** - Closes #11103
1 parent e1a9d75 commit 72a53a0

File tree

4 files changed

+80
-41
lines changed

4 files changed

+80
-41
lines changed

.changeset/two-rules-draw.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
swc_core: patch
3+
swc_ecma_minifier: patch
4+
---
5+
6+
fix(es/minifier): Inline block stmt into expr

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

Lines changed: 55 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,46 +1042,8 @@ impl Optimizer<'_> {
10421042
vars
10431043
}
10441044

1045-
fn inline_fn_like<'a>(
1046-
&mut self,
1047-
params: impl Iterator<Item = &'a Ident> + Clone,
1048-
params_len: usize,
1049-
body: &mut BlockStmt,
1050-
args: &mut [ExprOrSpread],
1051-
) -> Option<Expr> {
1052-
if !self.can_inline_fn_like(params.clone(), params_len, &*body, false) {
1053-
return None;
1054-
}
1055-
1056-
if self.vars.inline_with_multi_replacer(body) {
1057-
self.changed = true;
1058-
}
1059-
1060-
let mut exprs = Vec::new();
1061-
let vars = self.inline_fn_param(params, params_len, args, &mut exprs);
1062-
1063-
if args.len() > params_len {
1064-
for arg in &mut args[params_len..] {
1065-
exprs.push(arg.expr.take());
1066-
}
1067-
}
1068-
1069-
if !vars.is_empty() {
1070-
trace_op!("iife: Creating variables: {:?}", vars);
1071-
1072-
self.prepend_stmts.push(
1073-
VarDecl {
1074-
span: DUMMY_SP,
1075-
kind: VarDeclKind::Var,
1076-
declare: Default::default(),
1077-
decls: vars,
1078-
..Default::default()
1079-
}
1080-
.into(),
1081-
);
1082-
}
1083-
1084-
for mut stmt in body.stmts.take() {
1045+
fn inline_into_expr(&mut self, stmts: Vec<Stmt>, exprs: &mut Vec<Box<Expr>>) -> Option<Expr> {
1046+
for mut stmt in stmts {
10851047
match stmt {
10861048
Stmt::Decl(Decl::Var(ref mut var)) => {
10871049
for decl in &mut var.decls {
@@ -1115,14 +1077,20 @@ impl Optimizer<'_> {
11151077
exprs.push(stmt.expr);
11161078
}
11171079

1080+
Stmt::Block(stmt) => {
1081+
if let Some(e) = self.inline_into_expr(stmt.stmts, exprs) {
1082+
return Some(e);
1083+
}
1084+
}
1085+
11181086
Stmt::Return(stmt) => {
11191087
let span = stmt.span;
11201088
let val = *stmt.arg.unwrap_or_else(|| Expr::undefined(span));
11211089
exprs.push(Box::new(val));
11221090

11231091
let mut e = SeqExpr {
11241092
span: DUMMY_SP,
1125-
exprs,
1093+
exprs: exprs.take(),
11261094
};
11271095
self.merge_sequences_in_seq_expr(&mut e);
11281096

@@ -1134,6 +1102,52 @@ impl Optimizer<'_> {
11341102
}
11351103
}
11361104

1105+
None
1106+
}
1107+
1108+
fn inline_fn_like<'a>(
1109+
&mut self,
1110+
params: impl Iterator<Item = &'a Ident> + Clone,
1111+
params_len: usize,
1112+
body: &mut BlockStmt,
1113+
args: &mut [ExprOrSpread],
1114+
) -> Option<Expr> {
1115+
if !self.can_inline_fn_like(params.clone(), params_len, &*body, false) {
1116+
return None;
1117+
}
1118+
1119+
if self.vars.inline_with_multi_replacer(body) {
1120+
self.changed = true;
1121+
}
1122+
1123+
let mut exprs = Vec::new();
1124+
let vars = self.inline_fn_param(params, params_len, args, &mut exprs);
1125+
1126+
if args.len() > params_len {
1127+
for arg in &mut args[params_len..] {
1128+
exprs.push(arg.expr.take());
1129+
}
1130+
}
1131+
1132+
if !vars.is_empty() {
1133+
trace_op!("iife: Creating variables: {:?}", vars);
1134+
1135+
self.prepend_stmts.push(
1136+
VarDecl {
1137+
span: DUMMY_SP,
1138+
kind: VarDeclKind::Var,
1139+
declare: Default::default(),
1140+
decls: vars,
1141+
..Default::default()
1142+
}
1143+
.into(),
1144+
);
1145+
}
1146+
1147+
if let Some(e) = self.inline_into_expr(body.stmts.take(), &mut exprs) {
1148+
return Some(e);
1149+
}
1150+
11371151
if let Some(last) = exprs.last_mut() {
11381152
*last = UnaryExpr {
11391153
span: DUMMY_SP,
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import assert from "node:assert";
2+
const miniDynamics = () => {
3+
if (true) {
4+
let url = "api";
5+
url += "/";
6+
return new URL(url, "https://example.com").toString();
7+
}
8+
};
9+
let url = miniDynamics();
10+
assert(url === "https://example.com/api/");
11+
export default function Home() {
12+
return React.createElement("p", null, url);
13+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import assert from "node:assert";
2+
let url = new URL("api/", "https://example.com").toString();
3+
assert("https://example.com/api/" === url);
4+
export default function Home() {
5+
return React.createElement("p", null, url);
6+
}

0 commit comments

Comments
 (0)