@samitouri / QOS-React / commits / 97f6786cba

Fix findDOMNode algorithm

Andrew Clark committed Jan 30, 2017 at 18:41 UTC 97f6786cba9cf1917ccc28d839a415c6a4c92581
1 file changed +55 -8
src/renderers/shared/fiber/ReactFiberTreeReflection.js
+55 -8
@@ -101,17 +101,16 @@ function findCurrentFiberUsingSlowPath(fiber : Fiber) : Fiber | null {
101 let b = alternate;
102 while (true) {
103 let parentA = a.return;
104 - let parentB = b.return;
104 + let parentB = parentA ? parentA.alternate : null;
105 if (!parentA || !parentB) {
106 // We're at the root.
107 break;
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.
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.
114 let child = parentA.child;
115 while (child) {
116 if (child === a) {
@@ -133,8 +132,56 @@ function findCurrentFiberUsingSlowPath(fiber : Fiber) : Fiber | null {
132 'Unable to find node on an unmounted component.'
133 );
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 + a = parentB;
172 + b = parentA;
173 + break;
174 + }
175 + if (child === b) {
176 + b = parentB;
177 + a = parentA;
178 + break;
179 + }
180 + child = child.sibling;
181 + }
182 + }
183 + }
184 +
185 invariant(
186 a.alternate === b,
187 'Return fibers should always be each others\' alternates.'