@@ -128,6 +128,7 @@ type ReactTypeOfSideEffectType = {|
128
128
PerformedWork : number ,
129
129
Placement : number ,
130
130
Incomplete : number ,
131
+ Hydrating : number ,
131
132
| } ;
132
133
133
134
function getFiberFlags ( fiber : Fiber ) : number {
@@ -156,6 +157,7 @@ export function getInternalReactConstants(
156
157
PerformedWork : 0b01 ,
157
158
Placement : 0b10 ,
158
159
Incomplete : 0b10000000000000 ,
160
+ Hydrating : 0b1000000000000 ,
159
161
} ;
160
162
161
163
// **********************************************************
@@ -526,7 +528,7 @@ export function attach(
526
528
} = getInternalReactConstants ( version ) ;
527
529
const {
528
530
DidCapture,
529
- Incomplete ,
531
+ Hydrating ,
530
532
NoFlags,
531
533
PerformedWork,
532
534
Placement,
@@ -2707,51 +2709,33 @@ export function attach(
2707
2709
return null ;
2708
2710
}
2709
2711
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
+ }
2713
2719
2714
2720
// This function is copied from React and should be kept in sync:
2715
2721
// 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 {
2717
2723
let node = fiber ;
2718
- let prevNode = null ;
2724
+ let nearestMounted = fiber ;
2719
2725
if ( ! fiber . alternate ) {
2720
2726
// If there is no alternate, this might be a new tree that isn't inserted
2721
2727
// 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 ;
2753
2736
}
2754
- }
2737
+ nextNode = node . return ;
2738
+ } while ( nextNode ) ;
2755
2739
} else {
2756
2740
while ( node . return ) {
2757
2741
node = node . return ;
@@ -2760,11 +2744,11 @@ export function attach(
2760
2744
if ( node . tag === HostRoot ) {
2761
2745
// TODO: Check if this was a nested HostRoot when used with
2762
2746
// renderContainerIntoSubtree.
2763
- return MOUNTED ;
2747
+ return nearestMounted ;
2764
2748
}
2765
2749
// If we didn't hit the root, that means that we're in an disconnected tree
2766
2750
// that has been unmounted.
2767
- return UNMOUNTED ;
2751
+ return null ;
2768
2752
}
2769
2753
2770
2754
// This function is copied from React and should be kept in sync:
@@ -2781,11 +2765,13 @@ export function attach(
2781
2765
const alternate = fiber.alternate;
2782
2766
if (!alternate) {
2783
2767
// 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.' ) ;
2787
2772
}
2788
- if ( state === MOUNTING ) {
2773
+
2774
+ if ( nearestMounted !== fiber ) {
2789
2775
return null ;
2790
2776
}
2791
2777
return fiber ;
@@ -2824,23 +2810,20 @@ export function attach(
2824
2810
while ( child ) {
2825
2811
if ( child === a ) {
2826
2812
// 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 ) ;
2830
2814
return fiber ;
2831
2815
}
2832
2816
if ( child === b ) {
2833
2817
// 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 ) ;
2837
2819
return alternate ;
2838
2820
}
2839
2821
child = child . sibling ;
2840
2822
}
2823
+
2841
2824
// We should never have an alternate for any mounting node. So the only
2842
2825
// 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.' ) ;
2844
2827
}
2845
2828
2846
2829
if ( a . return !== b . return ) {
@@ -2891,8 +2874,9 @@ export function attach(
2891
2874
}
2892
2875
child = child.sibling;
2893
2876
}
2877
+
2894
2878
if ( ! didFindChild ) {
2895
- throw Error (
2879
+ throw new Error (
2896
2880
'Child was not found in either parent set. This indicates a bug ' +
2897
2881
'in React related to the return pointer. Please file an issue.' ,
2898
2882
) ;
@@ -2901,17 +2885,19 @@ export function attach(
2901
2885
}
2902
2886
2903
2887
if ( a . alternate !== b ) {
2904
- throw Error (
2888
+ throw new Error (
2905
2889
"Return fibers should always be each others' alternates. " +
2906
2890
'This error is likely caused by a bug in React. Please file an issue.' ,
2907
2891
) ;
2908
2892
}
2909
2893
}
2894
+
2910
2895
// If the root is not a host container, we're in a disconnected tree. I.e.
2911
2896
// unmounted.
2912
2897
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.' ) ;
2914
2899
}
2900
+
2915
2901
if (a.stateNode.current === a) {
2916
2902
// We've determined that A is the current branch.
2917
2903
return fiber ;
0 commit comments