Commit Graph
89 Commits
Author SHA1 Message Date
Valentin Shergin c80192c2ab Fabric: EventBeat::Owner to help with crashes
Summary:
The purpose of `EventBeat` is handling an asynchronous callback to itself which is being delivered on some different thread. That brings a challenge of ensuring that the `EventBeat` object stays valid during the timeframe of callback execution. The concept of Owner helps with that.
The owner is a shared pointer that retains (probably indirectly) the `EventBeat` object. To ensure the correctness of the call, `EventBeat` retains the owner (practically creating a retain cycle) during executing the callback. In case if the pointer to the owner already null, `EventBeat` skips executing the callback.
It's impossible to retain itself directly or refer to the shared pointer to itself from a constructor. `OwnerBox` is designed to work around this issue; it allows to store the pointer later, right after the creation of some other object that owns an `EventBeat`.

Reviewed By: JoshuaGross

Differential Revision: D17128549

fbshipit-source-id: 7ed34fd865430975157fd362f51c4a3d64214430
2019-08-30 18:24:27 -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
Valentin Shergin 6a10feacda Fabric: Passing EventDispatcher as a weak pointer everywhere
Summary: Storing a strong shared pointer to `ComponentDescriptor` can cause a memory leak. Therefore we enforce all call sides and params to be weak pointers. The only Scheduler preserves a retaining pointer to it (to prevent preliminary deallocation).

Reviewed By: sammy-SC

Differential Revision: D17115540

fbshipit-source-id: fdea7d19f742ff04d5ba5470dd9748a5b226aa7c
2019-08-30 18:24:26 -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
Joshua Gross 62591ac840 Set scheduler delegate during construction
Summary: I think it's possible that there's a race condition between creating the scheduler and setting the delegate leading to bugs like T47272192.

Reviewed By: mdvacca

Differential Revision: D16537737

fbshipit-source-id: 9c579537658be5a9aeed37c0e4935c997cabb6aa
2019-07-29 10:42:31 -07:00
Eli White 6f09dc03bf Support View Manager Commands
Summary: Supporting View Manager Commands on the new UIManager in Fabric. This is needed for things like scrollTo on ScrollView.

Reviewed By: JoshuaGross

Differential Revision: D16175575

fbshipit-source-id: a74effdf7e47b56a150a4e3fb6c4d787659e0250
2019-07-19 11:54:44 -07:00
Valentin Shergin 12c09a2d6c Fabric: Bunch of code style changes
Summary: Code style only.

Reviewed By: sahrens

Differential Revision: D15681737

fbshipit-source-id: 24cc2e9b9434448026e7cb3cfd274ea14bd835a2
2019-06-07 12:03:58 -07:00
Valentin Shergin 205de0538c Fabric: New names for ContextContainer methods
Summary:
... and slighly new behaviour for one of them.

The method does nothing if given `key` already exists in the container.

This diff finishes the transition of ContextContainer from an internal bag of things with unclear yet ownership into a legit dedicated dependency injection container for the product code.

The original names of methods imply that the container can have only one object of a given type which is no longer true. The new API is much more generic and idiomatic to C++, it mimics `std:map` API which is intuitive to anyone who familiar with C++ containers.

Besides the naming, `insert` method changed the semantic a bit; now it does nothing in case of inserting an object with a key that already exists. That might seem counterintuitive for "normal" people, but C++ has some wired reasons for that and, hopefully, it's expected behavior in the C++ community.

Fun fact: We need this to fix hot-reload.

Reviewed By: sahrens

Differential Revision: D15681736

fbshipit-source-id: 194f342528446a911eaf072ba3a94a5d8af3cb52
2019-06-07 12:03:57 -07:00
Valentin Shergin a19cfc2273 Fabric: Scheduler-specific dependencies were moved to a separate class from ContextContainer
Summary: ContextContainer should contain only product/component-specific dependencies and stay unchanged during VM/Scheduler reloading.

Reviewed By: JoshuaGross

Differential Revision: D15636656

fbshipit-source-id: fe5de1b6c92f659b28d31eba901c04c5b23fe1d1
2019-06-07 12:03:57 -07:00
Emily Janzer 298f59c5d3 Use startSurface on Android
Summary:
We currently have two different codepaths for actually rendering a surface with Fabric on iOS and Android: on iOS we use Fabric's `UIManagerBinding.startSurface` to call `AppRegistry.runApplication`, but on Android we don't; instead we use the same codepath as paper, calling `ReactRootView.runApplication`.

This diff does a few different things:
1. Unify iOS and Android by removing the `#ifndef` for Android so that we call `startSurface` for both
2. Pass through the JS module name on Android so that this actually works (it currently passes in an empty string)
3. Remove the call to `ReactRootView.runApplication` for Fabric so that we don't end up doing this twice
4. Copy over some logic that we need from `ReactRootView.runApplication` (make sure that root layout specs get updated, and that content appeared gets logged)

Reviewed By: mdvacca

Differential Revision: D15501666

fbshipit-source-id: 5c96c8cf036261cb99729b1dbdff0f7c09a32d76
2019-05-28 12:23:00 -07:00
David Vacca bbf1a7d085 Back out "[Venice][Fabric] Use startSurface on Android"
Summary: Original commit changeset: 4a506a589108

Reviewed By: ejanzer

Differential Revision: D15497094

fbshipit-source-id: 47e5d0c3c69cc56cc3dd56d28e23e1db5b562fa4
2019-05-24 11:30:29 -07:00
Emily Janzer f23da3aeb0 Use startSurface on Android
Summary:
Right now calling FabricUIManager.addRootView() doesn't actually start running the application on Android. This diff:

1. Removes the #ifndef so that we actually call UIManagerBinding.startSurface() on Android
2. Passes through the JS module name from addRootView so we can render the surface (falls back to an empty string if not provided, which is the current behavior)
3. Adds an option for starting the surface using `RN$SurfaceRegistry` instead of `AppRegistry`, if that global property has been defined in JS. This is used for Venice (bridgeless RN)

Reviewed By: shergin

Differential Revision: D15366200

fbshipit-source-id: 4a506a589108905d4852b9723aac6fb0fad2d86e
2019-05-23 13:47:30 -07:00
Valentin Shergin 0f2a09d1f6 Fabric: MountingCoordinator - the new way to ensure ordering of mount transaction
Summary:
TBD.
This thing fixes flickering during appearing of Fabric screens on iOS.

Reviewed By: mdvacca

Differential Revision: D15116079

fbshipit-source-id: 95ed0ba94667cad67fe4317025128d01b34f69c5
2019-05-03 15:11:35 -07:00
Valentin Shergin 4803cab8c4 Fabric: MountingTelemetry and refinments in TimeUtils
Summary: This diff implements encapsulating all time metrics in a single class for better extensibility and readability.

Reviewed By: JoshuaGross

Differential Revision: D15179835

fbshipit-source-id: 62bdf94435a0d37a87ad9bad613cc8e38043a235
2019-05-03 15:11:34 -07:00
Valentin Shergin 035e0403bb Fabric: ShadowNodeFragment::rootTag was renamed to surfaceId
Summary:
Trivial.
We are replacing rootTag with surfaceId according to the plan describing here: https://fb.workplace.com/groups/rn.fabric/permalink/1374002366064519/

Reviewed By: JoshuaGross, mdvacca

Differential Revision: D15039134

fbshipit-source-id: ec8c3044f9f3f23939488bc01c66e9b653e651dd
2019-04-29 21:21:10 -07:00
Valentin Shergin af0daaf583 Fabric: Introducing MountingTransaction
Summary:
`MountingTransaction` encapsulates all artifacts of `ShadowTree` commit, particularly list of mutations and meta-data.
We will rely on this heavily in the coming diffs.

Reviewed By: JoshuaGross

Differential Revision: D15021795

fbshipit-source-id: 811da7afd7b929a34a81aa66566193d46bbc34f8
2019-04-20 10:53:16 -07:00
Valentin Shergin 00eab3d6fb Fabric: Introducing ComponentDescriptorProvider
Summary:
ComponentDescriptorProvider represents unified way to create a particular descriptor.
Now all ComponentViews (which support RCTComponentViewProtocol) expose a `ComponentDescriptorProvider` which will allow creating and registering ComponentDescriptor instances for all visual components automatically as a part of ComponentView registration process.
Don't panic, everything is still being as explicit as it always was, no magic involved; we just will have only one registration step instead of two parallel.

That also opens a way to register components on the fly.

Reviewed By: JoshuaGross

Differential Revision: D14963488

fbshipit-source-id: 9e9d9166fabaf7b30b35b8647faa6e3a19cd2435
2019-04-17 22:44:20 -07:00
Valentin Shergin 184cfd5594 Fabric: Bunch of small changes in ContextContainer
Summary:
So, changes:
* Correctness checks only in debug mode (codesize win?);
* `registerInstance` marked as const (because it's thread safe);
* ContextContainer::Shared also enforces constness;
* Using faster better::map;
* Using shared/RW mutex instead of regular one;
* SharedContextContainer got removed.

Reviewed By: sahrens

Differential Revision: D14920284

fbshipit-source-id: f0f8d970e7fae79a1abe3bc32827db9fd2d17e13
2019-04-16 07:35:07 -07:00
Valentin Shergin 3e4a8e35fe Fabric ShadowTree (and co) was moved to mounting module
Summary: Because it's kinda more logical and we will rely on this in comming diffs.

Reviewed By: mdvacca

Differential Revision: D14587124

fbshipit-source-id: 94ae9410b4ffeffd0fcb4da4a0518f0bb0d2ba63
2019-04-01 10:50:50 -07:00
Valentin Shergin 28e89e5081 Fabric: ShadowNodeFamily, the first steps
Summary:
ShadowNodeFamily is a new concept that allows us to implement an efficient way to solve the problem of finding a path to some ancestor node (practically reimplement ShadowNode::constructAncestorPath() in some efficient way).

This diff is the first one in the series. It introduces a new class and moves some data into it.

Reviewed By: JoshuaGross

Differential Revision: D14416947

fbshipit-source-id: c93865a8929a2128498e34d3589487696aac6283
2019-03-18 23:56:13 -07:00
empyrical 2ca8c94559 Fabric: Remove designated initializers in '/uimanager/' (#23717)
Summary:
This pull request removes the designated initializers under the `fabric/uimanager/` folder. This will help improve the portability of these files.

[General] [Fixed] - Removed designated initializers under the `fabric/uimanager/` folder
Pull Request resolved: https://github.com/facebook/react-native/pull/23717

Differential Revision: D14305203

Pulled By: shergin

fbshipit-source-id: 370911682e22cbb20c4bfd7382ed4da0ce1a598d
2019-03-04 12:58:59 -08:00
David Vacca 747d1f7029 Cleanup SchedulerDelegate interface
Summary: This diff removes the "isLayoutable" parameter from SchedulerDelegate.schedulerDidRequestPreliminaryViewAllocation. This now can be infered from the shadowView parameter

Reviewed By: shergin

Differential Revision: D14296481

fbshipit-source-id: b200504f9c2bef41f0a70257f1f5a274fbe97cbb
2019-03-03 15:51:32 -08:00
Valentin Shergin aed352246e Fabric: Using RootComponentDescriptor to manage RootShadowNode in ShadowTree
Summary: We need this change to migrate away `cloneFunction` (to a pointer to ComponentDescriptor) inside ShadowNode.

Reviewed By: mdvacca

Differential Revision: D14249197

fbshipit-source-id: 773edcf40e17989886e2c5d3955823a0dbf3857a
2019-03-03 13:50:35 -08:00
David Vacca 70447775f7 Update Props during pre-allocation avoiding re-updating the same props during mounting
Summary:
Update Props during pre-allocation avoiding re-updating the same props during mounting

MobileLab test showed an improvement of:
MARKETPLACE_YOU_TTI_SUCCESS: -3.34% = 58ms

Reviewed By: shergin

Differential Revision: D14252170

fbshipit-source-id: 1f4e9ad5dcecbc06651fa065135ffeed4892d984
2019-03-03 09:00:48 -08:00
David Vacca aa69e51096 Preallocate Image views
Summary:
This diff changes the pre-allocation of Images update the props on the ImageViews during the creation of ShadowNodes instead of during rendering.
The purpose of this change is to optimize TTI.

This was originally landed in D14214844 and then backed out in D14247897

Reviewed By: shergin

Differential Revision: D14286232

fbshipit-source-id: 8437f57f9473eb22ef98d80531b4020ee5fbb9ae
2019-03-03 09:00:47 -08:00
Yedidya Feldblum fc91bccd53 Add assorted missing includes in xplat
Summary: Add assorted missing includes in `xplat` that would be exposed by future changes.

Reviewed By: ispeters, nlutsenko

Differential Revision: D14213660

fbshipit-source-id: 329f133784015fe20ee99feaec8ef05e117fe3a6
2019-02-28 00:52:48 -08:00
David Vacca b3790d283f Back out "[Fabric][C++][Android] update props during pre allocation of views"
Summary:
This is a back-out of D14214844, we noticed that this regressed TTI for Marketplace You screen running in Fabric

Original commit changeset: b81005f2bf49

Reviewed By: JoshuaGross

Differential Revision: D14247897

fbshipit-source-id: de0cea92b437b2fbcd075f0d6a0066156800e3f0
2019-02-28 00:04:09 -08:00
Valentin Shergin 802534e611 Fabric: Introducting State, an escape path from unidirectional data flow
Summary:
In React Native there are several use cases where React State is not the only input that affects the component tree. E.g., in case of a <Modal> component, the screen size directly affects the layout of components inside modal; in the case of uncontrolled <TextInput> component, the text inside the input affects the layout of the surrounding components. `State` is a special (legit!) workaround for all those similar cases. Native part of React Native maintains a special shared object between all nodes of the same family and use that during cloning and commits.

See coming commits to know how to use that.

In the near future State will fully replace LocalData concept but for simplicity they both exist for now.

Reviewed By: mdvacca

Differential Revision: D14217184

fbshipit-source-id: 6e018c5b68208d662462013bce0f4e2733d2f673
2019-02-27 00:32:25 -08:00
David Vacca 19765c9b8c update props during pre allocation of views
Summary:
This diff changes the pre-allocation of Images update the props on the ImageViews during the creation of ShadowNodes instead of during rendering.

The purpose of this change is to optimize TTI.

Reviewed By: shergin

Differential Revision: D14214844

fbshipit-source-id: b81005f2bf494f62f421dc24846e1561e13b9a87
2019-02-25 17:21:24 -08:00
Spencer Ahrens ea54ceca13 basic useNativeDriver functionality
Summary:
Not super clean, but not terrible.

Unfortunately this still relies on the old Paper UIManager calling delegate methods to flush the operations queues. This will work for Marketplace You since Paper will be active, but we need to fix this, along with Animated Events which don't work at all yet.

Random aside: it seems like taps are less responsive in fabric vs. paper, at least on iOS. There is a sporadic delay between the touches event coming in nativly to the JS callback invoking the native module function to start the animation - this will need some debugging.

Reviewed By: shergin

Differential Revision: D14143331

fbshipit-source-id: 63a17eaafa1217d77a532a2716d9f886a96fae59
2019-02-25 12:25:34 -08:00
Valentin Shergin 77838b5504 Fabric: Systraces are back
Summary:
It's better to comment `DWITH_FBSYSTRACE` out in BUCK files instead of removing them from the code.
I'll publish the BUCK changes as separate diff for simpler backout in the future.

Reviewed By: mdvacca

Differential Revision: D14019272

fbshipit-source-id: 8b322b5c115efe33c15929e008b97a05220813df
2019-02-11 16:01:05 -08:00
David Vacca 7f27888878 Add performance counters for Fabric
Summary:
This diff adds performance loggers for Fabric in Android to be able to compare current version or RN with Fabric

This is the summary of Points and Annotations:

- **UIManager_CommitStart**: time that React starts the commit (react tree is ready to start rendering in native)
- **UIManager_LayoutTime**: this is the time it takes to calculate layout in yoga
- **UIManager_FabricFinishTransactionTime**: Time it takes transform "C++ mutationInstructions" into "Java MountItems" and cross boundaries from C++ to Java (including serialization of data) (THIS IS ONLY FABRIC)
- **UIManager_DispatchViewUpdates**: time right before RN moves the mount operations to the Queue that is going to be processed in the next tick UI thread
- **UIManager_BatchRunStart**: time right before the mountItems are going to be process in the UI Thread
- **UIManager_BatchedExecutionTime**: time it took to run batched mountItems (usually layout and prop updates on views)
- **UIManager_NonBatchedExecutionTime**: time it took to run non-batched mountItems (usually creation of views)

Reviewed By: fkgozali

Differential Revision: D13838337

fbshipit-source-id: 0a707619829e7d95ce94d9305ff434d1224afc46
2019-02-04 17:27:30 -08:00
David Vacca 842b9c106a Temporary remove systraces from Fabric core code
Summary: This is a temporary change to measure production data

Reviewed By: fkgozali

Differential Revision: D13906807

fbshipit-source-id: 2a2f71aa379c4aca63c7bb4a9644704f713cb088
2019-02-02 13:08:06 -08:00
Valentin Shergin 091edd2ef7 Fabric: Clear separation between commmit and tryCommit
Summary: Previously we had a single `commit` function that accepts an argument that enables auto-retry mechanism. As Spencer pointed out, that wasn't so useful and clear. So, I split the method into two with more expressive names.

Reviewed By: sahrens

Differential Revision: D13681594

fbshipit-source-id: 529f729d597206e9a0ac940f005a1569a9bef707
2019-01-16 20:22:40 -08:00
Valentin Shergin 84cf657308 Fabric: ShadowTree::completeByReplacingShadowNode was moved to RootShadowNode
Summary:
Removing additional complexity from ShadowTree should help with maintainability. Now, this class is "tricky", but short at least.
With new `commit` API, it's much more simple and expected this way.

Reviewed By: sahrens

Differential Revision: D13615365

fbshipit-source-id: 1fe851c1a2d3bdc7ac2f4a570cf0170eae3c4c67
2019-01-16 20:22:39 -08:00
Valentin Shergin c937300f5d Fabric: Layout-related methods were removed from ShadowTree
Summary: Now it's parts of RootShadowNode and Scheduler.

Reviewed By: sahrens

Differential Revision: D13615364

fbshipit-source-id: 13dbea1e69ef51b2679101915c01c6be7e15d859
2019-01-16 20:22:39 -08:00
Valentin Shergin 5a58ca4144 Fabric: New non-blocking treading model for ShadowTree
Summary:
Instead of the whole family of commit* and complete* methods, now we have one single `commit` method which performs pre- and post-commit operations and swap pointers in a thread-safe manner. The `commit` operation is also exposing `revision` number and allows perform multiple commit attempts.

`completeByReplacingShadowNode`, `measure` and `constraintLayout` are also going away to RootShadowNode class in the next commits.

Why?
* Nicer API;
* No more recursive_mutex, no more problems with thread jumps;
* All mutex locks are now leaf-locks, so no more deadlocks possible;
* Exposing `revision` should help with debugging races.

Reviewed By: sahrens

Differential Revision: D13613942

fbshipit-source-id: 94e797d2f7860717847e823b5d97c4f7b35f08df
2019-01-16 20:22:39 -08:00
Valentin Shergin 8f9ca2b9a0 Fabric: Even more systraces
Summary: Trivial.

Reviewed By: mdvacca

Differential Revision: D13664395

fbshipit-source-id: 3de5d65d6fcf8b68bce2636fc91492defdbe8405
2019-01-16 20:22:39 -08:00
David Vacca b421b5f4bd Open source Fabric android
Summary: This diff open sources Fabric Android implementation and it extracts ComponentDescriptorFactory into a function that can be "injected" per application

Reviewed By: shergin

Differential Revision: D13616172

fbshipit-source-id: 7b7a6461216740b5a1ad5ebbead9e37de4570221
2019-01-16 12:38:22 -08:00
David Vacca 79cc1468bc Fix race condition in Fabric Scheduler
Summary:
This diff fixes a race condition that was detected on "Marketplace You" production test for Android.
The race condition happens when the method ShadowTree::complete is executed concurrently from two threads (in this case this is called from Scheduller::constraintSurfaceLayout and Scheduler::uiManagerDidFinishTransaction), based on the order of execution this bug makes MountViewItems to be dispatched to the UI in the wrong order.

The root cause of the bug is in the method:

```
bool ShadowTree::complete(
    const SharedRootShadowNode &oldRootShadowNode,
    const UnsharedRootShadowNode &newRootShadowNode) const {
  newRootShadowNode->layout();
  newRootShadowNode->sealRecursive();

  auto mutations =
      calculateShadowViewMutations(*oldRootShadowNode, *newRootShadowNode);

  if (!commit(oldRootShadowNode, newRootShadowNode, mutations)) {
    return false;
  }

  emitLayoutEvents(mutations);

  if (delegate_) {
    delegate_->shadowTreeDidCommit(*this, mutations);
  }

  return true;
}
```
Notes:
- the commit method is guarded by the commitMutex_
- the shadowTreeDidCommit() method dispatches mutations instructions to the platform side.
- If there are two threads running concurrently, there is no guarantee that the shadowTreeDidCommit() is going to be called in the correct order.

The solution is to include the execution to shadowTreeDidCommit() in the same commitMutex_

Possible solutions:
1 - move the commitMutex_ out of the commit method (to the completeMethod)
2 - synchronize the call to complete method() - this is the implemented solution.
I chose this solution to make it consistent with the way Scheduler::constraintSurfaceLayout is implemented (https://fburl.com/8l49no5x)

This mechanism is very likely to change in the refactor of threading mechanism that Valentin Shergin is going to be working on January.

I would like to land this, so we can fix this bug and run another experiment in production as soon as possible.

Reviewed By: sahrens

Differential Revision: D13535587

fbshipit-source-id: bedd4d85f5569ab3733c302d1328aa48017bcaad
2018-12-26 11:15:34 -08:00
Spencer Ahrens 34ea65e3d9 tighter ContextContainer semantics
Summary:
shergin mentioned that he'd like to move away from RTTI a bit and use explicit key strings for context container instances rather than relying on the `typeid`, so this does this.

We also fatal with a useful error message if we get a collision, rather than failing silently.

Reviewed By: shergin

Differential Revision: D13384308

fbshipit-source-id: 0b06d7555b082be89e8f130c23e94be99749a7a3
2018-12-21 18:00:36 -08:00
Spencer Ahrens 089dba3842 expose contextContainer as application API
Summary: We need a way for different apps to inject dependencies or additional functionality into Fabric - ReactNativeConfig might be a special case, but I think this could clean up it's integration nicely, and I'm using this for a uitemplate cache system so we can use CompactDisk or other storage systems for caching depending on the app.

Reviewed By: mdvacca

Differential Revision: D13407287

fbshipit-source-id: 45481908434e6235850aa4d2d6b2bfb936a23be7
2018-12-21 18:00:35 -08:00
Kevin Gozali 4f9a3bc8f6 xplat: pass through config object to fabric UIManager layer
Summary: For configuration purpose, pass down config object from the hosting app and use it in UITemplateProcessor.

Reviewed By: sahrens

Differential Revision: D13290322

fbshipit-source-id: 8bb6d7f5a3f977b873e548e15603259876b46dc8
2018-12-05 15:03:27 -08:00
Valentin Shergin 757518edba Fabric: ShadowTreeRegistry::get was renamed to ShadowTreeRegistry::visit
Summary: Trivial. The name `visit` expresss intent more clearly and fits C++17 `std::visit` pattern.

Reviewed By: mdvacca

Differential Revision: D13269744

fbshipit-source-id: 6aa6569c58aa66673e3f3a1662390a74290b8e01
2018-11-30 17:29:31 -08:00
Valentin Shergin dea8773c19 Fabric: ValueFactory and EventEmitter::dispatchEvent based on that
Summary:
Now the event delive pipeline supports `JSI::Value`-based payload. Instead of passing `folly::dynamic`, now we are passing `std::function<jsi::Value(jsi::Runtime &runtime)>` as factory that can build a `JSI::Value` with given `jsi::Runtime` and any captured data.
The old (now legacy) way of calling `EventEmitter::dispatchEvent(..., const folly::dynamic &payload, ...)` is also supported.

Reviewed By: sahrens

Differential Revision: D13123043

fbshipit-source-id: d65348bb215013042abb2fcfe5083a8c697333d0
2018-11-27 21:00:55 -08:00
Valentin Shergin 62173a1569 Introducing fabric/mounting module
Summary:
ShadowView, ShadowViewMutation, and Differentiator were decoupled to separate module.
That enables us to use ShadowView more widely without facing a circular dependency problem.

Reviewed By: mdvacca

Differential Revision: D13205229

fbshipit-source-id: 7373864bf153a7813c2f97edb263a41454ce0b88
2018-11-27 18:34:14 -08:00
Valentin Shergin f8be867cd8 Fabric: Sharing a pointer to ShadowTreeRegister with UIManager
Summary: The diff adds a pointer to ShadowTreeRegistry to UIManager which enables the possibility of implementing ShadowTree mutating and inspecting methods like `setNativeProps` and `getRelativeLayoutMetrics`.

Reviewed By: mdvacca

Differential Revision: D13036549

fbshipit-source-id: 5ed1252d84c8dd895fe0e6e8cc71afbaa9dab4b7
2018-11-21 17:16:48 -08:00
Valentin Shergin b4fa1fa0c6 Fabric: Introducing ShadowTreeRegistry
Summary:
Why do we need a dedicated registry class?
* We need to simplify registry-related logic in Scheduler.
* We need to couple threading aspect of the registry with the registry itself, otherwise it's not clear why exactly we acquire the mutex. We also should not acquire the mutex in a per-method way (as we did before), because it's incorrect and misleading (only lines that access the registry should by protected).
* We need to have a way to share the registry with other classes (e.g. UIManager) without passing a reference to the whole Scheduler.

Reviewed By: mdvacca

Differential Revision: D13036550

fbshipit-source-id: 644da910e823666c586834a3da2b4cdcb90eebb2
2018-11-21 17:16:48 -08:00