Skip to content

fix(minifier): prevent incorrect array.join("") to string concat for nullable elements#11546

Open
veeceey wants to merge 4 commits intoswc-project:mainfrom
veeceey:fix/issue-11545-array-join-undefined
Open

fix(minifier): prevent incorrect array.join("") to string concat for nullable elements#11546
veeceey wants to merge 4 commits intoswc-project:mainfrom
veeceey:fix/issue-11545-array-join-undefined

Conversation

@veeceey
Copy link

@veeceey veeceey commented Feb 14, 2026

Fixes #11545

When compress.evaluate is enabled, compress_array_join_partial converts [...].join("") to string concatenation with +. This is incorrect when array elements can be undefined or null, because Array.prototype.join converts these to empty strings, while + converts them to "undefined" / "null".

For example:

["abc", cond ? undefined : "def"].join("")
// Expected when cond=true: "abc"
// Was producing: "abcundefined" (via "abc" + (cond ? void 0 : "def"))

The fix adds a check in the empty-separator path of compress_array_join_partial that bails out when non-literal expressions aren't guaranteed to be strings (checked via is_definitely_string). This prevents the semantics-changing transformation while still allowing the optimization for safe cases like template literals and known string concatenations.

All 471 exec tests pass, including 2 new tests covering the exact scenario from the issue.

…mization

Array.prototype.join converts null/undefined elements to empty strings,
but string concatenation with + converts them to "null"/"undefined".
This caused incorrect output when compress.evaluate was enabled for
arrays containing expressions that could evaluate to undefined/null.

For example:
  ["abc", cond ? undefined : "def"].join("") should produce "abc" when
  cond is true, but was being converted to "abc" + (cond ? void 0 : "def")
  which produces "abcundefined".

The fix bails out of the partial join optimization when non-literal
expressions that aren't guaranteed to be strings are present in the
array with an empty separator.

Closes swc-project#11545
@veeceey veeceey requested a review from a team as a code owner February 14, 2026 10:57
@changeset-bot
Copy link

changeset-bot bot commented Feb 14, 2026

🦋 Changeset detected

Latest commit: e7c4d9b

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@CLAassistant
Copy link

CLAassistant commented Feb 14, 2026

CLA assistant check
All committers have signed the CLA.

@codspeed-hq
Copy link

codspeed-hq bot commented Feb 14, 2026

Merging this PR will not alter performance

✅ 184 untouched benchmarks


Comparing veeceey:fix/issue-11545-array-join-undefined (e7c4d9b) with main (3cc286b)

Open in CodSpeed

@github-actions
Copy link
Contributor

github-actions bot commented Feb 14, 2026

Binary Sizes

File Size
swc.linux-x64-gnu.node 28M (28577736 bytes)

Commit: 0a09de5

@kdy1 kdy1 added this to the Planned milestone Feb 15, 2026
Copy link
Member

@kdy1 kdy1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

Copy link
Member

@kdy1 kdy1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI failed. Can you fix it?
You can do UPDATE=1 cargo test from the minifier directory or swc directory to update the test refernces

@veeceey veeceey requested a review from a team as a code owner February 15, 2026 04:26
veeceey and others added 2 commits February 14, 2026 23:11
…uard

The previous approach using is_definitely_string was too conservative and
blocked the join-to-concat optimization for function calls, variables,
and other expressions that terser also optimizes. This caused 8 fixture
test failures.

Replace with may_produce_null_or_undefined which only bails out when an
expression obviously produces null/undefined (direct null/undefined/void
literals, or conditional expressions with nullable branches). This still
prevents the incorrect transformation from swc-project#11545 while preserving
terser-compatible behavior for other cases.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@veeceey
Copy link
Author

veeceey commented Feb 16, 2026

Fixed the clippy issue — changed .map_or(false, ...) to .is_some_and(...). Should be good now, thanks for the heads up!

@veeceey
Copy link
Author

veeceey commented Feb 16, 2026

CI is green now after the clippy fix — switched to is_some_and() as suggested. Would appreciate a re-review when you get a chance!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect transformation of array join with conditional undefined element when compression + evaluate are enabled

3 participants