Fix dev mode hydration failure when page is served from HTTP cache (#92892)
PR #88182 introduced an experimental option to use `Cache-Control:
no-cache` instead of `no-store` in dev mode, and PR #91503 made it the
default. With `no-cache`, browsers may serve the page from HTTP cache on
back-forward navigation or tab duplication. The HTML, including the
inline RSC payload, is restored from cache and all scripts re-execute.
In dev mode, React's Flight client uses a debug channel (a
WebSocket-backed stream delivering component debug info) that adds
dependencies to model chunk initialization. On a fresh page load, the
WebSocket delivers this data and the dependencies resolve normally. On
HTTP cache restore, however, the bootstrap script re-executes and
creates a new debug channel stream, but the WebSocket doesn't re-send
debug data for the cached payload's request ID. The debug dependencies
are never fulfilled, blocking the entire model tree from initializing,
so `hydrateRoot` is never called and the page loses all interactivity.
This is dev-only — production builds have no debug channel, so there are
no stuck dependencies and no issue.
The fix buffers debug channel chunks in memory as they flow through the
`TransformStream` in `getOrCreateDebugChannelReadableWriterPair`. Once
all chunks have been received, the buffer is eagerly persisted to
`sessionStorage`. When the page detects it was served from HTTP cache
(via `PerformanceNavigationTiming.transferSize === 0`),
`createDebugChannel` restores the debug data from `sessionStorage` and
replays it as a synthetic `ReadableStream` instead of expecting it from
the WebSocket. If the restore fails (e.g., quota exceeded during the
earlier write, or the entry was overwritten by another page), the page
falls back to `location.reload()` to get a fresh page from the server.
A regression test is included that navigates to an external page and
verifies interactivity is preserved after clicking the browser back
button. Tab duplication (which triggers the same HTTP cache restore)
cannot be simulated in Playwright and was verified manually.
fixes #92238
fixes #91982
fixes #92687