Commit Graph
2232 Commits
Author SHA1 Message Date
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
Valentin Shergin aad99607de Fabric: Test for State Reconciliation mechanism
Summary:
It's not immediately obvious from the UI/UX when/if this mechanism breaks, so it's good to have a test.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: JoshuaGross

Differential Revision: D21184718

fbshipit-source-id: 25432a1398cff3ce61f62cf433e3cb73d7a7a93f
2020-04-24 21:39:08 -07:00
Valentin Shergin fef8bc33df Fabric: Added assert in ShadowNode
Summary:
It's not allowed to return nullptr from the callback. The assert ensures it which is helpful during development.

Probably, we should consider using `gsl::not_null<>` here.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: sammy-SC

Differential Revision: D21149891

fbshipit-source-id: a5f77b35029f22b499491721036405682f812a38
2020-04-24 21:26:42 -07:00
Marc Horowitz 81734276b9 Allow use of std::tuple<> with decorators directly
Summary:
Previously, a derived class, WithTuple, was used.  This ran
into bugs in MSVC (see https://github.com/microsoft/STL/issues/121).
Instead, use specialization to get the same result using std::tuple
directly.  This avoids the bug, and is a cleaner API.

Changelog: [Internal]

Reviewed By: dulinriley

Differential Revision: D21233677

fbshipit-source-id: 1d75991847164e525b4ba70f65a90627e5f8cd56
2020-04-24 15:42:47 -07:00
Valentin Shergin 78b1c85747 Fabric: Simplifying Yoga and Fabric integration
Summary:
The integration with Yoga was pretty complex from day one. The first attempt to make it simpler was in D19963353 when we removed a bunch of layers of indirection. This is the second iteration that aimed to simplify the structure of methods and their responsibilities.

The only conceptual change (that I am aware of) in this diff is that now we don't support (imaginary) case where a non-leaf YogaLayoutableShadowNode can have a non-YogaLayoutableShadowNode child. In the previous version, it was a no-op, now it's not supported and an assert will fire.

Alongside with refactoring, this diff implements several helper functions that verify the invariants important for the Concurrent Layout in debug mode.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: JoshuaGross

Differential Revision: D21198222

fbshipit-source-id: cc085904948056f861562af5bd2571de45a743b9
2020-04-23 15:00:46 -07:00
generatedunixname89002005287564 ca162560af Daily arc lint --take CLANGFORMAT
Reviewed By: zertosh

Differential Revision: D21202121

fbshipit-source-id: 6acb53e6ca941e465b11aeac4215533c16067eed
2020-04-23 06:53:42 -07:00
Ramanpreet Nara 2c473e1a38 Overhaul RCTTurboModule creation and initialization
Summary:
## Problems:
In my investigation of T65656635, I realized that the TurboModule system has a number of problems:
- In TurboModules, we use 1 lock to create n TurboModules. We should change this setup to n locks for n TurboModules. This way, two threads creating two different NativeModules don't compete for the same lock. Also, this is how it's done in Android (TurboModules & NativeModules), and iOS (NativeModules).
- In TurboModules, we don't calculate "requires main queue setup" faithfully. In the legacy system, if a NativeModule has a custom `init` method or a custom `constantsToExport` method, it "requires main queue setup" with a warning.
- In TurboModules, we don't create the NativeModule on the main queue, if "requires main queue setup" is true. Instead, the NativeModule is always created on the thread that requires it.
- In TurboModules, we don't perform any concurrency control around `id<RCTTurboModule>` setup. We should.

## What this diff does
In this diff, I fixed all the aforementioned issues by re-implementing `provideRCTTurboModule:`.

**Algorithm Notes:**
- **Gist:** When `n` threads race to create NativeModule `x`, only the first thread creates and sets up `x`. All others are told to wait. Once the creator thread finishes its job, it notifies all other waiting threads, which then wake up and return the newly created NativeModule. This algorithm was initially implemented in NativeModules for Android inside (ModuleHolder.java). I modified and implemented it for TurboModules for Android, and now this diff implements it for TurboModules for iOS.
- The TurboModule cache is replace with a TurboModuleHolder map. A TurboModuleHolder manages the creation lifecycle of a TurboModule, and holds a condition variable and mutex for doing concurrency control around it. When the bridge invalidates, in TurboModuleManager, we set the `invalidating` flag to true, which prevents the insertion of new entries into the TurboModuleHolder map.
- I added a `std::mutex` to serialize calls into the TurboModuleManagerDelegate, so we don't get races if the delegate isn't thread-safe.

Changelog:
[iOS][Fixed] - Re-implement RCTTurboModuleManager provideRCTTurboModule:

Reviewed By: shergin

Differential Revision: D21170099

fbshipit-source-id: 8792812c2237d3bfc80c9834c818e011de85b0ea
2020-04-22 16:13:47 -07:00
Valentin Shergin f64b39ea6c Fabric: Introducting ShadowNodeFamilyFragment::Value
Summary:
`ShadowNodeFamilyFragment::Value` is a value couter-part type for `ShadowNodeFamilyFragment`.
We need that to be able safely copy data stored inside a `ShadowNodeFamilyFragment` object.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: kacieb

Differential Revision: D21169580

fbshipit-source-id: 1a485e1b2ae47bc7da9476a60466934ac9d61366
2020-04-22 15:41:56 -07:00
Valentin Shergin 3246eaec44 Fabric: ConcreteShadowNode::initialStateData() now accepts a ShadowNodeFamilyFragment instead of just a SurfaceId
Summary:
We need it to be able pass an `EventEmitter` object to constructed concrete State objects.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: JoshuaGross

Differential Revision: D21169581

fbshipit-source-id: 3eef0310de7e2f061108aa85c1a39678a43fe85e
2020-04-22 15:41:55 -07:00
Panagiotis Vekris 57fee33898 Flow 0.123.0 in xplat/js
Summary:
Changelog: [Internal]

## Sync of generated files

Ran
```
js1 upgrade www-shared -p core_windowless
```
but had to manually revert
```
RKJSModules/Libraries/www-shared/core_windowless/logging/FBLoggerType.flow.js
RKJSModules/Libraries/www-shared/core_windowless/logging/FBLogger.js
```
because they introduced more errors

## Flow version bump
```
~/fbsource/fbcode/flow/facebook/deploy_xplat.sh 0.123.0
```

Reviewed By: gkz

Differential Revision: D21159821

fbshipit-source-id: e106fcb43e4fc525b9185f8fc8a246e6c3a6b14f
2020-04-21 22:43:24 -07:00
Tim Yung 5242ad931b RN: Add RootTag Type to TurboModule
Summary:
Adds `RootTag` as a valid type for arguments and return types in TurboModules (on both Android and iOS).

This will enable us to change `RootTag` into an opaque type. There are two compelling reasons to do this:

- JavaScript will no longer be able to safely depend on `RootTag` being a number (which means we can change this in the future).
- Call sites using `unstable_RootTagContext` will can get a `RootTag`, but call sites using the legacy `context.rootTag` will not. This means the opaque type will give us a strategy for migrating away from legacy context and eventually making `unstable_RootTagContext` the only way to access `RootTag`.

Changelog:
[Internal]

(Note: this ignores all push blocking failures!)

Reviewed By: RSNara

Differential Revision: D21127170

fbshipit-source-id: baec9d7ad17b2f8c4527f1a84f604fc0d28b97eb
2020-04-21 19:15:54 -07:00
David Vacca 05c76be176 Easy diff to document in code how to enable logging of Shadow Tree instrospection
Summary:
Easy diff to document in code how to enable logging of Shadow Tree instrospection

changeLog: [Internal] Internal change used on Fabric

Reviewed By: JoshuaGross

Differential Revision: D21150196

fbshipit-source-id: 8eb23ec3ea1d574b79b09333428ab52c851065dd
2020-04-20 23:31:21 -07:00
David Vacca 8c4efc94e1 Enable Yoga logging in Fabric Debug
Summary:
This diff extends Fabric to support Yoga logging

changeLog: [Internal] Internal changes in Fabric to enable yoga logging

Reviewed By: JoshuaGross

Differential Revision: D21150195

fbshipit-source-id: a2e8308a79a7b422bf9ecc3a65f822b305f02c5d
2020-04-20 23:31:21 -07:00
Joshua Gross 1fdb9ac69c Update Differ test
Summary:
Update differ test so it passes again. Previously to D21111423 (I think) nodes were being incorrectly detected as updated even if they weren't different, so now there are fewer unnecessary Update mutations generated.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D21148647

fbshipit-source-id: cab6e3ecd0a457e1ac3155b3468bcc56663dab0b
2020-04-20 23:19:29 -07:00
Valentin Shergin d639063499 Fabric: More strict policies to dirty Yoga nodes in YogaLayoutableShadowNode
Summary:
Yoga uses a dirty flag to re-layout nodes. In normal, single-threaded approach the policy for dirtying is simple: if a node was changed, we need to dirty it. In the Concurrent Yoga approach, those rules are not so simple, and it seems we haven't formalized those rules yet.

Investigating some layout issues that we have in Fabric, I tend to believe that we don't dirty as much we should. Hense this change adds mode dirtying.

Reviewed By: JoshuaGross

Differential Revision: D21092815

fbshipit-source-id: 4603c97ccb79efcdf5e6a4cc450ebe61b63effb3
2020-04-20 19:21:08 -07:00
Valentin Shergin 4afb8362ec Fabric: Fixed getDirtied vs isDirty in YogaLayoutableShadowNode
Summary:
This is quite a fateful mistake. `getDirtied()` returns the pointer to a function which is obviously a mistake here; we should use `isDirty()` instead.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: mdvacca

Differential Revision: D21028569

fbshipit-source-id: 95212b31f4e32d51c594d5209f295397af3f1252
2020-04-20 19:21:08 -07:00
Will Holen 33ccc0a0bc Implement Hermes.setPauseOnLoad
Summary:
This Hermes-specific mode is similar to Debugger.setPauseOnExceptions
and lets the VM know that it should enter a Pause state whenever a new
script is loaded/executed.

The debugger can then take its time to parse the source map and update
any breakpoints, before automatically continuing.

Changelog: [Internal] Implement a Hermes.setPauseOnLoad CDP call

Reviewed By: bestander

Differential Revision: D20754604

fbshipit-source-id: 7f9d0638706c99e9dcb534699b633f658e364909
2020-04-20 14:06:51 -07:00
Will Holen 04bc315eba Add support for generating custom messages
Summary:
Until now we've generated scaffolding entirely based on the official devtools
protocol spec. This diff adds support for defining custom domains in `custom.json`
which will be merged with the upstream protocol JSON definition.

ChangeLog: [Internal] Add support for Hermes-specific CDP messages

Reviewed By: bestander

Differential Revision: D20754605

fbshipit-source-id: a8075f81816a40114d1a3332192c7aa076b17848
2020-04-20 14:06:51 -07:00
Valentin Shergin 80575503d2 Fixed incorrect owner assignment in YGNode move constructor
Summary:
Assigning self as an owner makes a cycle which is obviously a bug.

Changelog: [Internal] Small change in Yoga (should not affect RN).

Reviewed By: SidharthGuglani

Differential Revision: D21111423

fbshipit-source-id: 1835561c055ac827f5ce98a044f25aed0d1845a5
2020-04-20 12:05:20 -07:00
Samuel Susla e7ef35c133 Fix mistake in swapping left/right layout properties
Summary:
Changelog: [Internal]

We were assigned `undefined` value to incorrect edge, instead of `YGEdgeLeft` it should have been `YGEdgeRight`.
If node has `YGEdgeRight` value, it needs to be reassigned to `YGEdgeEnd` and its original value set to undefined.

Reviewed By: mdvacca

Differential Revision: D21095234

fbshipit-source-id: fbecd9b7e6670742ad4a4bb097760aa10eec8685
2020-04-20 11:44:15 -07:00
Valentin Shergin 7cc791b978 Fabric: ComponentDescriptor::cloneProps() now never returns the base props objects
Summary:
The diff changes how the `empty raw props` optimization works in `ComponentDescriptor::cloneProps()`. Now it only fires only when the base `props` object is null, which is practically all production cases we have (and care about). (I tried, in a normal run there were no cases where the empty raw props were passed with non-null props.) From the other side, the old behavior that may return the same props objects previously several times created bugs and practically unexpected results and practically disallowed to clone props objects easily.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: JoshuaGross

Differential Revision: D21110608

fbshipit-source-id: 884807cd8e9c5c3e6cc1c9e4c1f0227259cc21fb
2020-04-20 00:19:56 -07:00
Valentin Shergin 5dc6eded1b Fabric: Using proper clock in MountingTelemetryTest
Summary:
Apparently, `std::this_thread::sleep_for` uses a different clock to measure time which causes ofter misalignment with the clock which Telemery uses which makes the test flaky. Using the same clock should fix it.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: JoshuaGross

Differential Revision: D21116058

fbshipit-source-id: 52dde2e325776d365431a2a957dcc12dfe53f890
2020-04-19 22:55:09 -07:00
empyrical b0006648e2 Fabric: Add Unicode prefix to AttachmentCharacter (#28617)
Summary:
This pull request adds a Unicode `u8` prefix to the string literal returned in `AttributedString.cpp`'s `Fragment::AttachmentCharacter()`.

This fixes the following error when building on MSVC:

```
react\attributedstring\AttributedString.cpp(21): error C4566: character represented by universal-character-name '\uFFFC' cannot be represented in the current code page (1252)
```

## Changelog

[Internal] [Fixed] - Fabric: Add Unicode prefix to AttachmentCharacter
Pull Request resolved: https://github.com/facebook/react-native/pull/28617

Test Plan: The Fabric test suite has been ran on a Clang-based build of Fabric on macOS, and no regressions in it have been noted.

Differential Revision: D21118078

Pulled By: shergin

fbshipit-source-id: c105de5e4edb67fed97ce44153a75d9d380bf588
2020-04-19 13:00:17 -07:00
empyrical de188a2c97 Fabric: Fix case of Glog include in MountingTest.cpp (#28616)
Summary:
This pull request changes the include of Glog from `<Glog/logging.h>` to `<glog/logging.h>` in `MountingTest.cpp`. This fixes building on a case-sensitive filesystem.

## Changelog

[Internal] [Fixed] - Fabric: Fix case of Glog include in MountingTest.cpp
Pull Request resolved: https://github.com/facebook/react-native/pull/28616

Test Plan: The `include` of Glog no longer causes issues with building `MountingTest.cpp` on a case-sensitive filesystem.

Differential Revision: D21118085

Pulled By: shergin

fbshipit-source-id: c958c54bf88333fd5001127779c855ce8c2666c3
2020-04-19 12:06:41 -07:00
Valentin Shergin 7a2c685ac1 Fabric: templateprocessor module was decoupled from uimanager
Summary:
We need to break up the `uimanager` module in order to solve circular dependencies problem (which future diff would have otherwise).

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: JoshuaGross

Differential Revision: D20885646

fbshipit-source-id: b8e3199c0eacc57a5be1481595cf97c84f972293
2020-04-18 15:00:22 -07:00
Valentin Shergin 599f1edd9a Fabric: scheduler module was decoupled from uimanager
Summary:
We need to break up the `uimanager` module in order to solve circular dependencies problem (which future diff would have otherwise).

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: JoshuaGross

Differential Revision: D20885645

fbshipit-source-id: 8148bd934879802b076261ed86fa78acf0a07ed3
2020-04-18 15:00:21 -07:00
Valentin Shergin e56950dc65 Fabric: componentregistry module was decoupled from uimanager
Summary:
We need to break up the `uimanager` module in order to solve circular dependencies problem (which future diff would have otherwise).

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: JoshuaGross

Differential Revision: D20885163

fbshipit-source-id: 08eb1ba1d408fc0948e8d0da62380786a40973af
2020-04-18 15:00:21 -07:00
Valentin Shergin e1eef24321 Fabric: Implementation of getDebugDescription for std::array
Summary:
Yoga uses `std::array` a lot (and `std::array` is not a `std::vector`), so it's useful for printing Yoga values.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: mdvacca

Differential Revision: D21028570

fbshipit-source-id: c6bf114d5362f085ea201ecdc5b7d59646b33ebd
2020-04-17 21:20:05 -07:00
Valentin Shergin cc07baa87e Fabric: "Attempt to mutate a sealed object." is now an assert (not exception)
Summary:
This is a debug-only feature that simply should be an assert. When it triggers in debugger and bubbles to some random exception catch block which makes it impossible to understand was exactly it happens. Making it an assert will stop debugger exactly where it happens.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: mdvacca

Differential Revision: D21028571

fbshipit-source-id: 3df4ec0da922026bb9df61081cb71113577e06e9
2020-04-17 21:20:04 -07:00
Valentin Shergin 62544c0830 Fabric: Proper traits for ImageShadowNode and ViewShadowNode
Summary:
* <Image> must be a leaf node; having a proper trait will fail earlier in case of misuse (mounting something inside).
* <View> must have a `View` trait because it's for what that trait is.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: sammy-SC

Differential Revision: D21028573

fbshipit-source-id: 457716d4661333eb2357f34316f3e495ab4fda24
2020-04-17 21:20:04 -07:00
Valentin Shergin 4c538fc8d0 Fabric: LayoutableShadowNode:getLayoutMetrics is not a virtual method anymore
Summary:
We don't use it as vitrual anymore (setLayoutMetrics is a non-virtual method already), so it does not need to be marker virtual.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: mdvacca

Differential Revision: D21028572

fbshipit-source-id: 99f86fdd4cf2f5972034d9058d7b82bdc8680187
2020-04-17 21:20:04 -07:00
Sidharth Guglani 49e16bdc2f use default value of enums YGDirection and YGMeasureMode instead of -1
Summary:
Changelog:
[Internal][Yoga] YGDirection variable was initialized incorrectly by casting -1 to YGDirection. Changing it to default value of direction

Same for YGMeasureMode.

Reviewed By: pasqualeanatriello

Differential Revision: D20869042

fbshipit-source-id: 7bfe490193321baae875ef6fb49a938851950c9f
2020-04-17 05:27:58 -07:00
Ramanpreet Nara d75401af96 Part 3: Update RCTTurboModuleManagerDelegate to use ObjCTurboModule::InitParams
Summary:
## Summary
Please check out D21035208.

## Changes
- Update `RCTTurboModuleManagerDelegate getTurboModule:instance:jsInvoker:nativeInvoker:perfLogger` to use `RCTTurboModuleManagerDelegate getTurboModule:(const ObjCTurboModule::InitParams)`
- Update all implementations of `RCTTurboModuleManagerDelegate` in accordance with this API change

Changelog:
[iOS][Changed] - Make RCTTurboModuleManagerDelegate create TurboModules via ObjCTurboModuleManager::InitParams

Reviewed By: PeteTheHeat

Differential Revision: D21036272

fbshipit-source-id: c16002c47db26e2ba143fc1080afe9e2fe1e7816
2020-04-16 17:29:56 -07:00
Ramanpreet Nara 03bd7d799e Part 2: Update ObjC++ codegen classes to use ObjCTurboModule::InitParams
Summary:
## Summary
Please check out D21035209.

## Changes
- Codemod all ObjC NativeModule `getTurboModuleWithJsInvoker:nativeInvoker:perfLogger` methods to `getTurboModule:(const ObjCTurboModule::Args)`

## Script
```
var withSpaces = (...args) => args.join('\s*')

var regexString = withSpaces(
  '-',
  '\(',
  'std::shared_ptr',
  '<',
  '(?<turboModuleClass>(facebook::react::|react::|::|)TurboModule)',
  '>',
  '\)',
  'getTurboModuleWithJsInvoker',
  ':',
  '\(',
  'std::shared_ptr',
  '<',
  '(?<fbNamespace>(facebook::react::|react::|::|))CallInvoker',
  '>',
  '\)',
  '(?<jsInvokerInstance>[A-Za-z0-9]+)',
  'nativeInvoker',
  ':',
  '\(',
  'std::shared_ptr',
  '<',
  '(facebook::react::|react::|::|)CallInvoker',
  '>',
  '\)',
  '(?<nativeInvokerInstance>[A-Za-z0-9]+)',
  'perfLogger',
  ':',
  '\(',
  'id',
  '<',
  'RCTTurboModulePerformanceLogger',
  '>',
  '\)',
  '(?<perfLoggerInstance>[A-Za-z0-9]+)',
  '{',
  'return',
  'std::make_shared',
  '<',
  '(?<specName>(facebook::react::|react::|::|)Native[%A-Za-z0-9]+SpecJSI)',
  '>',
  '\(',
  'self',
  ',',
  '\k<jsInvokerInstance>',
  ',',
  '\k<nativeInvokerInstance>',
  ',',
  '\k<perfLoggerInstance>',
  '\)',
  ';',
  '}',
)

var replaceString = `- (std::shared_ptr<$<turboModuleClass>>) getTurboModule:(const $<fbNamespace>ObjCTurboModule::InitParams &)params
{
  return std::make_shared<$<specName>>(params);
}`

const exec = require('../lib/exec');
const abspath = require('../lib/abspath');
const relpath = require('../lib/relpath');
const readFile = (filename) => require('fs').readFileSync(filename, 'utf8');
const writeFile = (filename, content) => require('fs').writeFileSync(filename, content);

function main() {
  const tmFiles = exec('cd ~/fbsource && xbgs -n 10000 -l getTurboModuleWithJsInvoker:').split('\n').filter(Boolean);

  tmFiles
    .filter((filename) => !filename.includes('microsoft-fork-of-react-native'))
    .map(abspath)
    .forEach((filename) => {
      const source = readFile(filename);
      const newSource = source.replace(new RegExp(regexString, 'g'), replaceString);

      if (source == newSource) {
        console.log(relpath(filename));
      }

      writeFile(filename, newSource);
    });
}

if (!module.parent) {
  main();
}
```

## Re-generating diff
```
> hg revert -r .^ --all
> node index.js # run script
```

Changelog: [iOS][Changed] - Make all ObjC NativeModules create TurboModules using ObjCTurboModule::Args

Reviewed By: PeteTheHeat

Differential Revision: D21036265

fbshipit-source-id: 404bcc548d1775ef23d793527606d02fe384a0a2
2020-04-16 17:29:55 -07:00
Ramanpreet Nara 251ff1bb0a Part 1: Update ObjC++ codegen classes to use ObjCTurboModule::InitParams
Summary:
## Summary
Please check out D21035208.

## Changes
- `ObjCTurboModule::ObjCTurboModule` changed to accept a bag of arguments `const ObjCTurboModule::InitParams` instead of an argument list.
- TurboModule iOS codegen scripts updated to generated `ObjCTurboModule` subclasses that accept a `const ObjCTurboModule::InitParams` object in their constructor, and forward it to `ObjCTurboModule::ObjCTurboModule`.
- All manually checked in code-generated ObjC++ classes (i.e: RCTNativeSampleTurboModule, RCTTestModule, FBReactNativeSpec) are updated.

## Rationale
This way, the code-gen can remain constant while we add, remove, or modify the arguments passed to ObjCTurboModule.

## Commands run
```
function update-codegen() {
  pushd ~/fbsource && js1 build oss-native-modules-specs -p ios && js1 build oss-native-modules-specs -p android && popd;
}

> update-codegen
```

Changelog:
[iOS][Changed] Update ObjCTurboModule to use ObjCTurboModule::InitParams

Reviewed By: PeteTheHeat

Differential Revision: D21036266

fbshipit-source-id: 6584b0838dca082a69e8c14c7ca50c3568b95086
2020-04-16 17:29:55 -07:00
Ryan Tremblay f5d00e5a29 Fix jsi cmake include dirs (#207)
Summary:
I'm trying to use JSI for a React Native custom module. I saw these existing examples where the JSI API is used in the context of a CMakeLists.txt:
https://github.com/terrysahaidak/host-object-test/blob/master/libs/android-jsi/test-jsi/src/main/cpp/CMakeLists.txt
https://github.com/ericlewis/react-native-hostobject-demo/pull/4/files#diff-834320be1b4e4016bac27c05dcd17fb9
In both cases, they manually grab the include directories and jsi.cpp from node_modules/react-native, but I also saw that node_modules/react-native/ReactCommon/jsi/jsi already has a CMakeLists.txt that appears to be intended to provide a jsi static lib, so I tried to pull this into my own CMakeLists.txt like this:
```
add_subdirectory(${RN_DIR}/ReactCommon/jsi/jsi ${CMAKE_CURRENT_BINARY_DIR}/jsi)
...
target_link_libraries(MyLib jsi)
```
Unfortunately when doing this, the consuming project still doesn't see the correct include directories. The change I'm proposing here is to use `target_include_directories` and declare that `..` is a public (to consumers) include directory for the library named `jsi`. With this change, you can do what I showed above to consume the jsi lib by just pulling in the CMakeLists.txt file into your own CMakeLists.txt file.

Changelog: [General][Fixed] Fix jsi cmake include dirs

Pull Request resolved: https://github.com/facebook/hermes/pull/207

Reviewed By: willholen

Differential Revision: D21074270

Pulled By: tmikov

fbshipit-source-id: 7d9ec3255f57a16c0b2be489dffa4540727738a1
2020-04-16 16:34:41 -07:00
Rick Hanlon 56583c6845 Remove out of date TODO
Summary:
No longer relevant.

Changelog: [Internal]

Reviewed By: mhorowitz

Differential Revision: D21070955

fbshipit-source-id: 11b0384501b2780f5ac41899b5e8bbb4f7a4d730
2020-04-16 13:43:07 -07:00
Ramanpreet Nara 25ed045e36 Switch over to JavaTurboModule::InitParams
Summary:
## Problem
Every time we want to add, remove, or change the data passed to JavaTurboModule's constructor, we have to modify the C++ TurboModule codegen. (The same is true of `ObjCTurboModule`).

**Why was this necessary?**
- `JavaTurboModule` is effectively an abstract class whose constructor is always invoked by code-generated C++ classes. These C++ code-generated class constructors accept an argument list, and manually foward each and every item in that list to `JavaTurboModule::JavaTurboModule`.

## The fix
In this diff, I introduce a struct `JavaTurboModule::InitParams`, to represent a bag of arguments:
```
class JSI_EXPORT JavaTurboModule : public TurboModule {
 public:
  struct InitParams {
    std::string moduleName;
    jni::alias_ref<JTurboModule> instance;
    std::shared_ptr<CallInvoker> jsInvoker;
    std::shared_ptr<CallInvoker> nativeInvoker;
  };
```

All `JavaTurboModules` will be created with an instance of this `InitParams` struct, instead of a list of arguments.  Our code-generated C++ `jsi::HostObject` sublcasses will simply accept `InitParams` in their constructor, and forward it to `JavaTurboModule`'s constructor. This way, the codegen remains oblivious to what arguments JavaTurboModule requires.

## Okay, but why do we need this change now?
In the future, I plan to modify the constructor for `JavaTurboModule` to accept a performance logger, and a `RuntimeExecutor`. Similar modifications are planned for ObjC. For this reason, to avoid these four codemods, and any potential other codemods that occur because we're making modifications to `JavaTurboModule` or `ObjCTurboModule`, I'm launching this codemod, and the codemods in this stack.

## Misc Fix
- Previously, we were generating the TurboModule name from the Spec filename. This is incorrect because that name represents the spec name. Now, the name will be forwarded from TurboModuleManager in the `JavaTurboModule::InitParams` struct.

## Alternative implementations
I initially considered using `ContextContainer`, but decided against it because:
1. There are no type-safety guarantees.
2. I think it's a bit overkill for this scenario. We just need an opaque bag of data, and for our purposes a simple struct does the job fine.

## Commands run

Reviewed By: fkgozali

Differential Revision: D21035208

fbshipit-source-id: 9542cafea192081bc34d337ab3a7a783083eb06c
2020-04-15 23:57:25 -07:00
empyrical eaba38361f Yoga Podspec: Export YGNode and YGStyle headers (#997)
Summary:
This pull request adds `YGNode.h` and `YGStyle.h` to the headers exported by Yoga's podspec. They are required by the new Fabric architecture of React Native.

The modulemap and its umbrella header automatically generated by Cocoapods adds all exported headers to the `modulemap`. Having YGNode and YGStyle exported through here has problems, because they are only available in environments that have C++ available, and will produce errors otherwise.

This pull request fences off the contents of those headers in an `#ifdef __cplusplus` block, so they will not cause errors when imported into environments where C++ isn't available.

I had considered adding a custom modulemap to the podspec as part of this pull request, but this way seems the least "invasive", and this way you are able to add and remove exported headers in the podspec without needing to worry about updating the umbrella header at the same time.

Changelog:

[Internal] - Yoga Podspec: Export YGNore and YGStyle headers

Pull Request resolved: https://github.com/facebook/yoga/pull/997

Reviewed By: hramos

Differential Revision: D20966075

Pulled By: mdvacca

fbshipit-source-id: 5f5caa6b639d11e660b968d681da9a4de6c0eb8e
2020-04-14 16:42:42 -07:00
Sidharth Guglani 49c90e96fa Set width/height also to Undefined when we change the measure mode to Undefined
Summary:
Make sure width/height is always passed as Undefined when measure mode is changed to Undefined.

Changelog: [Internal][Yoga] Set width and height as Undefined when we change measure mode to Undefined

Reviewed By: alickbass

Differential Revision: D20029838

fbshipit-source-id: b9931f6ddb13ffd1565889535ade5bbffbe0c304
2020-04-14 02:06:56 -07:00
Samuel Susla 00c4d950cf Implement event count for TextInput
Summary:
Changelog: [Internal]

Implementation of event count for Fabric's Text input.

Reviewed By: JoshuaGross

Differential Revision: D20800185

fbshipit-source-id: 988692cb2fc786649821cccb06e629b40b9b0479
2020-04-09 03:44:55 -07:00
Ramanpreet Nara fd5de50aca Fix Cocoapods builds
Summary:
## Problem
For some reason, D20831545 broke the `use_frameworks!` build of RNTester.

## Building RNTester
```
pushd ~/fbsource/xplat/js/react-native-github/RNTester && USE_FRAMEWORKS=1 pod install && open RNTesterPods.xcworkspace && popd;
```

## Error
I built RNTester locally, and the error was this:

```
Undefined symbols for architecture x86_64:
  "facebook::jsi::HostObject::set(facebook::jsi::Runtime&, facebook::jsi::PropNameID const&, facebook::jsi::Value const&)", referenced from:
      vtable for facebook::react::ObjCTurboModule in RCTImageEditingManager.o
      vtable for facebook::react::ObjCTurboModule in RCTImageLoader.o
      vtable for facebook::react::ObjCTurboModule in RCTImageStoreManager.o
  "facebook::jsi::HostObject::getPropertyNames(facebook::jsi::Runtime&)", referenced from:
      vtable for facebook::react::ObjCTurboModule in RCTImageEditingManager.o
      vtable for facebook::react::ObjCTurboModule in RCTImageLoader.o
      vtable for facebook::react::ObjCTurboModule in RCTImageStoreManager.o
ld: symbol(s) not found for architecture x86_64
```

## Fix
It looked like libraries that depend on "ReactCommon/turbomodule/core" weren't linking to JSI correctly. So, I modified all such Podspecs to also depend on "React-jsi":

```
arc rfr '  s.dependency "ReactCommon/turbomodule/core", version' '  s.dependency "ReactCommon/turbomodule/core", version\n  s.dependency "React-jsi", version'
```

This seemed to do the trick. In buck, we'd fix this problem using exported_dependencies. I skimmed through cocoapods, and couldn't find such a configuration option there. So, I guess this will have to do?

Changelog:
[iOS][Fixed] - Fix Cocoapods builds of RNTester

Reviewed By: fkgozali, hramos

Differential Revision: D20905465

fbshipit-source-id: 60218c8274ec165752a428f2a7a9a546607c8fec
2020-04-07 19:07:19 -07:00
Ramanpreet Nara 21733641a8 Make TurboModules dispatch method calls via native CallInvoker
Summary:
This diff:
1. Has ObjC NativeModules use the native `CallInvoker` to invoke JS -> native sync/async calls.
2. Integrates the native `CallInvoker` for each ObjC NativeModule with the bridge. This way, the bridge is informed of all JS -> native TurboModule method calls, and dispatches `onBatchComplete` appropriately.

Changelog:
[iOS][Fixed] Integrate ObjC TurboModules async method calls with the bridge

Reviewed By: fkgozali

Differential Revision: D20831545

fbshipit-source-id: da1cbb4ecef4cae85841ca7ef625ab8e380760cd
2020-04-03 17:57:20 -07:00
Ramanpreet Nara 553729f3d6 Create method queues for NativeModules that neither provide nor request one
Summary:
## Problem:
Let `A` be the set of all ObjC NativeModules that neither provide nor reqeust a method queue.

The TurboModule system dispatches all method calls to NativeModules in `A` synchronously to the JS thread. Here is the relevant logic:

**RCTTurboModule.mm:**
Link: https://fburl.com/diffusion/nz9gqje8
```
jsi::Value performMethodInvocation(
  // ...
)
{
  // ...

  dispatch_queue_t methodQueue = NULL;
  if ([instance_ conformsToProtocol:protocol(RCTBridgeModule)] &&
      [instance_ respondsToSelector:selector(methodQueue)]) {
    methodQueue = [instance_ performSelector:selector(methodQueue)];
  }

  if (methodQueue == NULL || methodQueue == RCTJSThread) {
    // This is the default mode of execution: on JS thread.
    block();
  } else if (methodQueue == dispatch_get_main_queue()) {

```

**Why does this end up happening?**
1. NativeModules that request a method queue have `synthesize methodQueue = _methodQueue` in their `implementation` section. This generates a `methodQueue` getter for the NativeModule, and also creates an ivar to back that getter. The TurboModule system generates a `dispatch_queue_t` and uses ObjC's KVC API to write to the ivar. So in the above logic, for NativeModules that provide a method queue, methodQueue will neither be `NULL` nor `RCTJSThread`, so we don't dispatch synchronously to the JS thread.
2. NativeModules that provide a method queue will return something that is not `NULL` or something that is `RCTJSThread`. If they return `NULL`, the infra will throw an error early. If they return `RCTJSThread`, we'll dispatch synchronously to the JS thread, as we should (...wait. For async NativeModule methods that dispatch to `RCTJSThread`, should we dispatch asynchronously to the JS thread, via jsInvoker? **Edit:** Nope: https://fburl.com/diffusion/ivt9b40s.). In all other cases, we dispatch to appropriately to the respective method queue.
3. For NativeModules that neither provide nor request a method queue (i.e: NativeModules in `A`), they don't implement the `methodQueue` selector. Therefore, we dispatch synchronously to the JS thread.

## The fix (Part 1):
The first step towards fixing this problem is to generate `dispatch_queue_t`s for NativeModules in `A`.

That's what this diff accomplishes.

Changelog:
[iOS][Fixed] - Create method queue for NativeModules that don't provide nor request one.

Reviewed By: fkgozali

Differential Revision: D20821054

fbshipit-source-id: 17a73550ad96766c5c7e719e28e1cc879e36465c
2020-04-03 12:28:43 -07:00
Ramanpreet Nara aef0ef4b31 Export Instance::getDecoratedNativeCallInvoker from RCTCxxBridge
Summary:
`RCTTurboModuleManager` will create a native `CallInvoker` for each ObjC NativeModule. This `CallInvoker` will be used to dispatch calls from JS to native. Before passing the native `CallInvoker` to the `ObjCTurboModule`, it'll first use `RCTCxxBridge decorateNativeCallInvoker` to get a bridge-aware decorated native `CallInvoker`. That way, the bridge remains informed about async TurboModule method calls that took place since the last time it was flushed. This ensures that we don't end up dispatching `onBatchComplete` any less with TurboModules on than we do with TurboModules off.

Changelog: [Internal]

Reviewed By: fkgozali

Differential Revision: D20831546

fbshipit-source-id: b2eb4e0097e0dabf8c4bd8fdc4c850a0858af699
2020-04-03 09:47:42 -07:00
Ramanpreet Nara de56649430 Add CallInvoker::invokeSync
Summary:
We'll be using a native CallInvoker to dispatch sync and async method calls to ObjC NativeModules. This native CallInvoker will hold a reference to the ObjC NativeModule's method queue.

**Why is the native CallInvoker required for ObjC NativeModules?**
In the case where the ObjC NativeModule neither provides nor requests a method queue, we must create a method queue for it. When we go to invoke a method from JS, for these NativeModules specifically, there is no way to access this method queue. A native CallInvoker is a convenient abstraction that holds on to that method queue. For async calls, we'll just call `CallInvoker::invokeAsync`, and for sync calls, we'll just call `CallInvoker::invokeSync`.

**Why do we need sync call support for native `CallInvoker`?**
In ObjC, sync NativeModule method calls block the JS thread, then execute synchronously on the NativeModule's method queue, and then unblock the JS thread. This is what'll be implemented by `CallInvoker::invokeSync`.

Changelog: [Internal]

Reviewed By: fkgozali

Differential Revision: D20829955

fbshipit-source-id: efb9d5408a1ade81069a943c865f232d4d10acfe
2020-04-03 09:47:42 -07:00
Ramanpreet Nara eb4e2baaa9 Rename Instance::getNativeCallinvoker to Instance::getDecoratedNativeCallInvoker
Summary:
Now, instead of accepting a `std::function` that schedules work, and returning a `CallInvoker`, `Instance::getDecoratedNativeCallInvoker`  will accept a `CallInvoker` that schedules work, and return a decorated `CallInvoker`.

I think this change will help with readability. It also clarifies that the bridge is adding additional behaviour to the native `CallInvoker`.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D20826885

fbshipit-source-id: a2c5681d10a4544ee3d2a0d1f1cbd386ef06d0e6
2020-04-03 09:47:41 -07:00
Ramanpreet Nara 3a11f0536e Make RCTTurboModuleManagerDelegate getTurboModule accept native CallInvoker and PerfLogger
Summary:
Might be worthwhile to just kill this method instead, since we're having all NativeModules provide their TurboModule jsi::HostObjects. But I'll leave that decision to a later time.

Changelog: [Internal]

Reviewed By: fkgozali

Differential Revision: D20809201

fbshipit-source-id: ee73d4b5454a76460832a54f9b864841e5b2b9c0
2020-04-03 02:27:10 -07:00
Ramanpreet Nara 69698b25fc Codemod all getTurboModuleWithJsInvoker methods to accept a native CallInvoker
Summary:
To make iOS TurboModules integrate with the bridge's onBatchComplete event, they need to use a native CallInvoker. This call invoker is created by the `NativeToJsBridge`, and ObjCTurboModule will use this native CallInvoker to dispatch TurboModule method calls. This diff makes sure that ObjCTurboModules are created with that native CallInvoker.

## Script
```
var withSpaces = (...args) => args.join('\s*')

var regexString = withSpaces(
  '-',
  '\(',
  'std::shared_ptr',
  '<',
  '(?<turboModuleClass>(facebook::react::|react::|::|)TurboModule)',
  '>',
  '\)',
  'getTurboModuleWithJsInvoker',
  ':',
  '\(',
  'std::shared_ptr',
  '<',
  '(?<callInvokerClass>(facebook::react::|react::|::|)CallInvoker)',
  '>',
  '\)',
  '(?<jsInvokerInstance>[A-Za-z0-9]+)',
  'perfLogger',
  ':',
  '\(',
  'id',
  '<',
  'RCTTurboModulePerformanceLogger',
  '>',
  '\)',
  '(?<perfLoggerInstance>[A-Za-z0-9]+)',
  '{',
  'return',
  'std::make_shared',
  '<',
  '(?<specName>(facebook::react::|react::|::|)Native[%A-Za-z0-9]+SpecJSI)',
  '>',
  '\(',
  'self',
  ',',
  '\k<jsInvokerInstance>',
  ',',
  '\k<perfLoggerInstance>',
  '\)',
  ';',
  '}',
)

var replaceString = `- (std::shared_ptr<$<turboModuleClass>>)
    getTurboModuleWithJsInvoker:(std::shared_ptr<$<callInvokerClass>>)$<jsInvokerInstance>
                  nativeInvoker:(std::shared_ptr<$<callInvokerClass>>)nativeInvoker
                     perfLogger:(id<RCTTurboModulePerformanceLogger>)$<perfLoggerInstance>
{
  return std::make_shared<$<specName>>(self, $<jsInvokerInstance>, nativeInvoker, $<perfLoggerInstance>);
}`

const exec = require('../lib/exec');
const abspath = require('../lib/abspath');
const relpath = require('../lib/relpath');
const readFile = (filename) => require('fs').readFileSync(filename, 'utf8');
const writeFile = (filename, content) => require('fs').writeFileSync(filename, content);

function main() {
  const tmFiles = exec('cd ~/fbsource && xbgs -n 10000 -l getTurboModuleWithJsInvoker:').split('\n').filter(Boolean);

  tmFiles
    .filter((filename) => !filename.includes('microsoft-fork-of-react-native'))
    .map(abspath)
    .forEach((filename) => {
      const source = readFile(filename);
      const newSource = source.replace(new RegExp(regexString, 'g'), replaceString);

      if (source == newSource) {
        console.log(relpath(filename));
      }

      writeFile(filename, newSource);
    });
}

if (!module.parent) {
  main();
}
```

Changelog: [Internal]

Reviewed By: fkgozali

Differential Revision: D20809202

fbshipit-source-id: 5d39b3cacdaa5681b70ce1803351d0432dd74550
2020-04-03 02:27:10 -07:00
Ramanpreet Nara 7e16a9d5e2 Manual changes required to make ObjCTurboModule accept native CallInvoker
Summary: Changelog: [Internal]

Reviewed By: fkgozali

Differential Revision: D20809200

fbshipit-source-id: d540eec9a3360a031f75d76a6ab9fb15303f8af5
2020-04-03 02:27:10 -07:00