Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DevTools] Remove findCurrentFiberUsingSlowPathByFiberInstance #30818

Merged
merged 1 commit into from
Aug 27, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
221 changes: 7 additions & 214 deletions packages/react-devtools-shared/src/backend/fiber/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3512,7 +3512,7 @@ export function attach(
fiberInstance: FiberInstance,
): $ReadOnlyArray<HostInstance> {
const hostInstances = [];
const fiber = findCurrentFiberUsingSlowPathByFiberInstance(fiberInstance);
const fiber = fiberInstance.data;
if (!fiber) {
return hostInstances;
}
Expand Down Expand Up @@ -3563,8 +3563,7 @@ export function attach(
// TODO: Handle VirtualInstance.
return null;
}
const fiber =
findCurrentFiberUsingSlowPathByFiberInstance(devtoolsInstance);
const fiber = devtoolsInstance.data;
if (fiber === null) {
return null;
}
Expand Down Expand Up @@ -3672,208 +3671,6 @@ export function attach(
return null;
}

// This function is copied from React and should be kept in sync:
// https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactFiberTreeReflection.js
function assertIsMounted(fiber: Fiber) {
if (getNearestMountedFiber(fiber) !== fiber) {
throw new Error('Unable to find node on an unmounted component.');
}
}

// This function is copied from React and should be kept in sync:
// https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactFiberTreeReflection.js
function getNearestMountedFiber(fiber: Fiber): null | Fiber {
let node = fiber;
let nearestMounted: null | Fiber = fiber;
if (!fiber.alternate) {
// If there is no alternate, this might be a new tree that isn't inserted
// yet. If it is, then it will have a pending insertion effect on it.
let nextNode: Fiber = node;
do {
node = nextNode;
// 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.
nearestMounted = node.return;
}
// $FlowFixMe[incompatible-type] we bail out when we get a null
nextNode = node.return;
} while (nextNode);
} else {
while (node.return) {
node = node.return;
}
}
if (node.tag === HostRoot) {
// TODO: Check if this was a nested HostRoot when used with
// renderContainerIntoSubtree.
return nearestMounted;
}
// If we didn't hit the root, that means that we're in an disconnected tree
// that has been unmounted.
return null;
}

// This function is copied from React and should be kept in sync:
// https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactFiberTreeReflection.js
// It would be nice if we updated React to inject this function directly (vs just indirectly via findDOMNode).
// BEGIN copied code
function findCurrentFiberUsingSlowPathByFiberInstance(
fiberInstance: FiberInstance,
): Fiber | null {
const fiber = fiberInstance.data;
const alternate = fiber.alternate;
if (!alternate) {
// If there is no alternate, then we only need to check if it is mounted.
const nearestMounted = getNearestMountedFiber(fiber);

if (nearestMounted === null) {
throw new Error('Unable to find node on an unmounted component.');
}

if (nearestMounted !== fiber) {
return null;
}
return fiber;
}
// If we have two possible branches, we'll walk backwards up to the root
// to see what path the root points to. On the way we may hit one of the
// special cases and we'll deal with them.
let a: Fiber = fiber;
let b: Fiber = alternate;
while (true) {
const parentA = a.return;
if (parentA === null) {
// We're at the root.
break;
}
const parentB = parentA.alternate;
if (parentB === null) {
// There is no alternate. This is an unusual case. Currently, it only
// happens when a Suspense component is hidden. An extra fragment fiber
// is inserted in between the Suspense fiber and its children. Skip
// over this extra fragment fiber and proceed to the next parent.
const nextParent = parentA.return;
if (nextParent !== null) {
a = b = nextParent;
continue;
}
// If there's no parent, we're at the root.
break;
}

// If both copies of the parent fiber point to the same child, we can
// assume that the child is current. This happens when we bailout on low
// priority: the bailed out fiber's child reuses the current child.
if (parentA.child === parentB.child) {
let child = parentA.child;
while (child) {
if (child === a) {
// We've determined that A is the current branch.
assertIsMounted(parentA);
return fiber;
}
if (child === b) {
// We've determined that B is the current branch.
assertIsMounted(parentA);
return alternate;
}
child = child.sibling;
}

// We should never have an alternate for any mounting node. So the only
// way this could possibly happen is if this was unmounted, if at all.
throw new Error('Unable to find node on an unmounted component.');
}

if (a.return !== b.return) {
// The return pointer of A and the return pointer of B point to different
// fibers. We assume that return pointers never criss-cross, so A must
// belong to the child set of A.return, and B must belong to the child
// set of B.return.
a = parentA;
b = parentB;
} else {
// The return pointers point to the same fiber. We'll have to use the
// default, slow path: scan the child sets of each parent alternate to see
// which child belongs to which set.
//
// Search parent A's child set
let didFindChild = false;
let child = parentA.child;
while (child) {
if (child === a) {
didFindChild = true;
a = parentA;
b = parentB;
break;
}
if (child === b) {
didFindChild = true;
b = parentA;
a = parentB;
break;
}
child = child.sibling;
}
if (!didFindChild) {
// Search parent B's child set
child = parentB.child;
while (child) {
if (child === a) {
didFindChild = true;
a = parentB;
b = parentA;
break;
}
if (child === b) {
didFindChild = true;
b = parentB;
a = parentA;
break;
}
child = child.sibling;
}

if (!didFindChild) {
throw new Error(
'Child was not found in either parent set. This indicates a bug ' +
'in React related to the return pointer. Please file an issue.',
);
}
}
}

if (a.alternate !== b) {
throw new Error(
"Return fibers should always be each others' alternates. " +
'This error is likely caused by a bug in React. Please file an issue.',
);
}
}

// If the root is not a host container, we're in a disconnected tree. I.e.
// unmounted.
if (a.tag !== HostRoot) {
throw new Error('Unable to find node on an unmounted component.');
}

if (a.stateNode.current === a) {
// We've determined that A is the current branch.
return fiber;
}
// Otherwise B has to be current branch.
return alternate;
}

// END copied code

function getElementAttributeByPath(
id: number,
path: Array<string | number>,
Expand Down Expand Up @@ -4058,8 +3855,7 @@ export function attach(
return {instance, style};
}

const fiber =
findCurrentFiberUsingSlowPathByFiberInstance(devtoolsInstance);
const fiber = devtoolsInstance.data;
if (fiber !== null) {
instance = fiber.stateNode;

Expand Down Expand Up @@ -4115,7 +3911,7 @@ export function attach(
function inspectFiberInstanceRaw(
fiberInstance: FiberInstance,
): InspectedElement | null {
const fiber = findCurrentFiberUsingSlowPathByFiberInstance(fiberInstance);
const fiber = fiberInstance.data;
if (fiber == null) {
return null;
}
Expand Down Expand Up @@ -4877,8 +4673,7 @@ export function attach(
// TODO: Handle VirtualInstance.
return;
}
const fiber =
findCurrentFiberUsingSlowPathByFiberInstance(devtoolsInstance);
const fiber = devtoolsInstance.data;
if (fiber !== null) {
const instance = fiber.stateNode;

Expand Down Expand Up @@ -4943,8 +4738,7 @@ export function attach(
// TODO: Handle VirtualInstance.
return;
}
const fiber =
findCurrentFiberUsingSlowPathByFiberInstance(devtoolsInstance);
const fiber = devtoolsInstance.data;
if (fiber !== null) {
const instance = fiber.stateNode;

Expand Down Expand Up @@ -5019,8 +4813,7 @@ export function attach(
// TODO: Handle VirtualInstance.
return;
}
const fiber =
findCurrentFiberUsingSlowPathByFiberInstance(devtoolsInstance);
const fiber = devtoolsInstance.data;
if (fiber !== null) {
const instance = fiber.stateNode;

Expand Down
Loading