[DevTools] Add ignore-listed stack frame disclosure (#36828)
GitHub Commits - Example: React

[DevTools] Add ignore-listed stack frame disclosure (#36828)

[DevTools] Add ignore-listed stack frame disclosure (#36828)

The diff introduces a new StackTraceGroup component that wraps stack trace displays and adds a toggle button for showing/hiding ignore-listed frames.

New imports

import { use, useContext, useState, useTransition } from 'react';
import FetchFileWithCachingContext from './FetchFileWithCachingContext';
import StackTraceView, { IgnoreListToggleButton } from './StackTraceView';
import Skeleton from './Skeleton';
import { symbolicateSourceWithCache } from 'react-devtools-shared/src/symbolicateSource';
import type { ReactStackTrace } from 'shared/ReactTypes';
import type { SourceMappedLocation } from 'react-devtools-shared/src/symbolicateSource';

New StackTraceGroup component

type StackTraceGroupProps = {
  children: (showIgnoreList: boolean) => React.Node,
  ioStack: null | ReactStackTrace,
  asyncInfoStack: null | ReactStackTrace,
};

function StackTraceGroup({
  children,
  ioStack,
  asyncInfoStack,
}: StackTraceGroupProps): React.Node {
  const [showIgnoreList, setShowIgnoreList] = useState(false);
  const fetchFileWithCaching = useContext(FetchFileWithCachingContext);

  const ioStackHasIgnoredFrames =
    ioStack !== null &&
    ioStack.some(callSite => {
      const [ , virtualURL, virtualLine, virtualColumn ] = callSite;

      // symbolicated output is cached
      const symbolicatedCallSite: null | SourceMappedLocation =
        fetchFileWithCaching !== null
          ? use(
              symbolicateSourceWithCache(
                fetchFileWithCaching,
                virtualURL,
                virtualLine,
                virtualColumn,
              ),
            )
          : null;

      return symbolicatedCallSite !== null && symbolicatedCallSite.ignored;
    });

  const asyncInfoStackHasIgnoredFrames =
    asyncInfoStack !== null &&
    asyncInfoStack.some(callSite => {
      const [ , virtualURL, virtualLine, virtualColumn ] = callSite;

      // symbolicated output is cached
      const symbolicatedCallSite: null | SourceMappedLocation =
        fetchFileWithCaching !== null
          ? use(
              symbolicateSourceWithCache(
                fetchFileWithCaching,
                virtualURL,
                virtualLine,
                virtualColumn,
              ),
            )
          : null;

      return symbolicatedCallSite !== null && symbolicatedCallSite.ignored;
    });

  const hasIgnoredFrames =
    ioStackHasIgnoredFrames || asyncInfoStackHasIgnoredFrames;

  return (
    <>
      {children(showIgnoreList)}
      {hasIgnoredFrames && (
        <IgnoreListToggleButton
          onClick={() => setShowIgnoreList(prev => !prev)}
          showIgnoreList={showIgnoreList}
        />
      )}
    </>
  );
}

Updated SuspendedByRow component

The SuspendedByRow component now wraps its stack trace content in a StackTraceGroup:

function SuspendedByRow({
  bridge,
  element,
  // ...
}) {
  // ...
  {isOpen && (
    <StackTraceGroup
      ioStack={ioStack}
      asyncInfoStack={asyncInfoStack}
    >
      {(showIgnoreList: boolean) => (
        <>
          {showIOStack && (
            // IO stack trace view
          )}
          {ioOwner !== null &&
            ioOwner.id !== inspectedElement.id &&
            (showIOStack ||
              !showAwaitStack ||
              asyncOwner === null ||
              ioOwner.id !== asyncOwner.id) ? (
            // IO owner view
          ) : null}
          {showAwaitStack ? (
            <>
              awaited at:
              {asyncInfo.stack !== null &&
                asyncInfo.stack.length > 0 && (
                // Async stack trace view
              )}
              {asyncOwner !== null &&
                asyncOwner.id !== inspectedElement.id ? (
                // Async owner view
              ) : null}
            </>
          ) : null}
        </>
      )}
    </StackTraceGroup>
  )}
}

0 commit comments

Comments

No comments yet. Start the discussion.