1022 Commits

Author SHA1 Message Date
Sebastian "Sebbie" Silbermann
0c44b96e97 [DevTools] Remove spurious warnings when creating Suspense timeline from a Transition (#36133) 2026-04-08 18:49:35 +02:00
Bodhi Russell Silberling
80b1cab397 Fix typos: occured->occurred, teh->the, accomodate->accommodate (#35616)
Fixed spelling errors in comments and error messages:
- Fixed 'occured' -> 'occurred' in ReactAsyncActions-test.js
- Fixed 'teh' -> 'the' in ReactFiberConfigDOM.js
- Fixed 'occured' -> 'occurred' in ErrorBoundary.js
- Fixed 'accomodate' -> 'accommodate' in InferMutationAliasingEffects.ts

<!--
  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?
-->

## 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.
-->
2026-03-31 16:01:58 -07:00
Ruslan Lesiutin
ed69815ceb [DevTools] feat: display subtree for Activity and dim in hidden mode (#36094)
With this change, Components panel will display subtree of the Activity.
When it is in hidden mode, the subtree will be dimmed.

Added Jest tests and a sandbox case to `react-devtools-shell`.

Demo:


https://github.com/user-attachments/assets/69a2e8d6-585d-4fcd-b57e-e9ae06d0a1b3
2026-03-23 14:29:38 +00:00
Ruslan Lesiutin
8b2e903a74 [DevTools] chore: extract getInternalReactConstants (#35986)
The test is quite naive, but worth having as additional check for
changes in this logic.
2026-03-20 14:17:15 +00:00
Ruslan Lesiutin
8f41506054 [DevTools] fix: don't show empty suspended by section (#36011)
The potential paddings and margins for the empty block are already
handled via CSS selectors.
2026-03-12 14:19:21 -07:00
Sebastian "Sebbie" Silbermann
7b5b561bd2 [DevTools] Ignore new production renderers if we already use "worse" versions of React on a page (#35994) 2026-03-11 10:26:35 +01:00
Sebastian "Sebbie" Silbermann
014138df87 [DevTools] Fix a crash when rendering a new class Component when simulating errored state (#35985) 2026-03-10 18:05:48 +01:00
fre$h
4610359651 [DevTools] Fix null ref crash in ContextMenu when items list is empty (#35929)
Co-authored-by: Sebastian Sebbie Silbermann <sebastian.silbermann@vercel.com>
2026-03-05 16:52:23 +01:00
Ruslan Lesiutin
aac12ce597 [DevTools] chore: extract pure functions from fiber/renderer.js (#35924)
I am in a process of splitting down the renderer implementation into
smaller units of logic that can be reused. This change is about
extracting pure functions only.
2026-03-03 12:27:05 +00:00
Sebastian "Sebbie" Silbermann
93a3935d02 [DevTools] Only schedule a single update per Supense when changing timeline (#35927) 2026-03-03 12:21:46 +01:00
Sebastian "Sebbie" Silbermann
3a2bee26d2 [DevTools] Fix alignment of breadcrumbs separator (#35817) 2026-02-18 10:53:49 -08:00
Ruslan Lesiutin
03ca38e6e7 [DevTools] Check suspense child node presence in parentSuspense.children before removing (#35775)
Currently, this silently removes the last child in the list, which
doesn't contain the `id`.
2026-02-13 15:33:22 +00:00
Sebastian "Sebbie" Silbermann
6066c782fe [DevTools] Dedicated empty state for roots that aren't suspended by anything (#35769) 2026-02-12 17:48:02 +01:00
Sebastian "Sebbie" Silbermann
705055d7ac [DevTools] Enable Suspense tab by default (#35768) 2026-02-12 16:50:29 +01:00
Ruslan Lesiutin
8374c2abf1 [DevTools] Remove experimental __IS_INTERNAL_MCP_BUILD__ flag and related code (#35755)
This is unused.
2026-02-11 16:59:43 +00:00
Sebastian "Sebbie" Silbermann
e49335e961 [DevTools] Display React.optimisticKey in key positions (#35760) 2026-02-11 00:35:36 +01:00
Sebastian "Sebbie" Silbermann
57b79b0388 [DevTools] Only block child Suspense boundaries if the parent has all shared suspenders removed (#35737) 2026-02-10 17:52:35 +01:00
Sebastian "Sebbie" Silbermann
70890e7c58 Consistent handling of work tags for rename, delete, and overriding state (#35740)
Co-authored-by: Ruslan Lesiutin <28902667+hoxyq@users.noreply.github.com>
2026-02-10 16:35:02 +01:00
Sebastian "Sebbie" Silbermann
f23aa1d9f5 [DevTools] Fix memory leak when unmounting hoistables (#35741) 2026-02-10 13:09:23 +01:00
Sebastian "Sebbie" Silbermann
49c3b270f9 [test] Include uniqueSuspenders in Suspense tree snapshots (#35736) 2026-02-10 12:51:58 +01:00
Ruslan Lesiutin
c6bb26bf83 [DevTools] Don't capture durations for disconnected subtrees when profiling (#35718)
After https://github.com/facebook/react/pull/34089, when updating
(possibly, mounting) inside disconnected subtree, we don't record this
as an operation. This only happens during reconnect. The issue is that
`recordProfilingDurations()` can be called, which diffs tree base
duration and reports it to the Frontend:

65db1000b9/packages/react-devtools-shared/src/backend/fiber/renderer.js (L4506-L4521)

This operation can be recorded before the "Add" operation, and it will
not be resolved properly on the Frontend side.

Before the fix:
```
commit tree › Suspense › should handle transitioning from fallback back to content during profiling

    Could not clone the node: commit tree does not contain fiber "5". This is a bug in React DevTools.

      162 |     const existingNode = nodes.get(id);
      163 |     if (existingNode == null) {
    > 164 |       throw new Error(
          |             ^
      165 |         `Could not clone the node: commit tree does not contain fiber "${id}". This is a bug in React DevTools.`,
      166 |       );
      167 |     }

      at getClonedNode (packages/react-devtools-shared/src/devtools/views/Profiler/CommitTreeBuilder.js:164:13)
      at updateTree (packages/react-devtools-shared/src/devtools/views/Profiler/CommitTreeBuilder.js:348:24)
      at getCommitTree (packages/react-devtools-shared/src/devtools/views/Profiler/CommitTreeBuilder.js:112:20)
      at ProfilingCache.getCommitTree (packages/react-devtools-shared/src/devtools/ProfilingCache.js:40:46)
      at Object.<anonymous> (packages/react-devtools-shared/src/__tests__/profilingCommitTreeBuilder-test.js:257:44)
```
2026-02-09 22:18:17 +00:00
Sebastian "Sebbie" Silbermann
6a939d0b54 [DevTools] Allow renaming Host Component props (#35735) 2026-02-09 23:14:46 +01:00
Sebastian "Sebbie" Silbermann
4c9d62d2b4 [DevTools] Fix crash when revealing stable, filtered <Activity> children (#35734) 2026-02-09 22:52:24 +01:00
Ruslan Lesiutin
24f215ce8b [DevTools] Fix false-positive re-render reports for filtered nodes (#35723)
Fixes https://github.com/facebook/react/issues/33423,
https://github.com/facebook/react/issues/35245,
https://github.com/facebook/react/issues/19732.

As demoed
[here](https://github.com/facebook/react/issues/33423#issuecomment-2970750588),
React DevTools incorrectly highlights re-renders for descendants of
filtered-out nodes that didn't actually render.

There were multiple fixes suggesting changes in `didFiberRender()`
function, but these doesn't seem right, because this function is used in
a context of whether the Fiber actually rendered something (updated),
not re-rendered compared to the previous Fiber.

Instead, this PR adds additional validation at callsites that either
used for highlighting re-renders or capturing tree base durations and
are relying on `didFiberRender`. I've also added a few tests that
reproduce the failure scenario. Without the changes, the tests are
failing.
2026-02-09 20:39:33 +00:00
Sebastian "Sebbie" Silbermann
eab523e2a9 [Fiber] Avoid duplicate debug info for array children (#35733) 2026-02-09 20:36:56 +01:00
Sebastian "Sebbie" Silbermann
65db1000b9 [test] Move profilingCommitTreeBuilder to versioned renderer (#35711) 2026-02-06 16:00:43 +01:00
Sebastian "Sebbie" Silbermann
2a879cdc95 [DevTools] Fix broken commit tree builder for initial operations (#35710) 2026-02-06 15:16:23 +01:00
Sebastian "Sebbie" Silbermann
1c66ac740c [DevTools] Separate breadcrumbs with » (#35705) 2026-02-06 00:40:31 +01:00
Sebastian "Sebbie" Silbermann
8b276df415 [DevTools] Avoid scrollbars in Suspense breadcrumbs (#35700) 2026-02-05 23:27:57 +01:00
Ruslan Lesiutin
b9323509be [DevTools] Throw an error when attempting to clone non-existent node (#35702)
There is an existing issue with serialisation logic for the traces from
Profiler panel.

I've discovered that `TREE_OPERATION_UPDATE_TREE_BASE_DURATION`
operation for some reason appears earlier in a sequence of operations,
before the `TREE_OPERATION_ADD` that registers the new node. It ends up
cloning non-existent node, which just creates an empty object and adds
it to the map of nodes.

This change only adds additional layer of validation to cloning logic,
so we don't swallow the error, if we attempt to clone non-existent node.
2026-02-05 17:49:18 +00:00
Sebastian "Sebbie" Silbermann
bb53387716 [DevTools] Shrink/Deshrink Owners breadcrumbs on any resizes (#35694) 2026-02-05 12:08:02 +01:00
Sebastian "Sebbie" Silbermann
c9ff56ec74 [DevTools] Disable Activity slices by default (#35685) 2026-02-04 10:56:33 +01:00
Ruslan Lesiutin
5dad2b47b8 [DevTools] Fix commit index reset when switching profiler roots (#35672)
Fixes https://github.com/facebook/react/issues/31463,
https://github.com/facebook/react/issues/30114.

When switching between roots in the profiler flamegraph, the commit
index was preserved from the previous root. This caused an error
"Invalid commit X. There are only Y commits." when the new root had
fewer commits than the selected index.

This fix resets the commit index to 0 (or null if no commits) when the
commitData changes, which happens when switching roots.
2026-02-03 12:44:04 +00:00
Sebastian "Sebbie" Silbermann
3e319a943c [DevTools] Apply component filters on initial load (#35587) 2026-01-26 11:06:04 +01:00
Sebastian "Sebbie" Silbermann
2c30ebc4e3 [DevTools] Update inspected element on component filter changes (#35599) 2026-01-26 11:04:06 +01:00
Sebastian "Sebbie" Silbermann
bef88f7c11 [DevTools] Stop setting unused global variables (#35532) 2026-01-16 16:13:29 +01:00
Sebastian "Sebbie" Silbermann
01c4d03d84 [DevTools] Clear element inspection if host element not owned by any renderer is selected (#35504) 2026-01-16 13:20:44 +01:00
Sebastian "Sebbie" Silbermann
cbc4d40663 Typecheck React DevTools extension main script (#35519) 2026-01-16 13:08:28 +01:00
Sebastian "Sebbie" Silbermann
bb8a76c6cc [DevTools] Show fallback in inspected element pane when no element is selected (#35503) 2026-01-15 14:28:02 +01:00
Sebastian "Sebbie" Silbermann
fae15df40e [DevTools] Add React Element pane to browser Elements panel (#35240) 2026-01-15 13:24:06 +01:00
Błażej Kustra
53daaf5aba Improve the detection of changed hooks (#35123)
## Summary

cc @hoxyq 

Fixes https://github.com/facebook/react/issues/28584. Follow up to PR:
https://github.com/facebook/react/pull/34547

This PR updates getChangedHooksIndices to account for the fact that
`useSyncExternalStore`, `useTransition`, `useActionState`,
`useFormState` internally mounts more than one hook while DevTools
should treat it as a single user-facing hook.

Approach idea came from
[this](https://github.com/facebook/react/pull/34547#issuecomment-3504113776)
comment 😄

Before:


https://github.com/user-attachments/assets/6bd5ce80-8b52-4bb8-8bb1-5e91b1e65043


After:


https://github.com/user-attachments/assets/47f56898-ab34-46b6-be7a-a54024dcefee



## How did you test this change?

I used this component to reproduce this issue locally (I followed
instructions in `packages/react-devtools/CONTRIBUTING.md`).

<details><summary>Details</summary>

```ts

import * as React from 'react';

function useDeepNestedHook() {
  React.useState(0); // 1
  return React.useState(1); // 2
}

function useNestedHook() {
  const deepState = useDeepNestedHook();
  React.useState(2); // 3
  React.useState(3); // 4

  return deepState;
}

// Create a simple store for useSyncExternalStore
function createStore(initialValue) {
  let value = initialValue;
  const listeners = new Set();
  return {
    getSnapshot: () => value,
    subscribe: listener => {
      listeners.add(listener);
      return () => {
        listeners.delete(listener);
      };
    },
    update: newValue => {
      value = newValue;
      listeners.forEach(listener => listener());
    },
  };
}

const syncExternalStore = createStore(0);

export default function InspectableElements(): React.Node {
  const [nestedState, setNestedState] = useNestedHook();

  // 5
  const syncExternalValue = React.useSyncExternalStore(
    syncExternalStore.subscribe,
    syncExternalStore.getSnapshot,
  );

  // 6
  const [isPending, startTransition] = React.useTransition();

  // 7
  const [formState, formAction, formPending] = React.useActionState(
    async (prevState, formData) => {
      return {count: (prevState?.count || 0) + 1};
    },
    {count: 0},
  );

  const handleTransition = () => {
    startTransition(() => {
      setState(Math.random());
    });
  };

  // 8
  const [state, setState] = React.useState('test');

  return (
    <>
      <div
        style={{
          padding: '20px',
          display: 'flex',
          flexDirection: 'column',
          gap: '10px',
        }}>
        <div
          onClick={() => setNestedState(Math.random())}
          style={{backgroundColor: 'red', padding: '10px', cursor: 'pointer'}}>
          State: {nestedState}
        </div>

        <button onClick={handleTransition} style={{padding: '10px'}}>
          Trigger Transition {isPending ? '(pending...)' : ''}
        </button>

        <div style={{display: 'flex', gap: '10px', alignItems: 'center'}}>
          <button
            onClick={() => syncExternalStore.update(syncExternalValue + 1)}
            style={{padding: '10px'}}>
            Trigger useSyncExternalStore
          </button>
          <span>Value: {syncExternalValue}</span>
        </div>

        <form
          action={formAction}
          style={{display: 'flex', gap: '10px', alignItems: 'center'}}>
          <button
            type="submit"
            style={{padding: '10px'}}
            disabled={formPending}>
            Trigger useFormState {formPending ? '(pending...)' : ''}
          </button>
          <span>Count: {formState.count}</span>
        </form>

        <div
          onClick={() => setState(Math.random())}
          style={{backgroundColor: 'red', padding: '10px', cursor: 'pointer'}}>
          State: {state}
        </div>
      </div>
    </>
  );
}
```


</details>

---------

Co-authored-by: Ruslan Lesiutin <28902667+hoxyq@users.noreply.github.com>
2026-01-15 11:06:14 +00:00
Sebastian "Sebbie" Silbermann
8a83073753 [test] Fix DevTools regression tests (#35501) 2026-01-13 16:00:16 +01:00
Sebastian "Sebbie" Silbermann
5aec1b2a8d [DevTools] Attach async info in filtered fallback to parent of Suspense (#35456) 2026-01-10 11:33:48 +01:00
lauren
00908be9ff [ci] Increase DevTools test shards and bump timeout (#35459)
[ci] Increase DevTools test shards and bump timeout

- Increase DevTools test shards from 3 to 5
- Bump timeout to 20s

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35459).
* #35458
* __->__ #35459
2026-01-06 21:23:05 -05:00
emily8rown
bcf97c7564 Devtools disable log dimming strict mode setting (#35207)
<!--

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`).

-->

## Summary

Currently, every second console log is dimmed, receiving a special style
that indicates to user that it was raising because of [React Strict
Mode](https://react.dev/reference/react/StrictMode) second rendering.
This introduces a setting to disable this.

## How did you test this change?
Test in console-test.js


https://github.com/user-attachments/assets/af6663ac-f79b-4824-95c0-d46b0c8dec12

Browser extension react devtools


https://github.com/user-attachments/assets/7e2ecb7a-fbdf-4c72-ab45-7e3a1c6e5e44

React native dev tools:


https://github.com/user-attachments/assets/d875b3ac-1f27-43f8-8d9d-12b2d65fa6e6

---------

Co-authored-by: Ruslan Lesiutin <28902667+hoxyq@users.noreply.github.com>
2025-12-15 13:41:43 +00:00
Ruslan Lesiutin
37bcdcde04 fix[devtools]: feature-check document with typeof instead of direct reference (#35343)
Follow-up to https://github.com/facebook/react/pull/35296.

We can get `ReferenceError` if this is unavailable. Using `typeof` check
instead for safety.
2025-12-11 12:15:00 +00:00
Ruslan Lesiutin
5a970933c0 fix[devtools]: feature-check structure stack trace methods (#35293)
`Error.prepareStackTrace` is non-standard feature and not all JavaScript
runtimes implement the methods that we are using in React DevTools
backend.

This PR adds additional checks for the presence of the methods that we
are using.
2025-12-10 19:21:54 +00:00
Ruslan Lesiutin
5d80124345 fix[devtools]: still show overlay, if getClientRects is not implemented (#35294)
Follow-up to https://github.com/facebook/react/pull/34653.

React Native doesn't implement `getClientRect`, since this is applicable
to CSS box, which is not a concept for Native (maybe yet).

I am loosening the condition that gates `showOverlay()` call to pass if
`getClientRect` is not implemented.

Conceptually, everything that is inside `react-devtools-shared/backend`
should be Host-agnostic, because both on Web and Native it is installed
inside the Host JavaScript runtime, be it main frame of the page, or RN
instance. Since overlay & highlighting logic also lives there, it should
also follow these principles.
2025-12-10 19:21:28 +00:00
emily8rown
d763f3131e [Devtools] Navigating commits performance panel hotkey (#35238)
## Summary
Add keyboard shortcuts (Cmd/Ctrl + Left/Right arrow keys) to navigate
between commits in the Profiler's snapshot view.

Moved `filteredCommitIndices` management and commit navigation logic
(`selectNextCommitIndex`, `selectPrevCommitIndex`) from
`SnapshotSelector` into `useCommitFilteringAndNavigation` used by
`ProfilerContext` to enable keyboard shortcuts from the top-level
Profiler component.

## How did you test this change?
- New tests in ProfilerContext-tests
- Built browser extension: `yarn build:<browser name>`
- tested in browser: `yarn run test:<browser name>`
- Manually verified Left/Right arrow navigation cycles through commits
- Verified navigation respects commit duration filter
- Verified reload-and-profile button unaffected

Chrome:


https://github.com/user-attachments/assets/01d2a749-13dc-4d08-8bcb-3d4d45a5f97c

Edge with duration filter:


https://github.com/user-attachments/assets/a7f76ff7-2a0b-4b9c-a0ce-d4449373308b

firefox mixing hotkey with clicking arrow buttons:


https://github.com/user-attachments/assets/48912d68-7c75-40f2-a203-5e6d7e6b2d99
2025-12-10 13:07:35 +00:00
Ruslan Lesiutin
ad5971febd fix[devtools]: no-op unsupported backend bridge events (#35296)
Follow-up to https://github.com/facebook/react/pull/34641.
Similar to https://github.com/facebook/react/pull/35293,
https://github.com/facebook/react/pull/35294.

React DevTools backend can be used in non-DOM environments, so we have
to feature-check some DOM APIs.
For now I am just no-oping newly added commands for Native, we should
revisit this decision once we would roll out Suspense panel there, if
needed. I am not sure if scrolling will be required as much as it is
needed on Web.

`isReactNativeEnvironment()` check is kinda clowny, but we've been
relying on it for quite some time already.
2025-12-05 16:41:58 +00:00