Repository navigation
fix(signals): a corrected guess keeps its action's hold open (#4690) - #4693
Conversation
When a refresh() from outside an action landed under a guess the screen showed, the correction re-homed the node into the action's hold, but nothing kept that hold open on the node's next flight, as an uncorrected guess does through guessFlights. A hold waits only on flights a render reader observes, so with nothing rendering the source the hold landed with the action's write: effects and untracked reads showed the re-ask's answer until the action's own refresh() landed, while rendered readers kept the guess (F-11, D-34). Corrected shown guesses are now marked and lanesBlocked keeps their hold open while the node is in flight; endLanes clears the marks at the landing. Co-authored-by: tembo[bot] <208362400+tembo-io[bot]@users.noreply.github.com>
app: hydrating + every store primitive family: +110 B minified from #4690, measured locally over next @ fb672ca with the in-repo compiler build; cap = measured brotli + 10 B (33.42 -> 33.41 KB), recorded minified 100,437 -> 100,547 B. No floor moves. Co-authored-by: tembo[bot] <208362400+tembo-io[bot]@users.noreply.github.com>
🦋 Changeset detectedLatest commit: ebc7925 The changes in this PR will be included in the next version bump. This PR includes changesets to release 15 packages
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 |
Size (brotli, eager entry chunk)
Bundled with Rolldown (what Vite ships), brotli q11, decimal KB. A scenario fails only when it is over its brotli cap and its minified size is more than 20 B over the minified recorded with the cap; over the cap within that allowance is brotli layout noise and passes with a warning. Caps and their recorded minified in |
Coverage Report for CI Build 42098822794Coverage remained the same at 78.249%Details
Uncovered ChangesNo uncovered changes found. Coverage RegressionsNo coverage regressions found. Coverage Stats
💛 - Coveralls |
Merging this PR will not alter performance1 warning
Comparing Footnotes
|
Summary
Fixes #4690, with the scope corrected in the issue's follow-up comment: a tear between effect-only readers and rendered readers, not a flicker a rendered app shows.
An action guesses, yields its write, then calls
refresh(source). If arefresh()from outside the action landed under the pending guess, the correction (supersede/dissolveLaneinlanes.ts) re-homed the guessed node into the action's hold, keeping the shown guess as the screen's value (F-11, D-34). But nothing kept that hold open on the node's next flight any more; an uncorrected guess does, throughguessFlights. A hold only waits on flights a render reader observes. So with nothing rendering the source, the hold landed with the action's write: effects and untracked reads showed the outside re-ask's old answer until the action's ownrefresh()landed, while rendered readers kept the guess.Fix (
lanes.ts):lanesBlockedkeeps that hold open while the marked node is in flight (D-7, D-35: the action'srefresh()is the answer the guess waits for). This applies to the hold only; when a lane guesses the node again, its flight blocks the parent as before (A17).endLanesclears the marks when the hold lands.revertedWeakSet (renamedmarked; a lane and a node can't collide), and the check sits behindguessed, so bundles without optimistic code don't change.A status note is appended to D-34 in
RULES-DERIVED.md; no rule text changes.#4689 (
latest()under such a guess answers the re-asked truth) is not part of this PR. It needs a ruling against F-11, which sayslatest()answers the truth once the slot's own source answers differently.Public API changes
None.
Size
One row moves: "app: hydrating + every store primitive family", +110 B minified, at 33,398 B brotli (cap 33.42 KB). Every floor and every other scenario is unchanged. The second commit re-records that row (cap = measured brotli + 10 B: 33.42 → 33.41 KB; recorded minified 100,437 → 100,547 B). No floor cap moves, so no
Size-Exceptionis needed. Measured locally overnext@ fb672ca with the compiler built from source, as insize.yml.How did you test this change?
packages/signals/tests/optimistic-outside-reask-4690.test.ts(45 tests): five reader kinds (untracked reads, effect only, a bare render effect, a text node under<Loading>, an effect beside that text node) × four sources (createOptimistic, keyed, unkeyed-array and objectcreateOptimisticStore). Each reader is checked at every moment of the issue's table and over its full value history. Without the fix, exactly the effect-only and untracked rows fail (plus a second-guess case); rendered readers pass either way. Disabling the mark clearing or the lane exclusion on its own makes its own tests fail.@solidjs/compilerbuild, thenpnpm build: 30/30 tasks..nvmrc), includingselect-retention.spec.ts.node scripts/size/size.mjs: the gate passes.check-floor-caps.mjs: no cap raised.node scripts/rules-index.mjs --check: current.