Skip to content

fix(signals): suspend stale readers on an uninitialized memo held by another transition - #3043

Open
brenelz wants to merge 1 commit into
solidjs:nextfrom
brenelz:fix/stale-read-uninitialized-cross-transition
Open

fix(signals): suspend stale readers on an uninitialized memo held by another transition#3043
brenelz wants to merge 1 commit into
solidjs:nextfrom
brenelz:fix/stale-read-uninitialized-cross-transition

Conversation

@brenelz

@brenelz brenelz commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • A render effect that switches onto an async memo still in flight under a different transaction hit the "stale reader shows the committed value, don't entangle" path in read(). An uninitialized memo has no committed value, so the reader got undefined as if settled, direct-committed outside both transactions, and never re-ran when either landed — stuck on its old value forever.
  • Repro shape (s.olid.uk playground report): a global cache[k] ??= createMemo(async …) shared by several inserts, setA then setB 300ms later where B's new key is the memo A already put in flight. Worked on beta.10, broke in beta.11.
  • Fix: drop owner !== el from the STATUS_UNINITIALIZED throw branch so plain memos suspend the way firewall-backed store reads already did. The reader registers as a reporter and the two transactions merge and reveal together.
  • Regression bisected to 7d4d0c3: its (correct) needsPendingCommit gate removed an accidental pending-node push that initTransition had been stamping with _transition, which was what entangled the reader before.

Test plan

  • New tests/stale-read-uninitialized-cross-transition.test.ts — fails without the fix; includes a control showing an initialized held memo still shows its committed value without entangling
  • @solidjs/signals suite: 1336 pass
  • solid-js suite: 561 pass
  • Original DOM repro (three <div> inserts under <Loading>) and variants end foo1 foo1 bar1

Note: 5 solid-web tests (frames-behavior-claims, server-functions-csrf/extensions, welcome-status-loaded/streamed) fail identically with and without this change on the published dom-expressions 0.50.0-next.43 — the committed link:../dom-expressions-dr2/... overrides in pnpm-workspace.yaml/lockfile from 515ff56 only resolve on a machine with that checkout.

🤖 Generated with Claude Code

…another transition

A render effect that switches onto an async memo still in flight under a
different transaction took the "show the committed value, don't entangle"
path in read(). An uninitialized memo has no committed value, so the reader
was served `undefined` as if settled, direct-committed outside both
transactions, and never re-ran when either landed — stuck on its old value
(a globally cached async memo shared by two inputs updated 300ms apart).

Throw NotReady like the firewall-backed branch already did: the reader
registers as a reporter of the source and the transactions merge and reveal
together. Regression from the needsPendingCommit gate in 7d4d0c3
(beta.11), which removed the accidental pending-node stamp that had been
entangling the reader.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Aug 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 6a67056

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

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