Skip to content

Commit 006bb01

Browse files
fix(minifier): Do not merge if statements with different local variable values
The `merge_similar_ifs` function was using `SyntaxContext::within_ignored_ctxt()` when comparing if statement consequence blocks. This made identifiers with the same name but different syntax contexts (different local variables) compare as equal, causing incorrect merging. Fixes #11517 Co-authored-by: Donny/강동윤 <kdy1@users.noreply.github.com>
1 parent fea6061 commit 006bb01

2 files changed

Lines changed: 44 additions & 7 deletions

File tree

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

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::mem::swap;
22

3-
use swc_common::{util::take::Take, EqIgnoreSpan, Spanned, SyntaxContext, DUMMY_SP};
3+
use swc_common::{util::take::Take, EqIgnoreSpan, Spanned, DUMMY_SP};
44
use swc_ecma_ast::*;
55
use swc_ecma_transforms_base::ext::ExprRefExt;
66
use swc_ecma_transforms_optimization::debug_assert_valid;
@@ -119,9 +119,12 @@ impl Optimizer<'_> {
119119
(
120120
Some(Stmt::If(l @ IfStmt { alt: None, .. })),
121121
Some(Stmt::If(r @ IfStmt { alt: None, .. })),
122-
) => SyntaxContext::within_ignored_ctxt(|| {
122+
) => {
123+
// We should NOT ignore syntax context here because the cons blocks
124+
// may contain references to local variables with the same name but
125+
// different values. See https://github.com/swc-project/swc/issues/11517
123126
l.cons.eq_ignore_span(&r.cons) && l.cons.terminates()
124-
}),
127+
}
125128
_ => false,
126129
});
127130
if !has_work {
@@ -143,9 +146,11 @@ impl Optimizer<'_> {
143146
match &mut cur {
144147
Some(cur_if) => {
145148
// If cons is same, we merge conditions.
146-
if SyntaxContext::within_ignored_ctxt(|| {
147-
cur_if.cons.eq_ignore_span(&stmt.cons)
148-
}) {
149+
// We should NOT ignore syntax context here because the cons
150+
// blocks may contain references to local variables with the
151+
// same name but different values.
152+
// See https://github.com/swc-project/swc/issues/11517
153+
if cur_if.cons.eq_ignore_span(&stmt.cons) {
149154
cur_if.test = BinExpr {
150155
span: DUMMY_SP,
151156
left: cur_if.test.take(),

crates/swc_ecma_minifier/tests/exec.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11498,7 +11498,39 @@ function printError() {
1149811498
}
1149911499
1150011500
printError()
11501-
11501+
11502+
",
11503+
);
11504+
}
11505+
11506+
#[test]
11507+
fn issue_11517() {
11508+
// Test that the minifier does not incorrectly merge if statements with
11509+
// similar structures but different string literal values in local variables.
11510+
run_default_exec_test(
11511+
"
11512+
const buildErrorLog = ({
11513+
errorType,
11514+
mode,
11515+
}) => {
11516+
const isModeA = mode === 'modeA';
11517+
const isModeB = mode === 'modeB';
11518+
11519+
if (errorType === 'A_ERROR') {
11520+
const message = 'A error occured';
11521+
return { fieldX: true, fieldY: true, message };
11522+
}
11523+
if (errorType === 'B_ERROR') {
11524+
const message = 'B error occured';
11525+
return { fieldX: true, fieldY: true, message };
11526+
}
11527+
return { fieldX: true, fieldY: true, message: 'Invalid configuration' };
11528+
};
11529+
11530+
const resultA = buildErrorLog({ errorType: 'A_ERROR', mode: 'modeA' });
11531+
const resultB = buildErrorLog({ errorType: 'B_ERROR', mode: 'modeB' });
11532+
console.log('A:', resultA.message);
11533+
console.log('B:', resultB.message);
1150211534
",
1150311535
);
1150411536
}

0 commit comments

Comments
 (0)