Fix findDOMNode algorithm

This commit is contained in:
Andrew Clark 2017-01-30 18:41:25 -08:00
parent ec936dd848
commit 97f6786cba
1 changed files with 55 additions and 8 deletions

View File

@ -101,17 +101,16 @@ function findCurrentFiberUsingSlowPath(fiber : Fiber) : Fiber | null {
let b = alternate;
while (true) {
let parentA = a.return;
let parentB = b.return;
let parentB = parentA ? parentA.alternate : null;
if (!parentA || !parentB) {
// We're at the root.
break;
}
// If both copies of the parent fiber point to the same child, we can
// assume that the child is current. This happens when we bailout on low
// priority: the bailed out fiber's child reuses the current child.
if (parentA.child === parentB.child) {
// If both parents are the same, then that is the current parent. If
// they're different but point to the same child, then it doesn't matter.
// Regardless, whatever child they point to is the current child.
// So we can now determine which child is current by scanning the child
// list for either A or B.
let child = parentA.child;
while (child) {
if (child === a) {
@ -133,8 +132,56 @@ function findCurrentFiberUsingSlowPath(fiber : Fiber) : Fiber | null {
'Unable to find node on an unmounted component.'
);
}
a = parentA;
b = parentB;
if (a.return !== b.return) {
// The return pointer of A and the return pointer of B point to different
// fibers. We assume that return pointers never criss-cross, so A must
// belong to the child set of A.return, and B must belong to the child
// set of B.return.
a = parentA;
b = parentB;
} else {
// The return pointers pointer to the same fiber. We'll have to use the
// default, slow path: scan the child sets of each parent alternate to see
// which child belongs to which set.
//
// Search parent A's child set
let didFindChild = false;
let child = parentA.child;
while (child) {
if (child === a) {
didFindChild = true;
a = parentA;
b = parentB;
break;
}
if (child === b) {
didFindChild = true;
b = parentA;
a = parentB;
break;
}
child = child.sibling;
}
if (!didFindChild) {
// Search parent B's child set
child = parentB.child;
while (child) {
if (child === a) {
a = parentB;
b = parentA;
break;
}
if (child === b) {
b = parentB;
a = parentA;
break;
}
child = child.sibling;
}
}
}
invariant(
a.alternate === b,
'Return fibers should always be each others\' alternates.'