Files
react-native/React/Fabric/Mounting/RCTMountingManager.mm
T
Valentin Shergin f2fdc1a5df Fabric: Simplifying RCTPerformMountInstructions
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
2020-07-07 12:01:56 -07:00

245 lines
9.1 KiB
Plaintext

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "RCTMountingManager.h"
#import <better/map.h>
#import <React/RCTAssert.h>
#import <React/RCTFollyConvert.h>
#import <React/RCTUtils.h>
#import <react/core/LayoutableShadowNode.h>
#import <react/core/RawProps.h>
#import <react/debug/SystraceSection.h>
#import "RCTComponentViewProtocol.h"
#import "RCTComponentViewRegistry.h"
#import "RCTConversions.h"
#import "RCTMountingTransactionObserverCoordinator.h"
using namespace facebook::react;
static void RCTPerformMountInstructions(
ShadowViewMutationList const &mutations,
RCTComponentViewRegistry *registry,
RCTMountingTransactionObserverCoordinator &observerCoordinator,
SurfaceId surfaceId)
{
SystraceSection s("RCTPerformMountInstructions");
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
for (auto const &mutation : mutations) {
switch (mutation.type) {
case ShadowViewMutation::Create: {
auto &newChildShadowView = mutation.newChildShadowView;
auto &newChildViewDescriptor =
[registry dequeueComponentViewWithComponentHandle:newChildShadowView.componentHandle
tag:newChildShadowView.tag];
observerCoordinator.registerViewComponentDescriptor(newChildViewDescriptor, surfaceId);
break;
}
case ShadowViewMutation::Delete: {
auto &oldChildShadowView = mutation.oldChildShadowView;
auto &oldChildViewDescriptor = [registry componentViewDescriptorWithTag:oldChildShadowView.tag];
observerCoordinator.unregisterViewComponentDescriptor(oldChildViewDescriptor, surfaceId);
[registry enqueueComponentViewWithComponentHandle:oldChildShadowView.componentHandle
tag:oldChildShadowView.tag
componentViewDescriptor:oldChildViewDescriptor];
break;
}
case ShadowViewMutation::Insert: {
auto &oldChildShadowView = mutation.oldChildShadowView;
auto &newChildShadowView = mutation.newChildShadowView;
auto &parentShadowView = mutation.parentShadowView;
auto &newChildViewDescriptor = [registry componentViewDescriptorWithTag:newChildShadowView.tag];
auto &parentViewDescriptor = [registry componentViewDescriptorWithTag:parentShadowView.tag];
UIView<RCTComponentViewProtocol> *newChildComponentView = newChildViewDescriptor.view;
[newChildComponentView updateProps:newChildShadowView.props oldProps:oldChildShadowView.props];
[newChildComponentView updateEventEmitter:newChildShadowView.eventEmitter];
[newChildComponentView updateState:newChildShadowView.state oldState:oldChildShadowView.state];
[newChildComponentView updateLayoutMetrics:newChildShadowView.layoutMetrics
oldLayoutMetrics:oldChildShadowView.layoutMetrics];
[newChildComponentView finalizeUpdates:RNComponentViewUpdateMaskAll];
[parentViewDescriptor.view mountChildComponentView:newChildComponentView index:mutation.index];
break;
}
case ShadowViewMutation::Remove: {
auto &oldChildShadowView = mutation.oldChildShadowView;
auto &parentShadowView = mutation.parentShadowView;
auto &oldChildViewDescriptor = [registry componentViewDescriptorWithTag:oldChildShadowView.tag];
auto &parentViewDescriptor = [registry componentViewDescriptorWithTag:parentShadowView.tag];
[parentViewDescriptor.view unmountChildComponentView:oldChildViewDescriptor.view index:mutation.index];
break;
}
case ShadowViewMutation::Update: {
auto &oldChildShadowView = mutation.oldChildShadowView;
auto &newChildShadowView = mutation.newChildShadowView;
auto &newChildViewDescriptor = [registry componentViewDescriptorWithTag:newChildShadowView.tag];
UIView<RCTComponentViewProtocol> *newChildComponentView = newChildViewDescriptor.view;
auto mask = RNComponentViewUpdateMask{};
if (oldChildShadowView.props != newChildShadowView.props) {
[newChildComponentView updateProps:newChildShadowView.props oldProps:oldChildShadowView.props];
mask |= RNComponentViewUpdateMaskProps;
}
if (oldChildShadowView.eventEmitter != newChildShadowView.eventEmitter) {
[newChildComponentView updateEventEmitter:newChildShadowView.eventEmitter];
mask |= RNComponentViewUpdateMaskEventEmitter;
}
if (oldChildShadowView.state != newChildShadowView.state) {
[newChildComponentView updateState:newChildShadowView.state oldState:oldChildShadowView.state];
mask |= RNComponentViewUpdateMaskState;
}
if (oldChildShadowView.layoutMetrics != newChildShadowView.layoutMetrics) {
[newChildComponentView updateLayoutMetrics:newChildShadowView.layoutMetrics
oldLayoutMetrics:oldChildShadowView.layoutMetrics];
mask |= RNComponentViewUpdateMaskLayoutMetrics;
}
if (mask != RNComponentViewUpdateMaskNone) {
[newChildComponentView finalizeUpdates:mask];
}
break;
}
}
}
[CATransaction commit];
}
@implementation RCTMountingManager {
RCTMountingTransactionObserverCoordinator _observerCoordinator;
BOOL _transactionInFlight;
BOOL _followUpTransactionRequired;
}
- (instancetype)init
{
if (self = [super init]) {
_componentViewRegistry = [[RCTComponentViewRegistry alloc] init];
}
return self;
}
- (void)scheduleTransaction:(MountingCoordinator::Shared const &)mountingCoordinator
{
if (RCTIsMainQueue()) {
// Already on the proper thread, so:
// * No need to do a thread jump;
// * No need to do expensive copy of all mutations;
// * No need to allocate a block.
[self initiateTransaction:mountingCoordinator];
return;
}
auto mountingCoordinatorCopy = mountingCoordinator;
RCTExecuteOnMainQueue(^{
RCTAssertMainQueue();
[self initiateTransaction:mountingCoordinatorCopy];
});
}
- (void)dispatchCommand:(ReactTag)reactTag commandName:(NSString *)commandName args:(NSArray *)args
{
if (RCTIsMainQueue()) {
// Already on the proper thread, so:
// * No need to do a thread jump;
// * No need to allocate a block.
[self synchronouslyDispatchCommandOnUIThread:reactTag commandName:commandName args:args];
return;
}
RCTExecuteOnMainQueue(^{
RCTAssertMainQueue();
[self synchronouslyDispatchCommandOnUIThread:reactTag commandName:commandName args:args];
});
}
- (void)initiateTransaction:(MountingCoordinator::Shared const &)mountingCoordinator
{
SystraceSection s("-[RCTMountingManager initiateTransaction:]");
RCTAssertMainQueue();
if (_transactionInFlight) {
_followUpTransactionRequired = YES;
return;
}
do {
_followUpTransactionRequired = NO;
_transactionInFlight = YES;
[self performTransaction:mountingCoordinator];
_transactionInFlight = NO;
} while (_followUpTransactionRequired);
}
- (void)performTransaction:(MountingCoordinator::Shared const &)mountingCoordinator
{
SystraceSection s("-[RCTMountingManager performTransaction:]");
RCTAssertMainQueue();
auto transaction = mountingCoordinator->pullTransaction();
if (!transaction.has_value()) {
return;
}
auto surfaceId = transaction->getSurfaceId();
auto &mutations = transaction->getMutations();
if (mutations.empty()) {
return;
}
auto telemetry = transaction->getTelemetry();
auto number = transaction->getNumber();
[self.delegate mountingManager:self willMountComponentsWithRootTag:surfaceId];
_observerCoordinator.notifyObserversMountingTransactionWillMount({surfaceId, number, telemetry});
telemetry.willMount();
RCTPerformMountInstructions(mutations, self.componentViewRegistry, _observerCoordinator, surfaceId);
telemetry.didMount();
_observerCoordinator.notifyObserversMountingTransactionDidMount({surfaceId, number, telemetry});
[self.delegate mountingManager:self didMountComponentsWithRootTag:surfaceId];
}
- (void)synchronouslyUpdateViewOnUIThread:(ReactTag)reactTag
changedProps:(NSDictionary *)props
componentDescriptor:(const ComponentDescriptor &)componentDescriptor
{
RCTAssertMainQueue();
UIView<RCTComponentViewProtocol> *componentView = [_componentViewRegistry findComponentViewWithTag:reactTag];
SharedProps oldProps = [componentView props];
SharedProps newProps = componentDescriptor.cloneProps(oldProps, RawProps(convertIdToFollyDynamic(props)));
[componentView updateProps:newProps oldProps:oldProps];
}
- (void)synchronouslyDispatchCommandOnUIThread:(ReactTag)reactTag
commandName:(NSString *)commandName
args:(NSArray *)args
{
RCTAssertMainQueue();
UIView<RCTComponentViewProtocol> *componentView = [_componentViewRegistry findComponentViewWithTag:reactTag];
[componentView handleCommand:commandName args:args];
}
@end