Summary:
This diff inlines all mount-instruction functions into a single one - RCTPerformMountInstructions.
The main purpose is to reduce the number of calls to `RCTComponentViewRegistry` for some instructions. E.g., before the change, the `Insert` (or `Update`) instruction had seven identical calls to the registry. That's not a huge deal but there is no need to pay for it either. Maybe it can save us a couple of milliseconds during TTI.
The code of those functions is quite straight-forward, so this change probably even improves readability.
Changelog: [Internal] Fabric-specific internal change.
Reviewed By: sammy-SC
Differential Revision: D22402987
fbshipit-source-id: 043a4114ba42622e9ed226f4d5e41ed45c1b066c
Summary:
Changelog:
Adding packager running check when RCTBundleURLProvider is returning JSLocation, this prevents an invalid address from being returned which might cause various issues.
Reviewed By: cpojer
Differential Revision: D22390156
fbshipit-source-id: a20dbf63103158a34cbf6dc0ae8349b2f9e5b0a8
Summary:
This refined algorithm now takes a zoom/scale into account and deals with `contentInset` properly.
Changelog: [Internal] Fabric-specific internal change.
Reviewed By: sammy-SC
Differential Revision: D22382482
fbshipit-source-id: 7e9d34d3bababf68e624c045c308957e7e5c9d84
Summary:
Changelog: [Internal]
When JS Inspector is activated, ScrollView is unmounted and then mounted again with same state.
ScrollView's content offset was being set to 0 inside `[RCTScrollViewComponentView prepareForRecycle]` during unmount but when it is mounted again, we ignored value inside state.
Reviewed By: shergin
Differential Revision: D22333125
fbshipit-source-id: f232dc95b695605f4819f29d8e0bf14b2f3e9150
Summary:
Pet Peeve: Metro is a brand name. You don't say "the Metro server" just like you don't say "the iPhone phone". This is a leftover from when it used to be called "the packager server".
Note: It makes sense to refer to "the Metro server" when talking about it in the context of Metro's features, like if you are discussing "Metro's bundling" and "Metro's server". However, when talking about the tool itself, just Metro is enough.
Changelog: [Internal]
Reviewed By: motiz88
Differential Revision: D22330966
fbshipit-source-id: 667618363c641884df543d88cac65d1e44956ad3
Summary:
Changelog:
[iOS][Added] - This is the first step to build RCTParagraphComponentAccessibilityProvider. The main idea of RCTParagraphComponentAccessibilityProvider is to provide an array of accessible elements for the AttributedString in PCTParagraphComponentView.
Reviewed By: sammy-SC
Differential Revision: D22214855
fbshipit-source-id: 69d47555e86452620f89a4b2e21ed6065c8e669c
Summary:
The change contains a bunch of additional asserts that verify some assumptions on which mounting relies on. Working on the previous diffs I realized that it's very easy to broke those and then spend hours trying to understand what exactly went wrong.
Changelog: [Internal] Fabric-specific internal change.
Reviewed By: sammy-SC
Differential Revision: D22324087
fbshipit-source-id: 1152c40248885d02bde62a493a574868c3732273
Summary:
This is the first implementation stage of on-demand child views mounting for <ScrollView> feature.
It works this way. When mounting layer requests mounting of a subview of <ScrollView>, the component does not mount it immediately. Instead, it stores it in an internal collection, and then after the transaction finishes use that to mount views that are in a visible area.
Then we re-evaluate which child views are should be mounted and unmounted on every significant onScroll event. We use some leeway to do it not so often to save CPU cycles on scrolling.
This feature already works fine but to make it shippable we need to integrate it with an `overflow inset` feature to make it 100% reliable in complex cases when some views have overflow content.
Changelog: [Internal] Fabric-specific internal change.
Reviewed By: sammy-SC
Differential Revision: D22304012
fbshipit-source-id: be4ae21378d9d1c457cad2826da7d8c8d6395be5
Summary:
Changelog: [Internal]
Do not log warning for "Invalid view set to be the JS responder".
{F242140509}
Fabric doesn't store views in view registry, therefore this warning would be shown to the developer everytime `[RCTUIManager setJSResponder]` is called.
Reviewed By: shergin
Differential Revision: D22309447
fbshipit-source-id: cac8985cdc79ab2d03a246cc2d9377472a64a683
Summary:
The method does not do anything besides calling a super method. Even if this method does nothing special, overriding it can have negative performance implications.
Changelog: [Internal] Fabric-specific internal change.
Reviewed By: sammy-SC
Differential Revision: D22309895
fbshipit-source-id: bd8237d15df20017629223f278b1b6ac628b0cc7
Summary:
Changelog: [Internal]
Introducing InputAccessoryView.
There is one big difference between Fabric's implementation and Paper's implementation.
Fabric searches for text input from InputAccessoryView, unlike Paper where it is the other way around.
Reviewed By: shergin
Differential Revision: D22160445
fbshipit-source-id: 55313fe50afeced7aead5b57137d711dd1cfd3ae
Summary:
Here is why:
* It was with us from the very beginning but we never use it.
* The main purpose of this - snap-to-pixel layout - was moved to Yoga, where it should be.
* The current implementation has a bug.
* It's not really correct conceptually because the value becomes incorrect when an immutable subtree is being reused as part of a new tree.
* It over-complicates a new feature I am working on.
Changelog: [Internal] Fabric-specific internal change.
Reviewed By: sammy-SC
Differential Revision: D22284645
fbshipit-source-id: c4c2df8d24e8fe924725b465e04e8154d097d226
Summary:
Changelog: [Internal]
In D8552360 (https://github.com/facebook/react-native/commit/48b9a6f887c09f78944053a6658106a01dc20fea) an experimental integration between old and new UIManager has been introduced.
It isn't needed anymore.
I did some measurements and it is the slowest part of `[RCTComponentViewDescriptor dequeueComponentViewWithComponentHandle]`.
{F241943384}
Reviewed By: shergin
Differential Revision: D22274782
fbshipit-source-id: 799ba047f1c57f68f00b0b6fa7c58782874991bc
Summary:
Changelog: [Internal]
The methods were out of order, this diff reorders them.
Reviewed By: shergin
Differential Revision: D22233255
fbshipit-source-id: ea66bc701c4d021ec5721e191bc0d3413b3d36ae
Summary:
Changelog: [Internal]
# Why we crash?
`cStringUsingEncoding` returns `char *`, not `std::string`. Compiler uses implicit conversion to construct and copy `char *` into `std::string`. Maybe optimiser does something unexpected there? Maybe something weird happens there? I think it is worth trying to be more explicit about it and construct std::string there explicitly. Also if you do a google search, this seems to be a go to strategy when converting `NSString` to `std::string`.
This is all just an assumption, I can't repro the crash
# Why get rid of 2nd argument in RCTStringFromNSString
2nd argument is `NSStringEncoding`. It isn't being used, we always use default value.
Also, if you pass in `NSUTF16StringEncoding` or `NSUTF32StringEncoding`, you get undefined behaviour.
Check https://developer.apple.com/documentation/foundation/nsstring/1408489-cstringusingencoding?language=objc# section "Special Considerations"
Reviewed By: shergin
Differential Revision: D22089694
fbshipit-source-id: d449b383c61983c3822bc589c0a01fa97c0b6e64
Summary:
Changelog: [Internal]
Add support for dynamic font size.
New class `ThreadStorage` is introduced, which is used to pass LayoutContext to `YogaLayoutableShadowNode::yogaNodeMeasureCallbackConnector`.
## Shortcoming
This implementation doesn't cause re-render, if user changes font size and comes to the app without restarting it, it will show old font size. I believe this is fine for now as most people set their font size before they use the app and keep the same setting for a long time.
Reviewed By: shergin
Differential Revision: D22043728
fbshipit-source-id: 7453d165c280a2f4bcb73f4ee6daf9e64b637ded
Summary:
This function is unused. (Followup to D21941946)
Changelog: [iOS] Deprecate calculateChildFrames from RCTScrollView
Reviewed By: sammy-SC
Differential Revision: D22071415
fbshipit-source-id: 0c996ab02df1431ee9cfa082bc99681a2ec7118c
Summary:
Changelog: [Internal]
Paper views are not designed to be recycled, that's why a new view is created each time legacy interop layer is used.
However paper view was not deallocated immediately after it was used, it was still being strongly referenced by `self.contentView`.
This doesn't cause an immediate issue because eventually when legacy interop layer does get reused, it will create a new paper view and replace the old one inside `self.contentView`, triggering deallocation of the old one. But we were retaining the paper view beyond what was necessary.
Reviewed By: mdvacca
Differential Revision: D22066022
fbshipit-source-id: 17c3b81468f50ebcc05f1a7cdf4d4b9b00965fc3
Summary:
Changelog: [Internal]
A long time ago we experimented with JSC bytecode. We are not experimenting with JSC bytecode any more. This code can be removed.
Reviewed By: mhorowitz
Differential Revision: D22017374
fbshipit-source-id: 6fe3fb7ad7966f92a5cd103605ac5c0bd1f17a8e
Summary:
Fixes some comment typos, moves hit testing and accessibility code so it's beside each other.
No functionality changes.
Changelog:[Internal]
Reviewed By: RSNara
Differential Revision: D22003047
fbshipit-source-id: 0e785364d7e1a080034d24c9676a56acb45686bb
Summary:
Changelog: [Internal]
There is no need for custom dealloc, let's get rid of it.
We also prefer east const over west const.
Reviewed By: shergin
Differential Revision: D21997545
fbshipit-source-id: aa017f99aa26421fc59b353d0012687cb38fac08
Summary:
Changelog: [Internal]
Here is what I believe happens.
We have an instance of `RCTSliderComponentView` which has green thumb tint color.
It gets reused, in prepareForRecycle we call `setThumbTintImage:nil` on its UISlider which internally sets an ivar to `nil`.
Next time `RCTSliderComponentView` gets used without explicit thumb tint color, we assign nil to UISlider's thumb tint color.
Internally this nil gets compared to nil that it saved during `prepareForRecycle` and concludes that the value is already sets and exists early.
Since we don't have access to `UISlider` I can't prove this but here is a short video where I showcase this behavior
{F239923204}
The code in video is here P133083862.
Reviewed By: shergin
Differential Revision: D21997324
fbshipit-source-id: 28a11ed817cc863a313217c475042918ee726011
Summary:
Changelog: [internal]
We were not reseting value of slider when recycling, this would result in wrong value being displayed once slider gets reused.
Reviewed By: shergin
Differential Revision: D21996786
fbshipit-source-id: 3beac4936d0719c4ac5ac0499209300a912f6986
Summary:
Changelog:
[iOS][Removed] - Removed DEPRECATED_sendUpdatedChildFrames prop to ScrollView component because there are no callsites of it anymore
Reviewed By: shergin
Differential Revision: D21941946
fbshipit-source-id: 0b7d6d0986ddff4b250e70e0450a6f7e166b41f4
Summary:
Changelog: [Internal]
RCTScheduler was storing Scheduler as `shared_ptr`, but `RCTScheduler` is sole owner of it.
`unique_ptr` better expresses this ownership.
Reviewed By: JoshuaGross
Differential Revision: D21923573
fbshipit-source-id: e382f2d6e0a4875e1441b6063c1ad7056b338e29
Summary:
From the header of `RCTSurfaceHostingProxyRootView`:
This is a RCTRootView-compatible implementation of RCTSurfaceHostingView.
Use this class to replace all usages of RCTRootView in the app for easier migration
I need to do exactly this, but for a bridgeless mode callsite. This proxy class only uses the bridge for some perf logging, which we're fine with not having right now.
Reviewed By: shergin
Differential Revision: D21893522
fbshipit-source-id: 3547cff6143f44714e39e4104d03336010081e2e
Summary:
Changelog: [Internal]
# Problem
`MountingCoordinator` holds a pointer to instance of `MountingOverrideDelegate` which becomes invalid.
# Solution
Use `std::weak_ptr` instead of raw pointer so it is possible to tell whether the pointer is expired.
Reviewed By: JoshuaGross
Differential Revision: D21905351
fbshipit-source-id: c7bf9635742a6ec086a03ba83202e46e1f1f373f
Summary:
## Context
- If a NativeModule requires main queue setup, its `constantsToExport` method is executed on the main queue.
- In the TurboModule system, `constantsToExport` or `getConstants` is treated like a regular synchronous NativeModule method. Therefore, it's always executed on the JS thread.
This difference in behaviour is dangerous when we're A/B testing the TurboModule infra: One could write a NativeModule that requires main queue setup, and have it expose constants that access objects/state only accessible on the UI thread. This NativeModule would work fine in the legacy infra, which could be the case if the NativeModule author is testing locally. But once it ships to prod, it may run with the TurboModule system, and crash the application. To mitigate this risk, I'm removing this special main queue execution of `constantsToExport` from the legacy infrastructure.
## Consequences
- If a NativeModule's `constantsToExport` method accesses objects/state only accessible on the UI thread, it must do so by explicitly scheduling work on the main thread. I wrote up a codemod to fix this for our OSS modules: D21797048.
- Eagerly initialized NativeModules that required main queue setup had their constants calculated eagerly. After the changes in this diff, those NativeModules will have their constants calculated lazily. I don't think this is a big deal because only a handful of NativeModules are eagerly initialized, and eagerly initialized NativeModules are going away anyway.
Changelog:
[iOS][Removed] - Main queue execution of constantsToExport in NativeModules requiring main queue setup
Reviewed By: fkgozali
Differential Revision: D21829091
fbshipit-source-id: df21fd5fd2ef45a291c07400f360bba801ae290f
Summary:
If a NativeModule requires main queue setup, its `getConstants()` method must be executed on the main thead. The legacy NativeModule infra takes care of this for us. With TurboModules, however, all synchronous methods, including `getConstants()`, execute on the JS thread. Therefore, if a TurboModule requires main queue setup, and exports constants, we must execute its `getConstants()` method body on the main queue explicitly.
**Notes:**
- The changes in this diff should be a noop when TurboModules is off, because `RCTUnsafeExecuteOnMainQueueSync` synchronously execute its block on the current thread if the current thread is the main thread.
- If a NativeModule doens't have the `requiresMainQueueSetup` method, but has the `constantsToExport` method, both NativeModules and TurboModules assume that it requires main queue setup.
## Script
```
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 constantsToExport")
.split("\n")
.filter(Boolean);
const filesWithoutConstantsToExport = [];
const filesWithConstantsToExportButNotGetConstants = [];
const filesExplicitlyNotRequiringMainQueueSetup = [];
tmFiles
.filter((filename) => {
if (filename.includes("microsoft-fork-of-react-native")) {
return false;
}
return /\.mm?$/.test(filename);
})
.map(abspath)
.forEach((filename) => {
const code = readFile(filename);
const relFilename = relpath(filename);
if (!/constantsToExport\s*{/.test(code)) {
filesWithoutConstantsToExport.push(relFilename);
return;
}
if (!/getConstants\s*{/.test(code)) {
filesWithConstantsToExportButNotGetConstants.push(relFilename);
return;
}
if (/requiresMainQueueSetup\s*{/.test(code)) {
const requiresMainQueueSetupRegex = /requiresMainQueueSetup\s*{\s*return\s+(?<requiresMainQueueSetup>YES|NO)/;
const requiresMainQueueSetupRegexMatch = requiresMainQueueSetupRegex.exec(
code
);
if (!requiresMainQueueSetupRegexMatch) {
throw new Error(
"Detected requiresMainQueueSetup method in file " +
relFilename +
" but was unable to parse the method return value"
);
}
const {
requiresMainQueueSetup,
} = requiresMainQueueSetupRegexMatch.groups;
if (requiresMainQueueSetup == "NO") {
filesExplicitlyNotRequiringMainQueueSetup.push(relFilename);
return;
}
}
const getConstantsTypeRegex = () => /-\s*\((?<type>.*)\)getConstants\s*{/;
const getConstantsTypeRegexMatch = getConstantsTypeRegex().exec(code);
if (!getConstantsTypeRegexMatch) {
throw new Error(
`Failed to parse return type of getConstants method in file ${relFilename}`
);
}
const getConstantsType = getConstantsTypeRegexMatch.groups.type;
const getConstantsBody = code
.split(getConstantsTypeRegex())[2]
.split("\n}")[0];
const newGetConstantsBody = `
__block ${getConstantsType} constants;
RCTUnsafeExecuteOnMainQueueSync(^{${getConstantsBody
.replace(/\n/g, "\n ")
.replace(/_bridge/g, "self->_bridge")
.replace(/return /g, "constants = ")}
});
return constants;
`;
writeFile(
filename,
code
.replace(getConstantsBody, newGetConstantsBody)
.replace("#import", "#import <React/RCTUtils.h>\n#import")
);
});
console.log("Files without constantsToExport: ");
filesWithoutConstantsToExport.forEach((file) => console.log(file));
console.log();
console.log("Files with constantsToExport but no getConstants: ");
filesWithConstantsToExportButNotGetConstants.forEach((file) =>
console.log(file)
);
console.log();
console.log("Files with requiresMainQueueSetup = NO: ");
filesExplicitlyNotRequiringMainQueueSetup.forEach((file) =>
console.log(file)
);
}
if (!module.parent) {
main();
}
```
Changelog: [Internal]
Reviewed By: fkgozali
Differential Revision: D21797048
fbshipit-source-id: a822a858fecdbe976e6197f8339e509dc7cd917f
Summary:
This change is especially important for Fabric when a lot of objects (mostly ShadowNodes) have shared ownership. Without this change, JSVM could not know that bunch of natively allocated objects should be deallocated.
Changelog: [Internal] Fabric-specific internal change.
Reviewed By: mdvacca
Differential Revision: D21798527
fbshipit-source-id: f2051721b074b99660cdfd6c5b75679b9792403e
Summary:
This diff updates our RCTKeyCommands code to be more resilient by copying the [FLEX strategy for key commands](https://github.com/Flipboard/FLEX/blob/master/Classes/Utility/Keyboard/FLEXKeyboardShortcutManager.m).
This strategy swizzles UIApplication handleKeyUIEvent which is further upstream than our UIResponder. It also allows for single key hotkeys like pressing just `r` instead of `cmd+r`. It does this without interfering with typing input by checking the first responder first.
I've also updated our hotkey handling to support using just the keys like `r` in addition to `cmd+r`. In addition to brining these hotkeys more in line with other iOS tools, they're also easier to use and do not suffer the same issues hotkeys with modifiers like `cmd` have where keys are dropped.
Changelog: [iOS] [Added] Allow hotkeys to be used without command key
Reviewed By: shergin
Differential Revision: D21635129
fbshipit-source-id: 36e0210a62b1f310473e152e8305165024cd338b
Summary:
This was added in D3343907 June 1st 2016, disabled in D3428043 June 16, 2016 and never re-enabled.
Changelog: [Internal]
Reviewed By: shergin
Differential Revision: D21635227
fbshipit-source-id: db51dfb6271359bea7da34b4e2a71931fc7c2a63
Summary:
This diff adds a new swizzling method for replacing instance methods with blocks.
Changelog: [Internal]
Reviewed By: shergin
Differential Revision: D21635131
fbshipit-source-id: c8061817bed66dad160efffee5a13c8714134540
Summary:
While we build react native 0.62.2 via our Bazel build system, encountered those following errors due to lack of appropriate imports:
```
external/React-Core/React/Base/RCTUtilsUIOverride.h:8:33: error: cannot find interface declaration for 'NSObject', superclass of 'RCTUtilsUIOverride'
interface RCTUtilsUIOverride : NSObject
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^
external/React-Core/React/Base/RCTUtilsUIOverride.h:12:37: error: expected a type
+ (void)setPresentedViewController:(UIViewController *)presentedViewController;
^
```
Add the appropriate imports `<Foundation/Foundation.h>` and `<UIKit/UIKit.h>` fix those errors.
Honestly I dont know how it's supposed to work without those imports. Also all the siblings files have the correct imports. e.g. [RCTUtils.h](https://github.com/discord/react-native/blob/15a5f3624c40624d8dd0307bbcc1f2b2aba15a1b/React/Base/RCTUtils.h)
## Changelog
[iOS] [Fixed] - Fix imports in `RCTUtilsUIOverride.h`
Pull Request resolved: https://github.com/facebook/react-native/pull/28946
Test Plan: RN tester iOS app runs fine.
Differential Revision: D21700030
Pulled By: shergin
fbshipit-source-id: 9ef806b8f656bdad289fbdd3d84ecefb0dea6afb
Summary:
Changelog: [Internal]
# Problem
We were recording mount child component calls with its arguments and the replaying them inside `finalizeUpdates`.
However we store the events in NSDictionary where `key` was index at which the child should be added.
Then in `finalizeUpdates` we iterated over this NSDictionary and added those views into our paper view.
`NSDictionary` is unordered, it isn't guaranteed what was first inserted into it, will be first iterated over.
# Solution
Use `NSMutableArray` instead which guarantees order.
Reviewed By: shergin
Differential Revision: D21685993
fbshipit-source-id: 3b933f05125130eef175d7a8a56f29012ee76bb3
Summary:
## Motivation
We got this crash T67304907, which shows a `EXC_BAD_ACCESS / KERN_INVALID_ADDRESS` when calling this line:
```
NativeModulePerfLogger::getInstance().asyncMethodCallBatchPreprocessStart();
```
There are no arguments in that call, so I figured the only error could be when we try to invoke `getInstance()` or `asyncMethodCallBatchPreprocessStart()`.
This diff:
1. Removes the `NativeModulePerfLogger::getInstance()` bit. Now NativeModulePerfLogger is used via regular static C functions. So, there's no way that simply invoking one of the logging functions crashes the application: there's no vtable lookup.
2. Inside each logging function, when perf-logging is disabled, the global perflogger should be `nullptr`. This diff makes it so that in that case, we won't execute any code in the control group of the perf-logging experiment.
## Changes
**How do we enable NativeModule perf-logging?**
- Previously:
- `NativeModulePerfLogger::setInstance(std::make_shared<FBReactNativeModulePerfLogger>(...))`
- `TurboModulePerfLogger::setInstance(std::make_shared<FBReactNativeModulePerfLogger>(...))`.
- Now:
- `BridgeNativeModulePerfLogger::enableLogging(std::make_unique<FBReactNativeModulePerfLogger>(...))`
- `TurboModulePerfLogger::enableLogging(std::make_unique<FBReactNativeModulePerfLogger>(...))`
**How do we do NativeModule perf-logging now?**
- Previously:
- `NativeModulePerfLogger::getInstance().command(...args)`
- `TurboModulePerfLogger::getInstance().command(...args)`.
- Now:
- `BridgeNativeModulePerfLogger::command(...args)`
- `TurboModulePerfLogger::command(...args)`.
The benefit of this approach is that each method in `BridgeNativeModulePerfLogger` is guarded with an if check. Example:
```
void moduleCreateConstructStart(const char *moduleName, int32_t id) {
NativeModulePerfLogger *logger = g_perfLogger.get();
if (logger != nullptr) {
logger->moduleCreateConstructStart(moduleName, id);
}
}
```
Therefore, we don't actually execute any code when perf-logging is disabled.
Changelog:
[Internal]
Reviewed By: fkgozali
Differential Revision: D21669888
fbshipit-source-id: 80c73754c430ce787404b563878bad146295e01f