Repository navigation
fix(signals): a lane's held reader settling never makes the flush join the lane (#4440) - #4477
Conversation
…n the lane (#4440) A landing's settle walk joins the flush to the transaction of each held reader it releases (`joinFuture(txOf(node))`). A render or user effect a guess's lane holds has that lane as its transaction, so the flush took the lane as its transaction. The lane was dissolved later in the same flush (a correction), and every node born held after that (the rows `<For>` mounted for the refreshed list) was listed on the dead lane and never committed: the row rendered with every hole empty. Lane work never makes its node the transaction's (D-37), so the walk now skips a reader held by a lane. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015hPxMkC3jg3Uivh65gvaf2
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015hPxMkC3jg3Uivh65gvaf2
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015hPxMkC3jg3Uivh65gvaf2
# Conflicts: # scripts/size/scenarios.js
The simple-app floor goes over its frozen cap (9,789 B brotli, +22 B minified over the recorded) and needs a Size-Exception in the PR body. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015hPxMkC3jg3Uivh65gvaf2
Two frozen floors go over their caps (each +24 B minified over the recorded): the simple-app floor (9,790 B brotli) and the hydrating (no stores) floor (18,758 B). Both need a Size-Exception in the PR body. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015hPxMkC3jg3Uivh65gvaf2
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015hPxMkC3jg3Uivh65gvaf2
Size (brotli, eager entry chunk)
|
Coverage Report for CI Build 41105284084Coverage remained the same at 78.1%Details
Uncovered ChangesNo uncovered changes found. Coverage RegressionsNo coverage regressions found. Coverage Stats
💛 - Coveralls |
Merging this PR will improve performance by 11.24%2 warnings
Performance Changes
Tip Curious why performance improved? Comment Comparing Footnotes
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015hPxMkC3jg3Uivh65gvaf2
… lanes The merge of next above also moved the #4440 guard from the settle walk into joinFuture (`laneStageHook && t?._lane`), so it covers every held-node joinFuture call and bundles without lanes pay 0 B. This commit re-records the lane bundles' sizes; the floor raises and Size-Exception are gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015hPxMkC3jg3Uivh65gvaf2
🦋 Changeset detectedLatest commit: 94eab76 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 |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015hPxMkC3jg3Uivh65gvaf2
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015hPxMkC3jg3Uivh65gvaf2
Before: an optimistic guess's lane could hold a render or user effect, and that effect's transaction is the lane. When a landing settled such a reader, the settle walk joined the flush to the lane's transaction (
joinFuture(txOf(node))), so the flush took the lane as its transaction. A correction later in the same flush dissolved the lane. Every node born held after that, such as the rows<For>mounted for the refreshed list, was listed on the dead lane and never committed, so those rows rendered with every hole empty.After: a refresh that lands beside an optimistic guess mounts its rows with their content.
D-37 (RULES-DERIVED) says "A lane sees the screen plus its own guesses and never holds a sync write". Lane work never makes its node the transaction's.
How:
joinFuture(core/scheduler.ts) returns when the transaction it is asked to join is a lane, gated on the lane engine (laneStageHook). Bundles without lanes pay 0 B. The guard sits injoinFutureitself, so it also covers the other held-nodejoinFuture(txOf(x))calls:setSignalincore.ts,notifyContainerinstore.ts, and the pending propagation inasync.ts. In the signals suite only the settle walk reaches it with a lane; I couldn't build a test that reaches one of the other call sites with a lane's transaction.Size vs next @ d0fc285 (after #4479), measured locally (linux), brotli / minified:
signals: + isPending/latestpage: compiled live server componentspage: live server components(frozen floor)app: hydrating + every store primitivepage: live + routerThe brotli deltas over 20 B are layout from the same +18 B of minified code. No floor changes, so there is no Size-Exception.
How did you test this change?
New
packages/signals/tests/optimistic-lane-held-landing-4440.test.tsandpackages/web/test/optimistic-guess-joins-refresh-4440.spec.tsx.Suites:
Fixes #4440.
🤖 Generated with Claude Code
https://claude.ai/code/session_015hPxMkC3jg3Uivh65gvaf2