Skip to content

Commit

Permalink
Guard against unmounted components when using traversal APIs (faceboo…
Browse files Browse the repository at this point in the history
…k#41451)

Summary:

After [this change in React](facebook/react#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
  • Loading branch information
rubennorte authored and facebook-github-bot committed Nov 14, 2023
1 parent ef7ac36 commit 9690476
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down
14 changes: 9 additions & 5 deletions packages/react-native/Libraries/DOM/Nodes/ReadOnlyNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,9 @@ export default class ReadOnlyNode {
return null;
}

return getPublicInstanceFromInternalInstanceHandle(parentInstanceHandle);
return (
getPublicInstanceFromInternalInstanceHandle(parentInstanceHandle) ?? null
);
}

get previousSibling(): ReadOnlyNode | null {
Expand Down Expand Up @@ -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(
Expand All @@ -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.
Expand Down

0 comments on commit 9690476

Please sign in to comment.