Skip to content

Adopted claims derive their prefix from the wire id, not the call address - #2973

Merged
ryansolid merged 1 commit into
solidjs:nextfrom
brenelz:fix/adopt-claim-scope-wire-id
Aug 5, 2026
Merged

Adopted claims derive their prefix from the wire id, not the call address#2973
ryansolid merged 1 commit into
solidjs:nextfrom
brenelz:fix/adopt-claim-scope-wire-id

Conversation

@brenelz

@brenelz brenelz commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Summary

The identity split (bcbe7e5) rebound adopted document frames to the call's address (function id + args hash), but the document producer still stamps _hk hydration keys and region fids under the bare wire id. ctx.frame falls back to the frame's id when no claimScope is provided (frame-client.js: claimScope ?? id), so every adopted claim on an args-bearing call derived a :hash-suffixed prefix (sc-…-noteListView:28y-item#0-1 vs the stamped sc-…-noteListView-item#0-1), missed the registry, and re-rendered fresh template clones. The clones' insert(props.children) then moved the adopted {$frame} region elements — the server-rendered interiors — out of the live document into the discarded detached tree: streamed content flashed on screen and went blank at hydration, leaving the gutted server markup in place.

Argless calls (address === id) masked the break, which is why simple pages kept working.

Fix

claimScope is the runtime's existing seam for exactly this — nested region frames already thread the root boundary's scope down (claimScope ?? id at both consumption sites). adoptBoundary now passes the wire id through it, next to the other unpublished FrameOptions in the spread-cast.

Repro / verification

examples/notes in dev: sidebar note titles stream in, then blank out at hydration (every item#N.children / item#N.expandedChildren region frame is reparented into a detached clone and dropped). With this change the items claim the server DOM in place (_hk markup retained, region frames intact) and titles persist; navigation and selection behave.

Diagnosed by instrumenting getNextElement to log miss-key vs registry — the :28y args-hash suffix on every requested key against hash-less registry keys pins the mismatch. The removal itself was invisible to removal-API patches because it's a connected→detached insertBefore/appendChild move by reconcileArrays.

🤖 Generated with Claude Code

…ress

The identity split (bcbe7e5) rebound adopted frames to the call's
address — function id + args hash — but the document producer stamps
_hk keys and region fids under the bare wire id. ctx.frame falls back
to the frame id when no claimScope is given, so every adopted claim on
an args-bearing call derived a ':hash'-suffixed prefix, missed the
registry, and re-rendered fresh clones; their inserts then moved the
adopted {$frame} region elements (server-rendered interiors) into the
discarded detached tree — streamed content flashed on screen and went
blank at hydration. Argless calls (address === id) masked the break.

claimScope is the runtime's existing seam for exactly this — region
frames already thread the root boundary's scope down — so adoptBoundary
now passes the wire id through it, alongside the other unpublished
FrameOptions in the spread-cast.

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

changeset-bot Bot commented Aug 5, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 19d75b1

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

This PR includes changesets to release 9 packages
Name Type
@solidjs/web Patch
@solidjs/element Patch
@solidjs/h Patch
@solidjs/html Patch
test-integration Patch
solid-js Patch
babel-preset-solid Patch
@solidjs/universal Patch
@solidjs/signals 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 Aug 5, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 7 untouched benchmarks
⏩ 117 skipped benchmarks1


Comparing brenelz:fix/adopt-claim-scope-wire-id (19d75b1) with next (3ba6c86)

Open in CodSpeed

Footnotes

  1. 117 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@ryansolid
ryansolid merged commit 977b176 into solidjs:next Aug 5, 2026
4 of 5 checks passed
ryansolid added a commit that referenced this pull request Aug 5, 2026
Argless calls (address === id) masked the claim-prefix break, which is
why the adopted-slot suites never caught it: this spec seeds an _$SC.a
address record so the adopted frame binds a hash-suffixed address while
the markup's _hk keys stay under the wire id, and asserts the fill
CLAIMS the producer's server-rendered node instead of re-rendering a
clone over it. Fails without adoptBoundary's claimScope threading.

Co-authored-by: Cursor <cursoragent@cursor.com>
ryansolid added a commit that referenced this pull request Aug 5, 2026
@solidjs/web's test-types script re-ran `types` before its tsc, and that
script begins with `rimraf types/ types-cjs/`. Turbo already orders the
types task ahead of test-types (dependsOn) but has no edge between
test-types and the EXAMPLES' typecheck tasks, so in CI the rimraf could
wipe @solidjs/web/types/** mid-typecheck — the example's tsc then lost
the jsx-runtime namespace and every type-only export (frames' Slot),
falling through to the built JS. Flaky by scheduling: notes typechecked
seconds earlier and passed while hackernews lost the race (#2973's red
check). solid-js's test-types is already a pure consumer; now web's is
too, and the types work isn't done twice per CI run.

Co-authored-by: Cursor <cursoragent@cursor.com>
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.

2 participants