Commit Graph

51 Commits

Author SHA1 Message Date
Joshua Gross f6168d2661 Bail out of createInterpolatedShadowView if generated props are null
Summary:
We have no evidence of this happening, but it matches other bail-out cases that already exist in this function. If we
fail something that would have been an assert in debug mode, bail out so we don't return garbage values in production.

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D27449775

fbshipit-source-id: 5b85016c9611484b615debec514d12a984e6b1ff
2021-03-31 21:33:05 -07:00
Joshua Gross 01f7d4f720 Refactor duplicated code into queueFinalMutationsForCompletedKeyFrame
Summary:
This chunk of code is repeated 3x in the codebase with minor variations. Consolidate as `queueFinalMutationsForCompletedKeyFrame`.

Should be no changes in behavior.

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D27407766

fbshipit-source-id: 196f0d4c7868007f0d103b024feb4450640a3f62
2021-03-31 21:33:05 -07:00
Joshua Gross 17c3846838 Only run assert-only path in debug mode
Summary:
This probably won't compile outside of debug mode, because variables are unused outside of asserts. Don't do any of this outside of debug mode.

This path is also a pessimisation, we shouldn't need to run it unless we're running in ultra-conservative debug mode.

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D27407767

fbshipit-source-id: 71a8d025463c85d65cd2bc193a19953b97669d84
2021-03-31 21:33:05 -07:00
Joshua Gross 92b8075120 Recursively clean up conflicting animations
Summary:
Call getAndEraseConflictingAnimations recursively, to clean up any conflicting animations.

With a specific sequence of mutation instructions, it is possible that an animation on a tree is set up, and the entire tree needs to be cleaned up if a parent is deleted, say.

This can happen especially if rapidly mutating trees in such a way that invokes view flattening and unflattening (which is not recommended, but is certainly possible).

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D27407776

fbshipit-source-id: 5125250f051c58870692f8fdc43ed23da5058a7f
2021-03-31 21:33:04 -07:00
Joshua Gross ae264b995f Update 'viewPrev' as well as 'viewStart' when transitioning from one animation to another
Summary:
When reconstructing a second animation based on a conflict with a first, we want to ensure we set 'viewPrev' of the second animation properly.

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D27407777

fbshipit-source-id: 8fcc72c4c5fadaab4287824a944ad21230f2f97d
2021-03-31 21:33:04 -07:00
Joshua Gross 9ea0020054 For certain types of conflicts we do *not* want to generate a final UPDATE mutation
Summary:
In general, when an animation is interrupted or completed, we want to forcibly "flush" an update that will make the StubViewTree/mounting layer consistent with the ShadowTree.

However, in cases where a conflict creates a second animation and stops the first, we simply updated the "viewPrev" of the second animation and smoothly transition to it.

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D27407774

fbshipit-source-id: 928363867d8994c9d69c53154a07bda94f954afa
2021-03-31 21:33:04 -07:00
Joshua Gross 22c9b7d520 If a parent node is DELETEd or CREATEd, immediately end animation
Summary:
Detect conflicts not just when a node is updated, but when its parent is DELETEd or CREATEd.

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D27407781

fbshipit-source-id: 719d9a8822bf691d9059073a30d8b5ccb50eece1
2021-03-31 21:33:04 -07:00
Joshua Gross f915ca99be EZ refactor
Summary:
pull out tag so it's easier to read

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D27407770

fbshipit-source-id: e7d2a3ce8e4ac55b6446cddc8c39e73a18fa7170
2021-03-31 21:33:04 -07:00
Joshua Gross 706a223dd2 Refactor LA: keyFrames have N "final items" to execute
Summary:
One of the struggles with the LA engine is to make sure that LA doesn't break the StubViewTree. In particular, we have strict requirements that the "oldShadowView" with every mutation matches exactly what is in the shadow tree, so it appears that there is a linear progression of ShadowNodes for every mutation instruction.

This is a struggle to do with the current setup, requires some wacky code, and doesn't work properly. Instead of spreading REMOVE/DELETE (especially) or INSERT/UPDATE instructions across multiple keyframes, we now allow keyframes to have multiple "final" instructions to execute,
which makes it much easier to keep state consistent.

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D27407769

fbshipit-source-id: 3a709503dc30be69efc345690cb1920eb9591e9a
2021-03-31 21:33:04 -07:00
Joshua Gross 7ac5d48341 Generalize "isVirtualView" logic to make debug asserts consistent with platform
Summary:
On Android we have the notion of "virtual views", which are defined consistently but the logic is scattered and duplicated throughout the codebase.

The logic exists to mark nodes that exist in the ShadowTree, but not the View tree. We want to CREATE, UPDATE, and DELETE them on the platform, but not INSERT or REMOVE
them. They basically exist as EventEmitter objects.

The only issue with this is (1) duplicated code, which opened the possibility for inconsistent definition (2) StubViewTree did not account for virtualized views, which caused
assert crashes in debug mode for certain LayoutAnimations on Android.

By moving the definition to ShadowViewMutation and accounting for it in StubViewTree, asserts are correct and consistent on all platforms.

This was not caught until recently, because, until recently, no asserts actually ran on Android.

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D27001199

fbshipit-source-id: eb29085317037ba8a286d7813bdd57095ad4746f
2021-03-15 13:50:56 -07:00
Joshua Gross 5be2843c1c Use react_native_assert in LayoutAnimations
Summary:
Use react_native_assert in LayoutAnimations to enable asserts to fire on Android.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D26517096

fbshipit-source-id: f000c4848f29c8779170625d357f547f2e9e6365
2021-02-18 14:31:57 -08:00
Joshua Gross fb1833eede Consolidate various debug-only flags into flags.h (#30988)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/30988

We have a bunch of flags scattered throughout the codebase with poor hygiene and commenting. Consolidate.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D26392518

fbshipit-source-id: 2823de123a5009d6b8c358e8a3f451b9fa0e05b7
2021-02-17 18:00:47 -08:00
Joshua Gross e723294630 LayoutAnimations: remove dead code
Summary:
remove dead code; this flag is always defaulted to false, and not used anywhere

Changelog: [Internal]

Reviewed By: sammy-SC, mdvacca

Differential Revision: D26271507

fbshipit-source-id: e2277cc24f164c53f2e8a0aa72456ac400834d70
2021-02-09 22:43:42 -08:00
Joshua Gross 49baf65844 LayoutAnimations: assert -> LA_ASSERT
Summary:
Add LA_ASSERT macro, this just makes debugging easier on Android since these asserts are compiled out for us even in debug.

Changelog: [internal]

Reviewed By: mdvacca

Differential Revision: D26271508

fbshipit-source-id: 9be8c71e273d762a4f31ff1fcc629ce48218b98d
2021-02-09 22:43:42 -08:00
Joshua Gross 76c384ff61 LayoutAnimations: in setup, guard against props being null in prod
Summary:
These asserts don't run in prod; only set starting/final view props if the result props object is non-null.

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D26271512

fbshipit-source-id: b495c014a062cf255fd4b5cb8609582f23edcec8
2021-02-09 22:43:42 -08:00
Joshua Gross 2218952d8b LayoutAnimations: when detecting conflicting mutations: crash more in debug, fail elegantly in prod
Summary:
In this case where there's an ongoing UPDATE animation and an INSERT of the same node, make sure the ongoing animation type is what we expect, and that the `newChildShadowView` is valid.

We were already guarding against these, but we should (1) crash more in debug and (2) fail more elegantly in prod when the asserts don't run.

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D26271514

fbshipit-source-id: 48e7d37a2493241f16099d9fe5ecb0d247707ca7
2021-02-09 22:43:41 -08:00
Joshua Gross 95cab24a6e LayoutAnimations: assert that tag >0 instead of != 0
Summary:
LayoutAnimations: assert that tag >0 instead of != 0. It's possible that a corrupt tag value would be below zero which is not valid.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D26271515

fbshipit-source-id: a62445ad29d60e5180e62ec4c6d5b08784655808
2021-02-05 00:57:42 -08:00
Joshua Gross 1c2a95d6c6 LayoutAnimations: when setting up animation start/final ShadowViews, ensure props are not null
Summary:
LayoutAnimations: when setting up animation start/final ShadowViews, ensure props are not null

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D26271510

fbshipit-source-id: 8d99ba8272fb63103a8d85bb0e14d02256a6d74d
2021-02-05 00:57:41 -08:00
Joshua Gross cc9a3e27c2 LayoutAnimations: ensure that interpolated props are never null
Summary:
ensure that interpolated props are never null

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D26271516

fbshipit-source-id: d012e530e92dabce1e0a7df8edf670e90367a892
2021-02-05 00:57:41 -08:00
Joshua Gross f0a599a112 LayoutAnimations: in createInterpolatedShadowView, ensure that props are never null
Summary:
props should never be null

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D26271513

fbshipit-source-id: 126f4e11f0f0f4e4c911e445fa8f6632a1c77cf2
2021-02-05 00:57:41 -08:00
Joshua Gross 87fe643a2f LayoutAnimations: ensure that we always have a valid ComponentDescriptor
Summary:
We should always be able to reference a ComponentDescriptor. If there are any valid cases where the ComponentDescriptor doesn't exist (?) we need to document those and investigate more.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D26271511

fbshipit-source-id: 659d160f82f1e78025d3dbe16efa0fa2d072d15f
2021-02-05 00:57:41 -08:00
Joshua Gross 512fd0e0b8 Add asserts to LayoutAnimations to check that ShadowViews are always valid
Summary:
Make sure there's no corruption happening to these ShadowViews.

Changelog: [internal]

Reviewed By: mdvacca

Differential Revision: D26271509

fbshipit-source-id: 01bfa1bfce56e72b48304fe15b6f6426d3b5247e
2021-02-05 00:57:40 -08:00
Andres Suarez 0f4f917663 Apply clang-format update fixes
Reviewed By: igorsugak

Differential Revision: D25861683

fbshipit-source-id: 616afca13ae64c76421053ce49286035e0687e36
2021-01-09 22:11:00 -08:00
Joshua Gross 266108d7d8 LayoutAnimations: use the final view as the baseline for animations, instead of the initial view
Summary:
To ensure that we're not sending old eventEmitters or State objects to the mounting layer, or potentially out-of-date Props objects, base
animated interpolations on the final ShadowNode instead of the initial.

Changelog: [Internal]

Reviewed By: shergin

Differential Revision: D25727481

fbshipit-source-id: 560ae8d25c7cec4c2137e70b4571b762f461edff
2020-12-29 15:54:45 -08:00
Joshua Gross e8770d7bb2 Code quality: Refactor ShadowViewMutation::UpdateMutation to remove index, parentShadowView parameters
Summary:
The `index` parameter for UpdateMutation is optional, and is normally just -1. It's not useful, so remove it. `parentShadowView` is also not relevant and is not used; in some existing use-cases the actual parent view of the updated view is available, and in some contexts the parent view is not set.

The function now will always set the index to -1 for UpdateMutations, and `{}` for ParentShadowView.

This should have no impact on iOS or Android, as this parameter is not used. It could theoretically have an impact on lifetimes of objects retained (now not retained) by not passing parentShadowView into the mutation. For example, any shared props or state associated with the parent will not be retained in the Update mutation now.

Changelog: [Internal]

Reviewed By: shergin

Differential Revision: D25342943

fbshipit-source-id: 0ddbef76a6e2eefc2629c9729f721d8674d7737e
2020-12-07 13:37:10 -08:00
Joshua Gross c224e9f155 Fix LayoutAnimations issue that could result in elements getting stuck with opacity ~0
Summary:
If a ShadowNode is being animated from opacity 0 to 1, and that animation is interrupted by another update to the same ShadowNode, we stop the animation and send the original "final" ShadowView
to the mounting layer. On iOS, this is enough to make the Mounting layer consistent with the Shadow layer. However, on Android, since only prop deltas are passed to the mounting layer and not the
entire props bag, this will NOT be enough because the opacity will not be updated in that final step.

Therefore, in those cases where we've detected a conflict and we're cleaning up after an interrupted animation, we must send two updates to the mounting layer: one to force the opacity to 1,
and another to make the ShadowTree consistent with the Mounting layer.

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D25324942

fbshipit-source-id: 5d9666128feaae87d7530c394ef05db580aa5a75
2020-12-04 14:46:52 -08:00
Joshua Gross 50dde4b7b7 LayoutAnimations: Fix out-of-order DELETE and REMOVE instruction generation
Summary:
In very marginal cases, it was possible to set up an animation of the following diffing instructions:

```
REMOVE X from parent Y
DELETE X
```

If your LayoutAnimation configuration had no "delete" config, the DELETE would be executed immediately; the REMOVE was erroneously being categorized as an "update" (now fixed)
which caused the REMOVE to be delayed, but then executed very shortly thereafter. So the order of instructions would become:

```
DELETE X
REMOVE X from parent Y
```

which would crash (or at least fail an assertion) when the REMOVE instruction was processed.

This fixes the issue by ensuring that REMOVEs have a corresponding "delete" config, or they are also executed immediately; unless followed by an INSERT (and any combination of `REMOVE, DELETE, INSERT` in the same frame is not possible).

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D25292560

fbshipit-source-id: 7ffdd6cbcb43126de07a70c197dfaf1ebff83555
2020-12-03 17:09:51 -08:00
Samuel Susla 8478f461df Simplify interface of LayoutAnimationKeyFrameManager::getAndEraseConflictingAnimations
Summary:
Changelog: [internal]

Return value from `LayoutAnimationKeyFrameManager::getAndEraseConflictingAnimations` was a tuple with 3 elements. Two of them are not being used so let's get rid of them.

Reviewed By: JoshuaGross

Differential Revision: D25220601

fbshipit-source-id: 35781e735b6a2e518337fdeaf956c18bb370993b
2020-11-30 12:27:46 -08:00
Joshua Gross f9a4cafa20 LayoutAnimations: Remove unnecessary optionals in config
Summary:
These configs are never actually empty, so they shouldn't be optionals.

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D25129254

fbshipit-source-id: 626119fefad0440732541c680286ebbbfab6aeba
2020-11-20 17:30:11 -08:00
Samuel Susla 29bbeaf8ac Fix race condition in LayoutAnimationKeyFrameManager::currentAnimation_
Summary:
Changelog: [internal]

`currentAnimation_` is accessed on multiple threads and has dedicated mutex, but it was not acquiring the mutex in `LayoutAnimationKeyFrameManager::shouldAnimateFrame`

Reviewed By: JoshuaGross

Differential Revision: D25121654

fbshipit-source-id: 38b1c82eaabab283beab18dc210ea21379edbe93
2020-11-20 13:23:47 -08:00
Samuel Susla f6fb1d0936 Use auto and implicit type conversion to improve readability in LayoutAnimationKeyFrameManager
Summary:
Changelog: [internal]

Readability improvements.

Reviewed By: JoshuaGross

Differential Revision: D25121829

fbshipit-source-id: f2937150ca078cc07befd873e91779cb960529a2
2020-11-20 13:05:38 -08:00
Joshua Gross b3865a9143 LayoutAnimations: attempt to re-queue animations if an UPDATE conflicts with a REMOVE+INSERT (move) without a corresponding Update
Summary:
Imagine the scenario in which there's an ongoing UPDATE animation; a REMOVE+INSERT (move) is queued up for the same tag, but there's no
new corresponding UPDATE - so maybe the indices of the view have changed, but the layout stays the same. Under the old model, the previous animation would be canceled and the node would jump to the final position. In theory, if there's no new UPDATE, we should continue animating the node to its final position.

I'm much happier with this - conflicting animations transition into each other super seamlessly now, and I think the logic is more straightforward as well.

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D25071664

fbshipit-source-id: fcefc4619dc34cdafdc4d8e8e730b935e5528290
2020-11-19 14:53:23 -08:00
Joshua Gross 0423eab4ee LayoutAnimations: remove noisy, non-useful log
Summary:
This is noisy when enabled, and not very useful.

Changelog: [Internal]

Reviewed By: PeteTheHeat

Differential Revision: D25071584

fbshipit-source-id: 7205b5fa39622feccaf315ccebb181dbdac4281d
2020-11-19 14:53:23 -08:00
Joshua Gross a45c921396 Keep "previous" ShadowView for animations consistent with MOVE sequences (UPDATE/REMOVE/INSERT)
Summary:
See comments, hopefully they explain this situation. This fixes the last remaining case that I have repro'd where StubViewTree asserts fire.

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D25062135

fbshipit-source-id: a28afba21f4094200aa0502b1e085dcbc10f9835
2020-11-19 14:53:23 -08:00
Joshua Gross 5bd5fcdd38 LayoutAnimations: ensure that all mutations retain the correct "old" node
Summary:
The current implementation of LayoutAnimations assumed that the "previous/old" ShadowView passed into the diff mutation didn't matter except for purposes of diffing.

As it turns out, iOS components could possibly use the "old" version of props, state, etc - so we should try to keep track of the current value in the tree as much as possible.

This diff accomplishes that by keeping track of the "previous" view, which the AnimationDriver will update over time. This also allows us to simplify logic around conflicting animations.

I'm also adding a few additional asserts to assist in debugging.

This doesn't totally eliminate all asserts hit on iOS, yet, but it does reduce the number of times the asserts are hit in StubViewTree.

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D25048644

fbshipit-source-id: d00aeece5af04624d8193063be453c7ce4a6e565
2020-11-19 14:53:23 -08:00
Samuel Susla 3c8d0112b3 Use variable instead of reference
Summary:
Changelog: [internal]

Reference here is incorrect, we need a container for `ShadowViewMutation`.

Reviewed By: JoshuaGross

Differential Revision: D25024080

fbshipit-source-id: f59a18d859ad391bc168c8990d40b25d18003f74
2020-11-18 06:57:10 -08:00
Samuel Susla 312226362d Add const annotations to LayoutAnimationKeyFrameManager
Summary: Changelog: [internal]

Reviewed By: JoshuaGross

Differential Revision: D25023706

fbshipit-source-id: 678377e2c471386670d1eab9c5adbe8aa6473a3c
2020-11-18 06:57:10 -08:00
Joshua Gross 61c1d60356 LayoutAnimations: generate final mutation instruction for interrupted animations without a final Mutation already queued up
Summary:
For some interrupted animations we will execute a "final" mutation associated with the animation, if it exists. For example, "UPDATE" animations always have a final Update animation associated with them.
Some, however, do not. For example: INSERT animations do not have a final mutation associated by default. In these cases (before this diff) if the animation from opacity 0 to 1 was interrupted, the View will
appear "stuck" at some intermediate opacity. To mitigate that, we generate a synthetic "final" mutation at 100% progress through the animation if it is interrupted.

Changelog: [Internal]

Reviewed By: fred2028

Differential Revision: D24691151

fbshipit-source-id: d9730b8a3493a5eeac4de325e7e0a7a64f73c8a0
2020-11-03 09:08:19 -08:00
Joshua Gross f40cdcdfe7 LayoutAnimations: remove "ConsecutiveMetadata" adjustment concept, adjust immediate and delayed mutation indices at the same time
Summary:
Index adjustment is tricky. Seems more reliable to adjust each immediate mutation, and then immediately adjust delayed mutations based on it, rinse and repeat.

Previously it was possible to construct examples where the UI would get into a weird state because index adjustment caused items to be inserted in the wrong location.

Changelog: [Internal]

Reviewed By: kacieb

Differential Revision: D24232926

fbshipit-source-id: f8c445213528c2d2aedacf3e0c73c5bbeb62bc3d
2020-10-09 19:02:19 -07:00
Joshua Gross 9f00752a97 LayoutAnimations: force props to update when executing "final" mutations
Summary:
When an animation is completed or a conflicting animation is detected, force props, state, layout, etc to update.

Currently, when a final animation mutation is queued, some attributes can be updated but not others, causing unexpected visual glitches at least on Android.

Some of these are arguably component bugs, but it's easier to just flush all attributes by tricking the platforms into updating all attributes. This will also prevent us from having to track down more of these bugs, potentially.

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D23886519

fbshipit-source-id: 8e5081bbe3b7843c16c0f283fa07fdec0e211aa8
2020-09-24 11:59:31 -07:00
Joshua Gross 81c61705f7 LayoutAnimations: simplify index adjustment, (un)flattening detection
Summary:
In this diff I simplify index adjustment and add comments to rigorously describe what we're doing at each step of index adjustment.

I've also made unflattening detection more correct, robust, and slightly more efficient.

Bugs that existed before:

1) The reparenting detection that existed in the animations layer had some subtle bugs. I don't have proof that it results in any correctness issues or crashes, but I suspect it.
2) Correctness of index adjustment: there were cases where the Android mounting layer would crash because LayoutAnimations would try to remove a View at an index, but the index was wrong. This is why I sat down and diagrammed the relationships between all the bits of data we have for index readjustment - I believe this to be correct now.
3) Correctness of INSERT index adjustment: I had the insight that when we have batches of INSERTs to consecutive indices, we essentially want them to be treated as a single INSERT for adjustment purposes, so that they're all placed consecutively in the view layer. I added `ConsecutiveAdjustmentMetadata` to deal with this, and there are more comments in the code.

Changelog: [Internal]

Reviewed By: yungsters

Differential Revision: D23806163

fbshipit-source-id: cd9e94945034db8b840f2a806c6377034a91af61
2020-09-20 14:54:00 -07:00
Joshua Gross 3585bb422f Fix compilation for LayoutAnimations debug mode
Summary:
iOS needs this function to be marked as static.

Changelog: [internal]

Reviewed By: shergin

Differential Revision: D23749613

fbshipit-source-id: a8c160646853450fc7d849448bdbb45e02beb964
2020-09-17 12:29:29 -07:00
Joshua Gross 012ac09fa1 Fix LayoutAnimations assertion on adjustDelayedMutationIndicesForMutation
Summary:
`adjustDelayedMutationIndicesForMutation` asserts that the mutation is either Remove or Insert. At one callsite, we weren't checking the mutation type before calling `adjustDelayedMutationIndicesForMutation`.

Changelog: [Internal]

Reviewed By: shergin

Differential Revision: D23746617

fbshipit-source-id: 6046fec2eb4821094937b1b16f40347bbc55c20e
2020-09-17 12:29:29 -07:00
Valentin Shergin bc3251c6a5 Fabric: MountingTelemetry renamed to TransactionTelemetry
Summary:
Just renaming, nothing more.
The idea of MountingTelemetry already grown to something bigger than just mounting telemetry, so we are renaming it.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: mdvacca

Differential Revision: D23374947

fbshipit-source-id: f60ce38b75d1ce77498b84688e59598314c69a78
2020-08-28 10:22:41 -07:00
Joshua Gross fe7ff13fcf LayoutAnimations: stopSurface
Summary:
Implementing stopSurface to stop ongoing animations.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D23382974

fbshipit-source-id: 478e0b1ad443ceeb771b03bd1689ec2bdbe02979
2020-08-27 19:37:06 -07:00
Joshua Gross 6a3c866b6a LayoutAnimations: work on making index adjustment more robust to flattening/unflattening and many reorders
Summary:
My goal in this diff is to make LayoutAnimations more stable, and more resilient to challenging situations. Namely, LayoutAnimations already works fine with:

1) Reorders
2) Flattening/unflattening
3) Deletion and recreation of the same hierarchy
4) Updates conflicting with an existing animation

However, what if /all/ of those things are combined? Handling update conflicts with multiple ongoing animations, repeatedly flattening/unflattening the same layer of hierarchy and reordering both parents and children, etc .

This diff does not make LayoutAnimations perfect, but it does make LayoutAnimations much more resilient to situations it was not able to handle before.

My primary method of testing was to use two Playground examples: one just repeatedly queues up mutations (some animated, some not) that create, update, and delete in the same hierarchy layer. The second, more complex one, mutates between random view hierarchies that involve a lot of flattening and unflattening as well as reordering, over a depth of 5. It also exercises animations over TextInlineViews, which is more challenging.

LayoutAnimations works best with the new "Flattening Differ" for now, because the Flattening Differ produces a much smaller, nearly minimal set of instructions in cases of flattening-unflattening. I would like that to not be a hard requirement for using LayoutAnimations, but it's a good starting-point for now.

As part of this work, I also developed a lot of debugging and logging mechanisms that are handy for detecting inconsistencies and debugging crashes. Some are included in this diff behind `#define` statements that are disabled by default, and the rest will be published separately and likely cannot be landed permanently, as they're more invasive changes that are only helpful in debugging.

# Followups:

- Automate testing: write a suite of C++ tests that mutates between random diffs and guarantees that all mutations in a StubViewTree are sensible
- Construct a set of minimal repros that catalogues all remaining crashes and inconsistency issues (these seem to be extremely marginal cases and are very hard to repro - so I think it's fine to run this in prod for now, but I will follow-up as soon as I'm back to catalogue and fix all remaining issues)
- This diff focuses on *not crashing*, but it is still possible to construct a sequence of complex mutations that results in (for example) views having some opacity between 0 and 1 if animations are interrupted repeatedly. Although this is easy enough to prevent in product code - the types of scenarios I'm running in tests are very unlikely to ever happen in production - it would be nice to be *sure* that LayoutAnimations will always converge to a sensible View hierarchy with up-to-date props.
- In general, the index adjustment logic is complicated. I don't know if there's a great way around it, so I need to at least catalogue and test all edge-cases as mentioned above.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D23382975

fbshipit-source-id: f379d9aa2a4b9c33fa2ba8fa07870c9e31fad5e7
2020-08-27 19:37:06 -07:00
David Vacca 48e9f0a1c0 Extend 'animations' module to compile in OSS
Summary:
This diff extends the 'animations' module to compile in OSS

changelog: [internal] internal

Reviewed By: JoshuaGross

Differential Revision: D22963702

fbshipit-source-id: e432e2f98b47a4b0456fd5e3d0f5263631782b29
2020-08-07 11:12:02 -07:00
Joshua Gross 28ff63f669 Optional verbose logging for LayoutAnimations
Summary:
I've used this while debugging LayoutAnimations a few times. It compiles out to nothing when the define is not set.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D22962113

fbshipit-source-id: 88b7bb1c20a07a7d804e5c81d31cf871d58bee92
2020-08-05 17:44:06 -07:00
Joshua Gross 1b575e8d1f Simplify and correct LayoutAnimations index adjustment
Summary:
Consolidated a few places where index adjustment was happening with nearly identical code. There was also one remaining case where index adjustment should be happening, but was not previously.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D22962115

fbshipit-source-id: 732c026b5a3c60bb0eadb8d49826ffd6367f7f62
2020-08-05 17:44:05 -07:00
Joshua Gross e3302eeeab LayoutAnimations: call onSuccess, onFailure callbacks
Summary:
Hook up onSuccess and onFailure callbacks to LayoutAnimations.

Note that in non-Fabric RN, onSuccess is not known to work in Android. I could not find any uses of onFailure and it's not documented, so for now, it is only called if the setup of the animation fails.

Changelog: [Internal]

Reviewed By: shergin

Differential Revision: D22889352

fbshipit-source-id: 4306debb350388dd2b7a2cbfe295eb99723988e2
2020-08-02 16:37:03 -07:00