Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 62 additions & 8 deletions src/renderers/shared/fiber/ReactFiberTreeReflection.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -133,8 +132,63 @@ 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) {
didFindChild = true;
a = parentB;
b = parentA;
break;
}
if (child === b) {
didFindChild = true;
b = parentB;
a = parentA;
break;
}
child = child.sibling;
}
invariant(
didFindChild,
'Child was not found in either parent set. This indicates a bug ' +
'related to the return pointer.'
);
}
}

invariant(
a.alternate === b,
'Return fibers should always be each others\' alternates.'
Expand Down