diff --git a/Libraries/NativeAnimation/Nodes/RCTAnimatedNode.h b/Libraries/NativeAnimation/Nodes/RCTAnimatedNode.h index 81b5b8b90..376f9e602 100644 --- a/Libraries/NativeAnimation/Nodes/RCTAnimatedNode.h +++ b/Libraries/NativeAnimation/Nodes/RCTAnimatedNode.h @@ -23,6 +23,8 @@ @property (nonatomic, readonly) BOOL needsUpdate; +-(BOOL)isManagedByFabric; + /** * Marks a node and its children as needing update. */ diff --git a/Libraries/NativeAnimation/Nodes/RCTAnimatedNode.m b/Libraries/NativeAnimation/Nodes/RCTAnimatedNode.m index 7d9a2fc6f..6f61e084a 100644 --- a/Libraries/NativeAnimation/Nodes/RCTAnimatedNode.m +++ b/Libraries/NativeAnimation/Nodes/RCTAnimatedNode.m @@ -115,4 +115,14 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init) // during the current update loop } +- (BOOL)isManagedByFabric +{ + for (RCTAnimatedNode *child in _childNodes.objectEnumerator) { + if ([child isManagedByFabric]) { + return YES; + } + } + return NO; +} + @end diff --git a/Libraries/NativeAnimation/Nodes/RCTPropsAnimatedNode.m b/Libraries/NativeAnimation/Nodes/RCTPropsAnimatedNode.m index 1b8e3e16f..0a9a33434 100644 --- a/Libraries/NativeAnimation/Nodes/RCTPropsAnimatedNode.m +++ b/Libraries/NativeAnimation/Nodes/RCTPropsAnimatedNode.m @@ -36,6 +36,11 @@ return self; } +- (BOOL)isManagedByFabric +{ + return _managedByFabric; +} + - (void)connectToView:(NSNumber *)viewTag viewName:(NSString *)viewName bridge:(RCTBridge *)bridge diff --git a/Libraries/NativeAnimation/RCTNativeAnimatedModule.m b/Libraries/NativeAnimation/RCTNativeAnimatedModule.m index 5b8e165b4..69bf078f8 100644 --- a/Libraries/NativeAnimation/RCTNativeAnimatedModule.m +++ b/Libraries/NativeAnimation/RCTNativeAnimatedModule.m @@ -19,7 +19,6 @@ typedef void (^AnimatedOperation)(RCTNativeAnimatedNodesManager *nodesManager); // Operations called before views have been updated. NSMutableArray *_preOperations; NSMutableDictionary *_animIdIsManagedByFabric; - NSMutableDictionary *_animatedNodeIsManagedByFabric; } RCT_EXPORT_MODULE(); @@ -88,7 +87,7 @@ RCT_EXPORT_METHOD(startAnimatingNode:(nonnull NSNumber *)animationId [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { [nodesManager startAnimatingNode:animationId nodeTag:nodeTag config:config endCallback:callBack]; }]; - if ([_animatedNodeIsManagedByFabric[nodeTag] boolValue]) { + if ([_nodesManager isNodeManagedByFabric:nodeTag]) { _animIdIsManagedByFabric[animationId] = @YES; [self flushOperationQueues]; } @@ -138,9 +137,6 @@ RCT_EXPORT_METHOD(connectAnimatedNodeToView:(nonnull NSNumber *)nodeTag viewTag:(nonnull NSNumber *)viewTag) { NSString *viewName = [self.bridge.uiManager viewNameForReactTag:viewTag]; - if (RCTUIManagerTypeForTagIsFabric(nodeTag)) { - _animatedNodeIsManagedByFabric[nodeTag] = @YES; - } [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { [nodesManager connectAnimatedNodeToView:nodeTag viewTag:viewTag viewName:viewName]; }]; diff --git a/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.h b/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.h index 122205058..79e954dac 100644 --- a/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.h +++ b/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.h @@ -19,6 +19,8 @@ - (void)stepAnimations:(nonnull CADisplayLink *)displaylink; +- (BOOL)isNodeManagedByFabric:(nonnull NSNumber *)tag; + // graph - (void)createAnimatedNode:(nonnull NSNumber *)tag diff --git a/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.m b/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.m index 03bded86a..1a47f1b7a 100644 --- a/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.m +++ b/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.m @@ -50,6 +50,12 @@ return self; } +- (BOOL)isNodeManagedByFabric:(nonnull NSNumber *)tag +{ + RCTAnimatedNode *node = _animationNodes[tag]; + return [node isManagedByFabric]; +} + #pragma mark -- Graph - (void)createAnimatedNode:(nonnull NSNumber *)tag diff --git a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index 581e46098..f01a8dfce 100644 --- a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -29,10 +29,14 @@ using namespace facebook::react; static const auto defaultProps = std::make_shared(); _props = defaultProps; } - return self; } +- (facebook::react::SharedProps)props +{ + return _props; +} + - (void)setContentView:(UIView *)contentView { if (_contentView) { diff --git a/React/Fabric/Mounting/RCTComponentViewProtocol.h b/React/Fabric/Mounting/RCTComponentViewProtocol.h index f049b8f33..fe23ee305 100644 --- a/React/Fabric/Mounting/RCTComponentViewProtocol.h +++ b/React/Fabric/Mounting/RCTComponentViewProtocol.h @@ -85,6 +85,11 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)prepareForRecycle; +/** + * Read the last props used to update the view. + */ +- (facebook::react::SharedProps)props; + @end NS_ASSUME_NONNULL_END diff --git a/React/Fabric/Mounting/RCTMountingManager.h b/React/Fabric/Mounting/RCTMountingManager.h index 21e3a8c19..19d945abb 100644 --- a/React/Fabric/Mounting/RCTMountingManager.h +++ b/React/Fabric/Mounting/RCTMountingManager.h @@ -9,6 +9,7 @@ #import #import +#import #import #import #import @@ -40,8 +41,9 @@ NS_ASSUME_NONNULL_BEGIN - (void)optimisticallyCreateComponentViewWithComponentHandle:(facebook::react::ComponentHandle)componentHandle; - (void)synchronouslyUpdateViewOnUIThread:(ReactTag)reactTag - oldProps:(facebook::react::SharedProps)oldProps - newProps:(facebook::react::SharedProps)newProps; + changedProps:(NSDictionary *)props + componentDescriptor:(const facebook::react::ComponentDescriptor &)componentDescriptor; + @end NS_ASSUME_NONNULL_END diff --git a/React/Fabric/Mounting/RCTMountingManager.mm b/React/Fabric/Mounting/RCTMountingManager.mm index 8bcc71cc4..6ae407992 100644 --- a/React/Fabric/Mounting/RCTMountingManager.mm +++ b/React/Fabric/Mounting/RCTMountingManager.mm @@ -8,8 +8,10 @@ #import "RCTMountingManager.h" #import +#import #import #import +#import #import #import "RCTComponentViewProtocol.h" @@ -40,7 +42,7 @@ using namespace facebook::react; return self; } -- (void)performTransactionWithMutations:(facebook::react::ShadowViewMutationList)mutations rootTag:(ReactTag)rootTag +- (void)performTransactionWithMutations:(ShadowViewMutationList)mutations rootTag:(ReactTag)rootTag { NSMutableArray *mountItems; @@ -193,9 +195,12 @@ using namespace facebook::react; } - (void)synchronouslyUpdateViewOnUIThread:(ReactTag)reactTag - oldProps:(SharedProps)oldProps - newProps:(SharedProps)newProps + changedProps:(NSDictionary *)props + componentDescriptor:(const ComponentDescriptor &)componentDescriptor { + UIView *componentView = [self->_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]; diff --git a/React/Fabric/Mounting/UIView+ComponentViewProtocol.h b/React/Fabric/Mounting/UIView+ComponentViewProtocol.h index 7ea8dc5d7..d18e83366 100644 --- a/React/Fabric/Mounting/UIView+ComponentViewProtocol.h +++ b/React/Fabric/Mounting/UIView+ComponentViewProtocol.h @@ -34,6 +34,8 @@ NS_ASSUME_NONNULL_BEGIN - (void)prepareForRecycle; +- (facebook::react::SharedProps)props; + @end NS_ASSUME_NONNULL_END diff --git a/React/Fabric/Mounting/UIView+ComponentViewProtocol.mm b/React/Fabric/Mounting/UIView+ComponentViewProtocol.mm index 428a7844c..54fb66d9c 100644 --- a/React/Fabric/Mounting/UIView+ComponentViewProtocol.mm +++ b/React/Fabric/Mounting/UIView+ComponentViewProtocol.mm @@ -87,4 +87,10 @@ using namespace facebook::react; // Default implementation does nothing. } +- (facebook::react::SharedProps)props +{ + RCTAssert(NO, @"props access should be implemented by RCTViewComponentView."); + return nullptr; +} + @end diff --git a/React/Fabric/RCTSurfacePresenter.mm b/React/Fabric/RCTSurfacePresenter.mm index 13c77871d..b39567e4d 100644 --- a/React/Fabric/RCTSurfacePresenter.mm +++ b/React/Fabric/RCTSurfacePresenter.mm @@ -74,7 +74,7 @@ using namespace facebook::react; } else { _reactNativeConfig = std::make_shared(); } - + _observers = [NSMutableArray array]; [[NSNotificationCenter defaultCenter] addObserver:self @@ -176,17 +176,9 @@ using namespace facebook::react; } ComponentHandle handle = [[componentView class] componentHandle]; const facebook::react::ComponentDescriptor &componentDescriptor = [self._scheduler getComponentDescriptor:handle]; - - // Note: we use an empty object for `oldProps` to rely on the diffing algorithm internal to the - // RCTComponentViewProtocol::updateProps method. If there is a bug in that diffing, some props - // could get reset. One way around this would be to require all RCTComponentViewProtocol - // implementations to expose their current props so we could clone them, but that could be - // problematic for threading and other reasons. - facebook::react::SharedProps newProps = - componentDescriptor.cloneProps(nullptr, RawProps(convertIdToFollyDynamic(props))); - facebook::react::SharedProps oldProps = componentDescriptor.cloneProps(nullptr, RawProps(folly::dynamic::object())); - - [self->_mountingManager synchronouslyUpdateViewOnUIThread:tag oldProps:oldProps newProps:newProps]; + [self->_mountingManager synchronouslyUpdateViewOnUIThread:tag + changedProps:props + componentDescriptor:componentDescriptor]; return YES; } @@ -225,7 +217,7 @@ using namespace facebook::react; // Make sure initializeBridge completed messageQueueThread->runOnQueueSync([] {}); } - + auto runtime = (facebook::jsi::Runtime *)((RCTCxxBridge *)_batchedBridge).runtime; RuntimeExecutor runtimeExecutor =