Repository navigation
Update the React DevTools integration to React DevTools 8.0.0 - #10677
Conversation
Goes with the RDT routine update in the backend: the operations in the `react-devtools-bridge` annotations now come from (Replay's fork of) React DevTools 8.0.0, which supports current React 19. - Use upstream `react-devtools-inline@8.0.0` for the Store and bridges, instead of our 4.28 fork `@replayio/react-devtools-inline` and the yarn patch that made it work with React 19. Only the Store and the bridge were ever used from it, which upstream provides as is. - The bundle injected into pauses is now react-devtools-core's backend (hook, renderer and agent in one file) from the same fork commit as the routine's. The injection installs the hook with the default component filters, attaches an agent, injects the saved Fiber renderers in the order the routine does (so renderer IDs match) and commits the saved roots, which mounts the current tree under the same element IDs as the operations. Web Storage and microtasks are shadowed for the bundle. - `__RECORD_REPLAY_REACT_DEVTOOLS_SEND_MESSAGE__` is now defined by the injection (it used to be part of the fork), on the hook's agent. - `findNativeNodesForFiberID()` is `findHostInstancesForElementID()` now. - Operations use the 7.0+ format; the parser handles it, and resetting the displayed tree generates removals of everything the Store holds (Suspense nodes, then elements, children first), as React DevTools no longer has a "remove root" operation. This also fixes the subtree mode being read from the wrong index when printing operations.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
…notations The backend's RDT routine now saves the operations (in the format of React DevTools 7.0+) under a new annotation kind. The previous kind had the earlier format, which a parser can't tell apart (the bridge protocol version is 2 in both), so with separate kinds a frontend and backend that disagree, e.g. while one of them is being deployed or rolled back, show no React tree instead of a wrong one.
The bridge batches outgoing messages and sends them from a microtask, which the injection shadowed with a no-op: the first message scheduled a flush that never ran, and every later one stayed queued. Nothing listens to that bridge in a pause, so send each batch (to nowhere) right away.
|
🤖review: Reviewed Comments, none blocking:
|
React DevTools reports exceptions thrown by its event listeners with `reportError()`, which would dispatch an error event on the paused page, and it reads resource timings (`performance.getEntriesByType`) and evaluates stylesheets' media queries (`matchMedia`), neither of which matters for the frontend. Shadow them like the backend's RDT routine does.
5efc420 to
f3f8f99
Compare
…sole The agent schedules a timer to persist the selection whenever an element is inspected, and the hook wraps console.error/console.warn when it is installed. Shadow setTimeout, clearTimeout and console for the bundle, like the backend routine does. Also put the agent's bridge back after each request instead of leaving the capture object in place.
f3f8f99 to
24e2c92
Compare
…ols-02 React DevTools doesn't list the children of hidden Offscreen fibers. In the logpoints-01 recording, which predates React's separate Activity fiber, a hidden <Activity> is a plain hidden Offscreen, and one of the <Suspense> components mounts inside one (in a hidden panel) and stays there until the end of the recording. The old React DevTools fork listed it; 8.0 doesn't.
Goes with the RDT routine update in replayio/backend#13510: the React DevTools operations now come from (Replay's fork of) React DevTools 8.0.0, which supports current React 19, and are read from the new
react-devtools-bridge-v2annotations.Use upstream
react-devtools-inline@8.0.0(pinned exactly, see below) for the Store and bridges, instead of our 4.28 fork@replayio/react-devtools-inlineand the yarn patch that made it work with React 19. Only the Store and the bridge were ever used from it, which upstream provides as is.Read the operations from
react-devtools-bridge-v2annotations. The oldreact-devtools-bridgekind has the earlier operations format, which a parser can't tell apart from the new one (the bridge protocol version is 2 in both). With separate kinds, a frontend and backend that disagree (during a deploy or a rollback) show no React tree instead of a wrong one.The bundle injected into pauses is now react-devtools-core's backend (hook, renderer and agent in one file), built from the same fork commit as the routine's (replayio/react@b01ae07908). The injection installs the hook with the default component filters and attaches an agent. It then injects the saved Fiber renderers in the order the routine does, so renderer IDs match, and commits the saved roots. That mounts the current tree under the same element IDs as the operations.
Page APIs are shadowed for the bundle like the routine does, so that nothing it does in a pause reaches the page:
setTimeout/clearTimeout: the agent's timer that persists the selection;console: the hook wrapsconsole.error/console.warn;reportError;performanceandmatchMedia: resource timings and stylesheet media queries.queueMicrotaskruns its callback right away, so the bridge, which nothing listens to here, sends each batch to nowhere instead of queueing messages forever.__RECORD_REPLAY_REACT_DEVTOOLS_SEND_MESSAGE__is now defined by the injection (it used to be part of the fork). It calls the agent's handler and returns the message it sends back, restoring the agent's bridge afterwards.findNativeNodesForFiberID()isfindHostInstancesForElementID()now.Operations use the 7.0+ format. Resetting the displayed tree generates removals of everything the Store holds (Suspense nodes, then elements, children first), because React DevTools no longer has a "remove root" operation. It builds them from private Store fields, so
react-devtools-inlinehas to stay pinned to exactly8.0.0. This also fixes the subtree mode being read from the wrong index when printing operations.Deploy after replayio/backend#13510. Until a recording has been processed by the new routine (version 14, which runs again the next time a recording is opened), there are no
-v2annotations, and the React panel is empty. The e2e React tests here fail until that backend change is deployed.