Skip to content

Commit bf7b7ae

Browse files
authored
findDOMNode: Remove return pointer mutation (#20272)
The last step of the `findDOMNode` algorithm is a search of the current tree. When descending into a child node, it mutates `child.return` so that it points to the current fiber pair, instead of a work-in-progress. This can cause bugs if `findDOMNode` is called at the wrong time, like in an interleaved event. For this reason (among others), you're not suppposed to use `findDOMNode` in Concurrent Mode. However, we still have some internal uses that we haven't migrated. To reduce the potential for bugs, I've removed the `.return` pointer assignment in favor of recursion.
1 parent 369c3db commit bf7b7ae

File tree

1 file changed

+37
-51
lines changed

1 file changed

+37
-51
lines changed

packages/react-reconciler/src/ReactFiberTreeReflection.js

+37-51
Original file line numberDiff line numberDiff line change
@@ -265,71 +265,57 @@ export function findCurrentFiberUsingSlowPath(fiber: Fiber): Fiber | null {
265265

266266
export function findCurrentHostFiber(parent: Fiber): Fiber | null {
267267
const currentParent = findCurrentFiberUsingSlowPath(parent);
268-
if (!currentParent) {
269-
return null;
270-
}
268+
return currentParent !== null
269+
? findCurrentHostFiberImpl(currentParent)
270+
: null;
271+
}
271272

273+
function findCurrentHostFiberImpl(node: Fiber) {
272274
// Next we'll drill down this component to find the first HostComponent/Text.
273-
let node: Fiber = currentParent;
274-
while (true) {
275-
if (node.tag === HostComponent || node.tag === HostText) {
276-
return node;
277-
} else if (node.child) {
278-
node.child.return = node;
279-
node = node.child;
280-
continue;
281-
}
282-
if (node === currentParent) {
283-
return null;
284-
}
285-
while (!node.sibling) {
286-
if (!node.return || node.return === currentParent) {
287-
return null;
288-
}
289-
node = node.return;
275+
if (node.tag === HostComponent || node.tag === HostText) {
276+
return node;
277+
}
278+
279+
let child = node.child;
280+
while (child !== null) {
281+
const match = findCurrentHostFiberImpl(child);
282+
if (match !== null) {
283+
return match;
290284
}
291-
node.sibling.return = node.return;
292-
node = node.sibling;
285+
child = child.sibling;
293286
}
294-
// Flow needs the return null here, but ESLint complains about it.
295-
// eslint-disable-next-line no-unreachable
287+
296288
return null;
297289
}
298290

299291
export function findCurrentHostFiberWithNoPortals(parent: Fiber): Fiber | null {
300292
const currentParent = findCurrentFiberUsingSlowPath(parent);
301-
if (!currentParent) {
302-
return null;
303-
}
293+
return currentParent !== null
294+
? findCurrentHostFiberWithNoPortalsImpl(currentParent)
295+
: null;
296+
}
304297

298+
function findCurrentHostFiberWithNoPortalsImpl(node: Fiber) {
305299
// Next we'll drill down this component to find the first HostComponent/Text.
306-
let node: Fiber = currentParent;
307-
while (true) {
308-
if (
309-
node.tag === HostComponent ||
310-
node.tag === HostText ||
311-
(enableFundamentalAPI && node.tag === FundamentalComponent)
312-
) {
313-
return node;
314-
} else if (node.child && node.tag !== HostPortal) {
315-
node.child.return = node;
316-
node = node.child;
317-
continue;
318-
}
319-
if (node === currentParent) {
320-
return null;
321-
}
322-
while (!node.sibling) {
323-
if (!node.return || node.return === currentParent) {
324-
return null;
300+
if (
301+
node.tag === HostComponent ||
302+
node.tag === HostText ||
303+
(enableFundamentalAPI && node.tag === FundamentalComponent)
304+
) {
305+
return node;
306+
}
307+
308+
let child = node.child;
309+
while (child !== null) {
310+
if (child.tag !== HostPortal) {
311+
const match = findCurrentHostFiberWithNoPortalsImpl(child);
312+
if (match !== null) {
313+
return match;
325314
}
326-
node = node.return;
327315
}
328-
node.sibling.return = node.return;
329-
node = node.sibling;
316+
child = child.sibling;
330317
}
331-
// Flow needs the return null here, but ESLint complains about it.
332-
// eslint-disable-next-line no-unreachable
318+
333319
return null;
334320
}
335321

0 commit comments

Comments
 (0)