From c6e3a1773703d4f8b42f001e1b506b012f6c12c1 Mon Sep 17 00:00:00 2001 From: Minsik Kim Date: Wed, 25 Feb 2026 17:29:15 +0900 Subject: [PATCH 1/2] [Android][NativeAnimated] Add regression test for detached tracking spring toValue --- .../NativeAnimatedNodeTraversalTest.kt | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/animated/NativeAnimatedNodeTraversalTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/animated/NativeAnimatedNodeTraversalTest.kt index dfb2afefec9a..c4f6eac45c79 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/animated/NativeAnimatedNodeTraversalTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/animated/NativeAnimatedNodeTraversalTest.kt @@ -1370,6 +1370,44 @@ class NativeAnimatedNodeTraversalTest { assertThat(previousValue).isEqualTo(1.5) } + @Test + fun testTrackingSpringDoesNotCrashWhenToValueNodeIsDetached() { + val springConfig: JavaOnlyMap = + JavaOnlyMap.of( + "type", + "spring", + "stiffness", + 230.2, + "damping", + 22.0, + "mass", + 1.0, + "initialVelocity", + 0.0, + "restSpeedThreshold", + 0.001, + "restDisplacementThreshold", + 0.001, + "overshootClamping", + false, + ) + + createAnimatedGraphWithTrackingNode(springConfig) + + nativeAnimatedNodesManager.setAnimatedNodeValue(1, 1.0) + nativeAnimatedNodesManager.runUpdates(nextFrameTime()) + + nativeAnimatedNodesManager.disconnectAnimatedNodes(1, 2) + nativeAnimatedNodesManager.dropAnimatedNode(1) + + nativeAnimatedNodesManager.runUpdates(nextFrameTime()) + + val trackedNode = nativeAnimatedNodesManager.getNodeById(3) as? ValueAnimatedNode + assertThat(trackedNode).isNotNull + val trackedValue = checkNotNull(trackedNode).getValue() + assertThat(trackedValue.isNaN()).isFalse + } + companion object { private const val FRAME_LEN_NANOS: Long = 1000000000L / 60L private const val INITIAL_FRAME_TIME_NANOS: Long = 14599233201256L /* random */ From 2579213e080711b6f34b1046302f88c0deceb892 Mon Sep 17 00:00:00 2001 From: Minsik Kim Date: Wed, 25 Feb 2026 17:29:20 +0900 Subject: [PATCH 2/2] [Android][NativeAnimated] Guard tracking spring when toValue node is detached --- .../com/facebook/react/animated/TrackingAnimatedNode.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/TrackingAnimatedNode.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/TrackingAnimatedNode.kt index 1a355743fda7..dbc491a10b3b 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/TrackingAnimatedNode.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/TrackingAnimatedNode.kt @@ -25,7 +25,11 @@ internal class TrackingAnimatedNode( if (valAnimatedNode != null) { animationConfig.putDouble("toValue", valAnimatedNode.getValue()) } else { - animationConfig.putNull("toValue") + val drivenNode = nativeAnimatedNodesManager.getNodeById(valueNode) as? ValueAnimatedNode + if (drivenNode == null) { + return + } + animationConfig.putDouble("toValue", drivenNode.getValue()) } nativeAnimatedNodesManager.startAnimatingNode(animationId, valueNode, animationConfig, null) }