Skip to content

Fix LayoutAnimation crash from mutation sort ordering#56629

Open
fkgozali wants to merge 1 commit intofacebook:mainfrom
fkgozali:export-D102696875
Open

Fix LayoutAnimation crash from mutation sort ordering#56629
fkgozali wants to merge 1 commit intofacebook:mainfrom
fkgozali:export-D102696875

Conversation

@fkgozali
Copy link
Copy Markdown
Contributor

Summary:
LayoutAnimationDriver::animationMutationsForFrame was sorting animation-frame Update mutations together with structural mutations (Remove/Insert/Delete) from completed animations. Animation-frame Updates reference views by their pre-structural-change parentTag. When std::stable_sort reordered these Updates after Remove/Insert pairs that reparented a view, StubViewTree::mutate hit a parentTag mismatch assertion (react_native_assert(oldStubView->parentTag == mutation.parentTag)) and crashed with SIGABRT.

The fix records the boundary between animation-frame Updates and final structural mutations, then only sorts the structural portion. This preserves the invariant that animation-frame Updates execute before any structural changes.

Additionally, the mutation comparator in utils.h was missing an explicit Update < Insert ordering rule, which could cause nondeterministic sort results between Update and Insert mutations of different types. This is now handled.

The test fixture is converted to TEST_F with a LayoutAnimationTest class that enables the fixDifferentiatorParentTagForUnflattenCase feature flag, ensuring consistent parentTag assignment across platforms.

Changelog: [Internal]

Differential Revision: D102696875

Summary:
`LayoutAnimationDriver::animationMutationsForFrame` was sorting animation-frame Update mutations together with structural mutations (Remove/Insert/Delete) from completed animations. Animation-frame Updates reference views by their pre-structural-change parentTag. When `std::stable_sort` reordered these Updates after Remove/Insert pairs that reparented a view, `StubViewTree::mutate` hit a parentTag mismatch assertion (`react_native_assert(oldStubView->parentTag == mutation.parentTag)`) and crashed with SIGABRT.

The fix records the boundary between animation-frame Updates and final structural mutations, then only sorts the structural portion. This preserves the invariant that animation-frame Updates execute before any structural changes.

Additionally, the mutation comparator in `utils.h` was missing an explicit `Update < Insert` ordering rule, which could cause nondeterministic sort results between Update and Insert mutations of different types. This is now handled.

The test fixture is converted to `TEST_F` with a `LayoutAnimationTest` class that enables the `fixDifferentiatorParentTagForUnflattenCase` feature flag, ensuring consistent parentTag assignment across platforms.

Changelog: [Internal]

Differential Revision: D102696875
@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 Apr 28, 2026
@meta-codesync
Copy link
Copy Markdown

meta-codesync Bot commented Apr 28, 2026

@fkgozali has exported this pull request. If you are a Meta employee, you can view the originating Diff in D102696875.

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. fb-exported meta-exported p: Facebook Partner: Facebook Partner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant