import typeof ReactTestRenderer from 'react-test-renderer';
import type {Element} from 'react-devtools-shared/src/frontend/types';
import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
import type Store from 'react-devtools-shared/src/devtools/store';

import {getVersionedRenderImplementation} from './utils';

describe('OwnersListContext', () => {
  let React;
  let TestRenderer: ReactTestRenderer;
  let bridge: FrontendBridge;
  let store: Store;
  let utils;

  let BridgeContext;
  let Own

lobal.store;
    store.collapseNodesByDefault = false;

    React = require('react');
    TestRenderer = utils.requireTestRenderer();

    BridgeContext =
      require('react-devtools-shared/src/devtools/views/context').BridgeContext;
    OwnersListContex

ersListContext;
  let OwnersListContextController;
  let StoreContext;
  let TreeContextController;

  beforeEach(() => {
    utils = require('./utils');
    utils.beforeEachProfiling();

    bridge = global.bridge;
    store = g


se strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.Component = Component;

var _react = require("react");

/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 *
 */
const A = /*#__PURE__*/(0, _react.createContext)(1);
const B = /*#__PURE__*/(0, _react.createContext)(2);

function Component() {
  const a = (0, _react.useContext)(A);
  c

react.useContext)(B); // prettier-ignore

  const c = (0, _react.useContext)(A),
        d = (0, _react.useContext)(B); // eslint-disable-line one-var

  return a + b + c + d;
}
//# sourceMappingURL=ComponentWithMultipleHooksPerLine.js.map?foo=bar&param=so


exports, "ComponentUsingHooksIndirectly", {
  enumerable: true,
  get: function () {
    return _ComponentUsingHooksIndirectly.Component;
  }
});
Object.defineProperty(exports, "ComponentWithCustomHook", {
  enumerable: true,
  get: function () {
    return _ComponentWithCustomHook.Component;
  }
});
Object.defineProperty(exports, "ComponentWithExternalCustomHooks", {
  enumerable: true,
  get: function () {
    return _ComponentWithExternalCustomHooks.Component;
  }
});
Object.defineProperty(exports, "Comp

unction () {
    return _ComponentWithNestedHooks.Component;
  }
});
Object.defineProperty(exports, "ContainingStringSourceMappingURL", {
  enumerable: true,
  get: function () {
    return _ContainingStringSourceMappingURL.Component;
  }
});
Object.define

onentWithMultipleHooksPerLine", {
  enumerable: true,
  get: function () {
    return _ComponentWithMultipleHooksPerLine.Component;
  }
});
Object.defineProperty(exports, "ComponentWithNestedHooks", {
  enumerable: true,
  get: f


 MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import {
  getVersionedRenderImplementation,
  normalizeCodeLocInfo,
} from 'react-devtools-shared/src/__tests__/utils';

describe('component stack', () => {
  let React;
  let act;
  let supportsOwnerStacks;

  beforeEach(() => {
    const utils = require('./utils');
    act = utils.act;

    React = require('react');
    if (
      React.version.startsWith('19') &&
      React.version.includes('experiment

   const Grandparent = () => <Parent />;
    const Parent = () => <Child />;
    const Child = () => {
      console.error('Test error.');
      console.warn('Test warning.');
      return null;
    };

    act(() => render(<Grandparent />));

    expect(

al')
    ) {
      supportsOwnerStacks = true;
    }
  });

  const {render} = getVersionedRenderImplementation();

  // @reactVersion >=16.9
  it('should log the current component stack along with an error or warning', () => {


 MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */
import {getVersionedRenderImplementation} from './utils';

describe('Store React.optimisticKey', () => {
  let act;
  let actAsync;
  let React;
  let TestRenderer;
  let bridge;
  let store;

  let BridgeContext;
  let StoreContext;
  let TreeContext;

  let dispatch;
  let state;

  beforeAll(() => {
    // JSDDOM doesn't implement getClientRects so we're just faking one for testing purposes
    Element.pr

=> {
    global.IS_REACT_ACT_ENVIRONMENT = true;

    store = global.store;
    bridge = global.bridge;

    React = require('react');

    const utils = require('./utils');
    act = utils.act;
    actAsync = utils.actAsync;
    TestRenderer = utils.requi

ototype.getClientRects = function (this: Element) {
      const textContent = this.textContent;
      return [
        new DOMRect(1, 2, textContent.length, textContent.split('\n').length),
      ];
    };
  });

  beforeEach(()


 MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import {getVersionedRenderImplementation} from './utils';

describe('Profiler change descriptions', () => {
  let React;
  let store;
  let utils;

  beforeEach(() => {
    utils = require('./utils');
    utils.beforeEachProfiling();

    store = global.store;
    store.collapseNodesByDefault = false;
    store.recordChangeDescriptions = true;

    React = require('react');
  });

  const {render} = getVers

ntext(Context);
      return context;
    }

    function areEqual() {
      return true;
    }

    const MemoizedChild = React.memo(Child, areEqual);
    const ForwardRefChild = React.forwardRef(
      function RefForwardingComponent(props, ref) {

ionedRenderImplementation();

  // @reactVersion >=18.0
  it('should identify useContext as the cause for a re-render', () => {
    const Context = React.createContext(0);

    function Child() {
      const context = React.useCo


Types = require('prop-types');
    React = require('react');
  });

  const {render} = getVersionedRenderImplementation();

  describe('props', () => {
    let committedClassProps;
    let committedFunctionProps;
    let inputRef;
    let classID;
    let functionID;
    let hostComponentID;

    async function mountTestApp() {
      class ClassComponent extends React.Component {
        componentDidMount() {
          committedClassProps = this.props;
        }
        componentDidUpdate() {
          comm

  });
        return null;
      }

      inputRef = React.createRef(null);

      await utils.actAsync(() =>
        render(
          <>
            <ClassComponent
              array={[1, 2, 3]}
              object={{nested: 'initial'}}

ittedClassProps = this.props;
        }
        render() {
          return null;
        }
      }

      function FunctionComponent(props) {
        React.useLayoutEffect(() => {
          committedFunctionProps = props;


 = Scheduler.unstable_clearYields;
        const InternalTestUtils = require('internal-test-utils');
        assertLog = InternalTestUtils.assertLog;

        // polyfill waitFor as Scheduler.toFlushAndYieldThrough
        waitFor = expectedYields => {
          let actualYields = Scheduler.unstable_clearYields();
          if (actualYields.length !== 0) {
            throw new Error(
              'Log of yielded values is not empty. ' +
                'Call expect(Scheduler).toHaveYielded(...) first.',

  } else {
        const InternalTestUtils = require('internal-test-utils');
        assertLog = InternalTestUtils.assertLog;
        waitFor = InternalTestUtils.waitFor;
      }

      setPerformanceMock =
        require('react-devtools-shared/src/backen

           );
          }
          Scheduler.unstable_flushNumberOfYields(expectedYields.length);
          actualYields = Scheduler.unstable_clearYields();
          expect(actualYields).toEqual(expectedYields);
        };


const {printOwnersList} = require('../devtools/utils');
const {getVersionedRenderImplementation} = require('./utils');

describe('Store owners list', () => {
  let React;
  let act;
  let store;

  beforeEach(() => {
    store = global.store;
    store.collapseNodesByDefault = false;

    React = require('react');

    const utils = require('./utils');
    act = utils.act;
  });

  const {render} = getVersionedRenderImplementation();

  function getFormattedOwnersList(elementID) {
    const ownersList = sto

      </Intermediate>
    );
    const Wrapper = ({children}) => children;
    const Leaf = () =>
Leaf
;
    const Intermediate = ({children}) => <Wrapper>{children}</Wrapper>;

    act(() => render(<Root />));
    expect(store).toMatch

re.getOwnersListForElement(elementID);
    return printOwnersList(ownersList);
  }

  it('should drill through intermediate components', () => {
    const Root = () => (
      <Intermediate>
        <div>
          <Leaf />


;
    const E = () => 'e';
    const X = () => 'x';
    const a = <A key="a" />;
    const b = <B key="b" />;
    const c = <C key="c" />;
    const d = <D key="d" />;
    const e = <E key="e" />;

    function Parent({children}) {
      return children;
    }

    // 1. Render a normal version of [a, b, c, d, e].
    let container = document.createElement('div');
    let root = ReactDOMClient.createRoot(container);
    act(() => root.render(<Parent>{[a, b, c, d, e]}</Parent>));
    expect(store).toMatchInl

 const snapshotForABCDE = print(store);

    // 2. Render a version where <C /> renders an <X /> child instead of 'c'.
    // This is how we'll test an update to a single component.
    act(() => {
      setShowX(true);
    });
    expect(store).toMatchInl

ineSnapshot(`
      [root]
        ▾ <Parent>
            <A key="a">
            <B key="b">
            <C key="c">
            <D key="d">
            <E key="e">
    `);
    expect(container.textContent).toMatch('abcde');


import type Store from 'react-devtools-shared/src/devtools/store';

import {getVersionedRenderImplementation} from './utils';

describe('ProfilerStore', () => {
  let React;
  let store: Store;
  let utils;

  beforeEach(() => {
    global.IS_REACT_ACT_ENVIRONMENT = true;

    utils = require('./utils');
    utils.beforeEachProfiling();

    store = global.store;
    store.collapseNodesByDefault = false;
    store.recordChangeDescriptions = true;

    React = require('react');
  });

  const {render, unmoun

async () => {
    const Parent = ({count}) =>
      new Array(count)
        .fill(true)
        .map((_, index) => <Child key={index} duration={index} />);
    const Child = () =>
Hi!
;

    utils.act(() => {
      render(<Parent key="A" count=

t} = getVersionedRenderImplementation();
  const {render: renderOther, unmount: unmountOther} =
    getVersionedRenderImplementation();

  // @reactVersion >= 16.9
  it('should not remove profiling data when roots are unmounted',


: Store;
  let utils;

  beforeEach(() => {
    utils = require('./utils');
    utils.beforeEachProfiling();

    store = global.store;
    store.collapseNodesByDefault = false;
    store.recordChangeDescriptions = true;

    React = require('react');
    Scheduler = require('scheduler');
  });

  const {render} = getVersionedRenderImplementation();

  function getFlamegraphChartData(rootID, commitIndex) {
    const commitTree = store.profilerStore.profilingCache.getCommitTree({
      commitIndex,
      roo

tRankedChartData(rootID, commitIndex) {
    const commitTree = store.profilerStore.profilingCache.getCommitTree({
      commitIndex,
      rootID,
    });
    const chartData = store.profilerStore.profilingCache.getRankedChartData({
      commitIndex,

tID,
    });
    const chartData = store.profilerStore.profilingCache.getFlamegraphChartData(
      {
        commitIndex,
        commitTree,
        rootID,
      },
    );
    return {commitTree, chartData};
  }

  function ge


 MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import {
  getLegacyRenderImplementation,
  getModernRenderImplementation,
} from './utils';

describe('profiling HostRoot', () => {
  let React;
  let Scheduler;
  let store;
  let utils;
  let getEffectDurations;
  let effectDurations;
  let passiveEffectDurations;

  beforeEach(() => {
    utils = require('./utils');
    utils.beforeEachProfiling();

    getEffectDurations = require('../backend/utils').g

.beforEach()
    // The hook is installed as a read-only property on the window,
    // so for our test purposes we can just override the commit hook.
    const hook = global.__REACT_DEVTOOLS_GLOBAL_HOOK__;
    hook.onPostCommitFiberRoot = function onPostC

etEffectDurations;

    store = global.store;

    React = require('react');
    Scheduler = require('scheduler');

    effectDurations = [];
    passiveEffectDurations = [];

    // This is the DevTools hook installed by the env


t(() => render(<div />));
    expect(store).toMatchInlineSnapshot(`[root]`);
  });

  // This test is not the same cause as what's reported on GitHub,
  // but the resulting behavior (owner mounting after descendant) is the same.
  // Thec ase below is admittedly contrived and relies on side effects.
  // I'mnot yet sure of how to reduce the GitHub reported production case to a test though.
  // See https://github.com/facebook/react/issues/21445
  // @reactVersion >= 18.0
  it('should handle when a componen

     return Dynamic;
    };
    const Child = () => null;

    await act(() =>
      render(
        <>
          <React.Suspense fallback="Loading...">
            <Owner />
          </React.Suspense>
          <Parent />
        </>,
      ),
    );

t mounts before its owner', async () => {
    const promise = new Promise(resolve => {});

    let Dynamic = null;
    const Owner = () => {
      Dynamic = <Child />;
      readValue(promise);
    };
    const Parent = () => {


iates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import type Store from 'react-devtools-shared/src/devtools/store';

import {getVersionedRenderImplementation} from './utils';

describe('Store forcing errors', () => {
  let React;
  let agent;
  let store: Store;
  let utils;
  let actAsync;

  beforeEach(() => {
    agent = global.agent;
    store = global.store;
    store.collapseNodesByDefault = false;

();

  // @reactVersion >= 18.0
  it('resets forced error and fallback states when filters are changed', async () => {
    class AnyClassComponent extends React.Component {
      render() {
        return this.props.children;
      }
    }

    class Error

    store.componentFilters = [];
    store.recordChangeDescriptions = true;

    React = require('react');
    utils = require('./utils');

    actAsync = utils.actAsync;
  });

  const {render} = getVersionedRenderImplementation


e
  it('should handle a stress test with different tree operations (Legacy Mode)', () => {
    let setShowX;
    const A = () => 'a';
    const B = () => 'b';
    const C = () => {
      // We'll be manually flipping this component back and forth in the test.
      // We only do this for a single node in order to verify that DevTools
      // can handle a subtree switching alternates while other subtrees are memoized.
      const [showX, _setShowX] = React.useState(false);
      setShowX = _setShowX;

 const e = <E key="e" />;

    function Parent({children}) {
      return children;
    }

    // 1. Render a normal version of [a, b, c, d, e].
    act(() => render(<Parent>{[a, b, c, d, e]}</Parent>));
    expect(store).toMatchInlineSnapshot(`
      [roo

return showX ? <X /> : 'c';
    };
    const D = () => 'd';
    const E = () => 'e';
    const X = () => 'x';
    const a = <A key="a" />;
    const b = <B key="b" />;
    const c = <C key="c" />;
    const d = <D key="d" />;


on}) => {
      Scheduler.unstable_advanceTime(duration);
      return null;
    };
    const MemoizedChild = React.memo(Child);

    const RootA = ({children}) => children;
    const RootB = ({children}) => children;
    const RootC = ({children}) => children;

    const containerA = document.createElement('div');
    const containerB = document.createElement('div');
    const containerC = document.createElement('div');

    utils.act(() =>
      legacyRender(
        <RootA>
          <Parent count={2} />

rStore.startProfiling());
    utils.act(() =>
      legacyRender(
        <RootA>
          <Parent count={3} />
        </RootA>,
        containerA,
      ),
    );
    utils.act(() =>
      legacyRender(
        <RootC>
          <Parent count={1} />

        </RootA>,
        containerA,
      ),
    );
    utils.act(() =>
      legacyRender(
        <RootB>
          <Parent count={1} />
        </RootB>,
        containerB,
      ),
    );
    utils.act(() => store.profile


import type Store from 'react-devtools-shared/src/devtools/store';

import {getVersionedRenderImplementation} from './utils';

describe('commit tree', () => {
  let React = require('react');
  let Scheduler;
  let store: Store;
  let utils;

  beforeEach(() => {
    utils = require('./utils');
    utils.beforeEachProfiling();

    store = global.store;
    store.collapseNodesByDefault = false;
    store.recordChangeDescriptions = true;

    React = require('react');
    Scheduler = require('scheduler');
  }

e(10);
      return new Array(count)
        .fill(true)
        .map((_, index) => <Child key={index} />);
    };
    const Child = React.memo(function Child() {
      Scheduler.unstable_advanceTime(2);
      return null;
    });

    utils.act(() => stor

);

  const {render} = getVersionedRenderImplementation();

  // @reactVersion >= 16.9
  it('should be able to rebuild the store tree for each commit', () => {
    const Parent = ({count}) => {
      Scheduler.unstable_advanceTim


tent;
      return [
        new DOMRect(1, 2, textContent.length, textContent.split('\n').length),
      ];
    };
  });

  beforeEach(() => {
    agent = global.agent;
    bridge = global.bridge;
    store = global.store;
    store.collapseNodesByDefault = false;
    store.componentFilters = [];
    store.recordChangeDescriptions = true;

    React = require('react');
    Types = require('react-devtools-shared/src/frontend/types');
    utils = require('./utils');

    actAsync = utils.actAsync;
  });

  c

xpect(() => (store.componentFilters = [])).toThrow(
      'Cannot modify filter preferences while profiling',
    );
  });

  // @reactVersion >= 16.0
  it('should support filtering by element type', async () => {
    class ClassComponent extends React.Com

onst {render} = getVersionedRenderImplementation();

  // @reactVersion >= 16.0
  it('should throw if filters are updated while profiling', async () => {
    await actAsync(async () => store.profilerStore.startProfiling());
    e


ared/src/devtools/views/Profiler/ProfilerContext').ProfilerContext;
    ProfilerContextController =
      require('react-devtools-shared/src/devtools/views/Profiler/ProfilerContext').ProfilerContextController;
    StoreContext =
      require('react-devtools-shared/src/devtools/views/context').StoreContext;
    TreeContextController =
      require('react-devtools-shared/src/devtools/views/Components/TreeContext').TreeContextController;
    TreeDispatcherContext =
      require('react-devtools-shared/src/de

plementation();

  const Contexts = ({
    children = null,
    defaultInspectedElementID = null,
    defaultInspectedElementIndex = null,
  }: any) => (
    <BridgeContext.Provider value={bridge}>
      <StoreContext.Provider value={store}>
        <TreeC

vtools/views/Components/TreeContext').TreeDispatcherContext;
    TreeStateContext =
      require('react-devtools-shared/src/devtools/views/Components/TreeContext').TreeStateContext;
  });

  const {render} = getVersionedRenderIm


import {CustomConsole} from '@jest/console';

import type {
  BackendBridge,
  FrontendBridge,
} from 'react-devtools-shared/src/bridge';

const {getTestFlags} = require('../../../../scripts/jest/TestFlags');

// Argument is serialized when passed from jest-cli script through to setupTests.
const compactConsole = process.env.compactConsole === 'true';
if (compactConsole) {
  const formatter = (type, message) => {
    switch (type) {
      case 'error':
        return '\x1b[31m' + message + '\x1b[0m';

stToFail = async (callback, error) => {
  if (callback.length > 0) {
    throw Error(
      'Gated test helpers do not support the `done` callback. Return a ' +
        'promise instead.',
    );
  }
  try {
    const maybePromise = callback();
    if (

case 'warn':
        return '\x1b[33m' + message + '\x1b[0m';
      case 'log':
      default:
        return message;
    }
  };

  global.console = new CustomConsole(process.stdout, process.stderr, formatter);
}

const expectTe


 MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
'use strict';

const semver = require('semver');

let shouldPass;
let isFocused;
describe('transform-react-version-pragma', () => {
  const originalTest = test;

  // eslint-disable-next-line no-unused-vars
  const _test_react_version = (range, testName, cb) => {
    originalTest(testName, (...args) => {
      shouldPass = !!semver.satisfies('18.0.0', range);
      return cb(...args);
    });
  };

  // eslint-disable-n

rgs);
    });
  };

  // eslint-disable-next-line no-unused-vars
  const _test_ignore_for_react_version = (testName, cb) => {
    originalTest(testName, (...args) => {
      shouldPass = false;
      return cb(...args);
    });
  };

  beforeEach(() => {

ext-line no-unused-vars
  const _test_react_version_focus = (range, testName, cb) => {
    originalTest(testName, (...args) => {
      shouldPass = !!semver.satisfies('18.0.0', range);
      isFocused = true;
      return cb(...a


import {getVersionedRenderImplementation} from './utils';

describe('useEditableValue', () => {
  let act;
  let React;
  let useEditableValue;

  beforeEach(() => {
    const utils = require('./utils');
    act = utils.act;

    React = require('react');

    useEditableValue = require('../devtools/views/hooks').useEditableValue;
  });

  const {render} = getVersionedRenderImplementation();

  it('should not cause a loop with values like NaN', () => {
    let state;

    function Example({value = NaN}) {

expect(state.parsedValue).toEqual(NaN);
    expect(state.hasPendingChanges).toBe(false);
    expect(state.isValid).toBe(true);
  });

  it('should override editable state when external props are updated', () => {
    let state;

    function Example({value

     const tuple = useEditableValue(value);
      state = tuple[0];
      return null;
    }

    act(() => render(<Example />));

    expect(state.editableValue).toEqual('NaN');
    expect(state.externalValue).toEqual(NaN);


d/src/devtools/store';
import type {ProfilingDataFrontend} from 'react-devtools-shared/src/devtools/views/Profiler/types';
import type {ElementType} from 'react-devtools-shared/src/frontend/types';
import type {Node as ReactNode} from 'react';

import {ReactVersion} from '../../../../ReactVersions';

const requestedReactVersion = process.env.REACT_VERSION || ReactVersion;
export function getActDOMImplementation(): () => void | Promise<void> {
  // This is for React < 17, where act wasn't shipped yet.
  if (

 '18.0.0')) {
    const ReactDOMTestUtils = require('react-dom/test-utils');
    return ReactDOMTestUtils.act;
  }

  const React = require('react');
  // This is for React 18, where act was distributed in react as unstable.
  if (React.unstable_act) {

semver.lt(requestedReactVersion, '17.0.0')) {
    require('react-dom/test-utils');
    return cb => cb();
  }

  // This is for React < 18, where act was distributed in react-dom/test-utils.
  if (semver.lt(requestedReactVersion,


 Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

// `test` is part of Jest's serializer API
export function test(maybeDehydratedValue) {
  const {meta} = require('react-devtools-shared/src/hydration');

  const hasOwnProperty =
    Object.prototype.hasOwnProperty.bind(maybeDehydratedValue);
  return (
    maybeDehydratedValue !== null &&
    typeof maybeDehydra

const {meta} = require('react-devtools-shared/src/hydration');
  const indentation = Math.max(indent('.').indexOf('.') - 2, 0);
  const paddingLeft = ' '.repeat(indentation);
  return (
    'Dehydrated {\n' +
    paddingLeft +
    '  "preview_short": ' +

tedValue === 'object' &&
    hasOwnProperty(meta.inspectable) &&
    maybeDehydratedValue[meta.inspected] !== true
  );
}

// print() is part of Jest's serializer API
export function print(dehydratedValue, serialize, indent) {


printStore} from 'react-devtools-shared/src/devtools/utils';

// `test` is part of Jest's serializer API
export function test(maybeStore) {
  // It's important to lazy-require the Store rather than imported at the head of the module.
  // Because we reset modules between tests, different Store implementations will be used for each test.
  // Unfortunately Jest does not reset its own serializer modules.
  return (
    maybeStore instanceof
    require('react-devtools-shared/src/devtools/store').default
  );

t function print(store, serialize, indent, includeSuspense = true) {
  return printStore(store, false, null, includeSuspense);
}

// Used for Jest snapshot testing.
// May also be useful for visually debugging the tree, so it lives on the Store.
export {pr

}

// print() is part of Jest's serializer API
expor


  let ReactDOM;
  let bridge: FrontendBridge;
  let store: Store;

  const act = (callback: Function) => {
    callback();

    jest.runAllTimers(); // Flush Bridge operations
  };

  const flushPendingUpdates = () => {
    jest.runOnlyPendingTimers();
  };

  beforeEach(() => {
    bridge = global.bridge;
    store = global.store;
    store.collapseNodesByDefault = false;

    PropTypes = require('prop-types');

    // Redirect all React/ReactDOM requires to the v15 UMD.
    // We use the UMD because Jest

dom.js'),
    );

    React = require('react');
    ReactDOM = require('react-dom');
  });

  describe('props', () => {
    let committedProps;
    let id;

    function mountTestApp() {
      class ClassComponent extends React.Component {
        componen

 doesn't enable us to mock deep imports (e.g. "react/lib/Something").
    jest.mock('react', () => jest.requireActual('react-15/dist/react.js'));
    jest.mock('react-dom', () =>
      jest.requireActual('react-dom-15/dist/react-


pectElement(bridge, false, id, path, rendererID)
      .then(data =>
        backendAPI.convertInspectedElementBackendToFrontend(data.value),
      );

    jest.runOnlyPendingTimers();

    return promise;
  }

  beforeEach(() => {
    bridge = global.bridge;
    store = global.store;

    backendAPI = require('react-devtools-shared/src/backendAPI');

    // Redirect all React/ReactDOM requires to the v15 UMD.
    // We use the UMD because Jest doesn't enable us to mock deep imports (e.g. "react/lib/Somethi

equire('react-dom');
  });

  // @reactVersion >= 16.0
  it('should inspect the currently selected element', async () => {
    const Example = () => null;

    act(() =>
      ReactDOM.render(
        React.createElement(Example, {a: 1, b: 'abc'}),

ng").
    jest.mock('react', () => jest.requireActual('react-15/dist/react.js'));
    jest.mock('react-dom', () =>
      jest.requireActual('react-dom-15/dist/react-dom.js'),
    );

    React = require('react');
    ReactDOM = r


ng order within group', () => {
    const nodeToData = new Map([
      [
        {id: 1},
        {
          rect: {left: 0, top: 0, width: 100, height: 100},
          color: '#80b393',
          displayName: 'Node1',
          count: 3,
        },
      ],
      [
        {id: 2},
        {
          rect: {left: 0, top: 0, width: 100, height: 100},
          color: '#63b19e',
          displayName: 'Node2',
          count: 2,
        },
      ],
    ]);

    const result = groupAndSortNodes(nodeToData)

eft: 0, top: 0, width: 100, height: 100},
          color: '#63b19e',
          displayName: 'Node2',
          count: 2,
        },
      ],
    ]);
  });

  test('should sort groups by lowest count in each group', () => {
    const nodeToData = new Map([

;

    expect(result).toEqual([
      [
        {
          rect: {left: 0, top: 0, width: 100, height: 100},
          color: '#80b393',
          displayName: 'Node1',
          count: 3,
        },
        {
          rect: {l


 Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import {useState, useEffect} from 'react';
import type {FrontendBridge} from 'react-devtools-shared/src/bridge';

// Events that are prefixed with `extension` will only be emitted for the browser extension implementation.
// For other implementations, this hook will just return constant `true` value.
export funct

 onPanelHidden() {
      setIsVisible(false);
    }

    bridge.addListener('extensionComponentsPanelShown', onPanelShown);
    bridge.addListener('extensionComponentsPanelHidden', onPanelHidden);

    return () => {
      bridge.removeListener('extensionC

ion useExtensionComponentsPanelVisibility(
  bridge: FrontendBridge,
): boolean {
  const [isVisible, setIsVisible] = useState(true);

  useEffect(() => {
    function onPanelShown() {
      setIsVisible(true);
    }
    function


 Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import type {HostInstance} from './types';

// Some environments (e.g. React Native / Hermes) don't support the performance API yet.
export const getCurrentTime: () => number =
  // $FlowFixMe[method-unbinding]
  typeof performance === 'object' && typeof performance.now === 'function'
    ? () => performance.now()
    : () => Date.

  // So we need to detect this and use that as the public instance.

  // React Native. Modern. Fabric.
  if (typeof instance === 'object' && instance !== null) {
    if (typeof instance.canonical === 'object' && instance.canonical !== null) {
      if (

now();

// Ideally, this should be injected from Reconciler config
export function getPublicInstance(instance: HostInstance): HostInstance {
  // Typically the PublicInstance and HostInstance is the same thing but not in Fabric.


d: number,
  path: Array<string | number>,
  rendererID: number,
};

type InspectElementParams = {
  forceFullData: boolean,
  id: number,
  path: Array<string | number> | null,
  rendererID: number,
  requestID: number,
};

type InspectScreenParams = {
  forceFullData: boolean,
  id: number,
  path: Array<string | number> | null,
  requestID: number,
};

type OverrideHookParams = {
  id: number,
  hookID: number,
  path: Array<string | number>,
  rendererID: number,
  wasForwarded?: boolean,
  value: any,

PathType,
  hookID?: ?number,
  id: number,
  path: Array<string | number>,
  rendererID: number,
};

type RenamePathParams = {
  type: PathType,
  hookID?: ?number,
  id: number,
  oldPath: Array<string | number>,
  newPath: Array<string | number>,
  rend

};

type SetInParams = {
  id: number,
  path: Array<string | number>,
  rendererID: number,
  wasForwarded?: boolean,
  value: any,
};

type PathType = 'props' | 'hooks' | 'state' | 'context';

type DeletePathParams = {
  type:


 SCHEDULING_PROFILER_VERSION,
} from 'react-devtools-timeline/src/constants';
import {describeFiber} from './fiber/DevToolsFiberComponentStack';

// Add padding to the start/stop time of the profile.
// This makes the UI nicer to use.
const TIME_OFFSET = 10;

let performanceTarget: Performance | null = null;

// If performance exists and supports the subset of the User Timing API that we require.
let supportsUserTiming =
  typeof performance !== 'undefined' &&
  // $FlowFixMe[method-unbinding]
  typeof perf

    detail?: mixed,
    startTime?: number,
  } = {};
  Object.defineProperty(markOptions, 'startTime', {
    get: function () {
      supportsUserTimingV3 = true;
      return 0;
    },
    set: function () {},
  });

  try {
    performance.mark(CHECK_V3

ormance.mark === 'function' &&
  // $FlowFixMe[method-unbinding]
  typeof performance.clearMarks === 'function';

let supportsUserTimingV3 = false;
if (supportsUserTiming) {
  const CHECK_V3_MARK = '__v3';
  const markOptions: {


 MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import type {StyleXPlugin} from 'react-devtools-shared/src/frontend/types';
import isArray from 'react-devtools-shared/src/isArray';

const cachedStyleNameToValueMap: Map<string, string> = new Map();

export function getStyleXData(data: any): StyleXPlugin {
  const sources = new Set<string>();
  const resolvedStyles = {};

  crawlData(data, sources, resolvedStyles);

  return {
    sources: Array.from(sourc

      if (entry == null) {
        return;
      }

      if (isArray(entry)) {
        crawlData(entry, sources, resolvedStyles);
      } else {
        crawlObjectProperties(entry, sources, resolvedStyles);
      }
    });
  } else {
    crawlObjectProp

es).sort(),
    resolvedStyles,
  };
}

export function crawlData(
  data: any,
  sources: Set<string>,
  resolvedStyles: Object,
): void {
  if (data == null) {
    return;
  }

  if (isArray(data)) {
    data.forEach(entry => {


ight (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import type {InternalInstance} from './renderer';

export function decorate(object: Object, attr: string, fn: Function): Function {
  const old = object[attr];
  // $FlowFixMe[missing-this-annot] webpack config needs to be updated to allow `this` type annotations
  object[attr] = function (instance: InternalInstance) {

fns) {
    olds[name] = decorate(source, name, fns[name]);
  }
  return olds;
}

export function restoreMany(source: Object, olds: Object): void {
  for (const name in olds) {
    source[name] = olds[name];
  }
}

// $FlowFixMe[missing-this-annot] webpack

    return fn.call(this, old, arguments);
  };
  return old;
}

export function decorateMany(
  source: Object,
  fns: {[attr: string]: Function, ...},
): Object {
  const olds: {[string]: $FlowFixMe} = {};
  for (const name in


import type {Data} from './index';
import type {Rect} from '../utils';
import type {HostInstance} from '../../types';
import type Agent from '../../agent';

import {isReactNativeEnvironment} from 'react-devtools-shared/src/backend/utils';

// Note these colors are in sync with DevTools Profiler chart colors.
const COLORS = [
  '#37afa9',
  '#63b19e',
  '#80b393',
  '#97b488',
  '#abb67d',
  '#beb771',
  '#cfb965',
  '#dfba57',
  '#efbb49',
  '#febc38',
];

let canvas: HTMLCanvasElement | null = null;

funct

w);

  const mergedNodes = groupAndSortNodes(nodeToData);
  agent.emit('drawGroupedTraceUpdatesWithNames', mergedNodes);
}

function drawWeb(nodeToData: Map<HostInstance, Data>) {
  if (canvas === null) {
    initialize();
  }

  const dpr = window.deviceP

ion drawNative(nodeToData: Map<HostInstance, Data>, agent: Agent) {
  const nodesToDraw = [];
  iterateNodes(nodeToData, ({color, node}) => {
    nodesToDraw.push({node, color});
  });

  agent.emit('drawTraceUpdates', nodesToDra


 Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import type Agent from 'react-devtools-shared/src/backend/agent';
import type {HostInstance} from '../../types';

import {isReactNativeEnvironment} from 'react-devtools-shared/src/backend/utils';

import Overlay from './Overlay';

const SHOW_DURATION = 2000;

let timeoutID: TimeoutID | null = null;
let overlay: Overlay | null = nul

 function hideOverlay(agent: Agent): void {
  return isReactNativeEnvironment()
    ? hideOverlayNative(agent)
    : hideOverlayWeb();
}

function showOverlayNative(
  elements: $ReadOnlyArray<HostInstance>,
  agent: Agent,
): void {
  agent.emit('showNati

l;

function hideOverlayNative(agent: Agent): void {
  agent.emit('hideNativeHighlight');
}

function hideOverlayWeb(): void {
  timeoutID = null;

  if (overlay !== null) {
    overlay.remove();
    overlay = null;
  }
}

export


rom 'react';
import {symbolicateSource} from '../symbolicateSource';

describe('utils', () => {
  describe('getDisplayName', () => {
    // @reactVersion >= 16.0
    it('should return a function name', () => {
      function FauxComponent() {}
      expect(getDisplayName(FauxComponent)).toEqual('FauxComponent');
    });

    // @reactVersion >= 16.0
    it('should return a displayName name if specified', () => {
      function FauxComponent() {}
      FauxComponent.displayName = 'OverrideDisplayName';

toEqual('Fallback');
    });

    // @reactVersion >= 16.0
    it('should return Anonymous for anonymous functions without a fallback', () => {
      expect(getDisplayName(() => {})).toEqual('Anonymous');
    });

    // Simulate a reported bug:
    // htt

 expect(getDisplayName(FauxComponent)).toEqual('OverrideDisplayName');
    });

    // @reactVersion >= 16.0
    it('should return the fallback for anonymous functions', () => {
      expect(getDisplayName(() => {}, 'Fallback')).


nspectedElement) {
  if (
    maybeInspectedElement === null ||
    typeof maybeInspectedElement !== 'object'
  ) {
    return false;
  }

  const hasOwnProperty = Object.prototype.hasOwnProperty.bind(
    maybeInspectedElement,
  );

  return (
    hasOwnProperty('canEditFunctionProps') &&
    hasOwnProperty('canEditHooks') &&
    hasOwnProperty('canToggleSuspense') &&
    hasOwnProperty('canToggleError')
  );
}

// print() is part of Jest's serializer API
export function print(inspectedElement, serialize,

uld break nested serializers.
  return serialize({
    context: inspectedElement.context,
    events: inspectedElement.events,
    hooks: inspectedElement.hooks,
    id: inspectedElement.id,
    owners: inspectedElement.owners,
    props: inspectedElement.

 indent) {
  // Don't stringify this object; that wo


ctDOM = require('react-dom');
  });
  it('should not allow a root node to be collapsed', () => {
    const Component = () => React.createElement('div', null, 'Hi');
    act(() =>
      ReactDOM.render(
        React.createElement(Component, {
          count: 4,
        }),
        document.createElement('div'),
      ),
    );
    expect(store).toMatchInlineSnapshot(`
      [root]
        ▾ <Component>
            <div>
    `);
    expect(store.roots).toHaveLength(1);
    const rootID = store.roots[0];

se;
    });
    it('should support mount and update operations', () => {
      const Grandparent = ({count}) =>
        React.createElement(
          'div',
          null,
          React.createElement(Parent, {
            count: count,
          }),

 expect(() => store.toggleIsCollapsed(rootID, true)).toThrow(
      'Root nodes cannot be collapsed',
    );
  });
  describe('collapseNodesByDefault:false', () => {
    beforeEach(() => {
      store.collapseNodesByDefault = fal


 backwards compatibility when making changes.
 */

import type {
  Dehydrated,
  Unserializable,
} from 'react-devtools-shared/src/hydration';
import type {ReactFunctionLocation, ReactStackTrace} from 'shared/ReactTypes';
import type {UnknownSuspendersReason} from '../constants';

export type BrowserTheme = 'dark' | 'light';

export type Wall = {
  // `listen` returns the "unlisten" function.
  listen: (fn: Function) => Function,
  send: (event: string, payload: any, transferable?: Array<any>) => void,
};

 rather than re-ordering existing ones.
//
// Changing these types is also a backwards breaking change for the standalone shell,
// since the frontend and backend must share the same values-
// and the backend is embedded in certain environments (like Reac

// WARNING
// The values below are referenced by ComponentFilters (which are saved via localStorage).
// Do not change them or it will break previously saved user customizations.
// If new element types are added, use new numbers


iates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import Agent from './agent';

import type {DevToolsHook, RendererID, RendererInterface} from './types';

export type InitBackend = typeof initBackend;

export function initBackend(
  hook: DevToolsHook,
  agent: Agent,
  global: Object,
  isReloadAndProfileSupported: boolean,
): () => void {
  if (hook == null) {
    // DevTools didn't get injected into thi

;

    // Now that the Store and the renderer interface are connected,
    // it's time to flush the pending operation codes to the frontend.
    rendererInterface.flushInitialOperations();
  }

  const subs = [
    hook.sub(
      'renderer-attached',

s page (maybe b'c of the contentType).
    return () => {};
  }

  function registerRendererInterface(
    id: RendererID,
    rendererInterface: RendererInterface,
  ) {
    agent.registerRendererInterface(id, rendererInterface)


leEditor/setupNativeStyleEditor';
import type {InitBackend} from 'react-devtools-shared/src/backend';
import type {TimelineDataExport} from 'react-devtools-timeline/src/types';
import type {BackendBridge} from 'react-devtools-shared/src/bridge';
import type {ReactFunctionLocation, ReactStackTrace} from 'shared/ReactTypes';
import type Agent from './agent';
import type {UnknownSuspendersReason} from '../constants';

type BundleType =
  | 0 // PROD
  | 1; // DEV

export type WorkTag = number;
export type Work

tineHandlerPhase: WorkTag,
  DehydratedSuspenseComponent: WorkTag,
  ForwardRef: WorkTag,
  Fragment: WorkTag,
  FunctionComponent: WorkTag,
  HostComponent: WorkTag,
  HostPortal: WorkTag,
  HostRoot: WorkTag,
  HostHoistable: WorkTag,
  HostSingleton: Wo

Flags = number;
export type ExpirationTime = number;

export type WorkTagMap = {
  CacheComponent: WorkTag,
  ClassComponent: WorkTag,
  ContextConsumer: WorkTag,
  ContextProvider: WorkTag,
  CoroutineComponent: WorkTag,
  Corou


 {
    if (internalInstance._currentElement.key) {
      key = String(internalInstance._currentElement.key);
    }

    const elementType = internalInstance._currentElement.type;
    if (typeof elementType === 'string') {
      displayName = elementType;
    } else if (typeof elementType === 'function') {
      displayName = getDisplayName(elementType);
    }
  }

  return {
    displayName,
    key,
  };
}

function getElementType(internalInstance: InternalInstance): ElementType {
  // != used deliberately

Instance.getPublicInstance();
      if (publicInstance !== null) {
        return ElementTypeClass;
      } else {
        return ElementTypeFunction;
      }
    } else if (typeof elementType === 'string') {
      return ElementTypeHostComponent;
    }

 here to catch undefined and null
  if (internalInstance._currentElement != null) {
    const elementType = internalInstance._currentElement.type;
    if (typeof elementType === 'function') {
      const publicInstance = internal


tils.act(() => dispatch({type: 'SELECT_NEXT_ELEMENT_IN_TREE'}));
      utils.act(() => renderer.update(<Contexts />));
      expect(state).toMatchInlineSnapshot(`
        [root]
           ▾ <Grandparent>
        →    ▾ <Parent>
                 <Child>
                 <Child>
      `);

      utils.act(() => dispatch({type: 'SELECT_NEXT_ELEMENT_IN_TREE'}));
      utils.act(() => renderer.update(<Contexts />));
      expect(state).toMatchInlineSnapshot(`
        [root]
           ▾ <Grandparent>

nlineSnapshot(`
        [root]
           ▾ <Grandparent>
             ▾ <Parent>
                 <Child>
        →        <Child>
      `);

      // Test stepping back to the beginning

      utils.act(() => dispatch({type: 'SELECT_PREVIOUS_ELEMENT_IN_T

   ▾ <Parent>
        →        <Child>
                 <Child>
      `);

      utils.act(() => dispatch({type: 'SELECT_NEXT_ELEMENT_IN_TREE'}));
      utils.act(() => renderer.update(<Contexts />));
      expect(state).toMatchI


ame(hook) {
  const fileName = hook.hookSource ? hook.hookSource.fileName : null;
  if (fileName == null) {
    return false;
  } else {
    return fileName.indexOf('/react-devtools-shared/') > 0;
  }
}

function serializeHook(hook) {
  if (!hook.hookSource) return hook;

  // Remove user-specific portions of this file path.
  let fileName = hook.hookSource.fileName;
  const index = fileName.lastIndexOf('/react-devtools-shared/');
  fileName = fileName.slice(index + 1);

  let subHooks = hook.subHooks;
  if

tests.
      columnNumber: 'removed by Jest serializer',
      lineNumber: 'removed by Jest serializer',
    },
    subHooks,
  };
}

// `test` is part of Jest's serializer API
export function test(maybeHook) {
  if (maybeHook === null || typeof maybeHook

 (subHooks) {
    subHooks = subHooks.map(serializeHook);
  }

  return {
    ...hook,
    hookSource: {
      ...hook.hookSource,
      fileName,

      // Otherwise changes in any test case or formatting might invalidate other


m 'react-devtools-shared/src/devtools/utils';

// `test` is part of Jest's serializer API
export function test(maybeState) {
  if (maybeState === null || typeof maybeState !== 'object') {
    return false;
  }

  const hasOwnProperty = Object.prototype.hasOwnProperty.bind(maybeState);
  // Duck typing at its finest.
  return (
    hasOwnProperty('inspectedElementID') &&
    hasOwnProperty('ownerFlatTree') &&
    hasOwnProperty('ownerSubtreeLeafElementID')
  );
}

// print() is part of Jest's serializer API

// This is a big of a hack but it works around having to pass in a meta object e.g. {store, state}.
  // DevTools tests depend on a global Store object anyway (initialized via setupTest).
  const store = global.store;

  return printStore(store, false, sta

export function print(state, serialize, indent) {


describe('Stylex plugin utils', () => {
  let getStyleXData;
  let styleElements;

  function defineStyles(style) {
    const styleElement = document.createElement('style');
    styleElement.type = 'text/css';
    styleElement.appendChild(document.createTextNode(style));

    styleElements.push(styleElement);

    document.head.appendChild(styleElement);
  }

  beforeEach(() => {
    getStyleXData = require('../utils').getStyleXData;

    styleElements = [];
  });

  afterEach(() => {
    styleElements.forE

},
        "sources": [],
      }
    `);

    expect(getStyleXData(undefined)).toMatchInlineSnapshot(`
      {
        "resolvedStyles": {},
        "sources": [],
      }
    `);

    expect(getStyleXData('')).toMatchInlineSnapshot(`
      {
        "res

ach(styleElement => {
      document.head.removeChild(styleElement);
    });
  });

  it('should gracefully handle empty values', () => {
    expect(getStyleXData(null)).toMatchInlineSnapshot(`
      {
        "resolvedStyles": {


 MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import Agent from 'react-devtools-shared/src/backend/agent';
import {destroy as destroyCanvas, draw} from './canvas';
import {extractHOCNames, getNestedBoundingClientRect} from '../utils';

import type {HostInstance} from '../../types';
import type {Rect} from '../utils';

// How long the rect should be shown for?
const DISPLAY_DURATION = 250;

// What's the longest we are willing to show the overlay for?
/

fferent types of HOCs
const HOC_MARKERS = new Map([
  ['Forget', '✨'],
  ['Memo', '🧠'],
]);

// Some environments (e.g. React Native / Hermes) don't support the performance API yet.
const getCurrentTime =
  // $FlowFixMe[method-unbinding]
  typeof performa

/ This can be important if we're getting a flurry of events (e.g. scroll update).
const MAX_DISPLAY_DURATION = 3000;

// How long should a rect be considered valid for?
const REMEASUREMENT_AFTER_DURATION = 250;

// Markers for di


// This is a DevTools fork of ReactFiberComponentStack.
// This fork enables DevTools to use the same "native" component stack format,
// while still maintaining support for multiple renderer versions
// (which use different values for ReactTypeOfWork).

import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
import type {CurrentDispatcherRef, WorkTagMap} from '../types';

import type {ReactComponentInfo} from 'shared/ReactTypes';

import {
  describeBuiltInComponentFrame,
  describeFunctionComp

rkTagMap,
  workInProgress: Fiber,
  currentDispatcherRef: CurrentDispatcherRef,
): string {
  const {
    HostHoistable,
    HostSingleton,
    HostComponent,
    LazyComponent,
    SuspenseComponent,
    SuspenseListComponent,
    FunctionComponent,

onentFrame,
  describeClassComponentFrame,
  describeDebugInfoFrame,
} from '../shared/DevToolsComponentStackFrame';

import {formatOwnerStack} from '../shared/DevToolsOwnerStack';

export function describeFiber(
  workTagMap: Wo


export interface Rect {
  bottom: number;
  height: number;
  left: number;
  right: number;
  top: number;
  width: number;
}

// Get the window object for the document that a node belongs to,
// or return null if it cannot be found (node not attached to DOM,
// etc).
export function getOwnerWindow(node: HTMLElement): typeof window | null {
  if (!node.ownerDocument) {
    return null;
  }
  return node.ownerDocument.defaultView;
}

// Get the iframe containing a node, or return null if it cannot
// be fou

 Get a bounding client rect for a node, with an
// offset added to compensate for its border.
export function getBoundingClientRectWithBorderOffset(node: HTMLElement): Rect {
  const dimensions = getElementDimensions(node);
  // $FlowFixMe[incompatible-var

nd (node not within iframe, etc).
export function getOwnerIframe(node: HTMLElement): HTMLElement | null {
  const nodeWindow = getOwnerWindow(node);
  if (nodeWindow) {
    return nodeWindow.frameElement;
  }
  return null;
}

//


t type {HostInstance} from 'react-devtools-shared/src/backend/types';
import type {BackendBridge} from 'react-devtools-shared/src/bridge';
import type {RendererInterface} from '../../types';

// This plug-in provides in-page highlighting of the selected element.
// It is used by the browser extension and the standalone DevTools shell (when connected to a browser).
// It is not currently the mechanism used to highlight React Native views.
// That is done by the React Native Inspector component.

let iframesL

, clearHostInstanceHighlight);
  bridge.addListener('highlightHostInstance', highlightHostInstance);
  bridge.addListener('highlightHostInstances', highlightHostInstances);
  bridge.addListener('scrollToHostInstance', scrollToHostInstance);
  bridge.addLis

isteningTo: Set<HTMLIFrameElement> = new Set();
let inspectOnlySuspenseNodes = false;

export default function setupHighlighter(
  bridge: BackendBridge,
  agent: Agent,
): void {
  bridge.addListener('clearHostInstanceHighlight'


iates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import type {BoxStyle} from './types';

/**
 * This mirrors react-native/Libraries/Inspector/resolveBoxStyle.js (but without RTL support).
 *
 * Resolve a style property into it's component parts, e.g.
 *
 * resolveBoxStyle('margin', {margin: 5, marginBottom: 10})
 * -> {top: 5, left: 5, right: 5, bottom: 10}
 */
export default function resolveBoxStyle(
  p

eslint-disable-next-line no-for-of-loops/no-for-of-loops
    for (const key of Object.keys(result)) {
      result[key] = styleForAll;
    }
    hasParts = true;
  }

  const styleForHorizontal = style[prefix + 'Horizontal'];
  if (styleForHorizontal != nu

refix: string,
  style: Object,
): BoxStyle | null {
  let hasParts = false;
  const result = {
    bottom: 0,
    left: 0,
    right: 0,
    top: 0,
  };

  const styleForAll = style[prefix];
  if (styleForAll != null) {
    //


which use different values for ReactTypeOfWork).

import type {CurrentDispatcherRef} from '../types';

// The shared console patching code is DEV-only.
// We can't use it since DevTools only ships production builds.
import {disableLogs, reenableLogs} from './DevToolsConsolePatching';

let prefix;
export function describeBuiltInComponentFrame(name: string): string {
  if (prefix === undefined) {
    // Extract the VM specific prefix used by each line.
    try {
      throw Error();
    } catch (x) {
      co

FOX__) {
    suffix = '@unknown:0:0';
  }
  // We use the prefix to ensure our stacks line up with native stack frames.
  // We use a suffix to ensure it gets parsed natively.
  return '\n' + prefix + name + suffix;
}

export function describeDebugInfoFram

nst match = x.stack.trim().match(/\n( *(at )?)/);
      prefix = (match && match[1]) || '';
    }
  }
  let suffix = '';
  if (__IS_CHROME__ || __IS_EDGE__ || __IS_NATIVE__) {
    suffix = ' (<anonymous>)';
  } else if (__IS_FIRE


ource code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

// This keeps track of Server Component logs which may come from.
// This is in a shared module because Server Component logs don't come from a specific renderer
// but can become associated with a Virtual Instance of any renderer.

import type {ReactComponentInfo} from 'shared/ReactTypes';

type ComponentLogs = {
  errors: Map<string, number>,
  errorsCount: number,
  warnin

// This keeps it around as long as the ComponentInfo is alive which
// lets the Fiber get reparented/remounted and still observe the previous errors/warnings.
// Unless we explicitly clear the logs from a Fiber.
export const componentInfoToComponentLogsM

gs: Map<string, number>,
  warningsCount: number,
};


iates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

// This list should be kept updated to reflect additions to 'shared/ReactSymbols'.
// DevTools can't import symbols from 'shared/ReactSymbols' directly for two reasons:
// 1. DevTools requires symbols which may have been deleted in more recent versions (e.g. concurrent mode)
// 2. DevTools must support both Symbol and numeric forms of each symbol;
//    Sin

t const CONTEXT_NUMBER = 0xeace;
export const CONTEXT_SYMBOL_STRING = 'Symbol(react.context)';

export const SERVER_CONTEXT_SYMBOL_STRING = 'Symbol(react.server_context)';

export const DEPRECATED_ASYNC_MODE_SYMBOL_STRING = 'Symbol(react.async_mode)';

exp

ce e.g. standalone DevTools runs in a separate process, it can't rely on its own ES capabilities.

export const CONCURRENT_MODE_NUMBER = 0xeacf;
export const CONCURRENT_MODE_SYMBOL_STRING = 'Symbol(react.concurrent_mode)';

expor


 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import {PermissionNotGrantedError} from 'react-devtools-shared/src/errors/PermissionNotGrantedError';

type SupportedPermission = 'clipboardWrite';
type Permissions = Array<SupportedPermission>;
type PermissionsOptions = {permissions: Permissions};

// browser.permissions is not available for DevTools pages in

issionsOptions,
  callback: T,
): T | (() => Promise<ReturnType<T>>) {
  if (!__IS_CHROME__ && !__IS_EDGE__) {
    return callback;
  } else {
    return async () => {
      const granted = await chrome.permissions.request(options);
      if (granted) {

 Firefox
// https://bugzilla.mozilla.org/show_bug.cgi?id=1796933
// We are going to assume that requested permissions are not optional.
export function withPermissionsCheck<T: (...$ReadOnlyArray<empty>) => mixed>(
  options: Perm


iates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

// This is a DevTools fork of shared/ConsolePatchingDev.
// The shared console patching code is DEV-only.
// We can't use it since DevTools only ships production builds.

// Helpers to patch console.logs to avoid logging during side-effect free
// replaying on render function. This currently only patches the object
// lazily which won't cover if the log fun

g() {}
disabledLog.__reactDisabledLog = true;

export function disableLogs(): void {
  if (disabledDepth === 0) {
    prevLog = console.log;
    prevInfo = console.info;
    prevWarn = console.warn;
    prevError = console.error;
    prevGroup = console.gr

ction was extracted eagerly.
// We could also eagerly patch the method.

let disabledDepth = 0;
let prevLog;
let prevInfo;
let prevWarn;
let prevError;
let prevGroup;
let prevGroupCollapsed;
let prevGroupEnd;

function disabledLo


 MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import * as React from 'react';
import {Fragment, useCallback} from 'react';
import Icon from './Icon';

import styles from './TabBar.css';
import Tooltip from './Components/reach-ui/tooltip';

import type {IconType} from './Icon';

type TabInfo = {
  icon: IconType,
  id: string,
  label: string,
  title?: string,
};

export type Props = {
  currentTab: any,
  disabled?: boolean,
  id: string,
  selectTab:

 React.Node {
  if (!tabs.some(tab => tab !== null && tab.id === currentTab)) {
    const firstTab = ((tabs.find(tab => tab !== null): any): TabInfo);
    selectTab(firstTab.id);
  }

  const onChange = useCallback(
    ({currentTarget}: $FlowFixMe) => sel

 (tabID: any) => void,
  tabs: Array<TabInfo | null>,
  type: 'navigation' | 'profiler' | 'settings',
};

export default function TabBar({
  currentTab,
  disabled = false,
  id: groupName,
  selectTab,
  tabs,
  type,
}: Props):


 Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

// This is a DevTools fork of ReactComponentInfoStack.
// This fork enables DevTools to use the same "native" component stack format,
// while still maintaining support for multiple renderer versions
// (which use different values for ReactTypeOfWork).

import type {ReactComponentInfo} from 'shared/ReactTypes';

import {describeBui

{
  try {
    let info = '';

    // The owner stack of the current component will be where it was created, i.e. inside its owner.
    // There's no actual name of the currently executing component. Instead, that is available
    // on the regular stack th

ltInComponentFrame} from '../shared/DevToolsComponentStackFrame';

import {formatOwnerStack} from '../shared/DevToolsOwnerStack';

export function getOwnerStackByComponentInfoInDev(
  componentInfo: ReactComponentInfo,
): string


th('Error: react-stack-top-frame\n')) {
    // V8's default formatting prefixes with the error message which we
    // don't want/need.
    stack = stack.slice(29);
  }
  let idx = stack.indexOf('react_stack_bottom_frame');
  if (idx === -1) {
    idx = stack.indexOf('react-stack-bottom-frame');
  }
  if (idx !== -1) {
    idx = stack.lastIndexOf('\n', idx);
  }
  if (idx !== -1) {
    // Cut off everything after the bottom frame since it'll be internals.
    stack = stack.slice(0, idx);
  }
  const frames

aller.
  for (let i = skipFrames; i < frames.length; i++) {
    const parsed = chromeFrameRegExp.exec(frames[i]);
    if (!parsed) {
      continue;
    }
    let name = parsed[1] || '';
    let isAsync = parsed[8] === 'async ';
    if (name === '<anonymou

= stack.split('\n');
  const parsedFrames: ReactStackTrace = [];
  // We skip top frames here since they may or may not be parseable but we
  // want to skip the same number of frames regardless. I.e. we can't do it
  // in the c


ight (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

/************************************************************************
 * This file is forked between different DevTools implementations.
 * It should never be imported directly!
 * It should always be imported from "react-devtools-feature-flags".
 ********************************************************************

****/

export const enableActivitySlices: boolean = false;
export const enableLogger: boolean = true;
export const enableStyleXFeatures: boolean = true;
export const isInternalFacebookBuild: boolean = true;

/********************


ort {logEvent} from 'react-devtools-shared/src/Logger';

import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
import type {ProfilingDataBackend} from 'react-devtools-shared/src/backend/types';
import type {
  CommitDataFrontend,
  ProfilingDataForRootFrontend,
  ProfilingDataFrontend,
  SnapshotNode,
} from './views/Profiler/types';

export default class ProfilerStore extends EventEmitter<{
  isProcessingData: [],
  isProfiling: [],
  profilingData: [],
}> {
  _bridge: FrontendBridge;

  //

fter being collected from all renderers.
  _dataBackends: Array<ProfilingDataBackend> = [];

  // Data from the most recently completed profiling session,
  // or data that has been imported from a previously exported session.
  // This object contains all

 Suspense cache for lazily calculating derived profiling data.
  _cache: ProfilingCache;

  // Temporary store of profiling data from the backend renderer(s).
  // This data will be converted to the ProfilingDataFrontend format a


iates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import ProfilerStore from './ProfilerStore';
import {
  getCommitTree,
  invalidateCommitTrees,
} from 'react-devtools-shared/src/devtools/views/Profiler/CommitTreeBuilder';
import {
  getChartData as getFlamegraphChartData,
  invalidateChartData as invalidateFlamegraphChartData,
} from 'react-devtools-shared/src/devtools/views/Profiler/FlamegraphChartBuild

-shared/src/devtools/views/Profiler/types';
import type {ChartData as FlamegraphChartData} from 'react-devtools-shared/src/devtools/views/Profiler/FlamegraphChartBuilder';
import type {ChartData as RankedChartData} from 'react-devtools-shared/src/devtools/

er';
import {
  getChartData as getRankedChartData,
  invalidateChartData as invalidateRankedChartData,
} from 'react-devtools-shared/src/devtools/views/Profiler/RankedChartBuilder';

import type {CommitTree} from 'react-devtools


import type {
  ReactContext,
  Thenable,
  FulfilledThenable,
  RejectedThenable,
} from 'shared/ReactTypes';

import * as React from 'react';
import {createContext} from 'react';

// TODO (cache) Remove this cache; it is outdated and will not work with newer APIs like startTransition.

// Cache implementation was forked from the React repo:
// https://github.com/facebook/react/blob/main/packages/react-cache/src/ReactCacheOld.js
//
// This cache is simpler than react-cache in that:
// 1. Individual items d

 fully reset between profiling sessions.

export type {Thenable};

export type Resource<Input, Key, Value> = {
  clear(): void,
  invalidate(Key): void,
  read(Input): Value,
  preload(Input): void,
  write(Key, Value): void,
};

let readContext;
if (typeo

on't need to be invalidated.
//    Profiling data is invalidated as a whole.
// 2. We didn't need the added overhead of an LRU cache.
//    The size of this cache is bounded by how many renders were profiled,
//    and it will be


,
  supportsReloadAndProfile?: boolean,
  supportsTimeline?: boolean,
  supportsTraceUpdates?: boolean,
};

const ADVANCED_PROFILING_NONE = 0;
const ADVANCED_PROFILING_TIMELINE = 1;
const ADVANCED_PROFILING_PERFORMANCE_TRACKS = 2;
type AdvancedProfiling = 0 | 1 | 2;

export type Capabilities = {
  supportsBasicProfiling: boolean,
  hasOwnerMetadata: boolean,
  supportsStrictMode: boolean,
  supportsAdvancedProfiling: AdvancedProfiling,
};

function isNonZeroRect(rect: Rect) {
  return rect.width > 0 || rect

class Store extends EventEmitter<{
  backendVersion: [],
  collapseNodesByDefault: [],
  componentFilters: [],
  error: [Error],
  hookSettings: [$ReadOnly<DevToolsHookSettings>],
  hostInstanceSelected: [Element['id'] | null],
  settingsUpdated: [$ReadOnl

.height > 0 || rect.x > 0 || rect.y > 0;
}

/**
 * The store is the single source of truth for updates from the backend.
 * ContextProviders can subscribe to the Store for specific things they want to provide.
 */
export default


import JSON5 from 'json5';

import type {ReactFunctionLocation} from 'shared/ReactTypes';
import {ElementTypeActivity} from 'react-devtools-shared/src/frontend/types';
import type {
  Element,
  SuspenseNode,
} from 'react-devtools-shared/src/frontend/types';
import type {StateContext} from './views/Components/TreeContext';
import type Store from './store';

export function printElement(
  element: Element,
  includeWeight: boolean = false,
): string {
  let prefix = ' ';
  if (element.children.length > 0)

"`;
  }

  let hocDisplayNames = null;
  if (element.hocDisplayNames !== null) {
    hocDisplayNames = [...element.hocDisplayNames];
  }

  const hocs =
    hocDisplayNames === null ? '' : ` [${hocDisplayNames.join('][')}]`;

  let mode = '';
  if (element

{
    prefix = element.isCollapsed ? '▸' : '▾';
  }

  let key = '';
  if (element.key !== null) {
    key = ` key="${element.key}"`;
  }

  let name = '';
  if (element.nameProp !== null) {
    name = ` name="${element.nameProp}


  | 'expanded'
  | 'export'
  | 'filter'
  | 'import'
  | 'log-data'
  | 'more'
  | 'next'
  | 'parse-hook-names'
  | 'previous'
  | 'record'
  | 'reload'
  | 'save'
  | 'search'
  | 'settings'
  | 'panel-left-close'
  | 'panel-left-open'
  | 'panel-right-close'
  | 'panel-right-open'
  | 'panel-bottom-open'
  | 'panel-bottom-close'
  | 'filter-on'
  | 'filter-off'
  | 'play'
  | 'pause'
  | 'skip-previous'
  | 'skip-next'
  | 'error'
  | 'suspend'
  | 'undo'
  | 'up'
  | 'view-dom'
  | 'view-source';

typ

witch (type) {
    case 'add':
      pathData = PATH_ADD;
      break;
    case 'cancel':
      pathData = PATH_CANCEL;
      break;
    case 'clear':
      pathData = PATH_CLEAR;
      break;
    case 'close':
      pathData = PATH_CLOSE;
      break;

e Props = {
  className?: string,
  type: IconType,
};

const panelIcons = '96 -864 768 768';
export default function ButtonIcon({className = '', type}: Props): React.Node {
  let pathData = null;
  let viewBox = '0 0 24 24';
  s


ight (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

// This is a DevTools fork of shared/ReactOwnerStackFrames.

export function formatOwnerStack(error: Error): string {
  const prevPrepareStackTrace = Error.prepareStackTrace;
  // $FlowFixMe[incompatible-type] It does accept undefined.
  Error.prepareStackTrace = undefined;
  let stack = error.stack;
  Error.prepareSta

idx = stack.indexOf('\n');
  if (idx !== -1) {
    // Pop the JSX frame.
    stack = stack.slice(idx + 1);
  }
  idx = stack.indexOf('react_stack_bottom_frame');
  if (idx === -1) {
    idx = stack.indexOf('react-stack-bottom-frame');
  }
  if (idx !== -1)

ckTrace = prevPrepareStackTrace;

  if (stack.startsWith('Error: react-stack-top-frame\n')) {
    // V8's default formatting prefixes with the error message which we
    // don't want/need.
    stack = stack.slice(29);
  }
  let


iates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import type {ReactComponentInfo, ReactDebugInfo} from 'shared/ReactTypes';
import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
import type {WorkTagMap} from '../../types';
import type {Rect} from '../../types';

// $FlowFixMe[method-unbinding]
const toString = Object.prototype.toString;

export function isError(object: mixed): boolean {
  re

any).effectTag;
}

export function rootSupportsProfiling(root: any): boolean {
  if (root.memoizedInteractions != null) {
    // v16 builds include this field for the scheduler/tracing API.
    return true;
  } else if (
    root.current != null &&
    roo

turn toString.call(object) === '[object Error]';
}

export function getFiberFlags(fiber: Fiber): number {
  // The name of this field changed from "effectTag" to "flags"
  return fiber.flags !== undefined ? fiber.flags : (fiber:


 Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import type {ReactIOInfo, ReactAsyncInfo} from 'shared/ReactTypes';
import type {SuspenseNode} from './DevToolsFiberTypes';

export function ioExistsInSuspenseAncestor(
  suspenseNode: SuspenseNode,
  ioInfo: ReactIOInfo,
): boolean {
  let ancestor = suspenseNode.parent;
  while (ancestor !== null) {
    if (anc

ReactAsyncInfo {
  for (let i = 0; i < suspensedBy.length; i++) {
    const asyncInfo = suspensedBy[i];
    if (asyncInfo.awaited === ioInfo) {
      return asyncInfo;
    }
  }
  return null;
}

export function getVirtualEndTime(ioInfo: ReactIOInfo): numb

estor.suspendedBy.has(ioInfo)) {
      return true;
    }
    ancestor = ancestor.parent;
  }
  return false;
}

export function getAwaitInSuspendedByFromIO(
  suspensedBy: Array<ReactAsyncInfo>,
  ioInfo: ReactIOInfo,
): null |


 Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

// Do not add / import anything to this file.
// This function could be used from multiple places, including hook.

// Skips CSS and object arguments, inlines other in the first argument as a template string
export default function formatConsoleArguments(
  maybeMessage: any,
  ...inputArgs: $ReadOnlyArray<any>
): $ReadOnlyArray<an

eMessage.length; ++i) {
    const currentChar = maybeMessage[i];
    if (currentChar !== '%') {
      template += currentChar;
      continue;
    }

    const nextChar = maybeMessage[i + 1];
    ++i;

    // Only keep CSS and objects, inline other argumen

y> {
  if (inputArgs.length === 0 || typeof maybeMessage !== 'string') {
    return [maybeMessage, ...inputArgs];
  }

  const args = inputArgs.slice();

  let template = '';
  let argumentsPointer = 0;
  for (let i = 0; i < mayb


iates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

// Do not add / import anything to this file.
// This function could be used from multiple places, including hook.

// Formats an array of args with a style for console methods, using
// the following algorithm:
//     1. The first param is a string that contains %c
//          - Bail out and return the args without modifying the styles.
//            We do

     - Note: we assume that the string formatting that the developer uses
//            is correct.
//     3. The first param is a string that doesn't contain string formatting
//        OR is not a string
//          - Create a formatting string where:
//

n't want to affect styles that the developer deliberately set.
//     2. The first param is a string that doesn't contain %c but contains
//        string formatting
//          - [`%c${args[0]}`, style, ...args.slice(1)]
//


 MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import type {ReactContext} from 'shared/ReactTypes';
import * as React from 'react';
import {
  createContext,
  useCallback,
  useContext,
  useMemo,
  useReducer,
  useRef,
} from 'react';
import Button from './Button';
import {useModalDismissSignal} from './hooks';

import styles from './ModalDialog.css';

type ID = any;

type DIALOG_ACTION_HIDE = {
  type: 'HIDE',
  id: ID,
};
type DIALOG_ACTION_SHOW =

canBeDismissed: boolean,
  content: React$Node | null,
  id: ID,
  title: React$Node | null,
};

type State = {
  dialogs: Array<Dialog>,
};

type ModalDialogContextType = {
  ...State,
  dispatch: Dispatch,
};

const ModalDialogContext: ReactContext<Modal

{
  type: 'SHOW',
  canBeDismissed?: boolean,
  content: React$Node,
  id: ID,
  title?: React$Node | null,
};

type Action = DIALOG_ACTION_HIDE | DIALOG_ACTION_SHOW;

type Dispatch = (action: Action) => void;

type Dialog = {


 MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import * as React from 'react';
import {useEffect, useRef} from 'react';
import Button from './Button';
import ButtonIcon from './ButtonIcon';
import Icon from './Icon';

import styles from './SearchInput.css';

type Props = {
  goToNextResult: () => void,
  goToPreviousResult: () => void,
  placeholder: string,
  search: (text: string) => void,
  searchIndex: number,
  searchResultsCount: number,
  searchT

  const inputRef = useRef<HTMLInputElement | null>(null);

  const resetSearch = () => search('');

  // $FlowFixMe[missing-local-annot]
  const handleChange = ({currentTarget}) => {
    search(currentTarget.value);
  };
  // $FlowFixMe[missing-local-annot

ext: string,
  testName?: ?string,
};

export default function SearchInput({
  goToNextResult,
  goToPreviousResult,
  placeholder,
  search,
  searchIndex,
  searchResultsCount,
  searchText,
  testName,
}: Props): React.Node {


****/

export const enableActivitySlices: boolean = __DEV__;
export const enableLogger: boolean = false;
export const enableStyleXFeatures: boolean = false;
export const isInternalFacebookBuild: boolean = false;

/***************


iates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import * as React from 'react';
import {Fragment} from 'react';
import styles from './EditableValue.css';
import {useEditableValue} from '../hooks';

type OverrideValueFn = (path: Array<string | number>, value: any) => void;

type EditableValueProps = {
  className?: string,
  overrideValue: OverrideValueFn,
  path: Array<string | number>,
  value: any,
};

alid, parsedValue} = state;

  const reset = () =>
    dispatch({
      type: 'RESET',
      externalValue: value,
    });

  // $FlowFixMe[missing-local-annot]
  const handleChange = ({target}) =>
    dispatch({
      type: 'UPDATE',
      editableValue:

export default function EditableValue({
  className = '',
  overrideValue,
  path,
  value,
}: EditableValueProps): React.Node {
  const [state, dispatch] = useEditableValue(value);
  const {editableValue, hasPendingChanges, isV


import * as React from 'react';
import {Fragment, startTransition, useContext, useMemo, useState} from 'react';
import Store from 'react-devtools-shared/src/devtools/store';
import {ElementTypeActivity} from 'react-devtools-shared/src/frontend/types';
import ButtonIcon from '../ButtonIcon';
import {TreeDispatcherContext, TreeStateContext} from './TreeContext';
import {StoreContext} from '../context';
import {useSubscription} from '../hooks';
import {logEvent} from 'react-devtools-shared/src/Logger';
import

nd/types';

import styles from './Element.css';
import Icon from '../Icon';
import {useChangeOwnerAction} from './OwnersListContext';
import Tooltip from './reach-ui/tooltip';
import {useChangeActivitySliceAction} from '../SuspenseTab/ActivityList';

type

IndexableElementBadges from './IndexableElementBadges';
import IndexableDisplayName from './IndexableDisplayName';

import type {ItemData} from './Tree';
import type {Element as ElementType} from 'react-devtools-shared/src/fronte


ight (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import * as React from 'react';

import Badge from './Badge';
import ForgetBadge from './ForgetBadge';

import styles from './ElementBadges.css';

type Props = {
  hocDisplayNames: Array<string> | null,
  environmentName: string | null,
  compiledWithForget: boolean,
  className?: string,
};

export default function El

tName == null
  ) {
    return null;
  }

  return (
    <div className={`${styles.Root} ${className}`}>
      {compiledWithForget && <ForgetBadge indexable={false} />}

      {environmentName != null ? <Badge>{environmentName}</Badge> : null}

      {hocD

ementBadges({
  compiledWithForget,
  environmentName,
  hocDisplayNames,
  className = '',
}: Props): React.Node {
  if (
    !compiledWithForget &&
    (hocDisplayNames == null || hocDisplayNames.length === 0) &&
    environmen


, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import * as React from 'react';
import Button from '../Button';
import ButtonIcon from '../ButtonIcon';

import styles from './ExpandCollapseToggle.css';

type ExpandCollapseToggleProps = {
  disabled: boolean,
  isOpen: boolean,
  setIsOpen: Function,
};

export default function ExpandCollapseToggle({
  disabled,
  isOpen,
  setIsOpen,
}: E

   <Button
      className={styles.ExpandCollapseToggle}
      disabled={disabled}
      onClick={() => setIsOpen(prevIsOpen => !prevIsOpen)}
      title={`${isOpen ? 'Collapse' : 'Expand'} prop value`}>
      <ButtonIcon type={isOpen ? 'expanded' : 'colla

xpandCollapseToggleProps): React.Node {
  return (


 Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import * as React from 'react';

import Badge from './Badge';
import IndexableDisplayName from './IndexableDisplayName';
import Tooltip from './reach-ui/tooltip';

import styles from './ForgetBadge.css';

type CommonProps = {
  className?: string,
};

type PropsForIndexable = CommonProps & {
  indexable: true,

act.Node {
  const {className = ''} = props;

  const innerView = props.indexable ? (
    <IndexableDisplayName displayName="Memo" id={props.elementID} />
  ) : (
    'Memo'
  );

  const title =
    '✨ This component has been auto-memoized by the React Co

elementID: number,
};

type PropsForNonIndexable = CommonProps & {
  indexable: false | void,
  elementID?: number,
};

type Props = PropsForIndexable | PropsForNonIndexable;

export default function ForgetBadge(props: Props): Re


, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import type {ReactContext} from 'shared/ReactTypes';

import type {Thenable} from 'shared/ReactTypes';

import {createContext} from 'react';
import typeof * as ParseHookNamesModule from 'react-devtools-shared/src/hooks/parseHookNames';

export type HookNamesModuleLoaderFunction =
  () => Thenable<ParseHookNamesModule>;
export type Context =

ack 5) Hopefully we can remove this context entirely once the Webpack 5 upgrade is completed.
const HookNamesModuleLoaderContext: ReactContext<Context> =
  createContext<Context>(null);
HookNamesModuleLoaderContext.displayName = 'HookNamesModuleLoaderConte

HookNamesModuleLoaderFunction | null;

// TODO (Webp


 Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import * as React from 'react';

import {createRegExp} from '../utils';

import {TreeStateContext} from './TreeContext';
import styles from './Element.css';

const {useMemo, useContext} = React;

type Props = {
  displayName: string | null,
  id: number,
};

function IndexableDisplayName({displayName, id}: Props): React.Node {
  co

 null && id === searchResults[searchIndex];

  if (!isSearchResult || displayName === null) {
    return displayName;
  }

  const match = createRegExp(searchText).exec(displayName);

  if (match === null) {
    return displayName;
  }

  const startIndex

nst {searchIndex, searchResults, searchText} = useContext(TreeStateContext);
  const isSearchResult = useMemo(() => {
    return searchResults.includes(id);
  }, [id, searchResults]);
  const isCurrentResult =
    searchIndex !==


ight (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import * as React from 'react';

import Badge from './Badge';
import ForgetBadge from './ForgetBadge';
import IndexableDisplayName from './IndexableDisplayName';

import styles from './IndexableElementBadges.css';

type Props = {
  hocDisplayNames: Array<string> | null,
  compiledWithForget: boolean,
  elementID: numbe

== null || hocDisplayNames.length === 0)
  ) {
    return null;
  }

  return (
    <div className={`${styles.Root} ${className}`}>
      {compiledWithForget && (
        <ForgetBadge indexable={true} elementID={elementID} />
      )}

      {hocDisplayNam

r,
  className?: string,
};

export default function IndexableElementBadges({
  compiledWithForget,
  hocDisplayNames,
  elementID,
  className = '',
}: Props): React.Node {
  if (
    !compiledWithForget &&
    (hocDisplayNames


 Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import * as React from 'react';
import {useCallback, useContext, useEffect, useState} from 'react';
import {BridgeContext} from '../context';
import Toggle from '../Toggle';
import ButtonIcon from '../ButtonIcon';
import {logEvent} from 'react-devtools-shared/src/Logger';

export default function InspectHostNodesToggle({
  onlySusp

=> {
      setIsInspecting(isChecked);

      if (isChecked) {
        logEvent({event_name: 'inspect-element-button-clicked'});
        bridge.send('startInspectingHost', !!onlySuspenseNodes);
      } else {
        bridge.send('stopInspectingHost');

enseNodes,
}: {
  onlySuspenseNodes?: boolean,
}): React.Node {
  const [isInspecting, setIsInspecting] = useState(false);
  const bridge = useContext(BridgeContext);

  const handleChange = useCallback(
    (isChecked: boolean)


eContext} from './TreeContext';
import {BridgeContext, StoreContext, OptionsContext} from '../context';
import Button from '../Button';
import ButtonIcon from '../ButtonIcon';
import Icon from '../Icon';
import Toggle from '../Toggle';
import {
  ElementTypeSuspense,
  ElementTypeRoot,
} from 'react-devtools-shared/src/frontend/types';
import InspectedElementView from './InspectedElementView';
import {InspectedElementContext} from './InspectedElementContext';
import {getAlwaysOpenInEditor} from '../../../ut

eSource';
import OpenInEditorButton from './OpenInEditorButton';
import InspectedElementViewSourceButton from './InspectedElementViewSourceButton';
import useEditorURL from '../useEditorURL';

import styles from './InspectedElement.css';
import Tooltip fro

ils';
import {LOCAL_STORAGE_ALWAYS_OPEN_IN_EDITOR} from '../../../constants';
import FetchFileWithCachingContext from './FetchFileWithCachingContext';
import {symbolicateSourceWithCache} from 'react-devtools-shared/src/symbolicat


 Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import * as React from 'react';

import Badge from './Badge';
import ForgetBadge from './ForgetBadge';
import NativeTagBadge from './NativeTagBadge';

import styles from './InspectedElementBadges.css';

type Props = {
  hocDisplayNames: null | Array<string>,
  compiledWithForget: boolean,
  nativeTag: number | nu

) &&
    nativeTag === null
  ) {
    return null;
  }

  return (
    <div className={styles.Root}>
      {compiledWithForget && <ForgetBadge indexable={false} />}
      {nativeTag !== null && <NativeTagBadge nativeTag={nativeTag} />}

      {hocDisplayNa

ll,
};

export default function InspectedElementBadges({
  hocDisplayNames,
  compiledWithForget,
  nativeTag,
}: Props): React.Node {
  if (
    !compiledWithForget &&
    (hocDisplayNames == null || hocDisplayNames.length === 0


import type {ReactContext} from 'shared/ReactTypes';

import * as React from 'react';
import {
  createContext,
  startTransition,
  unstable_useCacheRefresh as useCacheRefresh,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useRef,
  useState,
} from 'react';
import {TreeStateContext} from './TreeContext';
import {BridgeContext, StoreContext} from '../context';
import {
  inspectElement,
  startElementUpdatesPolling,
} from 'react-devtools-shared/src/inspectedElementCache';
import {
  clearHookName

ools-shared/src/devtools/views/Components/FetchFileWithCachingContext';
import HookNamesModuleLoaderContext from 'react-devtools-shared/src/devtools/views/Components/HookNamesModuleLoaderContext';
import {SettingsContext} from '../Settings/SettingsContext'

sCache,
  hasAlreadyLoadedHookNames,
  loadHookNames,
} from 'react-devtools-shared/src/hookNamesCache';
import {loadModule} from 'react-devtools-shared/src/dynamicImportCache';
import FetchFileWithCachingContext from 'react-devt


 MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import {copy} from 'clipboard-js';
import * as React from 'react';
import Button from '../Button';
import ButtonIcon from '../ButtonIcon';
import KeyValue from './KeyValue';
import {alphaSortEntries, serializeDataForCopy} from '../utils';
import Store from '../../store';
import styles from './InspectedElementSharedStyles.css';
import {
  ElementTypeClass,
  ElementTypeFunction,
} from 'react-devtools-shared

e} from 'react-devtools-shared/src/bridge';
import type {Element} from 'react-devtools-shared/src/frontend/types';

type Props = {
  bridge: FrontendBridge,
  element: Element,
  inspectedElement: InspectedElement,
  store: Store,
};

export default functi

/src/frontend/types';
import {withPermissionsCheck} from 'react-devtools-shared/src/frontend/utils/withPermissionsCheck';

import type {InspectedElement} from 'react-devtools-shared/src/frontend/types';
import type {FrontendBridg


ight (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import * as React from 'react';
import {
  useCallback,
  useContext,
  unstable_useCacheRefresh as useCacheRefresh,
} from 'react';
import ErrorBoundary from '../ErrorBoundary';
import {TreeStateContext} from './TreeContext';
import {clearCacheBecauseOfError} from '../../../inspectedElementCache';
import styles from '

D so that changing the selected element automatically hides the boundary.
  // This seems best since an error inspecting one element isn't likely to be relevant to another element.
  const {inspectedElementID} = useContext(TreeStateContext);

  const refre

./InspectedElementErrorBoundary.css';

type WrapperProps = {
  children: React$Node,
};

export default function InspectedElementErrorBoundaryWrapper({
  children,
}: WrapperProps): React.Node {
  // Key on the selected element I


 MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import * as React from 'react';
import {
  unstable_useCacheRefresh as useCacheRefresh,
  useTransition,
} from 'react';
import Button from '../Button';
import ButtonIcon from '../ButtonIcon';
import Store from '../../store';
import sharedStyles from './InspectedElementSharedStyles.css';
import styles from './InspectedElementErrorsAndWarningsTree.css';
import {
  clearErrorsForElement as clearErrorsForEleme

act-devtools-shared/src/bridge';

type Props = {
  bridge: FrontendBridge,
  inspectedElement: InspectedElement,
  store: Store,
};

export default function InspectedElementErrorsAndWarningsTree({
  bridge,
  inspectedElement,
  store,
}: Props): React.Nod

ntAPI,
  clearWarningsForElement as clearWarningsForElementAPI,
} from 'react-devtools-shared/src/backendAPI';

import type {InspectedElement} from 'react-devtools-shared/src/frontend/types';
import type {FrontendBridge} from 're


tton';
import ButtonIcon from '../ButtonIcon';
import Toggle from '../Toggle';
import ExpandCollapseToggle from './ExpandCollapseToggle';
import KeyValue from './KeyValue';
import {getMetaValueLabel, serializeHooksForCopy} from '../utils';
import Store from '../../store';
import styles from './InspectedElementHooksTree.css';
import {meta} from '../../../hydration';
import {getHookSourceLocationKey} from 'react-devtools-shared/src/hookSourceLocation';
import HookNamesModuleLoaderContext from 'react-devtools-

 HooksTree} from 'react-debug-tools/src/ReactDebugHooks';
import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
import type {HookNames} from 'react-devtools-shared/src/frontend/types';
import type {Element} from 'react-devtools-shared/src/f

shared/src/devtools/views/Components/HookNamesModuleLoaderContext';
import isArray from 'react-devtools-shared/src/isArray';

import type {InspectedElement} from 'react-devtools-shared/src/frontend/types';
import type {HooksNode,


 MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import {copy} from 'clipboard-js';
import * as React from 'react';
import {OptionsContext} from '../context';
import Button from '../Button';
import ButtonIcon from '../ButtonIcon';
import KeyValue from './KeyValue';
import NewKeyValue from './NewKeyValue';
import {alphaSortEntries, serializeDataForCopy} from '../utils';
import Store from '../../store';
import styles from './InspectedElementSharedStyles.css

import type {InspectedElement} from 'react-devtools-shared/src/frontend/types';
import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
import type {Element} from 'react-devtools-shared/src/frontend/types';

type Props = {
  bridge: Frontend

';
import {
  ElementTypeClass,
  ElementTypeSuspense,
  ElementTypeActivity,
} from 'react-devtools-shared/src/frontend/types';
import {withPermissionsCheck} from 'react-devtools-shared/src/frontend/utils/withPermissionsCheck';


iates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import * as React from 'react';
import {Fragment, useContext, useEffect} from 'react';
import {BridgeContext} from './context';
import {ModalDialogContext} from './ModalDialog';

import styles from './WarnIfLegacyBackendDetected.css';

export default function WarnIfLegacyBackendDetected(_: {}): null {
  const bridge = useContext(BridgeContext);
  const {dis

tructions.
  useEffect(() => {
    // Wall.listen returns a cleanup function
    let unlisten: $FlowFixMe = bridge.wall.listen(message => {
      switch (message.type) {
        case 'call':
        case 'event':
        case 'many-events':
          // An

patch} = useContext(ModalDialogContext);

  // Detect pairing with legacy v3 backend.
  // We do this by listening to a message that it broadcasts but the v4 backend doesn't.
  // In this case the frontend should show upgrade ins


 Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import * as React from 'react';
import {useContext} from 'react';
import {createPortal} from 'react-dom';
import ErrorBoundary from './ErrorBoundary';
import {StoreContext} from './context';
import ThemeProvider from './ThemeProvider';

export type Props = {portalContainer?: Element, ...};

export default function portaledContent(

ore={store}>
        <Component {...rest} />
      </ErrorBoundary>
    );

    if (portalContainer != null) {
      // The ThemeProvider works by writing DOM style variables to an HTMLDivElement.
      // Because Portals render in a different DOM subtree,

  Component: component(...props: any),
): component(...props: any) {
  return function PortaledContent({portalContainer, ...rest}: Props) {
    const store = useContext(StoreContext);

    let children = (
      <ErrorBoundary st


ctTypes';

import type {SourceMappedLocation} from 'react-devtools-shared/src/symbolicateSource';

import type {SerializedAsyncInfo} from 'react-devtools-shared/src/frontend/types';

import FetchFileWithCachingContext from './Components/FetchFileWithCachingContext';

import {symbolicateSourceWithCache} from 'react-devtools-shared/src/symbolicateSource';

export default function useInferredName(
  asyncInfo: SerializedAsyncInfo,
): string {
  const fetchFileWithCaching = useContext(FetchFileWithCachingContex

 We only do this if the stack has more than one frame since
    // otherwise it's likely to just be the name of the component which isn't better.
    const bestStack = asyncInfo.awaited.stack || asyncInfo.stack;
    if (bestStack !== null && bestStack.leng

t);
  const name = asyncInfo.awaited.name;
  let inferNameFromStack = null;
  if (!name || name === 'Promise' || name === 'lazy') {
    // If all we have is a generic name, we can try to infer a better name from
    // the stack.


import escapeStringRegExp from 'escape-string-regexp';
import {meta} from '../../hydration';
import {formatDataForPreview} from '../../utils';
import isArray from 'react-devtools-shared/src/isArray';

import type {HooksTree} from 'react-debug-tools/src/ReactDebugHooks';

// $FlowFixMe[method-unbinding]
const hasOwnProperty = Object.prototype.hasOwnProperty;

export function alphaSortEntries(
  entryA: [string, mixed],
  entryB: [string, mixed],
): number {
  const a = entryA[0];
  const b = entryB[0];
  if

ast /
  if (string[0] === '/') {
    // Cut off first slash
    string = string.slice(1);
    // Cut off last slash, but only if it's there
    if (string[string.length - 1] === '/') {
      string = string.slice(0, string.length - 1);
    }
    try {

(String(+a) === a) {
    if (String(+b) !== b) {
      return -1;
    }
    return +a < +b ? -1 : 1;
  }
  return a < b ? -1 : 1;
}

export function createRegExp(string: string): RegExp {
  // Allow /regex/ syntax with optional l


ight (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import * as React from 'react';
import {useContext} from 'react';

import portaledContent from 'react-devtools-shared/src/devtools/views/portaledContent';
import {OptionsContext} from 'react-devtools-shared/src/devtools/views/context';
import InspectedElement from 'react-devtools-shared/src/devtools/views/Components/In

import {SettingsModalContextController} from 'react-devtools-shared/src/devtools/views/Settings/SettingsModalContext';
import styles from './InspectedElementPane.css';

function InspectedElementPane() {
  const {hideSettings} = useContext(OptionsContext);

spectedElement';
import SettingsModal from 'react-devtools-shared/src/devtools/views/Settings/SettingsModal';
import SettingsModalContextToggle from 'react-devtools-shared/src/devtools/views/Settings/SettingsModalContextToggle';


 Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import * as React from 'react';
import {useState, useContext, useCallback} from 'react';

import SearchInput from 'react-devtools-shared/src/devtools/views/SearchInput';
import {
  TreeDispatcherContext,
  TreeStateContext,
} from 'react-devtools-shared/src/devtools/views/Components/TreeContext';

export default function ComponentS

nst search = useCallback(
    (text: string) => {
      setLocalSearchQuery(text);
      transitionDispatch({type: 'SET_SEARCH_TEXT', payload: text});
    },
    [setLocalSearchQuery, transitionDispatch],
  );
  const goToNextResult = useCallback(
    () =

earchInput(): React.Node {
  const [localSearchQuery, setLocalSearchQuery] = useState('');
  const {searchIndex, searchResults} = useContext(TreeStateContext);
  const transitionDispatch = useContext(TreeDispatcherContext);

  co


iates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import * as React from 'react';
import {useCallback, useState} from 'react';
import AutoSizeInput from './NativeStyleEditor/AutoSizeInput';
import styles from './EditableName.css';

type Type = 'props' | 'state' | 'context' | 'hooks';
type OverrideNameFn = (
  oldName: Array<string | number>,
  newName: Array<string | number>,
) => void;

type EditableNameP

function EditableName({
  allowEmpty = false,
  allowWhiteSpace = false,
  autoFocus = false,
  className = '',
  initialValue = '',
  overrideName,
  path,
  type,
}: EditableNameProps): React.Node {
  const [editableName, setEditableName] = useState(init

rops = {
  allowEmpty?: boolean,
  allowWhiteSpace?: boolean,
  autoFocus?: boolean,
  className?: string,
  initialValue?: string,
  overrideName: OverrideNameFn,
  path: Array<string | number>,
  type: Type,
};

export default


tools/views/Settings/SettingsContext';

export const THEME_STYLES: {[style: Theme | DisplayDensity]: any, ...} = {
  light: {
    '--color-attribute-name': '#ef6632',
    '--color-attribute-name-not-editable': '#23272f',
    '--color-attribute-name-inverted': 'rgba(255, 255, 255, 0.7)',
    '--color-attribute-value': '#1a1aa6',
    '--color-attribute-value-inverted': '#ffffff',
    '--color-attribute-editable-value': '#1a1aa6',
    '--color-background': '#ffffff',
    '--color-background-hover': 'rgba(0, 13

cus': '#ededed',
    '--color-button-background-hover': 'rgba(0, 0, 0, 0.2)',
    '--color-button': '#5f6673',
    '--color-button-disabled': '#cfd1d5',
    '--color-button-active': '#0088fa',
    '--color-button-focus': '#23272f',
    '--color-button-hove

6, 250, 0.1)',
    '--color-background-inactive': '#e5e5e5',
    '--color-background-invalid': '#fff0f0',
    '--color-background-selected': '#0088fa',
    '--color-button-background': '#ffffff',
    '--color-button-background-fo


eact';
import {useCallback, useEffect, useLayoutEffect, useMemo, useRef} from 'react';
import Store from '../store';
import {
  BridgeContext,
  ContextMenuContext,
  StoreContext,
  OptionsContext,
} from './context';
import Components from './Components/Components';
import Profiler from './Profiler/Profiler';
import SuspenseTab from './SuspenseTab/SuspenseTab';
import TabBar from './TabBar';
import EditorPane from './Editor/EditorPane';
import InspectedElementPane from './InspectedElement/InspectedElement

chFileWithCachingContext from './Components/FetchFileWithCachingContext';
import {InspectedElementContextController} from './Components/InspectedElementContext';
import HookNamesModuleLoaderContext from 'react-devtools-shared/src/devtools/views/Components/

Pane';
import {SettingsContextController} from './Settings/SettingsContext';
import {TreeContextController} from './Components/TreeContext';
import ViewElementSourceContext from './Components/ViewElementSourceContext';
import Fet