Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Fiber] Collect Host Singleton children of Fragments - #37063

Merged
eps1lon merged 6 commits into
mainfrom
sebbie/fragment-ref-host-singleton
Jul 31, 2026
Merged

[Fiber] Collect Host Singleton children of Fragments#37063
eps1lon merged 6 commits into
mainfrom
sebbie/fragment-ref-host-singleton

Conversation

@eps1lon

@eps1lon eps1lon commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

Revisits the decision to exclude Host Singletons when collecting/traversing Fragment descendants for Fragment instance methods. Host Singletons were specifically excluded in #32465 (comment).

However, this leads to errors when calling dispatchEvent on empty singletons (e.g. <body>) as children of Fragment instances where dispatchEvent is called.

From a type perspective, we can safely start collecting HostSingleton in addition to HostComponent. Both have an Instance in their stateNode. It should also be sound from a hierarchy perspective: React doesn't hoist these elements into a different place in the document as opposed to HostHoistable which would be moved to a different spot.

@meta-cla meta-cla Bot added the CLA Signed label Jul 19, 2026
@github-actions github-actions Bot added the React Core Team Opened by a member of the React Core Team label Jul 19, 2026
@eps1lon
eps1lon force-pushed the sebbie/fragment-ref-host-singleton branch from e676855 to be1d940 Compare July 19, 2026 10:53
@eps1lon
eps1lon force-pushed the sebbie/fragment-ref-host-singleton branch from be1d940 to 90d2a58 Compare July 19, 2026 10:57
@eps1lon
eps1lon force-pushed the sebbie/fragment-ref-host-singleton branch 2 times, most recently from e6639af to 07807e3 Compare July 19, 2026 11:18
@eps1lon
eps1lon force-pushed the sebbie/fragment-ref-host-singleton branch 3 times, most recently from 1dd089d to e666f04 Compare July 19, 2026 12:18
@eps1lon
eps1lon force-pushed the sebbie/fragment-ref-host-singleton branch 2 times, most recently from 35d15d7 to 0c91646 Compare July 19, 2026 12:34
@eps1lon
eps1lon force-pushed the sebbie/fragment-ref-host-singleton branch 2 times, most recently from 237fcf9 to 8b1cf08 Compare July 20, 2026 20:44
Base automatically changed from sebbie/fragment-ref-blur-document to main July 21, 2026 08:26
… HostSingleton

`getFragmentParentInstanceOrContainerFiber` only treats HostRoot and
HostComponent fibers as host parents. In react-dom, `<html>`, `<head>`,
and `<body>` are HostSingleton fibers, so a fragment mounted directly
inside `<body>` of a root created on the document resolves its host
parent to the HostRoot, whose instance is the `Document` container.
`dispatchEvent()` then appends a temporary text node to that instance to
retarget the event, and appending a text node to a `Document` throws
with a `HierarchyRequestError`.

The test pins down the current throwing behavior. The fix in the next
commit treats HostSingleton fibers as host parents, so the temporary
event target is appended to `<body>` and the registered listener fires.

Co-Authored-By: Claude Fable 5 <[email protected]>
@eps1lon
eps1lon force-pushed the sebbie/fragment-ref-host-singleton branch from 8b1cf08 to 4c5be47 Compare July 31, 2026 13:49
eps1lon and others added 2 commits July 31, 2026 09:52
In react-dom, `<html>`, `<head>`, and `<body>` are HostSingleton fibers,
but `getFragmentParentInstanceOrContainerFiber` only matched HostRoot
and HostComponent. A fragment mounted directly inside `<body>` of a
document root therefore resolved its host parent to the HostRoot and
operated on the `Document` container, which crashed `dispatchEvent()`
when it appended the temporary event target to the document.

The parent lookup now matches HostSingleton, and
`getInstanceFromHostFiber` returns the singleton's `stateNode`, which is
an `Instance`, so no signatures or names change thanks to the
stateNode-based naming. `fiberIsPortaledIntoHost` and
`isFragmentContainedByFiber` compare fibers against the parent lookup's
result, so they learn the same tag to keep the host parent definition
consistent. Child and sibling traversal intentionally keep recursing
through singletons without collecting them; whether a fragment wrapping
`<html>` should anchor on the singleton itself is a separate decision.

The test from the previous commit flips from asserting the throw to
asserting that the registered listener fires.

Co-Authored-By: Claude Fable 5 <[email protected]>
…tons

The fragment child traversal only collects HostComponent fibers (plus
HostText behind a flag) and recurses through HostSingleton fibers
without collecting them. For a fragment wrapping the document shell,
`addEventListener` therefore attaches listeners to the elements inside
`<body>` rather than to `<html>`, and `getClientRects` measures those
inner elements instead of the singleton.

This is inconsistent with how HostComponent children behave, where the
fragment anchors on its nearest host child and does not descend into it,
and with the host parent lookup, which now treats singletons as host
parents. These tests pin down the current transparent behavior. The fix
in the next commit collects singletons like HostComponents and aligns
the commit phase accordingly.

Co-Authored-By: Claude Fable 5 <[email protected]>
@react-sizebot

react-sizebot commented Jul 31, 2026

Copy link
Copy Markdown

Comparing: 9b5b4d5...6685758

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.js = 7.45 kB 7.45 kB +0.05% 2.00 kB 2.00 kB
oss-stable/react-dom/cjs/react-dom-client.production.js +0.15% 616.59 kB 617.53 kB +0.12% 109.28 kB 109.41 kB
oss-experimental/react-dom/cjs/react-dom.production.js = 7.46 kB 7.46 kB +0.05% 2.00 kB 2.00 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js +0.14% 687.80 kB 688.75 kB +0.09% 120.74 kB 120.85 kB
facebook-www/ReactDOM-prod.classic.js +0.16% 707.88 kB 709.04 kB +0.11% 124.23 kB 124.37 kB
facebook-www/ReactDOM-prod.modern.js +0.17% 698.20 kB 699.35 kB +0.11% 122.66 kB 122.79 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js = 104.86 kB 102.52 kB = 21.48 kB 20.90 kB
oss-experimental/react-server/cjs/react-server-flight.production.js = 73.16 kB 70.89 kB = 14.43 kB 14.18 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name +/- Base Current +/- gzip Base gzip Current gzip
oss-experimental/react-reconciler/cjs/react-reconciler-reflection.production.js +1.23% 11.77 kB 11.91 kB +0.85% 2.71 kB 2.73 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler-reflection.production.js +1.23% 11.77 kB 11.91 kB +0.85% 2.71 kB 2.73 kB
oss-stable/react-reconciler/cjs/react-reconciler-reflection.production.js +1.23% 11.77 kB 11.91 kB +0.85% 2.71 kB 2.73 kB
oss-experimental/react-reconciler/cjs/react-reconciler-reflection.development.js +1.22% 13.37 kB 13.53 kB +0.76% 2.76 kB 2.78 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler-reflection.development.js +1.22% 13.37 kB 13.53 kB +0.76% 2.76 kB 2.78 kB
oss-stable/react-reconciler/cjs/react-reconciler-reflection.development.js +1.22% 13.37 kB 13.53 kB +0.76% 2.76 kB 2.78 kB
facebook-www/ReactReconciler-prod.modern.js +0.21% 517.22 kB 518.31 kB +0.14% 82.09 kB 82.21 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.production.js +0.21% 454.22 kB 455.16 kB +0.15% 72.73 kB 72.84 kB
oss-stable/react-reconciler/cjs/react-reconciler.production.js +0.21% 454.24 kB 455.18 kB +0.15% 72.75 kB 72.86 kB
facebook-www/ReactReconciler-prod.classic.js +0.21% 527.50 kB 528.59 kB +0.15% 83.69 kB 83.81 kB
facebook-www/ReactART-dev.classic.js = 791.04 kB 789.44 kB = 124.57 kB 124.12 kB
facebook-www/ReactART-dev.modern.js = 781.51 kB 779.92 kB = 122.75 kB 122.33 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.development.js = 257.97 kB 257.36 kB = 46.26 kB 46.17 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.development.js = 257.97 kB 257.36 kB = 46.26 kB 46.17 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.development.js = 257.96 kB 257.35 kB = 46.26 kB 46.17 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.development.js = 257.96 kB 257.35 kB = 46.26 kB 46.17 kB
oss-stable-semver/react-server-dom-unbundled/cjs/react-server-dom-unbundled-server.node.development.js = 256.76 kB 256.15 kB = 45.94 kB 45.85 kB
oss-stable/react-server-dom-unbundled/cjs/react-server-dom-unbundled-server.node.development.js = 256.76 kB 256.15 kB = 45.94 kB 45.85 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-server.node.development.js = 250.24 kB 249.63 kB = 44.87 kB 44.77 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-server.node.development.js = 250.24 kB 249.63 kB = 44.87 kB 44.77 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-server.node.development.js = 243.47 kB 242.86 kB = 44.24 kB 44.15 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-server.node.development.js = 243.47 kB 242.86 kB = 44.24 kB 44.15 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.edge.development.js = 225.63 kB 225.02 kB = 40.69 kB 40.58 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.edge.development.js = 225.63 kB 225.02 kB = 40.69 kB 40.58 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js = 225.63 kB 225.02 kB = 40.69 kB 40.58 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js = 225.63 kB 225.02 kB = 40.69 kB 40.58 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-server.browser.development.js = 221.97 kB 221.37 kB = 40.17 kB 40.05 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-server.browser.development.js = 221.97 kB 221.37 kB = 40.17 kB 40.05 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.browser.development.js = 221.50 kB 220.89 kB = 40.06 kB 39.94 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.browser.development.js = 221.50 kB 220.89 kB = 40.06 kB 39.94 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-server.edge.development.js = 217.91 kB 217.30 kB = 39.38 kB 39.26 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-server.edge.development.js = 217.91 kB 217.30 kB = 39.38 kB 39.26 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-server.browser.development.js = 213.89 kB 213.28 kB = 38.77 kB 38.64 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-server.browser.development.js = 213.89 kB 213.28 kB = 38.77 kB 38.64 kB
facebook-www/ReactFlightServer-dev.classic.js = 205.17 kB 204.56 kB = 37.17 kB 37.06 kB
facebook-www/ReactFlightServer-dev.modern.js = 205.17 kB 204.56 kB = 37.17 kB 37.06 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js = 76.37 kB 76.12 kB = 14.72 kB 14.70 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js = 76.37 kB 76.12 kB = 14.72 kB 14.70 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js = 76.33 kB 76.07 kB = 14.73 kB 14.70 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js = 76.33 kB 76.07 kB = 14.73 kB 14.70 kB
oss-stable-semver/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js = 75.20 kB 74.95 kB = 14.48 kB 14.45 kB
oss-stable/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js = 75.20 kB 74.95 kB = 14.48 kB 14.45 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js = 73.13 kB 72.88 kB = 14.08 kB 14.05 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js = 73.13 kB 72.88 kB = 14.08 kB 14.05 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js = 71.93 kB 71.67 kB = 13.84 kB 13.81 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js = 71.93 kB 71.67 kB = 13.84 kB 13.81 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js = 71.73 kB 71.47 kB = 14.02 kB 13.98 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js = 71.73 kB 71.47 kB = 14.02 kB 13.98 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js = 71.68 kB 71.43 kB = 14.02 kB 13.98 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js = 71.68 kB 71.43 kB = 14.02 kB 13.98 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js = 68.69 kB 68.44 kB = 13.42 kB 13.39 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js = 68.69 kB 68.44 kB = 13.42 kB 13.39 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js = 64.53 kB 64.28 kB = 12.26 kB 12.24 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js = 64.53 kB 64.28 kB = 12.26 kB 12.24 kB
oss-stable/react-client/cjs/react-client-flight.production.js = 71.61 kB 71.32 kB = 12.74 kB 12.72 kB
oss-stable-semver/react-client/cjs/react-client-flight.production.js = 71.58 kB 71.30 kB = 12.71 kB 12.69 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js = 64.16 kB 63.91 kB = 12.17 kB 12.15 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js = 64.16 kB 63.91 kB = 12.17 kB 12.15 kB
oss-stable-semver/react-server/cjs/react-server-flight.development.js = 151.43 kB 150.82 kB = 27.18 kB 27.08 kB
oss-stable/react-server/cjs/react-server-flight.development.js = 151.43 kB 150.82 kB = 27.18 kB 27.08 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js = 62.40 kB 62.14 kB = 11.82 kB 11.78 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js = 62.40 kB 62.14 kB = 11.82 kB 11.78 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js = 62.20 kB 61.95 kB = 11.78 kB 11.75 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js = 62.20 kB 61.95 kB = 11.78 kB 11.75 kB
facebook-www/ReactFlightClient-prod.classic.js = 62.19 kB 61.93 kB = 12.01 kB 11.99 kB
facebook-www/ReactFlightClient-prod.modern.js = 62.19 kB 61.93 kB = 12.01 kB 11.99 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js = 201.73 kB 200.75 kB = 35.15 kB 35.09 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js = 201.69 kB 200.71 kB = 35.15 kB 35.09 kB
oss-experimental/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js = 200.31 kB 199.33 kB = 34.86 kB 34.81 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js = 196.00 kB 195.03 kB = 34.40 kB 34.33 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js = 198.65 kB 197.67 kB = 34.61 kB 34.55 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js = 196.82 kB 195.84 kB = 34.57 kB 34.51 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js = 196.43 kB 195.45 kB = 34.51 kB 34.44 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js = 195.24 kB 194.26 kB = 34.33 kB 34.27 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js = 195.20 kB 194.22 kB = 34.33 kB 34.28 kB
oss-experimental/react-markup/cjs/react-markup.react-server.development.js = 703.41 kB 699.87 kB = 124.31 kB 123.86 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js = 193.24 kB 192.26 kB = 33.86 kB 33.77 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js = 191.86 kB 190.88 kB = 33.78 kB 33.72 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js = 191.21 kB 190.23 kB = 33.44 kB 33.35 kB
oss-experimental/react-client/cjs/react-client-flight.development.js = 185.44 kB 184.46 kB = 32.06 kB 31.99 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.production.js = 130.99 kB 130.24 kB = 26.11 kB 26.02 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.production.js = 130.99 kB 130.24 kB = 26.11 kB 26.02 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.production.js = 130.98 kB 130.22 kB = 26.12 kB 26.02 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.production.js = 130.98 kB 130.22 kB = 26.12 kB 26.02 kB
oss-stable-semver/react-server-dom-unbundled/cjs/react-server-dom-unbundled-server.node.production.js = 129.93 kB 129.18 kB = 25.88 kB 25.79 kB
oss-stable/react-server-dom-unbundled/cjs/react-server-dom-unbundled-server.node.production.js = 129.93 kB 129.18 kB = 25.88 kB 25.79 kB
oss-stable/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js = 243.74 kB 242.28 kB = 54.55 kB 54.10 kB
oss-stable-semver/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js = 243.71 kB 242.26 kB = 54.52 kB 54.07 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-server.node.production.js = 124.06 kB 123.31 kB = 24.93 kB 24.85 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-server.node.production.js = 124.06 kB 123.31 kB = 24.93 kB 24.85 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.edge.production.js = 123.02 kB 122.26 kB = 24.75 kB 24.66 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.edge.production.js = 123.02 kB 122.26 kB = 24.75 kB 24.66 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.production.js = 123.02 kB 122.26 kB = 24.76 kB 24.67 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.production.js = 123.02 kB 122.26 kB = 24.76 kB 24.67 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-server.node.production.js = 120.00 kB 119.24 kB = 24.35 kB 24.26 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-server.node.production.js = 120.00 kB 119.24 kB = 24.35 kB 24.26 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-server.browser.production.js = 117.43 kB 116.68 kB = 22.70 kB 22.64 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-server.browser.production.js = 117.43 kB 116.68 kB = 22.70 kB 22.64 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.browser.production.js = 117.08 kB 116.33 kB = 22.61 kB 22.54 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.browser.production.js = 117.08 kB 116.33 kB = 22.61 kB 22.54 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-server.edge.production.js = 116.08 kB 115.33 kB = 23.61 kB 23.52 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-server.edge.production.js = 116.08 kB 115.33 kB = 23.61 kB 23.52 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-server.browser.production.js = 111.57 kB 110.81 kB = 21.70 kB 21.63 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-server.browser.production.js = 111.57 kB 110.81 kB = 21.70 kB 21.63 kB
facebook-www/ReactFlightServer-prod.classic.js = 106.81 kB 106.05 kB = 21.72 kB 21.65 kB
facebook-www/ReactFlightServer-prod.modern.js = 106.81 kB 106.05 kB = 21.72 kB 21.65 kB
oss-experimental/react-markup/cjs/react-markup.react-server.production.js = 373.78 kB 370.89 kB = 69.26 kB 68.87 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js = 244.68 kB 242.29 kB = 54.65 kB 54.11 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.development.js = 262.14 kB 259.45 kB = 46.98 kB 46.60 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.development.js = 262.12 kB 259.44 kB = 46.98 kB 46.60 kB
oss-experimental/react-server-dom-unbundled/cjs/react-server-dom-unbundled-server.node.development.js = 260.93 kB 258.24 kB = 46.66 kB 46.28 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-server.node.development.js = 254.41 kB 251.72 kB = 45.60 kB 45.22 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js = 76.94 kB 76.12 kB = 14.80 kB 14.70 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js = 76.89 kB 76.07 kB = 14.80 kB 14.70 kB
oss-experimental/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js = 75.77 kB 74.95 kB = 14.56 kB 14.45 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-server.node.development.js = 247.64 kB 244.95 kB = 44.96 kB 44.58 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js = 73.70 kB 72.88 kB = 14.16 kB 14.05 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js = 72.49 kB 71.67 kB = 13.94 kB 13.81 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js = 72.30 kB 71.47 kB = 14.12 kB 13.98 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js = 72.25 kB 71.43 kB = 14.12 kB 13.98 kB
oss-stable-semver/react-server/cjs/react-server-flight.production.js = 69.89 kB 69.09 kB = 13.83 kB 13.76 kB
oss-stable/react-server/cjs/react-server-flight.production.js = 69.89 kB 69.09 kB = 13.83 kB 13.76 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.edge.development.js = 229.79 kB 227.11 kB = 41.39 kB 41.02 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js = 229.79 kB 227.11 kB = 41.39 kB 41.02 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js = 69.26 kB 68.44 kB = 13.52 kB 13.39 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.browser.development.js = 226.16 kB 223.47 kB = 40.88 kB 40.48 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.browser.development.js = 225.68 kB 223.00 kB = 40.76 kB 40.37 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-server.edge.development.js = 222.07 kB 219.39 kB = 40.07 kB 39.69 kB
oss-experimental/react-client/cjs/react-client-flight.production.js = 72.21 kB 71.33 kB = 12.82 kB 12.72 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-server.browser.development.js = 218.07 kB 215.38 kB = 39.46 kB 39.06 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js = 65.10 kB 64.28 kB = 12.33 kB 12.24 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js = 64.73 kB 63.91 kB = 12.24 kB 12.15 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js = 62.96 kB 62.14 kB = 11.88 kB 11.78 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js = 62.77 kB 61.95 kB = 11.84 kB 11.75 kB
oss-stable-semver/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js = 104.12 kB 102.52 kB = 21.43 kB 20.90 kB
oss-stable/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js = 104.12 kB 102.52 kB = 21.43 kB 20.90 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.production.js = 134.15 kB 132.03 kB = 26.71 kB 26.42 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.production.js = 134.14 kB 132.02 kB = 26.72 kB 26.42 kB
oss-experimental/react-server-dom-unbundled/cjs/react-server-dom-unbundled-server.node.production.js = 133.09 kB 130.97 kB = 26.48 kB 26.19 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-server.node.production.js = 127.22 kB 125.10 kB = 25.52 kB 25.23 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.edge.production.js = 126.18 kB 124.06 kB = 25.35 kB 25.05 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.production.js = 126.18 kB 124.06 kB = 25.36 kB 25.06 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-server.node.production.js = 123.16 kB 121.04 kB = 24.95 kB 24.64 kB
oss-experimental/react-server/cjs/react-server-flight.development.js = 155.60 kB 152.91 kB = 27.91 kB 27.53 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.browser.production.js = 120.60 kB 118.47 kB = 23.32 kB 23.04 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.browser.production.js = 120.24 kB 118.12 kB = 23.22 kB 22.94 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-server.edge.production.js = 119.25 kB 117.12 kB = 24.20 kB 23.92 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-server.browser.production.js = 114.73 kB 112.61 kB = 22.29 kB 22.02 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js = 104.86 kB 102.52 kB = 21.48 kB 20.90 kB
oss-experimental/react-server/cjs/react-server-flight.production.js = 73.16 kB 70.89 kB = 14.43 kB 14.18 kB

Generated by 🚫 dangerJS against 6685758

@eps1lon
eps1lon force-pushed the sebbie/fragment-ref-host-singleton branch from 4c5be47 to 66dd3b9 Compare July 31, 2026 14:57
@eps1lon
eps1lon requested a review from jackpope July 31, 2026 15:25
@eps1lon
eps1lon marked this pull request as ready for review July 31, 2026 15:25
@jackpope

Copy link
Copy Markdown
Collaborator

What do you think about adding HostSingleton support to commitImmutablePlacementNodeToFragmentInstances as well? I don't think there is any renderer that is both immutable and has singletons today, but it could work consistently if there was a use case for that in the future

eps1lon and others added 3 commits July 31, 2026 14:44
Fragment child and sibling traversal only collected HostComponent fibers
(plus HostText behind a flag) and recursed through HostSingleton fibers.
A fragment wrapping the document shell therefore anchored on the
elements inside `<body>` instead of on `<html>` itself, unlike how
HostComponent children behave, and inconsistent with the host parent
lookup, which treats singletons as host parents.

The traversal and the sibling search now collect HostSingleton fibers
and stop descending into them. The deep traversal used by `focus()`
still descends into singletons and attempts to focus them like any other
host child, with `setFocusIfFocusable` deciding whether they can receive
focus. Note that `<body>` is usually already the activeElement, so a
fragment wrapping the document shell reports it as focused rather than
searching its descendants.

The commit phase is updated to match, so singleton children receive the
same insertion and deletion effects as HostComponent children: the
placement functions commit a placed singleton to its parent fragment
instances and stop attributing its own children to them,
`commitNewChildToFragmentInstances` accepts singleton fibers, the
deletion, disappear, and reappear branches run the fragment effects for
singletons, and the fragment specific host parent walks stop at any
singleton rather than only at singleton scopes via a new
`isFragmentInstanceHostParent` that mirrors
`getFragmentParentInstanceOrContainerFiber`. The shared `isHostParent`
used for placement is unchanged. This follows the review guidance on the
original fragment refs PR that host tags must be included consistently
across these branches or not at all. HostHoistable remains excluded
everywhere since hoistables are reparented and their fiber position does
not reflect their DOM position.

The tests from the previous commit flip from documenting the transparent
traversal to asserting that the fragment anchors on the `<html>`
singleton.

Co-Authored-By: Claude Fable 5 <[email protected]>
Insertion effects must attach a fragment's listeners, observers, and
handles to exactly the nodes that the traversal based methods operate
on, and traversal stops at a collected HostSingleton child. These tests
pin down the two commit phase guards that keep those sides aligned.

The first test mounts a document shell into an existing fragment with a
registered listener. The placed singleton receives the listener as a new
fragment child while the content inside it is not attributed to the
fragment, so a click inside the shell fires the listener exactly once
when it bubbles to `<html>`. This covers the placement recursion that
stops propagating `parentFragmentInstances` below a singleton.

The second test mounts a new element inside a fragment nested in
`<body>`, with another fragment wrapping the shell from above. The inner
fragment owns the new child directly and attaches its listener on
insertion, while the outer fragment's child is the `<html>` singleton,
so its listener is not attached to the new element and fires only once
via bubbling. This covers the `commitPlacement` walk that stops
collecting fragment instances once it passes a fragment host parent
boundary.

Both tests fail with duplicated listener calls if either guard is
removed.

Co-Authored-By: Claude Fable 5 <[email protected]>
With `enableLegacyFBSupport`, every click dispatched through the plugin
event system is deferred by attaching a one time listener to
`targetContainer.ownerDocument`. When the root container is the document
itself, for example with `hydrateRoot(document)`, its `ownerDocument` is
null and the deferral crashed with "Cannot read properties of null
(reading 'addEventListener')" before any listeners ran.

The deferral target now resolves to the container itself when it is
already a `Document`. This surfaced through the fragment ref singleton
tests, which are the first to dispatch click events inside a root
created on the document under the www channel.

Co-Authored-By: Claude Fable 5 <[email protected]>
@eps1lon
eps1lon force-pushed the sebbie/fragment-ref-host-singleton branch from 66dd3b9 to 6685758 Compare July 31, 2026 18:45
@eps1lon
eps1lon requested a review from jackpope July 31, 2026 18:47
@eps1lon
eps1lon merged commit 3a717e4 into main Jul 31, 2026
181 checks passed
github-actions Bot pushed a commit that referenced this pull request Jul 31, 2026
github-actions Bot pushed a commit that referenced this pull request Jul 31, 2026
github-actions Bot pushed a commit to code/lib-react that referenced this pull request Aug 1, 2026
github-actions Bot pushed a commit to code/lib-react that referenced this pull request Aug 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed React Core Team Opened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants