Skip to content

Fix iOS Fabric unmount crash when pointer hover shifts child indices - #59857

Open
lorenc-tomasz wants to merge 22 commits into
react:mainfrom
lorenc-tomasz:fix/ios-fabric-child-order
Open

lorenc-tomasz wants to merge 22 commits into
react:mainfrom
lorenc-tomasz:fix/ios-fabric-child-order

Conversation

@lorenc-tomasz

@lorenc-tomasz lorenc-tomasz commented Nov 7, 2026 •

Copy link
Copy Markdown

Summary

Fixes #55489. Supersedes #58686 with the same code and tests.

In a Debug build on iPad, hover over a Pressable styled with cursor: 'pointer', then press it to remove a sibling. UIKit can insert a hover-effect view ahead of that sibling. Fabric still asks to unmount the correct child, but RCTViewComponentView checks its index against UIKit’s subviews and raises an assertion. A navigation header hit this with Fabric index 0 and UIKit index 1. Storybook reproduced it by collapsing a sidebar group. Debugger observations · Storybook reproducer

RCTViewComponentView now keeps _reactSubviews in Fabric mounting order. With clipping off, it inserts the first child at index zero and each subsequent child above its Fabric predecessor. Unmount checks the supplied index against that list and removes the entry on every unmount, including when clipping has already detached the child from its superview.

Ownership and clipping

The previous review asked what releases the views when clipping changes. Enabling removeClippedSubviews uses the existing list, so UIKit effect views never enter it. Disabling clipping reattaches the tracked children in order. They stay in the list until Fabric unmounts them or prepareForRecycle resets the list. Original review · Follow-up lifetime tests

The trade-off for review is one additional strong reference per mounted Fabric child when clipping is off, plus the cost of maintaining the array. A prototype that moved the hover target into a wrapper also fixed the reproducer, but required changes to hit testing, shadows and recycling. Prototype and alternatives

Changelog

[IOS] [FIXED] - Fix a crash when a pointer hover effect is active and Fabric unmounts a sibling view.

Test Plan

  • Manual reproduction. In RNTester Debug, open Cursor -> Mount and unmount while hovering. In Simulator, enable Send Pointer to Device. Hover over Toggle sibling and press it repeatedly. The removable text should toggle, the last label should stay last, and the app should keep running. The original PR reports reproducing the crash on an iPad mini (A17 Pro) and verifying touch and pointer interaction with the fix.
  • Native coverage. The original run passed 56 tests, including the first six regression tests. Five of those six failed before the fix. Paragraph tests were excluded because of a local ComponentBuilder linkage issue. Four later weak-reference tests cover clipped unmount, repeated clipping toggles, removal of a UIKit-owned sibling, and recycling followed by reuse. The native suite was not rerun for this resubmission.
  • Targeted formatting, ESLint, and git diff --check passed.

UIKit can insert native hover-effect views alongside Fabric children,
shifting the subview indices used during mounting and unmounting. Track
Fabric children separately and insert them relative to their predecessor.
Use that same list when toggling clipping so UIKit-owned views are not
tracked as Fabric children.

Add six native regression tests and an RNTester cursor example. Update
existing clipping expectations and the unmount assertion comment to match
the new child tracking behavior.

Changelog:
[IOS] [FIXED] - Fix Fabric child mounting and unmounting around pointer hover effects.

Test Plan:
- 56 native tests passed, including all six regression tests; five of the
  six failed before the fix. The unrelated paragraph test file was excluded
  because of an existing ComponentBuilder linkage issue; local include-path
  overrides were also needed to build the test suite.
- RNTester Debug simulator build succeeded. Baseline hover crash confirmed
  on iPad mini (A17 Pro); fixed-build touch interaction passed. Fixed-build
  pointer hover still needs manual verification.
- Targeted clang-format, Prettier, ESLint, and git diff --check passed.

Refs react#55489
# Conflicts:
#	packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Nov 7, 2026
@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Nov 7, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

iOS RCTAssert crash when unmounting near cursor pointer hover effect

1 participant