@@ -101,17 +101,16 @@ function findCurrentFiberUsingSlowPath(fiber : Fiber) : Fiber | null {
101
101
let b = alternate ;
102
102
while ( true ) {
103
103
let parentA = a . return ;
104
- let parentB = b . return ;
104
+ let parentB = parentA ? parentA . alternate : null ;
105
105
if ( ! parentA || ! parentB ) {
106
106
// We're at the root.
107
107
break ;
108
108
}
109
+
110
+ // If both copies of the parent fiber point to the same child, we can
111
+ // assume that the child is current. This happens when we bailout on low
112
+ // priority: the bailed out fiber's child reuses the current child.
109
113
if ( parentA . child === parentB . child ) {
110
- // If both parents are the same, then that is the current parent. If
111
- // they're different but point to the same child, then it doesn't matter.
112
- // Regardless, whatever child they point to is the current child.
113
- // So we can now determine which child is current by scanning the child
114
- // list for either A or B.
115
114
let child = parentA . child ;
116
115
while ( child ) {
117
116
if ( child === a ) {
@@ -133,8 +132,63 @@ function findCurrentFiberUsingSlowPath(fiber : Fiber) : Fiber | null {
133
132
'Unable to find node on an unmounted component.'
134
133
) ;
135
134
}
136
- a = parentA ;
137
- b = parentB ;
135
+
136
+ if ( a . return !== b . return ) {
137
+ // The return pointer of A and the return pointer of B point to different
138
+ // fibers. We assume that return pointers never criss-cross, so A must
139
+ // belong to the child set of A.return, and B must belong to the child
140
+ // set of B.return.
141
+ a = parentA ;
142
+ b = parentB ;
143
+ } else {
144
+ // The return pointers pointer to the same fiber. We'll have to use the
145
+ // default, slow path: scan the child sets of each parent alternate to see
146
+ // which child belongs to which set.
147
+ //
148
+ // Search parent A's child set
149
+ let didFindChild = false ;
150
+ let child = parentA . child ;
151
+ while ( child ) {
152
+ if ( child === a ) {
153
+ didFindChild = true ;
154
+ a = parentA ;
155
+ b = parentB ;
156
+ break ;
157
+ }
158
+ if ( child === b ) {
159
+ didFindChild = true ;
160
+ b = parentA ;
161
+ a = parentB ;
162
+ break ;
163
+ }
164
+ child = child . sibling ;
165
+ }
166
+ if ( ! didFindChild ) {
167
+ // Search parent B's child set
168
+ child = parentB . child ;
169
+ while ( child ) {
170
+ if ( child === a ) {
171
+ didFindChild = true ;
172
+ a = parentB ;
173
+ b = parentA ;
174
+ break ;
175
+ }
176
+ if ( child === b ) {
177
+ didFindChild = true ;
178
+ b = parentB ;
179
+ a = parentA ;
180
+ break ;
181
+ }
182
+ child = child . sibling ;
183
+ }
184
+ invariant (
185
+ didFindChild ,
186
+ 'Child was not found in either parent set. This indicates a bug ' +
187
+ 'related to the return pointer.'
188
+ ) ;
189
+ }
190
+ }
191
+
138
192
invariant (
139
193
a . alternate === b ,
140
194
'Return fibers should always be each others\' alternates.'
0 commit comments