Avatar for the swc-project user
swc-project
swc
BlogDocsChangelog

Performance History

Latest Results

fix(es/fixer): wrap function declarations in sloppy-mode loop bodies
baltasarblanco:fix/fn-decl-loop-body-sloppy
8 hours ago
fix(es/minifier): preserve rest array identity when its reference runs more than once (#12546) **Description:** With the default options, the `Pat::Rest` arm of `inline_args_of_iife` copies the new array literal into the rest parameter's only reference even when that reference runs more than once (in a loop or in a nested function). Each evaluation then allocates a new array, so mutations and identity are lost: ```js function logAll(...lines) { for (let i = 0; i < 3; i++) console.log(lines.shift()); } logAll("a", "b", "c"); ``` With `module: true` this becomes `for(let o=0;o<3;o++)console.log(["a","b","c"].shift());`, which prints `a a a` instead of `a b c` (`logAll` is used once, so it becomes an IIFE first). With the default script options, `var g = function (...a) { return () => a.push(0); }(1); console.log(g(), g());` prints `2 2` instead of `2 3`. #12238 made this arm refuse RegExp arguments because they allocate on each evaluation. The rest array allocates on each evaluation too, but the arm only checks `ref_count == 1`, which counts occurrences, not evaluations. This adds one `continue` to that arm. If the reference can run more than once (`EXECUTED_MULTIPLE_TIME`, or not `IS_FN_LOCAL`) and the array is mutated, indexed with a dynamic key, used as a value (`USED_AS_REF`, as in `({ length: a }).length`), or used through any property other than `length`, the rest parameter is kept. These are the flags `store_var_for_inlining` already checks for a single-use RegExp and for arrays whose element reads are inlined. Reads of `length` and of literal indices are still inlined: `((...r) => () => r[0])(1)` from #12238 still becomes `()=>1`, and `((...a) => () => a.length)(1, 2)` still becomes `()=>2`. When the `continue` applies, the IIFE keeps its rest parameter and the arguments it collects as written, like the existing `continue` for RegExp arguments. The analyzer is unchanged. The cost: when the reference can run more than once, some forms that were already correct also keep the rest parameter. These are non-mutating methods (`a.join(" ")`, `a.includes(x)`), writes such as `a.length = 0`, `a[i]` with a dynamic `i`, and a rest IIFE that is itself inside a loop. For example, `function fmt(...p) { return () => p.join(" "); } console.log(fmt("a", "b")());` with `module: true` goes from 19 to 64 bytes. Performance: a few flag tests, plus a scan of `accessed_props` when the reference can run more than once, only for a rest parameter that already passed the existing checks. **Tests:** `tests/fixture/issues/12545/`, with `expected.stdout`: - 8 cases that print a different value without the change: - `push` in a loop and in a closure; - `shift` through a function used once (`makeQueue`, `logAll`); - `a[0]++` in a loop; - `a[k](v)` in a closure; - the array escaping through a literal (`[a, h()][0].push(0)`, `{ length: a }.length`). - 2 controls that keep inlining: `a.length` in a closure and a `push` that runs once. They and the #12219 fixtures pass before and after. Checks: - `cargo test -p swc_ecma_minifier`: 8033 passed, 0 failed (8023 + 10). No fixture or snapshot output changes, including `benches-full` (`d3`, `victory`). - `./scripts/exec.sh`: passes. - `cargo clippy -p swc_ecma_minifier --all-targets -- -D warnings` and `cargo fmt --all -- --check`: clean. - End to end with the `Compiler::minify` pipeline (40 snippets, script and module): 52 of 80 runs differ without the change, none with it. **Related issue (if exists):** Closes #12545 --- Found with a differential fuzzer. Drafted with AI assistance.
main
9 hours ago
fix(deps): update npm
renovate/npm
1 day ago
fix(deps): update cargo
renovate/patch-cargo
1 day ago
chore(deps): update actions
renovate/actions
1 day ago
remove tests
Austaras:main
2 days ago

Latest Branches

CodSpeed Performance Gauge
+6%
fix(es/fixer): wrap function declarations in sloppy-mode loop bodies#12567
4 days ago
252500f
baltasarblanco:fix/fn-decl-loop-body-sloppy
CodSpeed Performance Gauge
-2%
1 day ago
5c4c2a1
renovate/npm
CodSpeed Performance Gauge
+1%
1 day ago
f541d49
renovate/patch-cargo
© 2026 CodSpeed Technology
Home Terms Privacy Docs