Commit Graph
79 Commits
Author SHA1 Message Date
Samuel Susla 6860cb0775 Fix KERN_INVALID_ADDRESS in configureNextLayoutAnimation
Summary:
Changelog: [Internal]

The crash is caused by dereferencing invalid pointer.
This can happen because `UIManager` can outlive `RCTScheduler` and `Scheduler`.

Here we make sure when `Scheduler` is being deconstructed, UIManager's pointer is invalidated.

I don't think this is ideal solution but it should fix the crash.
Ideally we want the owner of animation delegate to invalidate the pointer.

Reviewed By: JoshuaGross

Differential Revision: D21922910

fbshipit-source-id: b2a56c1104574cecebaffad1bcbcbff82c1fa0cf
2020-06-07 13:17:52 -07:00
Joshua Gross 3331962279 C++ Fabric Core LayoutAnimations
Summary:
This is the V1 implementation of Fabric Core LayoutAnimations.

The intention is to structure this in such a way that it's easy for each platform to customize the "AnimationDriver" class (to do platform-specific optimizations) without changing the KeyFrameManager at all.

In the future, this structure and architecture should allow us to iterate faster on new animation APIs.

Changelog: [Internal] Support for LayoutAnimations in Fabric

Reviewed By: mdvacca

Differential Revision: D21675808

fbshipit-source-id: b3ef44729bb8b6217f90760aec9737276c9601d1
2020-05-20 19:45:49 -07:00
Ishan Khot eb504e613e Revert D17486030: C++ Fabric Core LayoutAnimations
Differential Revision:
D17486030

Original commit changeset: 95c72cf9fc2b

fbshipit-source-id: fa7ef058f5d0dea0154c62718a8a11d9330698d9
2020-05-20 16:34:29 -07:00
Joshua Gross e9d6fb2ec6 C++ Fabric Core LayoutAnimations
Summary:
This is the V1 implementation of Fabric Core LayoutAnimations.

The intention is to structure this in such a way that it's easy for each platform to customize the "AnimationDriver" class (to do platform-specific optimizations) without changing the KeyFrameManager at all.

In the future, this structure and architecture should allow us to iterate faster on new animation APIs.

TODOs:

- Use std::chrono for timekeeping

Changelog: [Internal] Support for LayoutAnimations in Fabric

Reviewed By: shergin

Differential Revision: D17486030

fbshipit-source-id: 95c72cf9fc2b4bf3fe652fbd249cf2ad113033c7
2020-05-20 14:16:45 -07:00
Valentin Shergin dafa975352 Fabric: Simplification of UIManager::getRelativeLayoutMetrics
Summary:
Using of the new API makes clear that we don't need to calculate the newest descendant node.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: mdvacca

Differential Revision: D21480202

fbshipit-source-id: c54998573baffe4a05726e3402da027f052b049a
2020-05-18 14:08:27 -07:00
Samuel Susla a7bbc858c5 Use vector.empty() to check for emptyness
Summary:
Changelog: [Internal]

Using `empty()` vs `size() == 0` or `size() > 0`.
It is a more semantic way to check whether container is empty or not.

Reviewed By: JoshuaGross

Differential Revision: D21573183

fbshipit-source-id: b83283f687432a037941852114717a0f014e28db
2020-05-14 11:58:58 -07:00
Valentin Shergin 497191601b Fabric: Checks for corner cases in UIManager::getNewestCloneOfShadowNode
Summary:
We should check for corner cases.
Another interesting detail is behavior. Now (and previously) we return nullptr if case we could not find the most recent node. But maybe we should return the given node instead?

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: mdvacca

Differential Revision: D21480874

fbshipit-source-id: bb943c4508ec025316a3665d652e4b5e06dd795c
2020-05-10 13:28:46 -07:00
Valentin Shergin 0d2fcb1ed7 Fabric: Making UIManager::getNewestCloneOfShadowNode even more safer
Summary:
We cannot use a raw pointer here because the tree might progress right after we call to `shadowTree.tryCommit` and we will get a dangling pointer as a result.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: mdvacca

Differential Revision: D21464832

fbshipit-source-id: 3998b39d29db672da54d4adcb6be55cd3d44d862
2020-05-10 13:28:46 -07:00
Valentin Shergin 604402678b Fabric: Making UIManager::getRelativeLayoutMetrics safer
Summary:
In this method we have to maintain a retaining pointer to the node in order to access it as a raw pointer.
See also a comment in the codee.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: JoshuaGross

Differential Revision: D21464834

fbshipit-source-id: 69f6894009509e5feca291fab12c019208933816
2020-05-10 13:28:46 -07:00
Valentin Shergin af1fe62ae0 Fabric: Changes in UIManager::getNewestCloneOfShadowNode to make it safer
Summary:
There is no need to use a raw pointer to a shared pointer as a return value of `UIManager::getNewestCloneOfShadowNode`. If it would be a very hot path, we could you a raw pointer to the node instead but it's not a hot path.
Prooving that using a raw pointer here is safe is quite complex (and I don't know if it's safe or not). So, I changed it to just a shared pointer.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: JoshuaGross

Differential Revision: D21464833

fbshipit-source-id: 813a3c9fca0147afb322db6855a0ce8fd2d47909
2020-05-10 13:28:45 -07:00
Joshua Gross aae38c3dfe Support calling LayoutAnimation APIs in Fabric from JS
Summary:
Call Fabric's LayoutAnimation APIs from JS.

Changelog: [Internal] A step towards supporting LayoutAnimations on Fabric

Reviewed By: shergin, mdvacca

Differential Revision: D21297975

fbshipit-source-id: 6d530b01d8152e7c803a7c0299b918a32fb39dc0
2020-05-04 21:28:35 -07:00
Samuel Susla 81bdeade54 Fix broken touches on all Fabric surfaces
Reviewed By: shergin

Differential Revision: D21261996

fbshipit-source-id: f42c19295ac127eca653631faad0ced4900f4758
2020-04-27 15:15:32 -07:00
Joshua Gross 8ca5594549 All measure* calls should use the latest committed version of a ShadowNode
Summary:
Because of StateReconciliation (?) it is possible, even likely, that eventually the ShadowNode that ReactJS holds onto will not be the latest ShadowNode, and will not contain the latest LayoutMetrics.

This fixes the problem by always resolving the latest committed version of the ShadowNode before measuring it.

Changelog: [Internal] Fabric measure bugfix

Reviewed By: sammy-SC, mdvacca

Differential Revision: D21248472

fbshipit-source-id: a4f034c36d89a91a804f3b4cdf35e7ae748a1b91
2020-04-26 12:28:04 -07:00
Joshua Gross c3d0f3b2de Ship State Reconciliation 100% on all platforms
Summary:
State Reconciliation has been running 50/50 for a while and all metrics look stable. This is necessary for providing a good experience so we should ship to everyone unconditionally.

Changelog: [Internal] Fabric diffing reconciliation process improvement

Reviewed By: mdvacca

Differential Revision: D20715694

fbshipit-source-id: 25b2635ecc29b67e2911679c9db66bc84d37dec1
2020-03-27 18:44:02 -07:00
Valentin Shergin 100bf9076a Fabric: Changing signature of ComponentDescriptor::createState
Summary:
This is pure syntactic change. Often we don't have a shared pointer to ShadowNodeFamily and only have just a reference. At the same time, `ComponentDescriptor::createState` does not have to accept a shared pointer. So, it's better to accept just a reference.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: sammy-SC

Differential Revision: D20578787

fbshipit-source-id: 905277001e096d41e75007575b59ea2ea15fbf4b
2020-03-23 13:33:21 -07:00
Samuel Susla f96dc274d1 FindNodeAtPoint now accounts for scrollView offset
Summary:
Changelog: [internal]
FindNodeAtPoint was not taking transform into account.

Reviewed By: JoshuaGross

Differential Revision: D20288026

fbshipit-source-id: a8ff09bc265de983e42610c5d23837a2000f9dd2
2020-03-09 05:57:20 -07:00
Valentin Shergin dbc35267a0 Fabric: Removing unnecessary code fragments
Summary:
Those `true &&` code fragments don't look intentional.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D20135541

fbshipit-source-id: a7f2a99b2cbcd82023ec40c6b6211ad4f91d65a4
2020-02-27 09:46:29 -08:00
Valentin Shergin 1aab70d0e2 Fabric: RootShadowNode::clone was renamed/moved to ShadowNode::cloneTree
Summary:
Cloning subtrees is not something specific to a RootNode, so it makes sense to have it in ShadowNode. Soon we will use that to clone subtrees inside Paragraph component to implement Inline Views.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: mdvacca

Differential Revision: D20090666

fbshipit-source-id: 0a64ef9bda438cd55d5fd21d3ad83b36221fa89e
2020-02-26 22:08:22 -08:00
Valentin Shergin 1090b05e61 Fabric: Using traitCast in UIManager
Summary:
This is another perf-critical place where using traitCast should help with perf.
After this change we practically will not have any `dynamic_cast`s (except those which will be delited (with methods where they are used) in the future diffs).

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: sammy-SC

Differential Revision: D20052029

fbshipit-source-id: 63b589d3c3322f0afd72f18b4701fe31d0e05c2f
2020-02-26 22:08:18 -08:00
Valentin Shergin 91540d74b1 Fabric: Fixing a retain cycle in between State and ShadowNodeFamily
Summary:
This change removes the concept of `StateTarget`, replacing its role with `ShadowNodeFamily`.
When `StateTarget` was built, we didn't have a concept of `Family`, and when we added it we introduced a retain-cycle: ShadowNode -> Family -> StateTarget -> ShadowNode. This diff fixes that.

This change does not change conceptually how the state behaves, it just adjusts internal machinery.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: sammy-SC

Differential Revision: D19799013

fbshipit-source-id: c1360bfbf6b8ac34e2a856a40047eafeb50ed070
2020-02-09 22:28:40 -08:00
Joshua Gross c525ab5e04 Only use State Reconciliation during certain commits from ReactJS, not during State commits or others
Summary:
Only use State Reconciliation during certain commits from ReactJS, not during State commits or others

The idea is that this will have better perf, since many types of commits don't need State Reconciliation at all.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D19794999

fbshipit-source-id: 336325f225d993a6aae9f55cb95a7a2b38a6d853
2020-02-08 11:33:43 -08:00
Samuel Susla 595e954b13 Use ShadowNodeFamily in state updates
Summary:
Changelog: [internal]

`ShadowNodeFamily` can be used as target in state updates instead of `ShadowNode`.

Reviewed By: shergin

Differential Revision: D19517428

fbshipit-source-id: 6831357e749239d5afec1dfd2d44a26ca6553e51
2020-02-03 06:25:26 -08:00
Samuel Susla d418750359 Merge StateCoordinator into ShadowNodeFamily
Summary:
Changelog: [internal]

Merges all of responsibilities of `StateCoordinator` into `ShadowNodeFamily`.

Reviewed By: shergin

Differential Revision: D19500104

fbshipit-source-id: f31ffded5a840e722fd898eef6a9f52cd2186df7
2020-02-03 06:25:25 -08:00
David Vacca 4bfe8937b6 Replace usage of SharedShadowNode for ShadowNode::Shared
Summary:
ShadowNode::Shared and SharedShadowNode represent the exact same type. Nowadays we use ShadowNode::Shared instead of SharedShadowNode.
This diff replaces usages of SharedShadowNode for ShadowNode::Shared in the fabric folder.

Changelog: [internal]

Reviewed By: shergin

Differential Revision: D19217717

fbshipit-source-id: 112331b22251aa3a3d5e183395c54f2ca0f56e47
2020-01-29 21:06:55 -08:00
Samuel Susla 142c66f341 Create ShadowNodeFamily inside ComponentDescriptor
Summary:
Changelog: [internal]

1. Creates `ShadowNodeFamily` inside `ComponentDescriptor`.
2. As a side effect of this, we no longer need `ComponentDescriptor::createEventEmitter` so it is removed.

This is a step in order to merge `StateCoordinator` into `ShadowNodeFamily` and use it as target for state updates.

Reviewed By: shergin

Differential Revision: D19514906

fbshipit-source-id: 04ad3c621886be56925acd76f9b35a09d8c5e15a
2020-01-28 09:32:53 -08:00
Samuel Susla 7f79b46bad Initialise ShadowNodeFamily before ShadowNode is created
Summary:
Changelog: [internal]

1. Use `ShadowNode::Shared` instead of `SharedShadowNode`.
2. Initialise `ShadowNodeFamily` before `ShadowNode`.

Why?
This is a step in order to merge `StateCoordinator` into `ShadowNodeFamily` and use it as target for state updates.

Reviewed By: shergin

Differential Revision: D19471399

fbshipit-source-id: 2f67901c901349d238c711f9eeaadb19fe7c1110
2020-01-28 09:32:53 -08:00
Samuel Susla 01805636b9 Move ShadowNode::getAncestors to ShadowNodeFamily
Summary:
Changelog: [internal]

1. Moves `ShadowNode::getAncestors` to `ShadowNodeFamily`.
2. Exposes shadowNode's family through `ShadowNode::getFamily()`.

# Why?
This is a first step in order to merge `StateCoordinator` into `ShadowNodeFamily` and use it as target for state updates.

Reviewed By: shergin

Differential Revision: D19465188

fbshipit-source-id: b5a3625aa21c040301259de02beedbf97e11f20e
2020-01-28 09:32:52 -08:00
Joshua Gross 183b1c13c4 Always create new State object from latest
Summary:
Since we're using `tryCommit`, there could be races between two updates to state attached to the same node, especially if a ComponentDescriptor's `createState` implementation uses previous state data to create the new state object. By creating the State object from the "old" node within the tryCommit lambda, we prevent races.

Changelog: [Internal]

Reviewed By: shergin

Differential Revision: D19542908

fbshipit-source-id: 787e4aefc573adf1fa308a6fa859123976a823e7
2020-01-23 15:21:09 -08:00
Samuel Susla 5a94471650 Fabric: remove LocalData from ShadowNodeFragment
Summary:
LocalData isn't used by any components. We've moved towards State.
Changelog: [internal]

Reviewed By: mdvacca

Differential Revision: D19250603

fbshipit-source-id: f95da375117dcb8f6540a6c75d3a80bba630672c
2020-01-20 05:48:30 -08:00
David Vacca cf10cf56ea Remove method findShadowNodeByTag_DEPRECATED from UIManagerBinding class
Summary:
This diff removes the findShadowNodeByTag_DEPRECATED method from class UIManagerBinding. This method was created on D17175953 to implement findNodeHandle in Fabric. Recently we decided that we don't need to expose findNodeHandle anymore. This diff cleans up thi code.

Changelog: [internal]

Reviewed By: JoshuaGross

Differential Revision: D19216996

fbshipit-source-id: 07c16aeed28851afc09b0f5d6be338bb4440f813
2019-12-23 17:09:44 -08:00
David Vacca 5e7a03f7b6 Implement findNodeAtPoint method
Summary:
This diff implements the findNodeAtPoint method to return the ShadowNode that is positioned into a Point of the screen.

What's not supported:
- Scroll position
- Transform
- return layoutable nodes that are contained inside a non-layoutable node

Changelog: [internal]

Reviewed By: shergin

Differential Revision: D19190285

fbshipit-source-id: fdc0358dc21312e9950a4eb16c36020e9e43e33f
2019-12-23 17:09:44 -08:00
Samuel Susla 61f7639d38 Fabric: Remove eventEmitter from ShadowNodeFragment
Summary:
As part of the plan is splitting ShadowNodeFragment into two parts. ShadowNodeFamilyFragment is already in place. This diff removes use of `ShadowNodeFragment::eventEmitter` and goes over all call sites to change it to `ShadowNodeFamilyFragment::surfaceId`.
Changelog: [Internal]

Reviewed By: shergin

Differential Revision: D19146697

fbshipit-source-id: 22cae5404b0f3098feb86c0437a4aa256d5b773e
2019-12-19 13:48:22 -08:00
Samuel Susla 97f1c053b3 Fabric: Remove surfaceId from ShadowNodeFragment
Summary:
As part of the plan is splitting `ShadowNodeFragment` into two parts. `ShadowNodeFamilyFragment` is already in place. This diff removes use of `ShadowNodeFragment::surfaceId` and goes over all call sites to change it to `ShadowNodeFamilyFragment::surfaceId`.

Changelog: [Internal]

Reviewed By: shergin

Differential Revision: D19115785

fbshipit-source-id: 5972332c3360b88ca935581ed36070f26e678b22
2019-12-19 13:48:22 -08:00
Samuel Susla f9c5bf8bee Fabric: Remove tag from ShadowNodeFragment
Summary:
As part of the plan is splitting `ShadowNodeFragment` into two parts. `ShadowNodeFamilyFragment` is already in place. This diff removes use of `ShadowNodeFragment::tag` and goes over all call sites to change it to `ShadowNodeFamilyFragment::tag`.

Changelog: [Internal]

Reviewed By: shergin

Differential Revision: D19115781

fbshipit-source-id: 6ab3464a063c220d0924bf5a69b75449ca178650
2019-12-19 13:48:22 -08:00
Valentin Shergin c89ead313c Fabric: Proper implementation of ScrollView::contentOffset-aware measure functions (iOS only for now)
Summary:
This diff re-enables propagation of ScrollView's content-offset value down to the ShadowTree layer and enables measure fucntions opt-in incorporating this info to result.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: zackargyle

Differential Revision: D18981891

fbshipit-source-id: a6c0f4e690703b0ee07d45efab161750cfcc4b60
2019-12-18 10:48:40 -08:00
Valentin Shergin be324ca2dc Fabric: Adding some logs to Scheduler, UIManager and co
Summary:
We hope that will help us to understand more.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D18599164

fbshipit-source-id: 431f83de707fc7113e04abd3dd5b59ee5c9cc675
2019-11-21 16:21:25 -08:00
Valentin Shergin 806a2b8103 Fabric: ShadowTreeDelegate::shadowTreeDidCommit was renamed to shadowTreeDidFinishTransaction
Summary:
Simple renaming. Now the name is aligned with `SchedulerDelegate::schedulerDidFinishTransaction` and actually expresses the idea that not only commit finished but also a transaction was prepared and layout events were sent.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: mdvacca

Differential Revision: D18542503

fbshipit-source-id: 54d429ed139383621fe926fa48a4de062f724176
2019-11-15 21:49:44 -08:00
Valentin Shergin 1bc4bd333c Fabric: Inlining Scheduler::uiManagerDidFinishTransaction(surfaceId, rootChildren)
Summary:
There is no need for that functionality to be delegated to Scheduler, that's a leftover of the previous iteration of the design.
Nothing really changed.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: sammy-SC

Differential Revision: D18285501

fbshipit-source-id: 4b60445b663a2431fbdc7cc1120f46d56819c430
2019-11-06 14:43:42 -08:00
Valentin Shergin 04370256e0 Fabric: Routing all ShadowTree events via UIManager
Summary:
Now `UIManager` serves as `ShadowTree`'s delegate instead of `Scheduler`.
There is no good reason for Scheduler to be a ShadowTree delegate anymore, now UIManager owns all ShadowTree instances (via the registry). The existing configuration causes a crash because `ShadowTree` can overlive the `Scheduler`. Having a `UIManager` as a delegate of `ShadowTree` solves the problem because `UIManager` checks the own delegate for (which is actually a Scheduler) nullability before calling something on it (and `Scheduler` nulls that delegate during own deallocation process).

(No actual ownership relations were changed in the diff.)

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: JoshuaGross

Differential Revision: D18285500

fbshipit-source-id: 35ac4f37b6abdf4857a23c4869785a323e433317
2019-11-06 14:43:42 -08:00
Valentin Shergin b5080f7d77 Fabric: Fixing arbitrary-node-replacing (aka RootShadowNode::clone) algorithm
Summary:
This diff changes how arbitrary-node-replacing (aka `RootShadowNode::clone`) algorithm works.
Original implementation worked this way: We specified a node that needs to be replaced and a new replacement node. Then the algorithm finds a node with *the same family* as given the to-be-replaced node and replaced that with a given replacement.
The problem with this approach is that we are replacing a node that we have very little info about (we only know that it shares the same family as specified one). At the same time, we build the replacement based on the exact node that we have. Then imagine the case in which the "target" node can progress/change between a moment where we get a reference to it and a moment where we are trying to clone the tree. In this case, we will replace a "progressed" node with a modified version of the obsolete node.
Practically speaking, it was possible that during a state update we were replacing a node that just got new children with a bit older version of that with old children but with a new state.

How to deal with it? This diff introduces a new interface for this method that allows separating the target node and the actual act of cloning the corresponding node. Instead of specifying actual replacement, we now specify a function that performs the cloning/transformation on-demand on the very exact node that was in the tree at the moment of cloning.

This change does not change/affect any ownership-related relationships between trees and/or nodes.

Ideally, probably, the interface should accept ShadowNodeFamily instance instead of a ShadowNode instance to make the behavior very clear but that requires a bunch of low-level changes that it out of the scope of this fix.

```

                                                                   The old approach.

                     ┌─────────────────┐                          ┌─────────────────┐                          ┌─────────────────┐
                     │                 │                          │                 │                          │                 │
                     │      A(r0)      │                          │      A(r1)      │                          │      A(r2)      │
                     │                 │                          │                 │                          │                 │
                     └─────────────────┘                          └─────────────────┘                          └─────────────────┘
                              │                                            │                                            │
                              │          Let's update the                  │   Meanwhile the node B                     │
                              ▼           state of this                    ▼    gets new children.                      ▼
                     ┌─────────────────┐   node to s1.            ┌─────────────────┐                          ┌─────────────────┐
                     │                 │                          │                 │                          │                 │   Created
                     │    B(r0, s0)    │         ───────▶         │    B(r1, s0)    │         ───────▶         │    B(r2, s1)    │     from
                     │                 │                          │                 │                          │                 │    B(r0).
                     └─────────────────┘                          └─────────────────┘                          └─────────────────┘
                              │                                            │                                            │
                       ┌──────┴──────┐                       ┌─────────────┼─────────────┐                       ┌──────┴──────┐
                       │             │                       │             │             │                       │             │    What just
                       ▼             ▼                       ▼             ▼             ▼                       ▼             ▼     happe..?
                 ┌───────────┐ ┌───────────┐           ┌───────────┐ ┌───────────┐ ┌───────────┐           ┌───────────┐ ┌───────────┐
                 │           │ │           │           │           │ │           │ │           │           │           │ │           │
                 │   C(r0)   │ │   D(r0)   │           │   C(r1)   │ │   D(r1)   │ │   X(r0)   │           │   C(r0)   │ │   D(r0)   │
                 │           │ │           │           │           │ │           │ │           │           │           │ │           │
                 └───────────┘ └───────────┘           └───────────┘ └───────────┘ └───────────┘           └───────────┘ └───────────┘

                                                                   The new approach.

                     ┌─────────────────┐                          ┌─────────────────┐                           ┌─────────────────┐
                     │                 │                          │                 │                           │                 │
                     │      A(r0)      │                          │      A(r1)      │                           │      A(r2)      │
                     │                 │                          │                 │                           │                 │
                     └─────────────────┘                          └─────────────────┘                           └─────────────────┘
                              │                                            │                                             │
                              │         Let's update the                   │                                             │
                              ▼          state of this                     ▼                                             ▼
                     ┌─────────────────┐  node to s1.             ┌─────────────────┐                           ┌─────────────────┐
                     │                 │                          │                 │                           │                 │   Created
                     │    B(r0, s0)    │         ───────▶         │    B(r1, s0)    │         ───────▶          │    B(r2, s1)    │     from
                     │                 │                          │                 │                           │                 │    B(r1).
                     └─────────────────┘                          └─────────────────┘                           └─────────────────┘
                              │                                            │                                             │
                       ┌──────┴──────┐                       ┌─────────────┼─────────────┐                 ┌─────────────┼─────────────┐
                       │             │                       │             │             │                 │             │             │
                       ▼             ▼                       ▼             ▼             ▼                 ▼             ▼             ▼
                 ┌───────────┐ ┌───────────┐           ┌───────────┐ ┌───────────┐ ┌───────────┐     ┌───────────┐ ┌───────────┐ ┌───────────┐
                 │           │ │           │           │           │ │           │ │           │     │           │ │           │ │           │
                 │   C(r0)   │ │   D(r0)   │           │   C(r1)   │ │   D(r1)   │ │   X(r0)   │     │   C(r1)   │ │   D(r1)   │ │   X(r0)   │
                 │           │ │           │           │           │ │           │ │           │     │           │ │           │ │           │
                 └───────────┘ └───────────┘           └───────────┘ └───────────┘ └───────────┘     └───────────┘ └───────────┘ └───────────┘

```

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: JoshuaGross

Differential Revision: D18229704

fbshipit-source-id: face6d0e5c240224ce49e93e783cff3172b60529
2019-10-31 09:38:39 -07:00
Samuel Susla 7796b7e9af Avoid use of shared_from_this in StateTarget
Summary:
`StateTarget` no longer uses `shared_from_this`, this allows us to remove need for `enable_shared_from_this`

I decided to put `state->commit` call inside `ShadowTree.cpp` because I needed to have access to `shared_ptr` of shadow node from outside of the class itself.
`state->commit` was originally designed to be only called by `ShadowNode` but this does not seem to be the case anymore since it is called from `UIManager` as well.

changelog: [internal]

Reviewed By: shergin

Differential Revision: D18032532

fbshipit-source-id: 75c874fd04f86adc07bfddbef3a0384e17c2067b
2019-10-21 17:18:36 -07:00
Valentin Shergin c5f704b8e3 Changing signature of RootShadowNode::clone() to remove a shared_from_this() call
Summary:
This is the first diff in the journey of removing `enable_shared_from_this` from `ShadowNode` class.

In general, using `enable_shared_from_this` is fine, it's a normal standard feature and there is nothing wrong with that... besides the fact that using this thing is usually an indication of overall poor design.
In Fabric, we don't really have a good reason for that, I think in all cases it can be avoided, so I think we should remove that.
Removing that is also code-size and perf win.

This particular diff changes the signature of `RootShadowNode::clone()` which allows removing the necessity  of usage `.shared_from_this()` from callsites.
The rest changes are purely cosmetical.

Changelog: [Internal] Small Fabric-specific optimization.

Reviewed By: sammy-SC

Differential Revision: D17973958

fbshipit-source-id: 5539ceff9d11b4281a6ebe8d80e90d6bd90e44d8
2019-10-21 09:44:25 -07:00
Andres Suarez aee88b6843 Tidy up license headers [3/n]
Summary: Changelog: [General] [Fixed] - License header cleanup

Reviewed By: yungsters

Differential Revision: D17952693

fbshipit-source-id: 8fcb8e58a2e04e7a3169f4d525bffc00835768e6
2019-10-16 10:06:34 -07:00
Joshua Gross 87b94e60a6 Explicitly associate State with its owning ShadowNode immediately upon ShadowNode creation
Summary:
See comments for additional commentary. On Android we pass State to all views upon creation; currently we do Preallocation of views, which means that Views are created on the mounting layer before they're technically committed. Previously we were only assocation State -> ShadowNode upon tree commit.

This meant that during Preallocation, State was accessible but the `updateState` mechanism did not work because that requires a pointer from the State back to its owning ShadowNode.

We explicitly make that connection now when creating the ShadowNode and State. This should fix or prevent many subtle bugs with State, on Android but potentially other platforms as well, since now we guarantee that State is always updateable.

Changelog:
[[Internal]]

Reviewed By: shergin, mdvacca

Differential Revision: D17937687

fbshipit-source-id: a0cfdddbf1d97f1a64624bca6aa9536620f21ad4
2019-10-15 19:35:55 -07:00
Valentin Shergin 79ef5f9b0f Fabric: UIManager::findShadowNodeByTag_DEPRECATED
Summary: The mehtod implements the core functionality of finding a shadow node by given tag.

Reviewed By: zackargyle, JoshuaGross, mdvacca

Differential Revision: D17175955

fbshipit-source-id: 5cfbb80b2d4e54a33ca9c20a21988df4de54c800
2019-09-04 23:16:56 -07:00
Valentin Shergin 5c39c22187 Fabric: Moving ShadowTreeRegistry from Scheduler to UIManager
Summary:
Seems it's more logical and safe to store ShadowTreeRegistry in UIManager than in Scheduler. We also probably will move some functionality dealing with the registry to UIManager.

But most importantly we need it to manage the ownership properly. UIManager might overlive Scheduler and still get a call to process a shadow tree. In the current configuration, it causes a crash because the registry owns by Scheduler. Moving that to UIManager solves that.

Reviewed By: JoshuaGross

Differential Revision: D17128550

fbshipit-source-id: e6735acaa11f2ed82ca17f18a45e389d79aa1a08
2019-08-30 18:24:27 -07:00
Valentin Shergin dd7f99b1ae Fabric: Changing retaining configuration among UIManager, UIManagerBindging, Scheduler and EventDisaptcher
Summary:
This diff changes the way how `UIManager`, `UIManagerBindging`, `Scheduler` and `EventDisaptcher` refer to each other which should help with stability and reliability.

Here is the node that describes the details:

# Retaining dilemma

# Players
We have many logical of moving pieces but most of them can be abstracted by following high-level components.

* **Scheduler**
`Scheduler` is the main representation of running React Native infrastructure. Creation of it means the creation of all React Native C++ subsystems (excluding RuntimeExecutor) and destruction of that means the destruction of all dependent parts. Both processes must be thread-safe.

* **UIManager**
UIManager is a module that contains the most high-level logic of managing shadow trees. All React Renderer calls are practically implemented there.

* **UIManagerBinding**
UIManagerBinding is a representation (aka `HostObject`) of UIManager in the JavaScript world.

* **EventDispatcher**
EventDispatcher is a class that implements all logic related to dispatching events: from calling event on any thread anywhere to executing a particular JavaScript handler responsible for handling that event.

Instances of those classes have complex relationships in terms of owning each other, order of creation and destruction. The configuration of these relationships is dictated by a set of constraints that those classes need to satisfy to be constructed, accessed, and destructed in a hostile multithreaded environment. Messing with that can cause deadlocks, random crashes, suboptimal performance or memory leaks. Make sure you consider all constraints and requirements before changing that.

# Goal

We need to have a safe and reliable way to construct and destroy those objects (on any thread, in any random moment). Keep in mind that all of those objects are being accessed from random threads and have random states in any particular moment. Switching threads happens all the time, so having some state in one place does not guarantee any state in other places.

# Caveats
Let's discuss all concrete constrains that the moving pieces have to satisfy.

* **UIManagerBinding is a HostObject**
Practically that means:
  1. It must be constructed "on JavaScript thread" (with exclusive access to JavaScript VM);
  2. It must not be retained by other parts of the system because overliving the VM will cause a crash.
  3. It can be destructed on any thread (VM does not give any guarantees here). The particular configuration guarantees that the destruction cannot be run concurrently with any JS execution though (because we never clear the reference to the host object from JavaScript side).

* **UIManager needs to be connected with UIManagerBinding and vice-versa**
Those to modules call each other to perform some UI updates or deliver events.

* **Scheduler can be deallocated on any thread at any time**
Timing and thread are up to the application side. The Scheduler must be resilient to that.

* **EventDispatcher can call UIManager at any time**
Luckily, that happens only on JavaScript thread.

* **Using weak pointers cames at a cost**
`std::weak_ptr` is a concept for managing the non-owning relationships in a safe manner. Dereferencing such pointers cames at a cost (additional object construction and atomic counters bumps). So, we should use that carefully; we cannot use shared and week pointers everywhere and assume that will work magically.

# How does this blow up?

Without describing the current configuration, here are a variety of cases that we currently observe.

1. `Scheduler` was deallocated and destroyed UIManager but VM is still running. The VM calls the UIManagerBinding, UIManagerBinding calls a method on already deallocated UIManager. Boom.
2. VM is being deallocated and deletes all host object as part of this process. Some UI event is sill in flight on some thread. The event retains UIManagerBinding via UIManager. VM cannot destroy UIManagerBinding because it's being retained. Boom.
3. VM was deallocated. `Scheduler` was deallocated. But some native state update is still in flight. It retains EventDispatcher and eventually trying to access some shadow tree that was retained by Scheduler and already dead. Boom.

That's pretty much routine endless nightmare of any low-level framework. Luckily, the good proper decisions (and iterating on that!) can solve that.

# Proposed configuration

The configuration is based on those ideas:
1. Never retain `UIManagerBinging`.
2. Never recreate `UIManagerBinging`. Create once and load lazily from JS environment on demand.
3. Consider UIManager as an object with shared ownership between JS and native. That object must be able to overlive native infra or JS VM.
4. Use EventDispatcher as a single weak representation of the JavaScript world; Never retain it strongly except by the Scheduler.
5. `UIManagerBinging` and `UIManager` can be attached or detached. `UIManagerBinging` retains `UIManager`, `UIManager` does not retain `UIManagerBinging` back. Destroying `UIManagerBinging` nulls the raw pointer to that from `UIManager`.
6. All calls from native to JavaScript can validate the pointer from `UIManager` to `UIManagerBinging` to check that the call is possible. All that calls happen on JavaScript thread.

## Stages

* **Creation process**
Creation Scheduler creates `UIManager` and scheduler asynchronous call to JavaScript to create `UIManagerBinding` and attach them. At the same time `Scheduler` creates `EventDispatcher` and makes it retains `UIManager`.

* **JavaScript-to-native invocation**
`UIManagerBinding` has a shared pointer to `UIManager` and can cheaply and safely verify that the pointer is not nullptr. Any mutation of this pointer happens on the JavaScript thread or effectively on VM destruction (non-concurrently).

* **Native-to-JavaScript invocation**
The invocation starts from retaining `EventDispatcher` (converting a weak pointer to strong one), that retains `UIManager`. Later, on the JavaScript thread, `UIManager` checks the raw pointer to `UIManagerBinding` to verify that the call can be performed safely.

# Easy ways to break the fragile balance
- Never retain `EventDispatcher` as a shared pointer. That causes a leak of UIManager and associated resources.
- Access a shared pointer to `UIManager` by value only. The simple way to break that is to specify `[=]` capture block for a lambda and access an instance variable pointing to a `UIManager` (that does not retain the pointer; make a copy on the stack and copy that to the lambda).

Reviewed By: JoshuaGross

Differential Revision: D17120333

fbshipit-source-id: 83138657683e91ceb2f48f18f30e745199c83e82
2019-08-30 18:24:27 -07:00
Samuel Susla e557901267 Fix crash when tapping full screen button on video ad
Summary:
Fragment was assigned incorrect `tag` and `surfaceID` (`surfaceID` is the important one).

Wrong `surfaceID` means that `navigationCoordinator` is never resolved. As a result of navigationCoordinator not being assigned, tapping a video ad on Marketplace results in showing video ad overlay rather than showing full screen video.

Reviewed By: JoshuaGross

Differential Revision: D16646492

fbshipit-source-id: 0da5c56ecb7c81e9f4a9469a3626ccd430a01558
2019-08-05 10:17:16 -07:00
David Vacca 08e4537680 Expose JS Responder handler in Scheduler API
Summary: This diff implements the JSResponderHandler methods in the core of RN (scheduler API and friends)

Reviewed By: ejanzer

Differential Revision: D16543437

fbshipit-source-id: dac03e30c4330d182ecf134f3174ba942dbf7289
2019-08-02 16:38:45 -07:00
David Vacca 8f055a0f8e Unify naming of dispatchCommand methods in UIManagerDelegate and Scheduler
Summary:
This diff changes the name of the DispatchCommand methods in the UIManagerDelegate and Scheduler classes.
The purpose of this change is to use a consistent naming with the rest of the methods od these classes.
We might re-name these interfaces later, but for now we want to keep a consistent naming. For more details see discussion in D16543437

Reviewed By: JoshuaGross

Differential Revision: D16575403

fbshipit-source-id: 8335be8dc3367372a8ef2d7e8ed78665f4c02699
2019-07-30 22:42:51 -07:00