fix(mangler): use retain instead of truncate to remove empty frequency slots#18225
Conversation
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
Merging this PR will not alter performance
Comparing Footnotes
|
35c4846 to
7d9fc4f
Compare
There was a problem hiding this comment.
Pull request overview
This PR fixes a bug in the mangler where empty frequency slots were incorrectly removed using truncate after an unstable sort. The issue was that sort_unstable_by_key doesn't guarantee order for items with equal keys (like frequency=0), so empty slots could appear before non-empty slots containing symbols that need renaming, causing those valid slots to be incorrectly truncated.
Changes:
- Replaced
truncatelogic withretainto filter out empty slots - Moved the filtering before sorting for better efficiency
- Updated snapshot test to reflect correct parameter renaming behavior
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| crates/oxc_mangler/src/lib.rs | Replaced truncate with retain and moved filtering before sort to fix bug and improve performance |
| crates/oxc_minifier/tests/mangler/snapshots/mangler.snap | Updated snapshot showing parameter a now correctly renamed to e |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
I thought // Initial:
[{ slot: 0, freq: 0, [] }, { slot: 1, freq: 0, [a] }]
// After sort_unstable_by_key - could be EITHER:
[{ slot: 0, freq: 0, [] }, { slot: 1, freq: 0, [a] }] // same order
// OR
[{ slot: 1, freq: 0, [a] }, { slot: 0, freq: 0, [] }] // swapped |
|
And the performance is actually better than |
|
Ah, my bad, I was thinking of |
sapphi-red
left a comment
There was a problem hiding this comment.
(the comment above is non-blocking)
|
I'm going to merge this as is because it's a blocker to doing a release. @Dunqing You may want to look into Sapphi's suggestion later. |
Merge activity
|
…uency slots (#18225) #18183 introduced a bug when removing empty frequency slots. The code used `truncate` after sorting: ```rust frequencies.sort_unstable_by_key(|x| std::cmp::Reverse(x.frequency)); if let Some(idx) = frequencies.iter().position(|x| x.symbol_ids.is_empty()) { frequencies.truncate(idx); } ``` The problem is that `sort_unstable_by_key` doesn't guarantee order for items with equal keys. When multiple slots have `frequency: 0`, some have symbols (that need renaming but have no references), and some are empty. Since the sort order is unstable, an empty slot could appear **before** a non-empty slot, and `truncate` would incorrectly remove valid slots. This fix uses `retain` instead, and moves it before the sort for better efficiency (sorting fewer elements): ```rust frequencies.retain(|x| !x.symbol_ids.is_empty()); frequencies.sort_unstable_by_key(|x| std::cmp::Reverse(x.frequency)); ``` Note for reviewer: I've locally tested in the `monitor-oxc`; there is no naming collision after this.
7d9fc4f to
ee9f6a4
Compare
### 🐛 Bug Fixes - f1e2dc0 semantic: No error in `check_function_redeclaration` for CommonJS files (#18231) (overlookmotel) - 645c3f0 transformer: Use `require` not `import` in CommonJS files (#18226) (overlookmotel) - ee9f6a4 mangler: Use `retain` instead of `truncate` to remove empty frequency slots (#18225) (Dunqing) ### ⚡ Performance - 52073d9 semantic: Use cheaper test for source type (#18235) (overlookmotel) Co-authored-by: overlookmotel <[email protected]>


#18183 introduced a bug when removing empty frequency slots. The code used
truncateafter sorting:The problem is that
sort_unstable_by_keydoesn't guarantee order for items with equal keys. When multiple slots havefrequency: 0, some have symbols (that need renaming but have no references), and some are empty. Since the sort order is unstable, an empty slot could appear before a non-empty slot, andtruncatewould incorrectly remove valid slots.This fix uses
retaininstead, and moves it before the sort for better efficiency (sorting fewer elements):Note for reviewer: I've locally tested in the
monitor-oxc; there is no naming collision after this.