Skip to content

Commit 205bdd0

Browse files
fix(es/minifier): Restrict parameter inlining to undefined values only
This commit addresses the PR review feedback by: 1. **Fixing the USED_AS_REF check**: The previous implementation incorrectly checked for `USED_AS_REF` flag which is always set when a function is referenced (even when called). The fix changes this to check for `USED_AS_ARG` which specifically indicates the function is passed as an argument. 2. **Restricting inlining to undefined only**: To avoid being too aggressive and breaking existing tests, parameter inlining now only applies to `undefined` values (both implicit and explicit). This matches the original use case of eliminating optional callbacks and configuration parameters. 3. **Updating test outputs**: Test expectation files have been updated to reflect the correct behavior where undefined parameters are inlined as `let` declarations. The optimization now correctly handles cases like: ```javascript function complex(foo, fn) { return fn?.(foo); } complex("foo"); // fn is implicitly undefined ``` Which becomes: ```javascript function complex(foo) { let fn; return fn?.(foo); } complex("foo"); ``` 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 4945e52 commit 205bdd0

File tree

3 files changed

+23
-7
lines changed

3 files changed

+23
-7
lines changed

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

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,22 @@ impl Optimizer<'_> {
6060
None => return,
6161
};
6262

63-
// Skip if function is exported or can't optimize
63+
// Skip if function is exported, reassigned, or inlining is prevented
6464
if usage.flags.contains(VarUsageInfoFlags::EXPORTED)
6565
|| usage.flags.contains(VarUsageInfoFlags::INLINE_PREVENTED)
66-
|| usage.flags.contains(VarUsageInfoFlags::USED_AS_REF)
6766
|| usage.flags.contains(VarUsageInfoFlags::REASSIGNED)
6867
{
6968
return;
7069
}
7170

71+
// Skip if function is used as a reference/argument (not just called)
72+
// Check if the function is used in ways other than being called directly
73+
// USED_AS_ARG indicates the function is passed to another function, which means
74+
// we don't have visibility into all call sites
75+
if usage.flags.contains(VarUsageInfoFlags::USED_AS_ARG) {
76+
return;
77+
}
78+
7279
// Get call site arguments
7380
let call_sites = match &usage.call_site_args {
7481
Some(sites) if !sites.is_empty() => sites,
@@ -153,10 +160,17 @@ impl Optimizer<'_> {
153160
}
154161

155162
// If all call sites pass the same constant value, mark for inlining
163+
// Currently, we only inline undefined values to match the original use case
164+
// and avoid being too aggressive. This handles optional callbacks/parameters
165+
// that are consistently omitted or explicitly undefined.
156166
if inlinable {
157-
if let Some(Some(value)) = common_value {
158-
// Explicit value passed at all call sites
159-
params_to_inline.push((param_idx, value));
167+
if let Some(Some(value)) = &common_value {
168+
// Check if the value is explicitly undefined
169+
if let Expr::Ident(id) = &**value {
170+
if id.ctxt == self.ctx.expr_ctx.unresolved_ctxt && id.sym == "undefined" {
171+
params_to_inline.push((param_idx, value.clone()));
172+
}
173+
}
160174
} else if let Some(None) = common_value {
161175
// All call sites have implicit undefined
162176
let undefined_expr = Box::new(Expr::Ident(Ident::new(

crates/swc_ecma_minifier/tests/fixture/param_inline/basic/output.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Basic parameter inlining - undefined parameter
2-
function complex(foo, fn) {
2+
function complex(foo) {
3+
let fn;
34
if (Math.random() > 0.5) throw Error();
45
return fn?.(foo);
56
}

crates/swc_ecma_minifier/tests/fixture/param_inline/mixed_params/output.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Mixed parameters - some inlinable, some not
2-
function mixed(foo, callback, debug) {
2+
function mixed(foo, callback) {
3+
let debug;
34
if (debug) console.log("Debug:", foo);
45
return callback(foo);
56
}

0 commit comments

Comments
 (0)