Skip to content

Commit 73d27d7

Browse files
authored
Merge pull request #8897 from acdlite/fiberfixfinddomnode
[Fiber] Fix findDOMNode algorithm
2 parents d845084 + ba5b9c0 commit 73d27d7

File tree

1 file changed

+62
-8
lines changed

1 file changed

+62
-8
lines changed

src/renderers/shared/fiber/ReactFiberTreeReflection.js

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -101,17 +101,16 @@ function findCurrentFiberUsingSlowPath(fiber : Fiber) : Fiber | null {
101101
let b = alternate;
102102
while (true) {
103103
let parentA = a.return;
104-
let parentB = b.return;
104+
let parentB = parentA ? parentA.alternate : null;
105105
if (!parentA || !parentB) {
106106
// We're at the root.
107107
break;
108108
}
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.
109113
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.
115114
let child = parentA.child;
116115
while (child) {
117116
if (child === a) {
@@ -133,8 +132,63 @@ function findCurrentFiberUsingSlowPath(fiber : Fiber) : Fiber | null {
133132
'Unable to find node on an unmounted component.'
134133
);
135134
}
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+
138192
invariant(
139193
a.alternate === b,
140194
'Return fibers should always be each others\' alternates.'

0 commit comments

Comments
 (0)