Skip to content

fix(reconcile): force replacement when nested value type changes between array and object#2796

Open
tsushanth wants to merge 1 commit into
solidjs:nextfrom
tsushanth:fix/reconcile-array-object-type-mismatch
Open

fix(reconcile): force replacement when nested value type changes between array and object#2796
tsushanth wants to merge 1 commit into
solidjs:nextfrom
tsushanth:fix/reconcile-array-object-type-mismatch

Conversation

@tsushanth

Copy link
Copy Markdown

When a tracked store property holds an array and reconcile replaces it with a plain object (or vice versa), the previous code entered the object-merge loop and called applyState recursively on the existing array-shaped proxy. The in-place patch swapped STORE_VALUE but left the signal node pointing at the old wrapper, so a memo or effect reading that property continued to see Array.isArray() === true even after the value became a plain object.

The guard that already handles non-wrappable values, missing values, and key identity mismatches now also catches Array.isArray(previousValue) !== Array.isArray(nextValue). When the structural type differs, the signal node is rewritten with a fresh wrap(nextValue, target) call rather than delegating to applyState, which correctly replaces the proxy for downstream subscribers.

The same one-line guard is added to both applyStateFast and applyStateSlow.

Fixes #2774

…een array and object

When a tracked store property holds an array and reconcile replaces it
with a plain object (or vice versa), the previous code recursively
called applyState on the same-typed proxy, leaving the signal node
pointing at the old array-shaped wrapper even after STORE_VALUE was
updated. Reading the property through a memo therefore still returned
Array.isArray() === true for the new object value.

The fix adds Array.isArray(previousValue) !== Array.isArray(nextValue)
to the early-replacement guard in both applyStateFast and applyStateSlow
so a type switch always forces the signal node to be rewritten with a
fresh wrapped value rather than patched in place.

Fixes solidjs#2774
@changeset-bot

changeset-bot Bot commented Jun 25, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 1265634

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

This PR includes changesets to release 9 packages
Name Type
@solidjs/signals Patch
test-integration Patch
solid-js Patch
babel-preset-solid Patch
@solidjs/web Patch
@solidjs/html Patch
@solidjs/h Patch
@solidjs/universal Patch
@solidjs/element Patch

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

@codspeed-hq

codspeed-hq Bot commented Jun 25, 2026

Copy link
Copy Markdown

Merging this PR will improve performance by 36.59%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 2 improved benchmarks
✅ 116 untouched benchmarks

Performance Changes

Benchmark BASE HEAD Efficiency
merge 331.5 µs 222.8 µs +48.77%
omit 215.7 µs 172 µs +25.4%

Tip

Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.


Comparing tsushanth:fix/reconcile-array-object-type-mismatch (1265634) with next (a4ca10b)

Open in CodSpeed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant