Skip to content

Commit

Permalink
DevTools: Inline references to fiber flags (facebook#26542)
Browse files Browse the repository at this point in the history
We shouldn't be referencing internal fields like fiber's `flag` directly
of DevTools. It's an implementation detail. However, over the years a
few of these have snuck in. Because of how DevTools is currently
shipped, where it's expected to be backwards compatible with older
versions of React, this prevents us from refactoring those fields inside
the reconciler.

The plan we have to address this is to fix how DevTools is shipped:
DevTools will be released in lockstep with each version of React.

Until then, though, I need a temporary solution because it's blocking a
feature I'm working on. So in meantime, I'm going to have to fork the
DevTool's code based on the React version, like we already do with the
fiber TypeOfWork enum.

As a first step, I've inlined all the references to fiber flags into the
specific call sites where they are used. Eventually we'll import these
functions from the reconciler so they stay in sync, rather than
maintaining duplicate copies of the logic.
  • Loading branch information
acdlite authored and AndyPengc12 committed Apr 15, 2024
1 parent e1df5a8 commit c8ec58d
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 30 deletions.
17 changes: 0 additions & 17 deletions packages/react-devtools-shared/src/backend/ReactFiberFlags.js

This file was deleted.

32 changes: 19 additions & 13 deletions packages/react-devtools-shared/src/backend/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,6 @@ import {
MEMO_SYMBOL_STRING,
SERVER_CONTEXT_SYMBOL_STRING,
} from './ReactSymbols';
import {
DidCapture,
NoFlags,
PerformedWork,
Placement,
Hydrating,
} from './ReactFiberFlags';
import {format} from './utils';
import {
enableProfilerChangedHookIndices,
Expand Down Expand Up @@ -1555,7 +1548,10 @@ export function attach(
case ForwardRef:
// For types that execute user code, we check PerformedWork effect.
// We don't reflect bailouts (either referential or sCU) in DevTools.
// eslint-disable-next-line no-bitwise
// TODO: This flag is a leaked implementation detail. Once we start
// releasing DevTools in lockstep with React, we should import a
// function from the reconciler instead.
const PerformedWork = 0b000000000000000000000000001;
return (getFiberFlags(nextFiber) & PerformedWork) === PerformedWork;
// Note: ContextConsumer only gets PerformedWork effect in 16.3.3+
// so it won't get highlighted with React 16.3.0 to 16.3.2.
Expand Down Expand Up @@ -2843,7 +2839,12 @@ export function attach(
let nextNode: Fiber = node;
do {
node = nextNode;
if ((node.flags & (Placement | Hydrating)) !== NoFlags) {
// TODO: This function, and these flags, are a leaked implementation
// detail. Once we start releasing DevTools in lockstep with React, we
// should import a function from the reconciler instead.
const Placement = 0b000000000000000000000000010;
const Hydrating = 0b000000000000001000000000000;
if ((node.flags & (Placement | Hydrating)) !== 0) {
// This is an insertion or in-progress hydration. The nearest possible
// mounted fiber is the parent but we need to continue to figure out
// if that one is still mounted.
Expand Down Expand Up @@ -3300,16 +3301,21 @@ export function attach(
const errors = fiberIDToErrorsMap.get(id) || new Map();
const warnings = fiberIDToWarningsMap.get(id) || new Map();

const isErrored =
(fiber.flags & DidCapture) !== NoFlags ||
forceErrorForFiberIDs.get(id) === true;

let isErrored = false;
let targetErrorBoundaryID;
if (isErrorBoundary(fiber)) {
// if the current inspected element is an error boundary,
// either that we want to use it to toggle off error state
// or that we allow to force error state on it if it's within another
// error boundary
//
// TODO: This flag is a leaked implementation detail. Once we start
// releasing DevTools in lockstep with React, we should import a function
// from the reconciler instead.
const DidCapture = 0b000000000000000000010000000;
isErrored =
(fiber.flags & DidCapture) !== 0 ||
forceErrorForFiberIDs.get(id) === true;
targetErrorBoundaryID = isErrored ? id : getNearestErrorBoundaryID(fiber);
} else {
targetErrorBoundaryID = getNearestErrorBoundaryID(fiber);
Expand Down

0 comments on commit c8ec58d

Please sign in to comment.