Skip to content

fix(signals): refresh() after a held manual write stays a quiet re-ask - #3265

Open
brenelz wants to merge 1 commit into
solidjs:nextfrom
brenelz:fix/refresh-held-write-reask
Open

fix(signals): refresh() after a held manual write stays a quiet re-ask#3265
brenelz wants to merge 1 commit into
solidjs:nextfrom
brenelz:fix/refresh-held-write-reask

Conversation

@brenelz

@brenelz brenelz commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Summary

An action doing affects(row, "id"); setList(...); yield save(); refresh(list) on a plain derived store lit up isPending(() => item.id) on every row during the refetch, not just the marked one.

Root cause

The setList puts a manual-write mask on the derived store, held open by the action's transaction. When refresh(list) runs after the yield it lifts that mask (#3026), and the lift deliberately skipped the re-ask classification. Without it the refetch was treated as a brand-new question, and a new question pends every leaf. A mark can only turn pending on, so affects() could not narrow it.

Measured on the app shape:

variant during the refetch
plain store, no write, refresh silent
plain store, setList + refresh, with or without affects every leaf pends, both rows
optimistic store, write + affects(row,"id") + refresh only the marked slot pends

Fix

The lift falls through to the normal re-ask marking. Same-question motion stays silent; only the written slot and any declared affects() mark read pending until the truth lands. Same-tick precedence (#2692) is unchanged, and the #3026 refresh-in-action tests still pass.

Tests

tests/question-scoped-pending.test.ts gains 3.4-held-write: the marked slot pends from click through landing, every sibling leaf and the array length stay silent. Verdicts are observed through tracked readers, as JSX reads them; a bare isPending() after the generator returns sees the mark as already released because nothing subscribed keeps the transaction alive through the refetch. Fails without the fix at the refetch-window assertion.

🤖 Generated with Claude Code

When an action wrote to a derived store and later called refresh(store),
the lift of the manual-write mask (solidjs#3026) dropped the re-ask
classification, so the refetch was treated as a brand-new question and
pended every leaf: every sibling row lit up isPending, and a row-scoped
affects() could not narrow it (a mark only turns pending on).

The lift now falls through to the normal re-ask marking. Same-question
motion stays silent; only the written slot and any declared affects() mark
read pending until the truth lands. Same-tick precedence (solidjs#2692) is
unchanged. Regression in the question-scoped pending suite, observed
through tracked readers as JSX reads them.

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

changeset-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: ccd451f

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

This PR includes changesets to release 11 packages
Name Type
@solidjs/signals Patch
test-integration Patch
@solidjs/web Patch
@solidjs/babel-plugin Patch
@solidjs/compiler Patch
@solidjs/diagnostics Patch
@solidjs/element Patch
@solidjs/h Patch
@solidjs/html Patch
solid-js Patch
@solidjs/universal 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 Sep 4, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 136 untouched benchmarks


Comparing brenelz:fix/refresh-held-write-reask (ccd451f) with next (439a2fe)

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