Skip to content

Commit 45de710

Browse files
kmsbernardmeta-codesync[bot]
authored andcommitted
Fix crash in tracking spring animations when toValue node is detached (#55734)
Summary: This PR fixes an Android Native Animated crash in tracking + spring animations when the tracked `toValue` node is detached. In `TrackingAnimatedNode.update`, if the tracked node could not be resolved, we used to write `toValue = null` into `animationConfig`. `SpringAnimation.resetConfig` expects `toValue` to be a number, so this could crash with `NullPointerException: null cannot be cast to non-null type kotlin.Number` This can happen in real apps during graph teardown (for example unmount/re-render/navigation transitions), where tracking may still update for a transient frame after the tracked node has been detached. Fix: - Do not propagate null `toValue` from `TrackingAnimatedNode`. - If the tracked node is missing, fallback to the driven value node’s current value. - If both nodes are unavailable, return safely. This PR also adds a regression test. ## Changelog: [ANDROID] [FIXED] - Prevent Native Animated tracking spring crash when tracked `toValue` node is detached. Pull Request resolved: #55734 Test Plan: Added regression test `NativeAnimatedNodeTraversalTest.testTrackingSpringDoesNotCrashWhenToValueNodeIsDetached` - On a test-only commit (without the fix), the new test fails with: `NullPointerException: null cannot be cast to non-null type kotlin.Number` - On this PR (with the fix), test pass. Reviewed By: christophpurrer Differential Revision: D94697059 Pulled By: zeyap fbshipit-source-id: c8f1f619c34ce7887d6f9bfb42a035d41d6a063a
1 parent ee5b089 commit 45de710

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/TrackingAnimatedNode.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@ internal class TrackingAnimatedNode(
2525
if (valAnimatedNode != null) {
2626
animationConfig.putDouble("toValue", valAnimatedNode.getValue())
2727
} else {
28-
animationConfig.putNull("toValue")
28+
val drivenNode = nativeAnimatedNodesManager.getNodeById(valueNode) as? ValueAnimatedNode
29+
if (drivenNode == null) {
30+
return
31+
}
32+
animationConfig.putDouble("toValue", drivenNode.getValue())
2933
}
3034
nativeAnimatedNodesManager.startAnimatingNode(animationId, valueNode, animationConfig, null)
3135
}

packages/react-native/ReactAndroid/src/test/java/com/facebook/react/animated/NativeAnimatedNodeTraversalTest.kt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1370,6 +1370,44 @@ class NativeAnimatedNodeTraversalTest {
13701370
assertThat(previousValue).isEqualTo(1.5)
13711371
}
13721372

1373+
@Test
1374+
fun testTrackingSpringDoesNotCrashWhenToValueNodeIsDetached() {
1375+
val springConfig: JavaOnlyMap =
1376+
JavaOnlyMap.of(
1377+
"type",
1378+
"spring",
1379+
"stiffness",
1380+
230.2,
1381+
"damping",
1382+
22.0,
1383+
"mass",
1384+
1.0,
1385+
"initialVelocity",
1386+
0.0,
1387+
"restSpeedThreshold",
1388+
0.001,
1389+
"restDisplacementThreshold",
1390+
0.001,
1391+
"overshootClamping",
1392+
false,
1393+
)
1394+
1395+
createAnimatedGraphWithTrackingNode(springConfig)
1396+
1397+
nativeAnimatedNodesManager.setAnimatedNodeValue(1, 1.0)
1398+
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
1399+
1400+
nativeAnimatedNodesManager.disconnectAnimatedNodes(1, 2)
1401+
nativeAnimatedNodesManager.dropAnimatedNode(1)
1402+
1403+
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
1404+
1405+
val trackedNode = nativeAnimatedNodesManager.getNodeById(3) as? ValueAnimatedNode
1406+
assertThat(trackedNode).isNotNull
1407+
val trackedValue = checkNotNull(trackedNode).getValue()
1408+
assertThat(trackedValue.isNaN()).isFalse
1409+
}
1410+
13731411
companion object {
13741412
private const val FRAME_LEN_NANOS: Long = 1000000000L / 60L
13751413
private const val INITIAL_FRAME_TIME_NANOS: Long = 14599233201256L /* random */

0 commit comments

Comments
 (0)