Fabric: Farewell MountItem classes

Summary:
This diff replaces all MountItem classes with a bunch of static C functions that do the same job as classes did.
Seems, originally we overestimated the complexity of MountItem classes and that they ended up being notably trivial. Now, maintaining that even longer would mean paying for abstractions and allocations that we don't really need and writing a lot of tedious code.
Besides that, the one particular change that will be introduced in the coming diffs is not particularly fit very well in the existing class-based model.

This change also should save us many hundreds of allocations and atomic counters bumps, so maybe we can get a millisecond-or-two win.

This diff does not introduce any practical behavioral/logical changes in the mounting layer.

Reviewed By: mdvacca

Differential Revision: D14893764

fbshipit-source-id: 6f1247923ae36f29c12a7d358e2d496cf6c3e298
This commit is contained in:
Valentin Shergin 2019-04-12 09:21:45 -07:00 коммит произвёл Facebook Github Bot
Родитель 66a294032a
Коммит 00243c580f
24 изменённых файлов: 182 добавлений и 769 удалений

Просмотреть файл

@ -1,27 +0,0 @@
/**
* 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 <UIKit/UIKit.h>
#import <React/RCTMountItemProtocol.h>
#import <React/RCTPrimitives.h>
#import <react/core/ReactPrimitives.h>
NS_ASSUME_NONNULL_BEGIN
@class RCTComponentViewRegistry;
/**
* Creates a ready-to-mount component view.
*/
@interface RCTCreateMountItem : NSObject <RCTMountItemProtocol>
- (instancetype)initWithComponentHandle:(facebook::react::ComponentHandle)componentHandle tag:(ReactTag)tag;
@end
NS_ASSUME_NONNULL_END

Просмотреть файл

@ -1,34 +0,0 @@
/**
* 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 "RCTCreateMountItem.h"
#import "RCTComponentViewRegistry.h"
using namespace facebook::react;
@implementation RCTCreateMountItem {
ComponentHandle _componentHandle;
ReactTag _tag;
}
- (instancetype)initWithComponentHandle:(facebook::react::ComponentHandle)componentHandle tag:(ReactTag)tag
{
if (self = [super init]) {
_componentHandle = componentHandle;
_tag = tag;
}
return self;
}
- (void)executeWithRegistry:(RCTComponentViewRegistry *)registry
{
[registry dequeueComponentViewWithComponentHandle:_componentHandle tag:_tag];
}
@end

Просмотреть файл

@ -1,25 +0,0 @@
/**
* 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 <UIKit/UIKit.h>
#import <React/RCTMountItemProtocol.h>
#import <React/RCTPrimitives.h>
#import <react/core/ReactPrimitives.h>
NS_ASSUME_NONNULL_BEGIN
/**
* Deletes (returns to recycle pool) a component view.
*/
@interface RCTDeleteMountItem : NSObject <RCTMountItemProtocol>
- (instancetype)initWithComponentHandle:(facebook::react::ComponentHandle)componentHandle tag:(ReactTag)tag;
@end
NS_ASSUME_NONNULL_END

Просмотреть файл

@ -1,40 +0,0 @@
/**
* 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 "RCTDeleteMountItem.h"
#import "RCTComponentViewRegistry.h"
using namespace facebook::react;
@implementation RCTDeleteMountItem {
ComponentHandle _componentHandle;
ReactTag _tag;
}
- (instancetype)initWithComponentHandle:(facebook::react::ComponentHandle)componentHandle tag:(ReactTag)tag
{
if (self = [super init]) {
_componentHandle = componentHandle;
_tag = tag;
}
return self;
}
- (void)executeWithRegistry:(RCTComponentViewRegistry *)registry
{
UIView<RCTComponentViewProtocol> *componentView = [registry componentViewByTag:_tag];
if (componentView == nil) {
return;
}
[registry enqueueComponentViewWithComponentHandle:_componentHandle tag:_tag componentView:componentView];
}
@end

Просмотреть файл

@ -1,26 +0,0 @@
/**
* 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 <UIKit/UIKit.h>
#import <React/RCTMountItemProtocol.h>
#import <React/RCTPrimitives.h>
NS_ASSUME_NONNULL_BEGIN
@class RCTComponentViewRegistry;
/**
* Inserts a component view into another component view.
*/
@interface RCTInsertMountItem : NSObject <RCTMountItemProtocol>
- (instancetype)initWithChildTag:(ReactTag)childTag parentTag:(ReactTag)parentTag index:(NSInteger)index;
@end
NS_ASSUME_NONNULL_END

Просмотреть файл

@ -1,41 +0,0 @@
/**
* 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 "RCTInsertMountItem.h"
#import "RCTComponentViewRegistry.h"
@implementation RCTInsertMountItem {
ReactTag _childTag;
ReactTag _parentTag;
NSInteger _index;
}
- (instancetype)initWithChildTag:(ReactTag)childTag parentTag:(ReactTag)parentTag index:(NSInteger)index
{
if (self = [super init]) {
_childTag = childTag;
_parentTag = parentTag;
_index = index;
}
return self;
}
- (void)executeWithRegistry:(RCTComponentViewRegistry *)registry
{
UIView<RCTComponentViewProtocol> *childComponentView = [registry componentViewByTag:_childTag];
UIView<RCTComponentViewProtocol> *parentComponentView = [registry componentViewByTag:_parentTag];
if (childComponentView == nil || parentComponentView == nil) {
return;
}
[parentComponentView mountChildComponentView:childComponentView index:_index];
}
@end

Просмотреть файл

@ -1,23 +0,0 @@
/**
* 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 <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@class RCTComponentViewRegistry;
/**
* Granular representation of any change in a user interface.
*/
@protocol RCTMountItemProtocol <NSObject>
- (void)executeWithRegistry:(RCTComponentViewRegistry *)registry;
@end
NS_ASSUME_NONNULL_END

Просмотреть файл

@ -1,24 +0,0 @@
/**
* 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 <UIKit/UIKit.h>
#import <React/RCTMountItemProtocol.h>
#import <React/RCTPrimitives.h>
NS_ASSUME_NONNULL_BEGIN
/**
* Removes a component view from another component view.
*/
@interface RCTRemoveMountItem : NSObject <RCTMountItemProtocol>
- (instancetype)initWithChildTag:(ReactTag)childTag parentTag:(ReactTag)parentTag index:(NSInteger)index;
@end
NS_ASSUME_NONNULL_END

Просмотреть файл

@ -1,41 +0,0 @@
/**
* 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 "RCTRemoveMountItem.h"
#import "RCTComponentViewRegistry.h"
@implementation RCTRemoveMountItem {
ReactTag _childTag;
ReactTag _parentTag;
NSInteger _index;
}
- (instancetype)initWithChildTag:(ReactTag)childTag parentTag:(ReactTag)parentTag index:(NSInteger)index
{
if (self = [super init]) {
_childTag = childTag;
_parentTag = parentTag;
_index = index;
}
return self;
}
- (void)executeWithRegistry:(RCTComponentViewRegistry *)registry
{
UIView<RCTComponentViewProtocol> *childComponentView = [registry componentViewByTag:_childTag];
UIView<RCTComponentViewProtocol> *parentComponentView = [registry componentViewByTag:_parentTag];
if (childComponentView == nil || parentComponentView == nil) {
return;
}
[parentComponentView unmountChildComponentView:childComponentView index:_index];
}
@end

Просмотреть файл

@ -1,25 +0,0 @@
/**
* 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 <UIKit/UIKit.h>
#import <React/RCTMountItemProtocol.h>
#import <React/RCTPrimitives.h>
#import <react/core/EventEmitter.h>
NS_ASSUME_NONNULL_BEGIN
/**
* Updates event handlers of a component view.
*/
@interface RCTUpdateEventEmitterMountItem : NSObject <RCTMountItemProtocol>
- (instancetype)initWithTag:(ReactTag)tag eventEmitter:(facebook::react::SharedEventEmitter)eventEmitter;
@end
NS_ASSUME_NONNULL_END

Просмотреть файл

@ -1,36 +0,0 @@
/**
* 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 "RCTUpdateEventEmitterMountItem.h"
#import "RCTComponentViewRegistry.h"
using namespace facebook::react;
@implementation RCTUpdateEventEmitterMountItem {
ReactTag _tag;
SharedEventEmitter _eventEmitter;
}
- (instancetype)initWithTag:(ReactTag)tag eventEmitter:(SharedEventEmitter)eventEmitter
{
if (self = [super init]) {
_tag = tag;
_eventEmitter = eventEmitter;
}
return self;
}
- (void)executeWithRegistry:(RCTComponentViewRegistry *)registry
{
UIView<RCTComponentViewProtocol> *componentView = [registry componentViewByTag:_tag];
[componentView updateEventEmitter:_eventEmitter];
}
@end

Просмотреть файл

@ -1,27 +0,0 @@
/**
* 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 <UIKit/UIKit.h>
#import <React/RCTMountItemProtocol.h>
#import <React/RCTPrimitives.h>
#import <react/core/LayoutMetrics.h>
NS_ASSUME_NONNULL_BEGIN
/**
* Updates layout metrics of a component view.
*/
@interface RCTUpdateLayoutMetricsMountItem : NSObject <RCTMountItemProtocol>
- (instancetype)initWithTag:(ReactTag)tag
oldLayoutMetrics:(facebook::react::LayoutMetrics)oldLayoutMetrics
newLayoutMetrics:(facebook::react::LayoutMetrics)newLayoutMetrics;
@end
NS_ASSUME_NONNULL_END

Просмотреть файл

@ -1,40 +0,0 @@
/**
* 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 "RCTUpdateLayoutMetricsMountItem.h"
#import "RCTComponentViewRegistry.h"
using namespace facebook::react;
@implementation RCTUpdateLayoutMetricsMountItem {
ReactTag _tag;
LayoutMetrics _oldLayoutMetrics;
LayoutMetrics _newLayoutMetrics;
}
- (instancetype)initWithTag:(ReactTag)tag
oldLayoutMetrics:(facebook::react::LayoutMetrics)oldLayoutMetrics
newLayoutMetrics:(facebook::react::LayoutMetrics)newLayoutMetrics
{
if (self = [super init]) {
_tag = tag;
_oldLayoutMetrics = oldLayoutMetrics;
_newLayoutMetrics = newLayoutMetrics;
}
return self;
}
- (void)executeWithRegistry:(RCTComponentViewRegistry *)registry
{
UIView<RCTComponentViewProtocol> *componentView = [registry componentViewByTag:_tag];
[componentView updateLayoutMetrics:_newLayoutMetrics oldLayoutMetrics:_oldLayoutMetrics];
}
@end

Просмотреть файл

@ -1,27 +0,0 @@
/**
* 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 <UIKit/UIKit.h>
#import <React/RCTMountItemProtocol.h>
#import <React/RCTPrimitives.h>
#import <react/core/LocalData.h>
NS_ASSUME_NONNULL_BEGIN
/**
* Updates local data of a component view.
*/
@interface RCTUpdateLocalDataMountItem : NSObject <RCTMountItemProtocol>
- (instancetype)initWithTag:(ReactTag)tag
oldLocalData:(facebook::react::SharedLocalData)oldLocalData
newLocalData:(facebook::react::SharedLocalData)newLocalData;
@end
NS_ASSUME_NONNULL_END

Просмотреть файл

@ -1,39 +0,0 @@
/**
* 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 "RCTUpdateLocalDataMountItem.h"
#import "RCTComponentViewRegistry.h"
using namespace facebook::react;
@implementation RCTUpdateLocalDataMountItem {
ReactTag _tag;
SharedLocalData _oldLocalData;
SharedLocalData _newLocalData;
}
- (instancetype)initWithTag:(ReactTag)tag
oldLocalData:(facebook::react::SharedLocalData)oldLocalData
newLocalData:(facebook::react::SharedLocalData)newLocalData
{
if (self = [super init]) {
_tag = tag;
_oldLocalData = oldLocalData;
_newLocalData = newLocalData;
}
return self;
}
- (void)executeWithRegistry:(RCTComponentViewRegistry *)registry
{
UIView<RCTComponentViewProtocol> *componentView = [registry componentViewByTag:_tag];
[componentView updateLocalData:_newLocalData oldLocalData:_oldLocalData];
}
@end

Просмотреть файл

@ -1,27 +0,0 @@
/**
* 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 <UIKit/UIKit.h>
#import <React/RCTMountItemProtocol.h>
#import <React/RCTPrimitives.h>
#import <react/core/Props.h>
NS_ASSUME_NONNULL_BEGIN
/**
* Updates props of a component view.
*/
@interface RCTUpdatePropsMountItem : NSObject <RCTMountItemProtocol>
- (instancetype)initWithTag:(ReactTag)tag
oldProps:(facebook::react::SharedProps)oldProps
newProps:(facebook::react::SharedProps)newProps;
@end
NS_ASSUME_NONNULL_END

Просмотреть файл

@ -1,37 +0,0 @@
/**
* 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 "RCTUpdatePropsMountItem.h"
#import "RCTComponentViewRegistry.h"
using namespace facebook::react;
@implementation RCTUpdatePropsMountItem {
ReactTag _tag;
SharedProps _oldProps;
SharedProps _newProps;
}
- (instancetype)initWithTag:(ReactTag)tag oldProps:(SharedProps)oldProps newProps:(SharedProps)newProps
{
if (self = [super init]) {
_tag = tag;
_oldProps = oldProps;
_newProps = newProps;
}
return self;
}
- (void)executeWithRegistry:(RCTComponentViewRegistry *)registry
{
UIView<RCTComponentViewProtocol> *componentView = [registry componentViewByTag:_tag];
[componentView updateProps:_newProps oldProps:_oldProps];
}
@end

Просмотреть файл

@ -1,27 +0,0 @@
/**
* 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 <UIKit/UIKit.h>
#import <React/RCTMountItemProtocol.h>
#import <React/RCTPrimitives.h>
#import <react/core/State.h>
NS_ASSUME_NONNULL_BEGIN
/**
* Updates state of a component view.
*/
@interface RCTUpdateStateMountItem : NSObject <RCTMountItemProtocol>
- (instancetype)initWithTag:(ReactTag)tag
oldState:(facebook::react::State::Shared)oldState
newState:(facebook::react::State::Shared)newState;
@end
NS_ASSUME_NONNULL_END

Просмотреть файл

@ -1,39 +0,0 @@
/**
* 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 "RCTUpdateStateMountItem.h"
#import "RCTComponentViewRegistry.h"
using namespace facebook::react;
@implementation RCTUpdateStateMountItem {
ReactTag _tag;
State::Shared _oldState;
State::Shared _newState;
}
- (instancetype)initWithTag:(ReactTag)tag
oldState:(facebook::react::State::Shared)oldState
newState:(facebook::react::State::Shared)newState
{
if (self = [super init]) {
_tag = tag;
_oldState = oldState;
_newState = newState;
}
return self;
}
- (void)executeWithRegistry:(RCTComponentViewRegistry *)registry
{
UIView<RCTComponentViewProtocol> *componentView = [registry componentViewByTag:_tag];
[componentView updateState:_newState oldState:_oldState];
}
@end

Просмотреть файл

@ -27,11 +27,10 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, strong) RCTComponentViewRegistry *componentViewRegistry;
/**
* Transfroms mutation instructions to mount items and executes them.
* The order of mutation instructions matters.
* Schedule mutations to be performed on the main thread.
* Can be called from any thread.
*/
- (void)performTransactionWithMutations:(facebook::react::ShadowViewMutationList)mutations rootTag:(ReactTag)rootTag;
- (void)scheduleMutations:(facebook::react::ShadowViewMutationList const &)mutations rootTag:(ReactTag)rootTag;
/**
* Suggests preliminary creation of a component view of given type.

Просмотреть файл

@ -16,21 +16,165 @@
#import "RCTComponentViewProtocol.h"
#import "RCTComponentViewRegistry.h"
#import "RCTMountItemProtocol.h"
#import "RCTConversions.h"
#import "RCTCreateMountItem.h"
#import "RCTDeleteMountItem.h"
#import "RCTInsertMountItem.h"
#import "RCTRemoveMountItem.h"
#import "RCTUpdateEventEmitterMountItem.h"
#import "RCTUpdateLayoutMetricsMountItem.h"
#import "RCTUpdateLocalDataMountItem.h"
#import "RCTUpdatePropsMountItem.h"
#import "RCTUpdateStateMountItem.h"
using namespace facebook::react;
// `Create` instruction
static void RNCreateMountInstruction(ShadowViewMutation const &mutation, RCTComponentViewRegistry *registry)
{
[registry dequeueComponentViewWithComponentHandle:mutation.newChildShadowView.componentHandle
tag:mutation.newChildShadowView.tag];
}
// `Delete` instruction
static void RNDeleteMountInstruction(ShadowViewMutation const &mutation, RCTComponentViewRegistry *registry)
{
auto const &oldChildShadowView = mutation.oldChildShadowView;
UIView<RCTComponentViewProtocol> *componentView = [registry componentViewByTag:oldChildShadowView.tag];
// TODO(shergin): Make sure that we don't need this check anymore and delete it.
if (componentView == nil) {
return;
}
[registry enqueueComponentViewWithComponentHandle:oldChildShadowView.componentHandle
tag:oldChildShadowView.tag
componentView:componentView];
}
// `Insert` instruction
static void RNInsertMountInstruction(ShadowViewMutation const &mutation, RCTComponentViewRegistry *registry)
{
auto const &newShadowView = mutation.newChildShadowView;
auto const &parentShadowView = mutation.parentShadowView;
UIView<RCTComponentViewProtocol> *childComponentView = [registry componentViewByTag:newShadowView.tag];
UIView<RCTComponentViewProtocol> *parentComponentView = [registry componentViewByTag:parentShadowView.tag];
// TODO(shergin): Make sure that we don't need this check anymore and delete it.
if (childComponentView == nil || parentComponentView == nil) {
return;
}
[parentComponentView mountChildComponentView:childComponentView index:mutation.index];
}
// `Remove` instruction
static void RNRemoveMountInstruction(ShadowViewMutation const &mutation, RCTComponentViewRegistry *registry)
{
auto const &oldShadowView = mutation.oldChildShadowView;
auto const &parentShadowView = mutation.parentShadowView;
UIView<RCTComponentViewProtocol> *childComponentView = [registry componentViewByTag:oldShadowView.tag];
UIView<RCTComponentViewProtocol> *parentComponentView = [registry componentViewByTag:parentShadowView.tag];
// TODO(shergin): Make sure that we don't need this check anymore and delete it.
if (childComponentView == nil || parentComponentView == nil) {
return;
}
[parentComponentView unmountChildComponentView:childComponentView index:mutation.index];
}
// `Update Props` instruction
static void RNUpdatePropsMountInstruction(ShadowViewMutation const &mutation, RCTComponentViewRegistry *registry)
{
auto const &oldShadowView = mutation.oldChildShadowView;
auto const &newShadowView = mutation.newChildShadowView;
UIView<RCTComponentViewProtocol> *componentView = [registry componentViewByTag:newShadowView.tag];
[componentView updateProps:newShadowView.props oldProps:oldShadowView.props];
}
// `Update EventEmitter` instruction
static void RNUpdateEventEmitterMountInstruction(ShadowViewMutation const &mutation, RCTComponentViewRegistry *registry)
{
auto const &newShadowView = mutation.newChildShadowView;
UIView<RCTComponentViewProtocol> *componentView = [registry componentViewByTag:newShadowView.tag];
[componentView updateEventEmitter:newShadowView.eventEmitter];
}
// `Update LayoutMetrics` instruction
static void RNUpdateLayoutMetricsMountInstruction(
ShadowViewMutation const &mutation,
RCTComponentViewRegistry *registry)
{
auto const &oldShadowView = mutation.oldChildShadowView;
auto const &newShadowView = mutation.newChildShadowView;
UIView<RCTComponentViewProtocol> *componentView = [registry componentViewByTag:newShadowView.tag];
[componentView updateLayoutMetrics:newShadowView.layoutMetrics oldLayoutMetrics:oldShadowView.layoutMetrics];
}
// `Update LocalData` instruction
static void RNUpdateLocalDataMountInstruction(ShadowViewMutation const &mutation, RCTComponentViewRegistry *registry)
{
auto const &oldShadowView = mutation.oldChildShadowView;
auto const &newShadowView = mutation.newChildShadowView;
UIView<RCTComponentViewProtocol> *componentView = [registry componentViewByTag:newShadowView.tag];
[componentView updateLocalData:newShadowView.localData oldLocalData:oldShadowView.localData];
}
// `Update State` instruction
static void RNUpdateStateMountInstruction(ShadowViewMutation const &mutation, RCTComponentViewRegistry *registry)
{
auto const &oldShadowView = mutation.oldChildShadowView;
auto const &newShadowView = mutation.newChildShadowView;
UIView<RCTComponentViewProtocol> *componentView = [registry componentViewByTag:newShadowView.tag];
[componentView updateState:newShadowView.state oldState:oldShadowView.state];
}
// `Update` instruction
static void RNPerformMountInstructions(ShadowViewMutationList const &mutations, RCTComponentViewRegistry *registry)
{
SystraceSection s("RNPerformMountInstructions");
for (auto const &mutation : mutations) {
switch (mutation.type) {
case ShadowViewMutation::Create: {
RNCreateMountInstruction(mutation, registry);
break;
}
case ShadowViewMutation::Delete: {
RNDeleteMountInstruction(mutation, registry);
break;
}
case ShadowViewMutation::Insert: {
RNUpdatePropsMountInstruction(mutation, registry);
RNUpdateEventEmitterMountInstruction(mutation, registry);
RNUpdateLocalDataMountInstruction(mutation, registry);
RNUpdateStateMountInstruction(mutation, registry);
RNUpdateLayoutMetricsMountInstruction(mutation, registry);
RNInsertMountInstruction(mutation, registry);
break;
}
case ShadowViewMutation::Remove: {
RNRemoveMountInstruction(mutation, registry);
break;
}
case ShadowViewMutation::Update: {
auto const &oldChildShadowView = mutation.oldChildShadowView;
auto const &newChildShadowView = mutation.newChildShadowView;
if (oldChildShadowView.props != newChildShadowView.props) {
RNUpdatePropsMountInstruction(mutation, registry);
}
if (oldChildShadowView.eventEmitter != newChildShadowView.eventEmitter) {
RNUpdateEventEmitterMountInstruction(mutation, registry);
}
if (oldChildShadowView.localData != newChildShadowView.localData) {
RNUpdateLocalDataMountInstruction(mutation, registry);
}
if (oldChildShadowView.state != newChildShadowView.state) {
RNUpdateStateMountInstruction(mutation, registry);
}
if (oldChildShadowView.layoutMetrics != newChildShadowView.layoutMetrics) {
RNUpdateLayoutMetricsMountInstruction(mutation, registry);
}
break;
}
}
}
}
@implementation RCTMountingManager
- (instancetype)init
@ -42,155 +186,34 @@ using namespace facebook::react;
return self;
}
- (void)performTransactionWithMutations:(ShadowViewMutationList)mutations rootTag:(ReactTag)rootTag
- (void)scheduleMutations:(ShadowViewMutationList const &)mutations rootTag:(ReactTag)rootTag
{
NSMutableArray<RCTMountItemProtocol> *mountItems;
{
// This section is measured separately from `_performMountItems:rootTag:` because that can be asynchronous.
SystraceSection s("-[RCTMountingManager performTransactionWithMutations:rootTag:]");
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]];
}
// State
if (mutation.newChildShadowView.state) {
[mountItems addObject:[[RCTUpdateStateMountItem alloc] initWithTag:mutation.newChildShadowView.tag
oldState:nullptr
newState:mutation.newChildShadowView.state]];
}
// 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];
}
// State
if (oldChildShadowView.state != newChildShadowView.state) {
RCTUpdateStateMountItem *mountItem = [[RCTUpdateStateMountItem alloc] initWithTag:newChildShadowView.tag
oldState:oldChildShadowView.state
newState:newChildShadowView.state];
[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;
}
}
}
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 mountMutations:mutations rootTag:rootTag];
return;
}
// We need a non-reference for `mutations` to allow copy semantic.
auto mutationsCopy = mutations;
RCTExecuteOnMainQueue(^{
[self _performMountItems:mountItems rootTag:rootTag];
RCTAssertMainQueue();
[self mountMutations:mutationsCopy rootTag:rootTag];
});
}
- (void)_performMountItems:(NSArray<RCTMountItemProtocol> *)mountItems rootTag:(ReactTag)rootTag
- (void)mountMutations:(ShadowViewMutationList const &)mutations rootTag:(ReactTag)rootTag
{
SystraceSection s("-[RCTMountingManager _performMountItems:rootTag:]");
SystraceSection s("-[RCTMountingManager mountMutations:rootTag:]");
RCTAssertMainQueue();
[self.delegate mountingManager:self willMountComponentsWithRootTag:rootTag];
for (id<RCTMountItemProtocol> mountItem in mountItems) {
[mountItem executeWithRegistry:_componentViewRegistry];
}
RNPerformMountInstructions(mutations, self.componentViewRegistry);
[self.delegate mountingManager:self didMountComponentsWithRootTag:rootTag];
}
@ -198,14 +221,11 @@ using namespace facebook::react;
changedProps:(NSDictionary *)props
componentDescriptor:(const ComponentDescriptor &)componentDescriptor
{
UIView<RCTComponentViewProtocol> *componentView = [self->_componentViewRegistry componentViewByTag:reactTag];
RCTAssertMainQueue();
UIView<RCTComponentViewProtocol> *componentView = [_componentViewRegistry componentViewByTag:reactTag];
SharedProps oldProps = [componentView props];
SharedProps newProps = componentDescriptor.cloneProps(oldProps, RawProps(convertIdToFollyDynamic(props)));
RCTUpdatePropsMountItem *mountItem = [[RCTUpdatePropsMountItem alloc] initWithTag:reactTag
oldProps:oldProps
newProps:newProps];
RCTAssertMainQueue();
[mountItem executeWithRegistry:self->_componentViewRegistry];
[componentView updateProps:newProps oldProps:oldProps];
}
- (void)optimisticallyCreateComponentViewWithComponentHandle:(ComponentHandle)componentHandle

Просмотреть файл

@ -23,7 +23,7 @@ NS_ASSUME_NONNULL_BEGIN
*/
@protocol RCTSchedulerDelegate
- (void)schedulerDidFinishTransaction:(facebook::react::ShadowViewMutationList)mutations
- (void)schedulerDidFinishTransaction:(facebook::react::ShadowViewMutationList const &)mutations
rootTag:(ReactTag)rootTag;
- (void)schedulerOptimisticallyCreateComponentViewWithComponentHandle:(facebook::react::ComponentHandle)componentHandle;

Просмотреть файл

@ -299,15 +299,14 @@ using namespace facebook::react;
#pragma mark - RCTSchedulerDelegate
- (void)schedulerDidFinishTransaction:(facebook::react::ShadowViewMutationList)mutations
rootTag:(ReactTag)rootTag
- (void)schedulerDidFinishTransaction:(facebook::react::ShadowViewMutationList const &)mutations
rootTag:(ReactTag)rootTag
{
RCTFabricSurface *surface = [_surfaceRegistry surfaceForRootTag:rootTag];
[surface _setStage:RCTSurfaceStagePrepared];
[_mountingManager performTransactionWithMutations:mutations
rootTag:rootTag];
[_mountingManager scheduleMutations:mutations rootTag:rootTag];
}
- (void)schedulerOptimisticallyCreateComponentViewWithComponentHandle:(ComponentHandle)componentHandle

Просмотреть файл

@ -26,7 +26,7 @@ class SchedulerDelegate {
*/
virtual void schedulerDidFinishTransaction(
Tag rootTag,
const ShadowViewMutationList &mutations,
ShadowViewMutationList const &mutations,
const long commitStartTime,
const long layoutTime) = 0;