react-native/React/Fabric/Mounting/RCTMountingManager.mm
Valentin Shergin e581977b51 Introducing RCTComponentViewFactory
Summary:
The whole mounting iOS infra now uses `ComponentHandle` instead of `std::string` as a reference to particular `ComponentView` implementation. All changes are pretty straightforward, we use a different thing/type to refer to the particular class; no changes in the logic besides a new `RCTComponentViewFactory` that serves the same role of classes registry as Objective-C runtime served previously.
That has several benefits:
* It should be slightly faster, mostly because we don't need to convert `char *` strings to `std::string` and then to `NSString *`.
* We don't need string-based component-name maps anymore (at least on this layer). We can call classes as we want and it will work because of classes are now explicit about which ShadowNodes they are compatible with.
* Most importantly, it's explicit now! That means that no runtime magic is involved anymore and we can rely on static linting tool now and not be afraid of improper code stripping/overoptimization.

Reviewed By: mdvacca

Differential Revision: D13130760

fbshipit-source-id: aadf70525a1335b96992443abae4da359efdc829
2018-11-25 22:17:30 -08:00

179 lines
6.9 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 <react/core/LayoutableShadowNode.h>
#import <React/RCTAssert.h>
#import <React/RCTUtils.h>
#import "RCTComponentViewProtocol.h"
#import "RCTComponentViewRegistry.h"
#import "RCTMountItemProtocol.h"
#import "RCTCreateMountItem.h"
#import "RCTConversions.h"
#import "RCTDeleteMountItem.h"
#import "RCTInsertMountItem.h"
#import "RCTRemoveMountItem.h"
#import "RCTUpdatePropsMountItem.h"
#import "RCTUpdateEventEmitterMountItem.h"
#import "RCTUpdateLocalDataMountItem.h"
#import "RCTUpdateLayoutMetricsMountItem.h"
using namespace facebook::react;
@implementation RCTMountingManager
- (instancetype)init
{
if (self = [super init]) {
_componentViewRegistry = [[RCTComponentViewRegistry alloc] init];
}
return self;
}
- (void)performTransactionWithMutations:(facebook::react::ShadowViewMutationList)mutations
rootTag:(ReactTag)rootTag
{
NSMutableArray<RCTMountItemProtocol> *mountItems =
[[NSMutableArray<RCTMountItemProtocol> alloc] initWithCapacity:mutations.size() * 2 /* ~ the worst case */];
for (const auto &mutation : mutations) {
switch (mutation.type) {
case ShadowViewMutation::Create: {
RCTCreateMountItem *mountItem =
[[RCTCreateMountItem alloc] initWithComponentHandle:mutation.newChildShadowView.componentHandle
tag:mutation.newChildShadowView.tag];
[mountItems addObject:mountItem];
break;
}
case ShadowViewMutation::Delete: {
RCTDeleteMountItem *mountItem =
[[RCTDeleteMountItem alloc] initWithComponentHandle:mutation.oldChildShadowView.componentHandle
tag:mutation.oldChildShadowView.tag];
[mountItems addObject:mountItem];
break;
}
case ShadowViewMutation::Insert: {
// Props
[mountItems addObject:[[RCTUpdatePropsMountItem alloc] initWithTag:mutation.newChildShadowView.tag
oldProps:nullptr
newProps:mutation.newChildShadowView.props]];
// EventEmitter
[mountItems addObject:[[RCTUpdateEventEmitterMountItem alloc] initWithTag:mutation.newChildShadowView.tag
eventEmitter:mutation.newChildShadowView.eventEmitter]];
// LocalData
if (mutation.newChildShadowView.localData) {
[mountItems addObject:[[RCTUpdateLocalDataMountItem alloc] initWithTag:mutation.newChildShadowView.tag
oldLocalData:nullptr
newLocalData:mutation.newChildShadowView.localData]];
}
// Layout
if (mutation.newChildShadowView.layoutMetrics != EmptyLayoutMetrics) {
[mountItems addObject:[[RCTUpdateLayoutMetricsMountItem alloc] initWithTag:mutation.newChildShadowView.tag
oldLayoutMetrics:{}
newLayoutMetrics:mutation.newChildShadowView.layoutMetrics]];
}
// Insertion
RCTInsertMountItem *mountItem =
[[RCTInsertMountItem alloc] initWithChildTag:mutation.newChildShadowView.tag
parentTag:mutation.parentShadowView.tag
index:mutation.index];
[mountItems addObject:mountItem];
break;
}
case ShadowViewMutation::Remove: {
RCTRemoveMountItem *mountItem =
[[RCTRemoveMountItem alloc] initWithChildTag:mutation.oldChildShadowView.tag
parentTag:mutation.parentShadowView.tag
index:mutation.index];
[mountItems addObject:mountItem];
break;
}
case ShadowViewMutation::Update: {
auto oldChildShadowView = mutation.oldChildShadowView;
auto newChildShadowView = mutation.newChildShadowView;
// Props
if (oldChildShadowView.props != newChildShadowView.props) {
RCTUpdatePropsMountItem *mountItem =
[[RCTUpdatePropsMountItem alloc] initWithTag:mutation.oldChildShadowView.tag
oldProps:mutation.oldChildShadowView.props
newProps:mutation.newChildShadowView.props];
[mountItems addObject:mountItem];
}
// EventEmitter
if (oldChildShadowView.eventEmitter != newChildShadowView.eventEmitter) {
RCTUpdateEventEmitterMountItem *mountItem =
[[RCTUpdateEventEmitterMountItem alloc] initWithTag:mutation.oldChildShadowView.tag
eventEmitter:mutation.oldChildShadowView.eventEmitter];
[mountItems addObject:mountItem];
}
// LocalData
if (oldChildShadowView.localData != newChildShadowView.localData) {
RCTUpdateLocalDataMountItem *mountItem =
[[RCTUpdateLocalDataMountItem alloc] initWithTag:newChildShadowView.tag
oldLocalData:oldChildShadowView.localData
newLocalData:newChildShadowView.localData];
[mountItems addObject:mountItem];
}
// Layout
if (oldChildShadowView.layoutMetrics != newChildShadowView.layoutMetrics) {
RCTUpdateLayoutMetricsMountItem *mountItem =
[[RCTUpdateLayoutMetricsMountItem alloc] initWithTag:mutation.oldChildShadowView.tag
oldLayoutMetrics:oldChildShadowView.layoutMetrics
newLayoutMetrics:newChildShadowView.layoutMetrics];
[mountItems addObject:mountItem];
}
break;
}
}
}
RCTExecuteOnMainQueue(^{
[self _performMountItems:mountItems rootTag:rootTag];
});
}
- (void)_performMountItems:(NSArray<RCTMountItemProtocol> *)mountItems
rootTag:(ReactTag)rootTag
{
RCTAssertMainQueue();
[self.delegate mountingManager:self willMountComponentsWithRootTag:rootTag];
for (id<RCTMountItemProtocol> mountItem in mountItems) {
[mountItem executeWithRegistry:_componentViewRegistry];
}
[self.delegate mountingManager:self didMountComponentsWithRootTag:rootTag];
}
- (void)optimisticallyCreateComponentViewWithComponentHandle:(ComponentHandle)componentHandle
{
RCTExecuteOnMainQueue(^{
[self->_componentViewRegistry optimisticallyCreateComponentViewWithComponentHandle:componentHandle];
});
}
@end