@@ -128,6 +128,7 @@ type ReactTypeOfSideEffectType = {|
128128 PerformedWork : number ,
129129 Placement : number ,
130130 Incomplete : number ,
131+ Hydrating : number ,
131132| } ;
132133
133134function getFiberFlags ( fiber : Fiber ) : number {
@@ -156,6 +157,7 @@ export function getInternalReactConstants(
156157 PerformedWork : 0b01 ,
157158 Placement : 0b10 ,
158159 Incomplete : 0b10000000000000 ,
160+ Hydrating : 0b1000000000000 ,
159161 } ;
160162
161163 // **********************************************************
@@ -526,7 +528,7 @@ export function attach(
526528 } = getInternalReactConstants ( version ) ;
527529 const {
528530 DidCapture,
529- Incomplete ,
531+ Hydrating ,
530532 NoFlags,
531533 PerformedWork,
532534 Placement,
@@ -2707,51 +2709,33 @@ export function attach(
27072709 return null ;
27082710 }
27092711
2710- const MOUNTING = 1;
2711- const MOUNTED = 2;
2712- const UNMOUNTED = 3;
2712+ // This function is copied from React and should be kept in sync:
2713+ // https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactFiberTreeReflection.js
2714+ function assertIsMounted(fiber) {
2715+ if ( getNearestMountedFiber ( fiber ) !== fiber ) {
2716+ throw new Error ( 'Unable to find node on an unmounted component.' ) ;
2717+ }
2718+ }
27132719
27142720 // This function is copied from React and should be kept in sync:
27152721 // https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactFiberTreeReflection.js
2716- function isFiberMountedImpl (fiber: Fiber): number {
2722+ function getNearestMountedFiber ( fiber : Fiber ) : null | Fiber {
27172723 let node = fiber ;
2718- let prevNode = null ;
2724+ let nearestMounted = fiber ;
27192725 if ( ! fiber . alternate ) {
27202726 // If there is no alternate, this might be a new tree that isn't inserted
27212727 // yet. If it is, then it will have a pending insertion effect on it.
2722- if ( ( getFiberFlags ( node ) & Placement ) !== NoFlags ) {
2723- return MOUNTING ;
2724- }
2725- // This indicates an error during render.
2726- if ( ( getFiberFlags ( node ) & Incomplete ) !== NoFlags ) {
2727- return UNMOUNTED ;
2728- }
2729- while ( node . return ) {
2730- prevNode = node ;
2731- node = node . return ;
2732-
2733- if ( ( getFiberFlags ( node ) & Placement ) !== NoFlags ) {
2734- return MOUNTING ;
2735- }
2736- // This indicates an error during render.
2737- if ( ( getFiberFlags ( node ) & Incomplete ) !== NoFlags ) {
2738- return UNMOUNTED ;
2739- }
2740-
2741- // If this node is inside of a timed out suspense subtree, we should also ignore errors/warnings.
2742- const isTimedOutSuspense =
2743- node . tag === SuspenseComponent && node . memoizedState !== null ;
2744- if ( isTimedOutSuspense ) {
2745- // Note that this does not include errors/warnings in the Fallback tree though!
2746- const primaryChildFragment = node . child ;
2747- const fallbackChildFragment = primaryChildFragment
2748- ? primaryChildFragment . sibling
2749- : null ;
2750- if ( prevNode !== fallbackChildFragment ) {
2751- return UNMOUNTED ;
2752- }
2728+ let nextNode = node ;
2729+ do {
2730+ node = nextNode ;
2731+ if ( ( node . flags & ( Placement | Hydrating ) ) !== NoFlags ) {
2732+ // This is an insertion or in-progress hydration. The nearest possible
2733+ // mounted fiber is the parent but we need to continue to figure out
2734+ // if that one is still mounted.
2735+ nearestMounted = node . return ;
27532736 }
2754- }
2737+ nextNode = node . return ;
2738+ } while ( nextNode ) ;
27552739 } else {
27562740 while ( node . return ) {
27572741 node = node . return ;
@@ -2760,11 +2744,11 @@ export function attach(
27602744 if ( node . tag === HostRoot ) {
27612745 // TODO: Check if this was a nested HostRoot when used with
27622746 // renderContainerIntoSubtree.
2763- return MOUNTED ;
2747+ return nearestMounted ;
27642748 }
27652749 // If we didn't hit the root, that means that we're in an disconnected tree
27662750 // that has been unmounted.
2767- return UNMOUNTED ;
2751+ return null ;
27682752 }
27692753
27702754 // This function is copied from React and should be kept in sync:
@@ -2781,11 +2765,13 @@ export function attach(
27812765 const alternate = fiber.alternate;
27822766 if (!alternate) {
27832767 // If there is no alternate, then we only need to check if it is mounted.
2784- const state = isFiberMountedImpl ( fiber ) ;
2785- if ( state === UNMOUNTED ) {
2786- throw Error ( 'Unable to find node on an unmounted component.' ) ;
2768+ const nearestMounted = getNearestMountedFiber ( fiber ) ;
2769+
2770+ if ( nearestMounted === null ) {
2771+ throw new Error ( 'Unable to find node on an unmounted component.' ) ;
27872772 }
2788- if ( state === MOUNTING ) {
2773+
2774+ if ( nearestMounted !== fiber ) {
27892775 return null ;
27902776 }
27912777 return fiber ;
@@ -2824,23 +2810,20 @@ export function attach(
28242810 while ( child ) {
28252811 if ( child === a ) {
28262812 // We've determined that A is the current branch.
2827- if ( isFiberMountedImpl ( parentA ) !== MOUNTED ) {
2828- throw Error ( 'Unable to find node on an unmounted component.' ) ;
2829- }
2813+ assertIsMounted ( parentA ) ;
28302814 return fiber ;
28312815 }
28322816 if ( child === b ) {
28332817 // We've determined that B is the current branch.
2834- if ( isFiberMountedImpl ( parentA ) !== MOUNTED ) {
2835- throw Error ( 'Unable to find node on an unmounted component.' ) ;
2836- }
2818+ assertIsMounted ( parentA ) ;
28372819 return alternate ;
28382820 }
28392821 child = child . sibling ;
28402822 }
2823+
28412824 // We should never have an alternate for any mounting node. So the only
28422825 // way this could possibly happen is if this was unmounted, if at all.
2843- throw Error ( 'Unable to find node on an unmounted component.' ) ;
2826+ throw new Error ( 'Unable to find node on an unmounted component.' ) ;
28442827 }
28452828
28462829 if ( a . return !== b . return ) {
@@ -2891,8 +2874,9 @@ export function attach(
28912874 }
28922875 child = child.sibling;
28932876 }
2877+
28942878 if ( ! didFindChild ) {
2895- throw Error (
2879+ throw new Error (
28962880 'Child was not found in either parent set. This indicates a bug ' +
28972881 'in React related to the return pointer. Please file an issue.' ,
28982882 ) ;
@@ -2901,17 +2885,19 @@ export function attach(
29012885 }
29022886
29032887 if ( a . alternate !== b ) {
2904- throw Error (
2888+ throw new Error (
29052889 "Return fibers should always be each others' alternates. " +
29062890 'This error is likely caused by a bug in React. Please file an issue.' ,
29072891 ) ;
29082892 }
29092893 }
2894+
29102895 // If the root is not a host container, we're in a disconnected tree. I.e.
29112896 // unmounted.
29122897 if ( a . tag !== HostRoot ) {
2913- throw Error ( 'Unable to find node on an unmounted component.' ) ;
2898+ throw new Error ( 'Unable to find node on an unmounted component.' ) ;
29142899 }
2900+
29152901 if (a.stateNode.current === a) {
29162902 // We've determined that A is the current branch.
29172903 return fiber ;
0 commit comments