fix(minifier): prevent incorrect ??= transformation when member base is mutated#17472
Merged
graphite-app[bot] merged 1 commit intomainfrom Dec 30, 2025
Merged
Conversation
Copilot
AI
changed the title
[WIP] Add tests for discussed feature in PR 16802
fix(minifier): prevent incorrect ??= transformation when member base is mutated
Dec 30, 2025
CodSpeed Performance ReportMerging #17472 will not alter performanceComparing Summary
Footnotes
|
Contributor
There was a problem hiding this comment.
Pull request overview
This PR prevents incorrect transformation of logical expressions to nullish coalescing assignment (??=) when the member expression's base object is mutated in the RHS. It extends the mutation detection from PR #16802 to the nullish coalescing optimization in remove_unused_expression.rs.
Key changes:
- Added
member_object_may_be_mutated()check before transforming to??=operator - Added comprehensive test cases covering both safe and unsafe transformation scenarios
- Ensures transformations fall back to safe
??operator when mutation is detected
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
sapphi-red
approved these changes
Dec 30, 2025
Member
Merge activity
|
…is mutated (#17472) Extends the mutation check from #16802 to `remove_unused_expression.rs`. The transformation `x.y != null || (x = {}, x.y = 3)` → `x.y ??= (x = {}, 3)` changes semantics when `x` is reassigned because `??=` captures the reference before evaluating the RHS. ### Changes - Add `member_object_may_be_mutated()` check before `??=` transformation in nullish coalescing optimization - Transformation now correctly: - Allows `x.y != null || (x = {}, x.y = 3)` → `x.y ?? (x = {}, x.y = 3)` (safe) - Blocks `x.y != null || (x = {}, x.y = 3)` → `x.y ??= (x = {}, 3)` (unsafe) - Permits `x.y != null || (foo(), x.y = 3)` → `x.y ??= (foo(), 3)` when no mutation ### Example ```js var x = {}; x.y != null || (x = {}, x.y = 3) // x becomes { y: 3 } x.y ??= (x = {}, 3) // x becomes {} (incorrect!) x.y ?? (x = {}, x.y = 3) // x becomes { y: 3 } (correct) ``` <!-- START COPILOT CODING AGENT SUFFIX --> <!-- START COPILOT ORIGINAL PROMPT --> <details> <summary>Original prompt</summary> > Add tests for #16802 (comment) </details> <!-- START COPILOT CODING AGENT TIPS --> --- 💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey).
1e6ccda to
68b2e54
Compare
graphite-app bot
pushed a commit
that referenced
this pull request
Jan 5, 2026
### 🚀 Features - 659c23e linter: Init note field boilerplate (#17589) (Shrey Sudhir) - 6870b64 parser: Add TS1363 error code (#17609) (Sysix) - 23680a3 mangler: Skip mangling only in scopes affected by direct eval (#17612) (camc314) - a7e1643 parser: Add TS2528 error code to duplicate_default_export diagnostic (#17558) (camc314) ### 🐛 Bug Fixes - 1044116 ecmascript: Mark `new Symbol` as non side-effect free (#17568) (camc314) - ab5e4ca isolated-declarations: Strip default values from rest parameter binding patterns (#17602) (camc314) - 68b2e54 minifier: Prevent incorrect ??= transformation when member base is mutated (#17472) (copilot-swe-agent) ### ⚡ Performance - 6067143 semantic: Remove hash when checking identifier (#17564) (camchenry) - a28ab3d semantic: Avoid bounds check when checking string literal (#17545) (camc314) - 04809d1 semantic: Use SIMD for finding backslashes in `check_string_literal` (#17534) (camchenry) - 49ad2f0 semantic: Mark all diagnostic functions as `#[cold]` (#17487) (camc314) - ea82b50 transformer: Mark all diagnostic functions as `#[cold]` (#17486) (camc314) - d968e51 semantic: Mark `checker::check` as `inline(always)` (#17459) (camc314)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Extends the mutation check from #16802 to
remove_unused_expression.rs. The transformationx.y != null || (x = {}, x.y = 3)→x.y ??= (x = {}, 3)changes semantics whenxis reassigned because??=captures the reference before evaluating the RHS.Changes
member_object_may_be_mutated()check before??=transformation in nullish coalescing optimizationx.y != null || (x = {}, x.y = 3)→x.y ?? (x = {}, x.y = 3)(safe)x.y != null || (x = {}, x.y = 3)→x.y ??= (x = {}, 3)(unsafe)x.y != null || (foo(), x.y = 3)→x.y ??= (foo(), 3)when no mutationExample
Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.