RCTMountingManager.mm 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /*
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. */
  7. #import "RCTMountingManager.h"
  8. #import <better/map.h>
  9. #import <React/RCTAssert.h>
  10. #import <React/RCTFollyConvert.h>
  11. #import <React/RCTUtils.h>
  12. #import <react/core/LayoutableShadowNode.h>
  13. #import <react/core/RawProps.h>
  14. #import <react/debug/SystraceSection.h>
  15. #import "RCTComponentViewProtocol.h"
  16. #import "RCTComponentViewRegistry.h"
  17. #import "RCTConversions.h"
  18. #import "RCTMountingTransactionObserverCoordinator.h"
  19. using namespace facebook;
  20. using namespace facebook::react;
  21. // `Create` instruction
  22. static void RNCreateMountInstruction(
  23. ShadowViewMutation const &mutation,
  24. RCTComponentViewRegistry *registry,
  25. RCTMountingTransactionObserverCoordinator &observerCoordinator,
  26. SurfaceId surfaceId)
  27. {
  28. auto componentViewDescriptor =
  29. [registry dequeueComponentViewWithComponentHandle:mutation.newChildShadowView.componentHandle
  30. tag:mutation.newChildShadowView.tag];
  31. observerCoordinator.registerViewComponentDescriptor(componentViewDescriptor, surfaceId);
  32. }
  33. // `Delete` instruction
  34. static void RNDeleteMountInstruction(
  35. ShadowViewMutation const &mutation,
  36. RCTComponentViewRegistry *registry,
  37. RCTMountingTransactionObserverCoordinator &observerCoordinator,
  38. SurfaceId surfaceId)
  39. {
  40. auto const &oldChildShadowView = mutation.oldChildShadowView;
  41. auto const &componentViewDescriptor = [registry componentViewDescriptorWithTag:oldChildShadowView.tag];
  42. observerCoordinator.unregisterViewComponentDescriptor(componentViewDescriptor, surfaceId);
  43. [registry enqueueComponentViewWithComponentHandle:oldChildShadowView.componentHandle
  44. tag:oldChildShadowView.tag
  45. componentViewDescriptor:componentViewDescriptor];
  46. }
  47. // `Insert` instruction
  48. static void RNInsertMountInstruction(ShadowViewMutation const &mutation, RCTComponentViewRegistry *registry)
  49. {
  50. auto const &newShadowView = mutation.newChildShadowView;
  51. auto const &parentShadowView = mutation.parentShadowView;
  52. auto const &childComponentViewDescriptor = [registry componentViewDescriptorWithTag:newShadowView.tag];
  53. auto const &parentComponentViewDescriptor = [registry componentViewDescriptorWithTag:parentShadowView.tag];
  54. [parentComponentViewDescriptor.view mountChildComponentView:childComponentViewDescriptor.view index:mutation.index];
  55. }
  56. // `Remove` instruction
  57. static void RNRemoveMountInstruction(ShadowViewMutation const &mutation, RCTComponentViewRegistry *registry)
  58. {
  59. auto const &oldShadowView = mutation.oldChildShadowView;
  60. auto const &parentShadowView = mutation.parentShadowView;
  61. auto const &childComponentViewDescriptor = [registry componentViewDescriptorWithTag:oldShadowView.tag];
  62. auto const &parentComponentViewDescriptor = [registry componentViewDescriptorWithTag:parentShadowView.tag];
  63. [parentComponentViewDescriptor.view unmountChildComponentView:childComponentViewDescriptor.view index:mutation.index];
  64. }
  65. // `Update Props` instruction
  66. static void RNUpdatePropsMountInstruction(ShadowViewMutation const &mutation, RCTComponentViewRegistry *registry)
  67. {
  68. auto const &oldShadowView = mutation.oldChildShadowView;
  69. auto const &newShadowView = mutation.newChildShadowView;
  70. auto const &componentViewDescriptor = [registry componentViewDescriptorWithTag:newShadowView.tag];
  71. [componentViewDescriptor.view updateProps:newShadowView.props oldProps:oldShadowView.props];
  72. }
  73. // `Update EventEmitter` instruction
  74. static void RNUpdateEventEmitterMountInstruction(ShadowViewMutation const &mutation, RCTComponentViewRegistry *registry)
  75. {
  76. auto const &newShadowView = mutation.newChildShadowView;
  77. auto const &componentViewDescriptor = [registry componentViewDescriptorWithTag:newShadowView.tag];
  78. [componentViewDescriptor.view updateEventEmitter:newShadowView.eventEmitter];
  79. }
  80. // `Update LayoutMetrics` instruction
  81. static void RNUpdateLayoutMetricsMountInstruction(
  82. ShadowViewMutation const &mutation,
  83. RCTComponentViewRegistry *registry)
  84. {
  85. auto const &oldShadowView = mutation.oldChildShadowView;
  86. auto const &newShadowView = mutation.newChildShadowView;
  87. auto const &componentViewDescriptor = [registry componentViewDescriptorWithTag:newShadowView.tag];
  88. [componentViewDescriptor.view updateLayoutMetrics:newShadowView.layoutMetrics
  89. oldLayoutMetrics:oldShadowView.layoutMetrics];
  90. }
  91. // `Update State` instruction
  92. static void RNUpdateStateMountInstruction(ShadowViewMutation const &mutation, RCTComponentViewRegistry *registry)
  93. {
  94. auto const &oldShadowView = mutation.oldChildShadowView;
  95. auto const &newShadowView = mutation.newChildShadowView;
  96. auto const &componentViewDescriptor = [registry componentViewDescriptorWithTag:newShadowView.tag];
  97. [componentViewDescriptor.view updateState:newShadowView.state oldState:oldShadowView.state];
  98. }
  99. // `Finalize Updates` instruction
  100. static void RNFinalizeUpdatesMountInstruction(
  101. ShadowViewMutation const &mutation,
  102. RNComponentViewUpdateMask mask,
  103. RCTComponentViewRegistry *registry)
  104. {
  105. auto const &newShadowView = mutation.newChildShadowView;
  106. auto const &componentViewDescriptor = [registry componentViewDescriptorWithTag:newShadowView.tag];
  107. [componentViewDescriptor.view finalizeUpdates:mask];
  108. }
  109. // `Update` instruction
  110. static void RNPerformMountInstructions(
  111. ShadowViewMutationList const &mutations,
  112. RCTComponentViewRegistry *registry,
  113. RCTMountingTransactionObserverCoordinator &observerCoordinator,
  114. SurfaceId surfaceId)
  115. {
  116. SystraceSection s("RNPerformMountInstructions");
  117. [CATransaction begin];
  118. [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
  119. for (auto const &mutation : mutations) {
  120. switch (mutation.type) {
  121. case ShadowViewMutation::Create: {
  122. RNCreateMountInstruction(mutation, registry, observerCoordinator, surfaceId);
  123. break;
  124. }
  125. case ShadowViewMutation::Delete: {
  126. RNDeleteMountInstruction(mutation, registry, observerCoordinator, surfaceId);
  127. break;
  128. }
  129. case ShadowViewMutation::Insert: {
  130. RNUpdatePropsMountInstruction(mutation, registry);
  131. RNUpdateEventEmitterMountInstruction(mutation, registry);
  132. RNUpdateStateMountInstruction(mutation, registry);
  133. RNUpdateLayoutMetricsMountInstruction(mutation, registry);
  134. RNFinalizeUpdatesMountInstruction(mutation, RNComponentViewUpdateMaskAll, registry);
  135. RNInsertMountInstruction(mutation, registry);
  136. break;
  137. }
  138. case ShadowViewMutation::Remove: {
  139. RNRemoveMountInstruction(mutation, registry);
  140. break;
  141. }
  142. case ShadowViewMutation::Update: {
  143. auto const &oldChildShadowView = mutation.oldChildShadowView;
  144. auto const &newChildShadowView = mutation.newChildShadowView;
  145. auto mask = RNComponentViewUpdateMask{};
  146. if (oldChildShadowView.props != newChildShadowView.props) {
  147. RNUpdatePropsMountInstruction(mutation, registry);
  148. mask |= RNComponentViewUpdateMaskProps;
  149. }
  150. if (oldChildShadowView.eventEmitter != newChildShadowView.eventEmitter) {
  151. RNUpdateEventEmitterMountInstruction(mutation, registry);
  152. mask |= RNComponentViewUpdateMaskEventEmitter;
  153. }
  154. if (oldChildShadowView.state != newChildShadowView.state) {
  155. RNUpdateStateMountInstruction(mutation, registry);
  156. mask |= RNComponentViewUpdateMaskState;
  157. }
  158. if (oldChildShadowView.layoutMetrics != newChildShadowView.layoutMetrics) {
  159. RNUpdateLayoutMetricsMountInstruction(mutation, registry);
  160. mask |= RNComponentViewUpdateMaskLayoutMetrics;
  161. }
  162. if (mask != RNComponentViewUpdateMaskNone) {
  163. RNFinalizeUpdatesMountInstruction(mutation, mask, registry);
  164. }
  165. break;
  166. }
  167. }
  168. }
  169. [CATransaction commit];
  170. }
  171. @implementation RCTMountingManager {
  172. RCTMountingTransactionObserverCoordinator _observerCoordinator;
  173. BOOL _transactionInFlight;
  174. BOOL _followUpTransactionRequired;
  175. }
  176. - (instancetype)init
  177. {
  178. if (self = [super init]) {
  179. _componentViewRegistry = [[RCTComponentViewRegistry alloc] init];
  180. }
  181. return self;
  182. }
  183. - (void)scheduleTransaction:(MountingCoordinator::Shared const &)mountingCoordinator
  184. {
  185. if (RCTIsMainQueue()) {
  186. // Already on the proper thread, so:
  187. // * No need to do a thread jump;
  188. // * No need to do expensive copy of all mutations;
  189. // * No need to allocate a block.
  190. [self initiateTransaction:mountingCoordinator];
  191. return;
  192. }
  193. auto mountingCoordinatorCopy = mountingCoordinator;
  194. RCTExecuteOnMainQueue(^{
  195. RCTAssertMainQueue();
  196. [self initiateTransaction:mountingCoordinatorCopy];
  197. });
  198. }
  199. - (void)dispatchCommand:(ReactTag)reactTag commandName:(NSString *)commandName args:(NSArray *)args
  200. {
  201. if (RCTIsMainQueue()) {
  202. // Already on the proper thread, so:
  203. // * No need to do a thread jump;
  204. // * No need to allocate a block.
  205. [self synchronouslyDispatchCommandOnUIThread:reactTag commandName:commandName args:args];
  206. return;
  207. }
  208. RCTExecuteOnMainQueue(^{
  209. RCTAssertMainQueue();
  210. [self synchronouslyDispatchCommandOnUIThread:reactTag commandName:commandName args:args];
  211. });
  212. }
  213. - (void)initiateTransaction:(MountingCoordinator::Shared const &)mountingCoordinator
  214. {
  215. SystraceSection s("-[RCTMountingManager initiateTransaction:]");
  216. RCTAssertMainQueue();
  217. if (_transactionInFlight) {
  218. _followUpTransactionRequired = YES;
  219. return;
  220. }
  221. do {
  222. _followUpTransactionRequired = NO;
  223. _transactionInFlight = YES;
  224. [self performTransaction:mountingCoordinator];
  225. _transactionInFlight = NO;
  226. } while (_followUpTransactionRequired);
  227. }
  228. - (void)performTransaction:(MountingCoordinator::Shared const &)mountingCoordinator
  229. {
  230. SystraceSection s("-[RCTMountingManager performTransaction:]");
  231. RCTAssertMainQueue();
  232. auto transaction = mountingCoordinator->pullTransaction(DifferentiatorMode::Classic);
  233. if (!transaction.has_value()) {
  234. return;
  235. }
  236. auto surfaceId = transaction->getSurfaceId();
  237. auto &mutations = transaction->getMutations();
  238. if (mutations.size() == 0) {
  239. return;
  240. }
  241. auto telemetry = transaction->getTelemetry();
  242. auto number = transaction->getNumber();
  243. [self.delegate mountingManager:self willMountComponentsWithRootTag:surfaceId];
  244. _observerCoordinator.notifyObserversMountingTransactionWillMount({surfaceId, number, telemetry});
  245. telemetry.willMount();
  246. RNPerformMountInstructions(mutations, self.componentViewRegistry, _observerCoordinator, surfaceId);
  247. telemetry.didMount();
  248. _observerCoordinator.notifyObserversMountingTransactionDidMount({surfaceId, number, telemetry});
  249. [self.delegate mountingManager:self didMountComponentsWithRootTag:surfaceId];
  250. }
  251. - (void)synchronouslyUpdateViewOnUIThread:(ReactTag)reactTag
  252. changedProps:(NSDictionary *)props
  253. componentDescriptor:(const ComponentDescriptor &)componentDescriptor
  254. {
  255. RCTAssertMainQueue();
  256. UIView<RCTComponentViewProtocol> *componentView = [_componentViewRegistry findComponentViewWithTag:reactTag];
  257. SharedProps oldProps = [componentView props];
  258. SharedProps newProps = componentDescriptor.cloneProps(oldProps, RawProps(convertIdToFollyDynamic(props)));
  259. [componentView updateProps:newProps oldProps:oldProps];
  260. }
  261. - (void)synchronouslyDispatchCommandOnUIThread:(ReactTag)reactTag
  262. commandName:(NSString *)commandName
  263. args:(NSArray *)args
  264. {
  265. RCTAssertMainQueue();
  266. UIView<RCTComponentViewProtocol> *componentView = [_componentViewRegistry findComponentViewWithTag:reactTag];
  267. [componentView handleCommand:commandName args:args];
  268. }
  269. @end