From c2abf11133ffea7980f2bdbae9fcf669f90f389a Mon Sep 17 00:00:00 2001 From: Juan Tejada Date: Fri, 8 Oct 2021 09:31:26 -0400 Subject: [PATCH 1/2] [DevTools] Update isMountedImpl to match implementation in React --- .../src/backend/renderer.js | 61 ++++++------------- 1 file changed, 20 insertions(+), 41 deletions(-) diff --git a/packages/react-devtools-shared/src/backend/renderer.js b/packages/react-devtools-shared/src/backend/renderer.js index 011f055e505a8..75bdae018594b 100644 --- a/packages/react-devtools-shared/src/backend/renderer.js +++ b/packages/react-devtools-shared/src/backend/renderer.js @@ -128,6 +128,7 @@ type ReactTypeOfSideEffectType = {| PerformedWork: number, Placement: number, Incomplete: number, + Hydrating: number, |}; function getFiberFlags(fiber: Fiber): number { @@ -156,6 +157,7 @@ export function getInternalReactConstants( PerformedWork: 0b01, Placement: 0b10, Incomplete: 0b10000000000000, + Hydrating: 0b0000000000001000000000000, }; // ********************************************************** @@ -526,7 +528,7 @@ export function attach( } = getInternalReactConstants(version); const { DidCapture, - Incomplete, + Hydrating, NoFlags, PerformedWork, Placement, @@ -2707,51 +2709,28 @@ export function attach( return null; } - const MOUNTING = 1; const MOUNTED = 2; const UNMOUNTED = 3; // 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 isFiberMountedImpl(fiber: Fiber): number { + function getNearestMountedFiber(fiber: Fiber): null | Fiber { let node = fiber; - let prevNode = null; + let nearestMounted = 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. - if ((getFiberFlags(node) & Placement) !== NoFlags) { - return MOUNTING; - } - // This indicates an error during render. - if ((getFiberFlags(node) & Incomplete) !== NoFlags) { - return UNMOUNTED; - } - while (node.return) { - prevNode = node; - node = node.return; - - if ((getFiberFlags(node) & Placement) !== NoFlags) { - return MOUNTING; - } - // This indicates an error during render. - if ((getFiberFlags(node) & Incomplete) !== NoFlags) { - return UNMOUNTED; + let nextNode = node; + do { + node = nextNode; + if ((node.flags & (Placement | Hydrating)) !== NoFlags) { + // 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; } - - // If this node is inside of a timed out suspense subtree, we should also ignore errors/warnings. - const isTimedOutSuspense = - node.tag === SuspenseComponent && node.memoizedState !== null; - if (isTimedOutSuspense) { - // Note that this does not include errors/warnings in the Fallback tree though! - const primaryChildFragment = node.child; - const fallbackChildFragment = primaryChildFragment - ? primaryChildFragment.sibling - : null; - if (prevNode !== fallbackChildFragment) { - return UNMOUNTED; - } - } - } + nextNode = node.return; + } while (nextNode); } else { while (node.return) { node = node.return; @@ -2760,11 +2739,14 @@ export function attach( if (node.tag === HostRoot) { // TODO: Check if this was a nested HostRoot when used with // renderContainerIntoSubtree. - return MOUNTED; + return nearestMounted; } // If we didn't hit the root, that means that we're in an disconnected tree // that has been unmounted. - return UNMOUNTED; + return null; + } + function isFiberMountedImpl(fiber: Fiber): number { + return getNearestMountedFiber(fiber) === fiber ? MOUNTED : UNMOUNTED; } // This function is copied from React and should be kept in sync: @@ -2785,9 +2767,6 @@ export function attach( if (state === UNMOUNTED) { throw Error('Unable to find node on an unmounted component.'); } - if (state === MOUNTING) { - return null; - } return fiber; } // If we have two possible branches, we'll walk backwards up to the root From 75e3f24b0b421290a0a36fa646efe2371e65a905 Mon Sep 17 00:00:00 2001 From: Juan Tejada Date: Fri, 8 Oct 2021 15:50:54 -0400 Subject: [PATCH 2/2] Also sync findCurrentFiberUsingSlowPathById --- .../src/backend/renderer.js | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/packages/react-devtools-shared/src/backend/renderer.js b/packages/react-devtools-shared/src/backend/renderer.js index 75bdae018594b..19155cb4e354f 100644 --- a/packages/react-devtools-shared/src/backend/renderer.js +++ b/packages/react-devtools-shared/src/backend/renderer.js @@ -157,7 +157,7 @@ export function getInternalReactConstants( PerformedWork: 0b01, Placement: 0b10, Incomplete: 0b10000000000000, - Hydrating: 0b0000000000001000000000000, + Hydrating: 0b1000000000000, }; // ********************************************************** @@ -2709,8 +2709,13 @@ export function attach( return null; } - const MOUNTED = 2; - const UNMOUNTED = 3; + // 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) { + 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 @@ -2745,9 +2750,6 @@ export function attach( // that has been unmounted. return null; } - function isFiberMountedImpl(fiber: Fiber): number { - return getNearestMountedFiber(fiber) === fiber ? MOUNTED : UNMOUNTED; - } // 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 @@ -2763,9 +2765,14 @@ export function attach( const alternate = fiber.alternate; if (!alternate) { // If there is no alternate, then we only need to check if it is mounted. - const state = isFiberMountedImpl(fiber); - if (state === UNMOUNTED) { - throw Error('Unable to find node on an unmounted component.'); + 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; } @@ -2803,23 +2810,20 @@ export function attach( while (child) { if (child === a) { // We've determined that A is the current branch. - if (isFiberMountedImpl(parentA) !== MOUNTED) { - throw Error('Unable to find node on an unmounted component.'); - } + assertIsMounted(parentA); return fiber; } if (child === b) { // We've determined that B is the current branch. - if (isFiberMountedImpl(parentA) !== MOUNTED) { - throw Error('Unable to find node on an unmounted component.'); - } + 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 Error('Unable to find node on an unmounted component.'); + throw new Error('Unable to find node on an unmounted component.'); } if (a.return !== b.return) { @@ -2870,8 +2874,9 @@ export function attach( } child = child.sibling; } + if (!didFindChild) { - throw Error( + 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.', ); @@ -2880,17 +2885,19 @@ export function attach( } if (a.alternate !== b) { - throw Error( + 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 Error('Unable to find node on an unmounted component.'); + 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;