Summary: This diff replaces usage of abort() with LOG(FATAL) when a prop-value is not found during parsing of prop values
Reviewed By: sahrens
Differential Revision: D14570713
fbshipit-source-id: 57b0f993ba264a4949baf4022d807c55cdfe03b1
Summary:
With our current infra, we support automatic conversion of method arguments using `RCTConvert`.
```
RCT_EXPORT_METHOD(foo:(RCTSound*) sound)
{
//...
}
```
```
interface RCTConvert (RCTSound)
+ (RCTSound *) RCTSound: (NSDictionary *) dict;
end
implementation RCTConvert (RCTSound)
+ (RCTSound *) RCTSound: (NSDictionary *) dict
{
//...
}
end
```
```
export interface Spec extends TurboModule {
+foo: (dict: Object) => void,
}
```
With this setup, when we call the foo method on the TurboModule in JS, we'd first convert `dict` from a JS Object to an `NSDictionary`. Then, because the `foo` method has an argument of type`RCTSound*`, and because `RCTConvert` has a method called `RCTSound`, before we invoke the `foo` NativeModule native method, we first convert the `NSDictionary` to `RCTSound` using `[RCTConvert RCTSound:obj]`. Essentially, if an argument type of a TurboModule method is neither a primitive type nor a struct (i.e: is an identifier), and it corresponds to a selector on `RCTConvert`, we call `[RCTConvert argumentType:obj]` to convert `obj` to the type `argumentType` before passing in `obj` as an argument to the NativeModule method call.
**Note:** I originally planned on using `NSMethodSignature` to get the argument types. Unfortunately, while the Objective C Runtime lets us know that the type is an identifier, it doesn't inform us which identifier it is. In other words, at runtime, we can't determine whether identifier represents `RCTSound *` or some other Objective C class. I figure this also the reason why the old code relies on the `RCT_EXPORT_METHOD` macros to implement this very same feature: https://git.io/fjJsC. It uses `NSMethodSignature` to switch on the argument type, and then uses the `RCTMethodInfo` struct to parse the argument type name, from which it constructs the RCTConvert selector.
One caveat of the current solution is that it won't work work unless we decorate our TurboModule methods with `RCT_EXPORT_METHOD`.
Reviewed By: fkgozali
Differential Revision: D14582661
fbshipit-source-id: 3c7dfb2059f031dba7495f12cbdf406b14f0b5b4
Summary:
Before invoking TurboModule ObjC methods, we loop through all the arguments and transform them from `jsi::Value` to ObjC data structures. `jsi::Value`s that represent JS Objects get converted to `NSDictionary`s in ObjC. This isn't good enough because `NSDictionary` isn't typed. What we really need is a C/C++ struct that represents the type of the JS Object.
Therefore, for every argument of a TurboModule method that is a JS Object, this diff allows you to specify a method on `RCTCxxConvert` (which you have to declare and implement) that transforms that type of JS Object into something else. Basically, with the changes in this diff, we'll be able to transform JS Objects into C++ struct instances, which gives us type safety for JS Object method argumetns to TurboModule functions.
I modified the codegen to also create a mapping from NativeModule method name => argument num => `RCTCxxModule` conversion selector. This way, the FB codegen that generates the `RCTCxxConversion` function also informs our TurboModule system which conversion function to use before we call the method requiring complex argument. I just had to extend the `ObjCTurboModule` class to accomplish this.
The old system relies on the additional method generated by `RCT_EXPORT_METHOD` macro. It takes the written code, does string processing on it to parse the type of the struct arguments, and then replaces all instances of `::` with `_`. Super hacky. I didn't take this approach because it seemed unnecessarily hacky brittle.
The other approach I considered was to try to use reflection to infer the type of the struct at runtime. We'd have to do a bit of string processing and concat the TurboModule class name with the struct type. The solution would be simpler because it'd only modify the objective C and it wouldn't touch the Codegen system. **Edit:** I implemented it here: D14513078. The one downside of this design is that the name of the conversion function is individually constructed in two different locations in the code (i.e: no source of truth for this name). The other downside is that we have to rely on `RCTBridgeModuleNameForClass`, which we want to eliminate. This also computationally more expensive since it requires string processing/regex parsing and additional reflection. Therefore, we decided to move on with the current solution.
Reviewed By: fkgozali
Differential Revision: D14513429
fbshipit-source-id: 3d1b87e02ee908a19305686ff82b2ed624d8ac67
Summary: [iOS] [Fixed] - The existing logic defaults `undefined` & `null` in JS to be `[NSNull null]` when converting JS object to `NSDictionary`. Let's not insert the prop to the dictionary if it's `undefined`.
Reviewed By: blairvanderhoof
Differential Revision: D14571128
fbshipit-source-id: e03c713b055672b0a001d3305d694912ee36ab36
Summary:
JSBigString was inadvertently changed to a shared mapping. This means
that any changes to the string will be written back to the file. Ensure
we have a private (COW) mapping.
Reviewed By: kodafb
Differential Revision: D14532757
fbshipit-source-id: 6afb9635493496c90904f1432847c2f0da882c58
Summary: Conceptually, this assert is correct, however, sometimes a new node got allocated by same address as old parent node (which does not exist already) which makes the assert fires.
Reviewed By: mdvacca
Differential Revision: D14533070
fbshipit-source-id: 3fcc71c25e7d724180dc85aaf2457227d22ddba0
Summary:
Custom containers are only enabled in release mode.
Using custom stuff complicates debugging process because it breaks embedded into IDE introspections mechanisms.
Reviewed By: mdvacca
Differential Revision: D14508299
fbshipit-source-id: d2dbe87764b17d75ccd544c0a4baf03dd9e0cd0b
Summary: Same algorithm using a new API.
Reviewed By: JoshuaGross
Differential Revision: D14423509
fbshipit-source-id: c40f61fdd001f68785512c304941f523585d641c
Summary: The basic idea of the implementation is the same, but it uses the new method for finding parenting chain and it does not use `shared_from_this()` anymore.
Reviewed By: JoshuaGross
Differential Revision: D14416949
fbshipit-source-id: 13ef928505a60280e2a6c30c76ac87d91cee326e
Summary:
The algorithm is quite simply:
1. Get family objects of the two nodes (inner and outer).
2. Traverse the list of family objects starting from the inner one and form a reversed list of them.
3. tarting from the inner node, traverse the tree layer-by-layer choosing a next element of the path by comparing the family object of each node on the level and an object from the list.
Reviewed By: JoshuaGross
Differential Revision: D14416950
fbshipit-source-id: 23c659a9e01690f90174193650a2b0ef09eadb4d
Summary:
One of the core feature of ShadowNodeFamily is having a pointer to a parent family. This diff implements it.
I don't think there is a hard retain cycle there, but for more lean memory usage we use weak_ptr here.
Reviewed By: JoshuaGross
Differential Revision: D14416948
fbshipit-source-id: 05fd2c4833146f007228363b1d958776b4a2a9cf
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
Summary: This is a leftover from the ealy days of Fabric. The mehtod does not have implementation counterpart and any usage.
Reviewed By: JoshuaGross
Differential Revision: D14402636
fbshipit-source-id: aa2e919084ae7382d3a62af761e1f6eac334fc75
Summary: The removed code does nothing because we are replacing the oldChild with newChild several lines above.
Reviewed By: JoshuaGross
Differential Revision: D14402637
fbshipit-source-id: 731a950f373e20f7d5bae3cbf6470335d3694ccc
Summary: In React, things like changing `tag`, `eventTarget` or reparenting are impossible by design. Which seems like a strange limitation actually allows us to do tremendous performance optimizations (stay tuned!).
Reviewed By: JoshuaGross
Differential Revision: D14402638
fbshipit-source-id: 3b7b7edaff0d55a3ca94e2ac4c753d630d07101d
Summary:
With recent changes, simple cloning a component does not mean that underlying Yoga node will be dirtied. Autodirtying is only performed if the child nodes were dirtied and/or if the YGStyles were changed.
That's not the case for Text component which does not have direct layotable children, so we have to call `dirtyLayout` explicitly.
Reviewed By: JoshuaGross
Differential Revision: D14508277
fbshipit-source-id: 2c52d7d40da963a976c7d28a13781cc1755ef591
Summary: In methods which implement move semantic we have to check the source object because it's (also) being mutated.
Reviewed By: JoshuaGross
Differential Revision: D14496937
fbshipit-source-id: f3f2299d14e41c8b269f1647336dbd5b45c235f4
Summary: More `assert`s and `ensureUnsealed` calls were added to YogaLayoutableShadowNode for simpler debugging and early failing.
Reviewed By: JoshuaGross
Differential Revision: D14496936
fbshipit-source-id: 898c6a0665aeac5d0b1995bd53046f58cec37007
Summary:
If the `HasNewLayout` flag is `false`, we should not copy the data from YGStyle/YGLayout to ShadowNode because the node can be already sealed and because it's unnecessary. Previously we workaround this case with a special check in `setLayoutMetrics` method, but that can be unreliable because of some side-effects related to pixel rounding and comparing floats.
The new approach is much more robust and explicit.
Reviewed By: JoshuaGross
Differential Revision: D14496939
fbshipit-source-id: deddb14d2206c5bd3f22154d0ea682e3c5888901
Summary: These default implementations are never being used. Removing them allowing to ensure that flags inside YGNode have same values as flags in YogaLayoutableShadowNode. That also saves a couple of bytes in size of ShadowNode.
Reviewed By: JoshuaGross
Differential Revision: D14496938
fbshipit-source-id: c43f9c8a2eec054f728ff54a6573668eccda55fb
Summary:
As a comment above changed lines states, RootShadowNode is a special one because it layouts itself. In normal case some parent node layouts its children, and it also checks getHasNewLayout flag. So, in the case of RootShadowNode it has to check its own flag by itself.
That fix should save some resources and generally correct.
After the change, changing a state of some node does not cause relayout process. If dirtying is required, the component should call `dirtyLayout()` explicitly in the constructor or in `adopt` method.
Reviewed By: JoshuaGross
Differential Revision: D14472751
fbshipit-source-id: 75bf62ac28991a39e5664aa71c08bd0e64fa275b
Summary: That diff fixes an obvious bug that prevents internal data of LayoutableShadowNode being cloned during cloning of YogaLayoutableShadowNode.
Reviewed By: JoshuaGross
Differential Revision: D14472753
fbshipit-source-id: d07be3bf36708690dfe10de7898e2b48648aa0f4
Summary: In addition to the previous change, now we handle a situation where some node receives a new set of children and all those children have the same styles. (See the previous diff for more details.)
Reviewed By: JoshuaGross
Differential Revision: D14472754
fbshipit-source-id: 16411036e14f18e730e064e33948440b05ff51c8
Summary:
After the change, YogaLayoutableShadowNode will preserve dirty flag (being false) in cases where:
* a node was cloned with same children;
* changes in props don't affect layout.
Motivation:
In Fabric we always were aggressive about dirting yoga nodes: when we clone the node, we always dirty underlying Yoga node. I think that was the case because we don't deeply understand how the system works and we always had more severe problems to fix. Now, we faced an issue that forces us to think about that problem carefully (more about that later).
(I don't expect that will improve TTI performance, but that's possible if we do a lot of changes in the hierarchy during initial load process.)
I see two main use cases where we have to be smart about dirtied yoga nodes:
Case 1. Native local commits which do *not* modify yoga styles.E.g. in a case where ScrollView updates the internal state (which has offset info) really really frequently. (It will be implemented later.) That `contentOffset` info does not or might not affect layout, so we should not pay for this.
Case 2. Legit React commits which do *not* modify yoga styles. E.g. in a case where only the background color of some view changes, we don't need to relayout anything. Unfortunately, we do this in Fabric because of two major reasons:
* We don't make a difference between any changes in Props.
* React constructs new children of cloned node iteratively, calling `appendChild`. That makes implementing optimization really challenging because we don't know when the process ends. And when it ends we have very few pieces of information about how the state looked before.
This diff stack will handle the problems of the first kind. The main motivation is: we want to have state updates to be as lean as possible.
Reviewed By: JoshuaGross
Differential Revision: D14472752
fbshipit-source-id: 68374f60cb07de9ab65bf1f6d94c828985359fa5
Summary:
Upgrade mobile `BUCK` and `.bzl` files to use C++14.
Let's see what happens.
Reviewed By: mzlee
Differential Revision: D14223329
fbshipit-source-id: ff642ca017103d9415c4d7f5beaf5ded07ef7ff1
Summary:
This is the couple of hacks I used after I finished #23802 in order to get fabric working on RNTester. This is inspired from prior work by kmagiera.
The goal of this PR is to show others what I’m struggling with, and to eventually merge it sans hacks.
- Yarn Install
- Uncomment the commented out pods in RNTester's pod file
- Open RNTesterPods workspace
- Run App
- this is only for pods, the non-pod RNTester will no longer work until updated with fabric too.
- `SurfaceHostingView` & `SurfaceHostingProxyRootView` both try to start the surface immediately, this leads to a race condition due to the javascript not having loaded yet, the hack here is:
1. Swizzle the `start` method on `RCTFabricSurface` to no-op when called.
2. Add observer for `RCTJavaScriptDidLoadNotification`
3. Call private method `_startAllSurfaces` on `_surfacePresenter` in AppDelegate when we receive `RCTJavaScriptDidLoadNotification`.
[General] [Added] - Use Fabric in RNTester
Pull Request resolved: https://github.com/facebook/react-native/pull/23803
Reviewed By: shergin, mdvacca
Differential Revision: D14450726
Pulled By: fkgozali
fbshipit-source-id: 8ae2d48634fecb60db539aaf0a2c89ba1f572c27
Summary: Several things need to ironed out: 1) LocalState in Fabric C++, 2) setting dimensions of BottomSheet component to 0,0 for parent.
Reviewed By: shergin
Differential Revision: D14426167
fbshipit-source-id: 45a90a7971c87672872108a9e360926b4a6095f0
Summary:
Accidentally I noticed that the signature of Folly's hash_combine is different from boost's one.
The Folly's one is:
`size_t hash_combine(const T& t, const Ts&... ts)`, so the first argument is immutable and the method returns the result normally.
It means that all hashes that we compute in Fabric using `hash_combine` were `0`.
So I fixed it.
I have no idea why this difference exists, but some modern papers suggest that folly's variant has good chances to be standardized.
E.g.: http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0814r0.pdf
Technically, it should improve performance, but I doubt that it can be more than 1-2 ms per screen TTI.
Reviewed By: JoshuaGross
Differential Revision: D14430380
fbshipit-source-id: 97da999ee5780b940bb789bc3eb5bf9f89c194ca
Summary:
While the proper typographical terminology is [Strikethrough](https://en.wikipedia.org/wiki/Strikethrough), we should still support `line-through` as it goes through a deprecation phase.
[iOS] [Added] - line-through support for fabric text components
Pull Request resolved: https://github.com/facebook/react-native/pull/23911
Differential Revision: D14460610
Pulled By: shergin
fbshipit-source-id: 0dae41b765f21d166ea3618c463ebe1330607b30
Summary:
Moves rn_codgen to rn_library behind a `codegen` flag to limit the number of rules we generate
WIth this, modules with native components can enable the react-native-codegen schema parsing by just updating their buck rule to:
```
rn_library(
name = 'lib',
codegen = True,
// ...
)
```
Reviewed By: TheSavior
Differential Revision: D14401263
fbshipit-source-id: 1675bc28389db64da10153c988bb4eb00d715056
Summary: This diff is a part of an effort to resolve build errors that appear when compiling with the latest version of clang.
Reviewed By: shergin
Differential Revision: D14369797
fbshipit-source-id: e4c6f53e293f336efad18597f9d2705c025e1051
Summary: The hope is that it will remove many unnececery allocations improving overal perfromance.
Reviewed By: mdvacca
Differential Revision: D14249198
fbshipit-source-id: f0442b3919ccead0582a3190dea0e33d517d85f6
Summary:
SharedShadowNodeList is one of the core collections in Fabric. Every ShadowNode has one, it's used intensivly during diffing and so on.
Usually, nodes have a very few children, so using `small_vector` instead of regular `vector` should save us a lot of memory allocations.
Reviewed By: JoshuaGross
Differential Revision: D14249201
fbshipit-source-id: 53297caa027a74099d0a1ed4a3cce78f8feb651b
Summary:
Nowadays, every ShadowNode has a reference to a ComponentDescriptor, so now there is no need to do registry lookup for that.
That should save us 0.5-1.0 ms in my non-scientific measurements.
Reviewed By: mdvacca
Differential Revision: D14348369
fbshipit-source-id: 57f6a6f2f8bf0b7e58d89a414fec20b2db8876f7
Summary:
Clowntown.
This fixes a recent regression happened becasuse wrong order of parameters in ShadowViewMutation constructor.
Reviewed By: JoshuaGross
Differential Revision: D14329164
fbshipit-source-id: 5a0dc04b889fb3357050b951d56c3e436dbeefb1
Summary: Use the codegen for the Slider component with the new `inferfaceOnly` option
Reviewed By: TheSavior
Differential Revision: D14295981
fbshipit-source-id: 0482572892fbcffada43c7c6fbf17e70546300b8
Summary: These were moved to the codgen
Reviewed By: TheSavior
Differential Revision: D14307470
fbshipit-source-id: 49030c245f11bd595bb97e1b2f34a7c454be5c56
Summary:
This pull request removes the designated initializer in `LayoutMetrics.h`. This will help improve the portability of this file.
[General] [Changed] - Fabric: Remove designated initializer in LayoutMetrics.h
Pull Request resolved: https://github.com/facebook/react-native/pull/23758
Differential Revision: D14320526
Pulled By: shergin
fbshipit-source-id: 076ad389d0985d5213b521a2ffaca4ca7ae31599
Summary:
This pull request removes the use of the GCC extension null coalescing operators (`?:`) and replaces them with ternary operators. This improves the portability of `ShadowNode.cpp` (and enables MSVC to build it)
[General] [Fixed] - Fabric: Removed null coalescing operators in `ShadowNode`
Pull Request resolved: https://github.com/facebook/react-native/pull/23438
Differential Revision: D14304958
Pulled By: shergin
fbshipit-source-id: 7d8e6778a72dabf09b1d99bc091a7578598b79c3
Summary:
This pull request removes the designated initializers in `RootShadowNode.cpp`. This will help improve the portability of this file.
[General] [Fixed] - Removed designated initializers in `RootShadowNode`
Pull Request resolved: https://github.com/facebook/react-native/pull/23715
Differential Revision: D14305167
Pulled By: shergin
fbshipit-source-id: e394580f103fdb59cf078828b5d2ee6df6cc534d