-
Notifications
You must be signed in to change notification settings - Fork 24.7k
Fix crash animated #51442
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix crash animated #51442
Conversation
When an array of styles are passed its get flattened here react-native/packages/react-native/Libraries/Animated/nodes/AnimatedStyle.js Lines 95 to 97 in f169754
Now if array with animated object keys is passed to flattened style
The result is below
It can be seen that react-native/packages/react-native/Libraries/Animated/nodes/AnimatedStyle.js Lines 100 to 106 in f169754
We don't recieve any animated nodes cause it doesn't exist in flattened array causing it to return null. These tricks it into passing an style array(before flattening) with animated values to View component which causes this crash. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
7c24e77
to
66338d7
Compare
@rshest has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for fixing this. Please add a unit test that shows how this behaviour previously broke.
Please also revert the changes to LogBoxInspectorSourceMapStatus
Thanks so much for the review, @javache! 🙏 .
However, it seems to pass even in scenarios where the component crashes on device. Also we need to update the snapshot for as the current fix involves flattening style arrays passed to Animated. The snapshot for LogBoxInspectorSourceMapStatus still expects a nested style array, which no longer reflects the updated structure. |
Instead of flattening, let's make sure all props passed through have values applied. You won't see this in jest, since processTransform is only called at the mounting layer. You'd need to validate there's no more Animated.Value in the final props. |
Thanks so much for the response, @javache! 🙏 You're absolutely right — though from what I understand, validating all the props might not be very helpful in this case, since they’ll likely be overwritten anyway during the later stages when styles are further flattened (especially in the cases that are currently crashing). Also, to properly apply all the style values when props are passed, it seems we would need to modify createAnimatedStyle itself to support working with style arrays directly, rather than flattened style object. react-native/packages/react-native/Libraries/Animated/nodes/AnimatedStyle.js Lines 96 to 104 in f169754
Please do correct me if I’ve misunderstood anything — happy to adjust the approach accordingly! |
Hey @javache , I was thinking about this yesterday night and now I think we can do this too .
Should we do something like this ? Whats your opinion? |
I think the fix you're looking for needs to be in
|
It's not super clear why we are flattening props there when we can see that in the end a series of unflattened props are passed through to the host component - that's incorrect. |
Hey @javache , |
Good catch. Perhaps that's a bug that should be fixed here first? If there's an animated value in the unflattened style we should still allocate the Animated.Style. cc @yungsters |
react-native/packages/react-native/Libraries/Animated/nodes/AnimatedStyle.js Lines 25 to 30 in f169754
I believe we may need to rewrite the function (and more support functions like __getValueWithStaticTransforms ) to support non-flattened styles. However, I’m not entirely sure if addressing this edge case is worth the added complexity.
|
I have updated this with new logic where I am not flattening the array but processing all the animated values (if found) . This should fix the issue without need for flattening before sending it to host component. |
This needs a unit test to demonstrate the fix. Wouldn't a better place for this fix be inside |
Thanks for the reply @javache .
Should we go ahead with the suggested approach? |
@javache Can you please check if this can be merged . I have added test cases |
I'll import this for the test-case - I think we can find a more generic solution. |
@javache has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator. |
Summary: When `Animated` traverses props for instances of `AnimatedNode`, it flattens `props.style` before traversing it so that we correctly ignore any `AnimatedNode` instances that may be shadowed by static values: ``` { style: [ {transform: [{translateX: new Animated.Value(0)}]}, {transform: [{translateX: 100}]}, ], } ``` However, there is a bug that occurs when *every* `AnimatedNode` instance is shadowed. In this case, `AnimatedProps` assumes that there are *no* `AnimatedNode` instances in the entire `props.style`. It then incorrectly operates on the unflattened `props.style`, which *does* have `AnimatedNode` instances. When this is passed to `View`, the `AnimatedNode` instances are encountered and can cause a crash in `processTransform`, as reported by: facebook#51395 The fix for this was originally attempted by riteshshukla04 in facebook#51442. This diff reuses the same unit test case, but it applies a different fix that does not involve re-traversing the `props.style` object. Changelog: [General][Fixed] - Animated will no longer produce invalid `props.style` if every `AnimatedNode` instance is shadowed via style flattening. Differential Revision: D75723284
Thanks for investigating this, sharing a detailed explanation of what you've found, and contributing a unit test case. I took a look and put up a different fix that I think will have better performance and will be a bit more intuitive for maintainers: #51719 I verified that the unit test you contributed passes with it. If you have a chance, can you try it out to see if it addresses all of the problems you encountered? |
Thanks @yungsters . Your fix looks better . Closing this |
Summary: When `Animated` traverses props for instances of `AnimatedNode`, it flattens `props.style` before traversing it so that we correctly ignore any `AnimatedNode` instances that may be shadowed by static values: ``` { style: [ {transform: [{translateX: new Animated.Value(0)}]}, {transform: [{translateX: 100}]}, ], } ``` However, there is a bug that occurs when *every* `AnimatedNode` instance is shadowed. In this case, `AnimatedProps` assumes that there are *no* `AnimatedNode` instances in the entire `props.style`. It then incorrectly operates on the unflattened `props.style`, which *does* have `AnimatedNode` instances. When this is passed to `View`, the `AnimatedNode` instances are encountered and can cause a crash in `processTransform`, as reported by: facebook#51395 The fix for this was originally attempted by riteshshukla04 in facebook#51442. This diff reuses the same unit test case, but it applies a different fix that does not involve re-traversing the `props.style` object. Changelog: [General][Fixed] - Animated will no longer produce invalid `props.style` if every `AnimatedNode` instance is shadowed via style flattening. Differential Revision: D75723284
Summary: Pull Request resolved: facebook#51719 When `Animated` traverses props for instances of `AnimatedNode`, it flattens `props.style` before traversing it so that we correctly ignore any `AnimatedNode` instances that may be shadowed by static values: ``` { style: [ {transform: [{translateX: new Animated.Value(0)}]}, {transform: [{translateX: 100}]}, ], } ``` However, there is a bug that occurs when *every* `AnimatedNode` instance is shadowed. In this case, `AnimatedProps` assumes that there are *no* `AnimatedNode` instances in the entire `props.style`. It then incorrectly operates on the unflattened `props.style`, which *does* have `AnimatedNode` instances. When this is passed to `View`, the `AnimatedNode` instances are encountered and can cause a crash in `processTransform`, as reported by: facebook#51395 The fix for this was originally attempted by riteshshukla04 in facebook#51442. This diff reuses the same unit test case, but it applies a different fix that does not involve re-traversing the `props.style` object. Changelog: [General][Fixed] - Animated will no longer produce invalid `props.style` if every `AnimatedNode` instance is shadowed via style flattening. Differential Revision: D75723284
Summary: When `Animated` traverses props for instances of `AnimatedNode`, it flattens `props.style` before traversing it so that we correctly ignore any `AnimatedNode` instances that may be shadowed by static values: ``` { style: [ {transform: [{translateX: new Animated.Value(0)}]}, {transform: [{translateX: 100}]}, ], } ``` However, there is a bug that occurs when *every* `AnimatedNode` instance is shadowed. In this case, `AnimatedProps` assumes that there are *no* `AnimatedNode` instances in the entire `props.style`. It then incorrectly operates on the unflattened `props.style`, which *does* have `AnimatedNode` instances. When this is passed to `View`, the `AnimatedNode` instances are encountered and can cause a crash in `processTransform`, as reported by: facebook#51395 The fix for this was originally attempted by riteshshukla04 in facebook#51442. This diff reuses the same unit test case, but it applies a different fix that does not involve re-traversing the `props.style` object. Changelog: [General][Fixed] - Animated will no longer produce invalid `props.style` if every `AnimatedNode` instance is shadowed via style flattening. Reviewed By: javache Differential Revision: D75723284
Summary: When `Animated` traverses props for instances of `AnimatedNode`, it flattens `props.style` before traversing it so that we correctly ignore any `AnimatedNode` instances that may be shadowed by static values: ``` { style: [ {transform: [{translateX: new Animated.Value(0)}]}, {transform: [{translateX: 100}]}, ], } ``` However, there is a bug that occurs when *every* `AnimatedNode` instance is shadowed. In this case, `AnimatedProps` assumes that there are *no* `AnimatedNode` instances in the entire `props.style`. It then incorrectly operates on the unflattened `props.style`, which *does* have `AnimatedNode` instances. When this is passed to `View`, the `AnimatedNode` instances are encountered and can cause a crash in `processTransform`, as reported by: facebook#51395 The fix for this was originally attempted by riteshshukla04 in facebook#51442. This diff reuses the same unit test case, but it applies a different fix that does not involve re-traversing the `props.style` object. Changelog: [General][Fixed] - Animated will no longer produce invalid `props.style` if every `AnimatedNode` instance is shadowed via style flattening. Reviewed By: javache Differential Revision: D75723284
Summary: Pull Request resolved: facebook#51719 When `Animated` traverses props for instances of `AnimatedNode`, it flattens `props.style` before traversing it so that we correctly ignore any `AnimatedNode` instances that may be shadowed by static values: ``` { style: [ {transform: [{translateX: new Animated.Value(0)}]}, {transform: [{translateX: 100}]}, ], } ``` However, there is a bug that occurs when *every* `AnimatedNode` instance is shadowed. In this case, `AnimatedProps` assumes that there are *no* `AnimatedNode` instances in the entire `props.style`. It then incorrectly operates on the unflattened `props.style`, which *does* have `AnimatedNode` instances. When this is passed to `View`, the `AnimatedNode` instances are encountered and can cause a crash in `processTransform`, as reported by: facebook#51395 The fix for this was originally attempted by riteshshukla04 in facebook#51442. This diff reuses the same unit test case, but it applies a different fix that does not involve re-traversing the `props.style` object. Changelog: [General][Fixed] - Animated will no longer produce invalid `props.style` if every `AnimatedNode` instance is shadowed via style flattening. Reviewed By: javache Differential Revision: D75723284
Summary: Pull Request resolved: facebook#51719 When `Animated` traverses props for instances of `AnimatedNode`, it flattens `props.style` before traversing it so that we correctly ignore any `AnimatedNode` instances that may be shadowed by static values: ``` { style: [ {transform: [{translateX: new Animated.Value(0)}]}, {transform: [{translateX: 100}]}, ], } ``` However, there is a bug that occurs when *every* `AnimatedNode` instance is shadowed. In this case, `AnimatedProps` assumes that there are *no* `AnimatedNode` instances in the entire `props.style`. It then incorrectly operates on the unflattened `props.style`, which *does* have `AnimatedNode` instances. When this is passed to `View`, the `AnimatedNode` instances are encountered and can cause a crash in `processTransform`, as reported by: facebook#51395 The fix for this was originally attempted by riteshshukla04 in facebook#51442. This diff reuses the same unit test case, but it applies a different fix that does not involve re-traversing the `props.style` object. The fix is gated behind a feature flag, `alwaysFlattenAnimatedStyles`. This will enable us to validate correctness of the new behavior before enabling it for everyone. (Beyond fixing the bug described above, this also causes styles to flatten more aggressively, so production testing is important to ensure stability.) Changelog: [General][Changed] - Creates a feature flag that changes Animated to no longer produce invalid `props.style` if every `AnimatedNode` instance is shadowed via style flattening. Reviewed By: javache Differential Revision: D75723284
Summary: Pull Request resolved: #51719 When `Animated` traverses props for instances of `AnimatedNode`, it flattens `props.style` before traversing it so that we correctly ignore any `AnimatedNode` instances that may be shadowed by static values: ``` { style: [ {transform: [{translateX: new Animated.Value(0)}]}, {transform: [{translateX: 100}]}, ], } ``` However, there is a bug that occurs when *every* `AnimatedNode` instance is shadowed. In this case, `AnimatedProps` assumes that there are *no* `AnimatedNode` instances in the entire `props.style`. It then incorrectly operates on the unflattened `props.style`, which *does* have `AnimatedNode` instances. When this is passed to `View`, the `AnimatedNode` instances are encountered and can cause a crash in `processTransform`, as reported by: #51395 The fix for this was originally attempted by riteshshukla04 in #51442. This diff reuses the same unit test case, but it applies a different fix that does not involve re-traversing the `props.style` object. The fix is gated behind a feature flag, `alwaysFlattenAnimatedStyles`. This will enable us to validate correctness of the new behavior before enabling it for everyone. (Beyond fixing the bug described above, this also causes styles to flatten more aggressively, so production testing is important to ensure stability.) Changelog: [General][Changed] - Creates a feature flag that changes Animated to no longer produce invalid `props.style` if every `AnimatedNode` instance is shadowed via style flattening. Reviewed By: javache Differential Revision: D75723284 fbshipit-source-id: 504f63e8edf836243d615783e119137a920ad271
Summary:
Fixes #51395 .
Changelog:
[GENERAL][FIXED]Crash when Animated value & primitive value used together
Test Plan:
Can be tested on RNTester with