Repository navigation
fix(signals): an error-boundary output reaching only hidden effects holds nothing through memos and nested boundaries (#4639 follow-up) - #4655
Conversation
…olds nothing through memos and nested boundaries (#4639 follow-up) #4639 made an error-boundary output transparent only to its direct readers. A memo or a second error boundary built outside the `<Loading>` between it and the content still held the frame, and so did an output nobody reads. `hiddenBy` now walks through every non-effect node below a boundary output to the render effects it reaches, and an output reaching none holds nothing (Vocabulary "Reader", F-3, F-4, D-14). The DEV LOADING_ON_OUTSIDE_HOLD report no longer fires for a reader under such a boundary while the re-armed fallback is on screen (D-16). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0117BoWNSSgtemsSYsaX2hXE
🦋 Changeset detectedLatest commit: f47ee47 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)
❌ Fails the gate
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 41613840475Coverage remained the same at 78.249%Details
Uncovered ChangesNo uncovered changes found. Coverage RegressionsNo coverage regressions found. Coverage Stats
💛 - Coveralls |
Merging this PR will degrade performance by 5.83%1 warning
Warning Please fix the performance issues or acknowledge them on CodSpeed. Performance Changes
Tip Investigate this regression by commenting Comparing Footnotes
|
…, trim (#4639 follow-up review) - hiddenBy walks each node once per walk (seen set): a memo lattice below an error-boundary output costs its size, not its paths. - A user effect reached through the output is never a reader (Vocabulary "Reader"): it holds nothing, as a plain read of the source. - DEV LOADING_ON_OUTSIDE_HOLD: the output check applies only when the reader is that boundary's tree (a header render effect inside it still reports). - s !== null -> s (trim). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0117BoWNSSgtemsSYsaX2hXE
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0117BoWNSSgtemsSYsaX2hXE
…#4639 follow-up review trim) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0117BoWNSSgtemsSYsaX2hXE
Follow-up to #4639 (#4638), for the gaps found in its review ("Merge, fix next").
What was wrong
#4639 made a pending error-boundary output transparent to the hold: it is on screen only through its readers, so read only behind fallbacks it holds nothing. That only looked at the output's direct readers. Three shapes from the same root still held the re-armed frame (the
<Loading on={sel()}>fallback never showed):<Loading>sits between the error-boundary output and the content.<Loading>.Also (4): DEV reported
LOADING_ON_OUTSIDE_HOLDfor the plain #4638 shape while the fallback was on screen. That false report was already onnextbefore #4639:reportOutsideHoldtreated the error boundary's tree as an outside frame reader.Probe frames after
sel(3 → 1)(detailandcommentsboth pending):Crash | c 1(held)loading #1 | loading cloading #1 | loading c, warnsCrash / Crash | c 1, warnsWhich rules decide the expected frames
LOADING_ON_OUTSIDE_HOLDreports exactly that case ("the fallback can never be seen"). With the fallback on screen the report is false (4). The header shape still holds and still warns.No existing pinned test changes.
Change (
packages/signals/src/boundaries.ts)hiddenBy(r, through?): below aCONFIG_REDERIVEoutput it now walks through every non-effect node (memo, nested boundary output, tree) to the render effects it reaches. A node that reaches none counts as hidden (1, which is truthy). This only ever happens for a non-effect, andheldRunonly asks about effects. At the top level the walk still starts only from a boundary output, so other callers are unchanged. Walking from every non-effect node at the top level broke web tests.reportOutsideHold(DEV only): a reader under a boundary whose output is hidden is not an outside reader.hiddenByis on the boundary path. About +55 B minified on rows with Loading/Errored (the per-walk seen Set that bounds the walk on memo lattices, and the render-effect terminal that keeps user effects from being readers). Hello world is 0 B. The Set is kept over an array:includesis O(n²) on wide fan-outs.Size-Exception: the #4639 follow-up walks an error-boundary output through memos and nested boundaries, bounded per walk (seen Set) so wide graphs stay linear; about +55 B minified on Loading/Errored rows including the frozen hydrating, base and live server-component floors. Caps are re-recorded by the ledger PR after the merge batch.
Tests
packages/signals/tests/loading-on-errorboundary-through-4639.test.ts: direct, memo, nested and unread, each resolving and rejecting (unread resolves only). All four show both fallbacks now and log noLOADING_ON_OUTSIDE_HOLD. The header shape (D-16) holds and warns once. 7 of 8 fail onnext.packages/web/test/loading-on-errorboundary-through-4639.spec.tsx: memo, nested and unread through<Loading>. All 3 fail onnext.Fixes the review gaps of #4639 (#4638).
Generated by Claude Code