## Summary
- Bump React DevTools from 7.0.1 to 8.0.0 (packages + extension
manifests only; no publish).
- `scripts/devtools/prepare-release.js` only supports minor/patch, so
this major bump is manual.
- Changelog is curated from DevTools commits since 7.0.1 (features vs
bugfixes; internal/test-only changes omitted).
## Test plan
- [ ] Confirm published package versions would be 8.0.0 for
`react-devtools`, `react-devtools-core`, and `react-devtools-inline`
- [ ] Confirm Chrome/Edge/Firefox extension manifests show 8.0.0
- [ ] Review `packages/react-devtools/CHANGELOG.md` 8.0.0 section for
accuracy before undrafting
## Summary
With the tab gone, everything that fed it is unreachable. This deletes
`packages/react-devtools-timeline` (74 files) and the backend that
produced its data, `backend/profilingHooks.js`, along with
`SidebarEventInfo`, the two timeline test suites, the `timelineData`
snapshot serializer, and the scheduling-profiler fixture.
It also unwires the plumbing that only existed to carry timeline data:
`recordTimeline` across the reload-and-profile path (hook →
sessionStorage → agent → renderer), `timelineData` on
`ProfilingDataBackend` and the profile export, the `supportsTimeline`
Store config, the `rootSupportsTimelineProfiling` capability, the
`DevToolsProfilingHooks` type and the `ReactRenderer` members DevTools
used to inject it, the 40 `--color-timeline-*` theme variables in both
themes plus the orphaned `--color-scroll-caret`, and `hook.js`'s
internal-module-range tracking with its `react-devtools-facade` stubs.
`yarn.lock` is regenerated: 52 distinct package-versions and 68
requirement specs drop out, with no additions and no version changes to
anything that remains.
## Deliberate non-changes
- **`PROFILER_EXPORT_VERSION` stays at 5.**
`prepareProfilingDataFrontendFromExport` compares versions with `!==`,
so a bump would reject every profile anyone has already saved.
`timelineData` was an optional key, so dropping it is invisible in both
directions.
- **Profiling flag bit `0b010` is retired, not reused**, and the
constant is replaced by a comment saying so. Shipped backends keep
setting it, so renumbering `PROFILING_FLAG_PERFORMANCE_TRACKS_SUPPORT`
into that slot would make a new frontend misread older backends as
tracks-capable.
- **The `displayName` properties on DevTools' cache thenables are
kept.** They look timeline-only, but `ReactFiberThenable` reads
`thenable.displayName` to name I/O in async debug info, which feeds the
Performance tracks. Only their stale comments are corrected.
- **`react-reconciler`, `shared/ReactFeatureFlags.js` and
`scripts/rollup` are untouched**; `enableSchedulingProfiler` is still
live for www and native-fb.
## Follow-ups (not in this stack)
Three stale comments still name the removed package:
`scripts/rollup/wrappers.js:532` and `ReactFiberLane.js:38,125`. Left
alone to keep this stack purely DevTools-side.
## Test plan
`yarn linc`, `yarn flow dom-node`, and the DevTools suite all pass on
this commit in isolation (40/40 suites, 582 tests).
Previously, every instance of ErrorBoundary, which wraps every custom
panel in extension, was subscribing to errors from the Store. This would
report the same error for every mounted panel.
ErrorBoundary now only intercepts render-time errors, and Store errors
are captured and reported in an external subscription at the place where
Store is created.
Builds on #37048 by replacing `any`-based Bridge and Wall boundaries
with typed `mixed` values and explicit runtime validation. Invalid
messages and post-shutdown operations now throw, while shutdown reliably
flushes queued messages even if cleanup fails.
Strengthens the DevTools Bridge and Wall contracts:
- Models event dictionaries as event-to-payload maps, using `void` for
events without payloads.
- Types `send(event, payload?)` directly, eliminating runtime
payload-arity handling.
- Replaces broad `any` transport types with `mixed` and boundary
validation.
- Throws on invalid lifecycle usage instead of warning or silently
returning.
- Ensures shutdown flushes queued messages even when Wall cleanup fails.
- Updates Wall implementations and adds Bridge lifecycle coverage.
Ensures the standalone DevTools Bridge fully shuts down when its
WebSocket closes, with re-entrancy protection. Adds tests confirming
event-only shutdown leaves the Bridge active while socket closure shuts
it down.
## Summary
- Render standalone DevTools server errors with DOM nodes instead of
HTML strings.
- Preserve the existing error box classes and copy while inserting error
text with `textContent`.
## How did you test this?
- `corepack yarn prettier`
- `corepack yarn lint packages/react-devtools-core/src/standalone.js`
## Summary
Mostly changing the casting syntax from `(x: Y)` to `x as Y`, as the old
syntax was deprecated and always causing an error in Flow
## How did you test this change?
`yarn flow-ci`
## Summary
Notable changes:
- Only $FlowFixMe, $FlowExpectedError suppression comments are supported
- All suppression comments need error code
- A lot of new invalid-compare and constant-condition errors suppressed.
These errors reveal potential logical bugs
## How did you test this change?
`yarn flow-ci`
## Summary
This enables routing the React Dev Tools through a remote server by
being able to specify host, port, and path for the client to connect to.
Basically allowing the React Dev Tools server to have the client connect
elsewhere.
This setups a `clientOptions` which can be set up through environment
variables when starting the React Dev Tools server.
This change shouldn't affect the traditional usage for React Dev Tools.
EDIT: the additional change was moved to another PR
## How did you test this change?
Run React DevTools with
```
$ REACT_DEVTOOLS_CLIENT_HOST=<MY_HOST> REACT_DEVTOOLS_CLIENT_PORT=443 REACT_DEVTOOLS_CLIENT_USE_HTTPS=true REACT_DEVTOOLS_PATH=/__react_devtools__/ yarn start
```
Confirm that my application connects to the local React Dev Tools
server/instance/electron app through my remote server.
## Summary
For apps that use AMD, we need to actually `require()` the
ReactDevToolsBackend and load it from the AMD module cache. This adds a
check for the case where the `ReactDevToolsBackend` isn't defined
globally, and so we load it with `require()`.
## How did you test this change?
Tested through https://github.com/facebook/react/pull/35886
The `useOpenResource` hook is now used to open links. Currently, the
`<>` icon for the component stacks and the link in the bottom of the
components stack. But it'll also be used for many new links like stacks.
If this new option is configured, and this is a local file then this is
opened directly in the external editor. Otherwise it fallbacks to open
in the Sources tab or whatever the standalone or inline is configured to
use.
<img width="453" height="252" alt="Screenshot 2025-07-24 at 4 09 09 PM"
src="https://github.com/user-attachments/assets/04cae170-dd30-4485-a9ee-e8fe1612978e"
/>
I prominently surface this option in the Source pane to make it
discoverable.
<img width="588" height="144" alt="Screenshot 2025-07-24 at 4 03 48 PM"
src="https://github.com/user-attachments/assets/0f3a7da9-2fae-4b5b-90ec-769c5a9c5361"
/>
When this is configured, the "Open in Editor" is hidden since that's
just the default. I plan on deprecating this button to avoid having the
two buttons going forward.
Notably there's one exception where this doesn't work. When you click an
Action or Event listener it takes you to the Sources tab and you have to
open in editor from there. That's because we use the `inspect()`
mechanism instead of extracting the source location. That's because we
can't do the "throw trick" since these can have side-effects. The Chrome
debugger protocol would solve this but it pops up an annoying dialog. We
could maybe only attach the debugger only for that case. Especially if
the dialog disappears before you focus on the browser again.
In RSC and other stacks now we use a lot of `ReactFunctionLocation` type
to represent the location of a function. I.e. the location of the
beginning of the function (the enclosing line/col) that is represented
by the "Source" of the function. This is also what the parent Component
Stacks represents.
As opposed to `ReactCallSite` which is what normal stack traces and
owner stacks represent. I.e. the line/column number of the callsite into
the next function.
We can start sharing more code by using the `ReactFunctionLocation` type
to represent the component source location and it also helps clarify
which ones are function locations and which ones are callsites as we
start adding more stack traces (e.g. for async debug info and owner
stack traces).
## Summary
This tool leverages DevTools to get the component tree from the
currently open React App. This gives realtime information to agents
about the state of the app.
## How did you test this change?
Tested integration with Claude Desktop
Stacked on https://github.com/facebook/react/pull/31131. See last
commit.
This is a clean-up and a pre-requisite for next changes:
1. `ReloadAndProfileConfig` is now split into boolean value and settings
object. This is mainly because I will add one more setting soon, and
also because settings might be persisted for a longer time than the flag
which signals if the Backend was reloaded for profiling. Ideally, this
settings should probably be moved to the global Hook object, same as we
did for console patching.
2. Host is now responsible for reseting the cached values, Backend will
execute provided `onReloadAndProfileFlagsReset` callback.
Fixes https://github.com/facebook/react/issues/31100.
There are 2 things:
1. In https://github.com/facebook/react/pull/30987, we've introduced a
breaking change: importing `react-devtools-core` is no longer enough for
installing React DevTools global Hook. You need to call `initialize`, in
which you may provide initial settings. I am not adding settings here,
because it is not implemented, and there are no plans for supporting
this.
2. Calling `installHook` is not necessary inside `standalone.js`,
because this script is running inside Electron wrapper (which is just a
UI, not the app that we are debugging). We will loose the ability to use
React DevTools on this React application, but I guess thats fine.
<!--
Thanks for submitting a pull request!
We appreciate you spending the time to work on these changes. Please
provide enough information so that others can review your pull request.
The three fields below are mandatory.
Before submitting a pull request, please make sure the following is
done:
1. Fork [the repository](https://github.com/facebook/react) and create
your branch from `main`.
2. Run `yarn` in the repository root.
3. If you've fixed a bug or added code that should be tested, add tests!
4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch
TestName` is helpful in development.
5. Run `yarn test --prod` to test in the production environment. It
supports the same options as `yarn test`.
6. If you need a debugger, run `yarn test --debug --watch TestName`,
open `chrome://inspect`, and press "Inspect".
7. Format your code with
[prettier](https://github.com/prettier/prettier) (`yarn prettier`).
8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only
check changed files.
9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`).
10. If you haven't already, complete the CLA.
Learn more about contributing:
https://reactjs.org/docs/how-to-contribute.html
-->
## Summary
In preparation to support reload-to-profile in Fusebox (#31021), we need
a way to check capability of different backends, e.g. web vs React
Native.
## How did you test this change?
<!--
Demonstrate the code is solid. Example: The exact commands you ran and
their output, screenshots / videos if the pull request changes the user
interface.
How exactly did you verify that your PR solves the issue you wanted to
solve?
If you leave this empty, your PR will very likely be closed.
-->
* Default, e.g. existing web impl = no-op
* Custom impl: is called
Stacked on https://github.com/facebook/react/pull/30986.
Previously, we would call `installHook` at a top level of the JavaScript
module. Because of this, having `require` statement for
`react-devtools-core` package was enough to initialize the React
DevTools global hook on the `window`.
Now, the Hook can actually receive an argument - initial user settings
for console patching. We expose this as a function `initialize`, which
can be used by third parties (including React Native) to provide the
persisted settings.
The README was also updated to reflect the changes.
Stacked on https://github.com/facebook/react/pull/30566 and whats under
it. See [this
commit](https://github.com/facebook/react/pull/30596/commits/374fd737e4b0b7028afb765838db7c0e22def865).
It is mostly copying code from one place to another and updating tests.
With these changes, for every console method that we patch, there is
going to be a single applied patch:
- For `error`, `warn`, and `trace` we are patching when hook is
installed. This guarantees that component stacks are going to be
appended even if browser DevTools are not opened. We pay some price for
it, though: if user has browser DevTools closed and if at this point
some warning or error is emitted (logged), the next time user opens
browser DevTools, they are going to see `hook.js` as the source frame.
Unfortunately, ignore listing from source maps is not applied
retroactively, and I don't know if its a bug or just a design
limitations. Once browser DevTools are opened, source maps will be
loaded and ignore listing will be applied for all emitted logs in the
future.
- For `log`, `info`, `group`, `groupCollapsed` we are only patching when
React notifies React DevTools about running in StrictMode. We unpatch
the methods right after it.
<!--
Thanks for submitting a pull request!
We appreciate you spending the time to work on these changes. Please
provide enough information so that others can review your pull request.
The three fields below are mandatory.
Before submitting a pull request, please make sure the following is
done:
1. Fork [the repository](https://github.com/facebook/react) and create
your branch from `main`.
2. Run `yarn` in the repository root.
3. If you've fixed a bug or added code that should be tested, add tests!
4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch
TestName` is helpful in development.
5. Run `yarn test --prod` to test in the production environment. It
supports the same options as `yarn test`.
6. If you need a debugger, run `yarn test --debug --watch TestName`,
open `chrome://inspect`, and press "Inspect".
7. Format your code with
[prettier](https://github.com/prettier/prettier) (`yarn prettier`).
8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only
check changed files.
9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`).
10. If you haven't already, complete the CLA.
Learn more about contributing:
https://reactjs.org/docs/how-to-contribute.html
-->
## Summary
<!--
Explain the **motivation** for making this change. What existing problem
does the pull request solve?
-->
When debugging applications that are experiencing runaway re-rendering,
it is helpful to profile them in the React Developer Tools.
Unfortunately there is a size limit on the captured profile which can
make them impossible to inspect or save. The limitations I have found
are in `postMessage` for the Chrome extension and in the `ws` websocket
server for the standalone app.
Profiling an app that produces a large profile artifact will simply show
that no profiling data was captured and output an error in the console,
here shown for the standalone app:
```text
standalone.js:92 [React DevTools] Error with websocket connection i {target: H, type: 'error', message: 'Max payload size exceeded', error: RangeError: Max payload size exceeded
at e.exports.haveLength (/Users/rune/.npm/_npx/8ea6ac5c50…}error: RangeError: Max payload size exceeded
```
This change simply increases the max payload of the websocket server in
the standalone app so that larger profiles may be captured and
inspected.
## How did you test this change?
<!--
Demonstrate the code is solid. Example: The exact commands you ran and
their output, screenshots / videos if the pull request changes the user
interface.
How exactly did you verify that your PR solves the issue you wanted to
solve?
If you leave this empty, your PR will very likely be closed.
-->
I verified that I could capture and inspect profiling data that
previously exceeded the default limitation for a particular app
Adding `__IS_NATIVE__` global, which will be used for forking backend
implementation. Will only be set to `true` for `react-devtools-core`
package, which is used by `react-native`.
Ideally, we should name it `react-devtools-native`, and keep
`react-devtools-core` as host-agnostic.
With this change, the next release of `react-devtools-core` should
append component stack as Error object, not as string, and should add
`(<anonymous>)` suffix to component stack frames.
Before:
<img width="844" alt="Screenshot 2024-07-04 at 3 20 34 PM"
src="https://github.com/facebook/react/assets/63648/0fd8a53f-538a-4429-a4cf-c22f85a09aa8">
After:
<img width="845" alt="Screenshot 2024-07-05 at 6 08 28 PM"
src="https://github.com/facebook/react/assets/63648/7b9da13a-fa97-4581-9899-06de6fface65">
Firefox:
<img width="1338" alt="Screenshot 2024-07-05 at 6 09 50 PM"
src="https://github.com/facebook/react/assets/63648/f2eb9f2a-2251-408f-86d0-b081279ba378">
The first log doesn't get a stack because it's logged before DevTools
boots up and connects which is unfortunate.
The second log already has a stack printed by React (this is on stable)
it gets replaced by our object now.
The third and following logs don't have a stack and get one appended.
I only turn the stack into an error object if it matches what we would
emit from DevTools anyway. Otherwise we assume it's not React. Since I
had to change the format slightly to make this work, I first normalize
the stack slightly before doing a comparison since it won't be 1:1.