Guard against unmounted components when using traversal APIs (#41451)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/41451

After [this change in React](https://github.com/facebook/react/pull/27687), `ReactFabric.getPublicInstanceFromInternalInstanceHandle` can return `null` if the instance handle is a fiber that was unmounted (before that PR, it would throw an error).

This modifies the DOM traversal API to gracefully handle that case.

Changelog: [internal]

Reviewed By: rshest

Differential Revision: D51210455

fbshipit-source-id: 05de682d840eed7f22473800efe5fb910c8f3a0d
This commit is contained in:
Rubén Norte
2023-11-14 06:11:13 -08:00
committed by Facebook GitHub Bot
parent e0aa9abfaf
commit fc0c084df0
2 changed files with 10 additions and 6 deletions
@@ -90,7 +90,7 @@ export default class ReactNativeElement
offsetParentInstanceHandle,
);
// $FlowExpectedError[incompatible-type] The value returned by `getOffset` is always an instance handle for `ReadOnlyElement`.
const offsetParentElement: ReadOnlyElement = offsetParent;
const offsetParentElement: ReadOnlyElement | null = offsetParent;
return offsetParentElement;
}
}
+9 -5
View File
@@ -134,7 +134,9 @@ export default class ReadOnlyNode {
return null;
}
return getPublicInstanceFromInternalInstanceHandle(parentInstanceHandle);
return (
getPublicInstanceFromInternalInstanceHandle(parentInstanceHandle) ?? null
);
}
get previousSibling(): ReadOnlyNode | null {
@@ -322,9 +324,11 @@ export function getChildNodes(
const childNodeInstanceHandles = nullthrows(
getFabricUIManager(),
).getChildNodes(shadowNode);
return childNodeInstanceHandles.map(instanceHandle =>
getPublicInstanceFromInternalInstanceHandle(instanceHandle),
);
return childNodeInstanceHandles
.map(instanceHandle =>
getPublicInstanceFromInternalInstanceHandle(instanceHandle),
)
.filter(Boolean);
}
function getNodeSiblingsAndPosition(
@@ -348,7 +352,7 @@ function getNodeSiblingsAndPosition(
export function getPublicInstanceFromInternalInstanceHandle(
instanceHandle: InternalInstanceHandle,
): ReadOnlyNode {
): ?ReadOnlyNode {
const mixedPublicInstance =
ReactFabric.getPublicInstanceFromInternalInstanceHandle(instanceHandle);
// $FlowExpectedError[incompatible-return] React defines public instances as "mixed" because it can't access the definition from React Native.