ComponentDescriptorRegistry.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  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. #include "ComponentDescriptorRegistry.h"
  8. #include <react/core/ShadowNodeFragment.h>
  9. #include <react/uimanager/ComponentDescriptorProviderRegistry.h>
  10. #include <react/uimanager/primitives.h>
  11. namespace facebook {
  12. namespace react {
  13. ComponentDescriptorRegistry::ComponentDescriptorRegistry(
  14. ComponentDescriptorParameters const &parameters,
  15. ComponentDescriptorProviderRegistry const &providerRegistry)
  16. : parameters_(parameters), providerRegistry_(providerRegistry) {}
  17. void ComponentDescriptorRegistry::add(
  18. ComponentDescriptorProvider componentDescriptorProvider) const {
  19. std::unique_lock<better::shared_mutex> lock(mutex_);
  20. auto componentDescriptor = componentDescriptorProvider.constructor(
  21. {parameters_.eventDispatcher,
  22. parameters_.contextContainer,
  23. componentDescriptorProvider.flavor});
  24. assert(
  25. componentDescriptor->getComponentHandle() ==
  26. componentDescriptorProvider.handle);
  27. assert(
  28. componentDescriptor->getComponentName() ==
  29. componentDescriptorProvider.name);
  30. auto sharedComponentDescriptor = std::shared_ptr<ComponentDescriptor const>(
  31. std::move(componentDescriptor));
  32. _registryByHandle[componentDescriptorProvider.handle] =
  33. sharedComponentDescriptor;
  34. _registryByName[componentDescriptorProvider.name] = sharedComponentDescriptor;
  35. }
  36. void ComponentDescriptorRegistry::registerComponentDescriptor(
  37. SharedComponentDescriptor componentDescriptor) const {
  38. ComponentHandle componentHandle = componentDescriptor->getComponentHandle();
  39. _registryByHandle[componentHandle] = componentDescriptor;
  40. ComponentName componentName = componentDescriptor->getComponentName();
  41. _registryByName[componentName] = componentDescriptor;
  42. }
  43. static std::string componentNameByReactViewName(std::string viewName) {
  44. // We need this function only for the transition period;
  45. // eventually, all names will be unified.
  46. std::string rctPrefix("RCT");
  47. if (std::mismatch(rctPrefix.begin(), rctPrefix.end(), viewName.begin())
  48. .first == rctPrefix.end()) {
  49. // If `viewName` has "RCT" prefix, remove it.
  50. viewName.erase(0, rctPrefix.length());
  51. }
  52. // Fabric uses slightly new names for Text components because of differences
  53. // in semantic.
  54. if (viewName == "Text") {
  55. return "Paragraph";
  56. }
  57. // TODO T63839307: remove this condition after deleting TextInlineImage from
  58. // Paper
  59. if (viewName == "TextInlineImage") {
  60. return "Image";
  61. }
  62. if (viewName == "VirtualText") {
  63. return "Text";
  64. }
  65. if (viewName == "ImageView") {
  66. return "Image";
  67. }
  68. if (viewName == "AndroidHorizontalScrollView") {
  69. return "ScrollView";
  70. }
  71. if (viewName == "RKShimmeringView") {
  72. return "ShimmeringView";
  73. }
  74. if (viewName == "RefreshControl") {
  75. return "PullToRefreshView";
  76. }
  77. if (viewName == "AndroidProgressBar") {
  78. return "ActivityIndicatorView";
  79. }
  80. // We need this temporarily for testing purposes until we have proper
  81. // implementation of core components.
  82. if (viewName == "ScrollContentView" ||
  83. viewName == "AndroidHorizontalScrollContentView" // Android
  84. ) {
  85. return "View";
  86. }
  87. // iOS-only
  88. if (viewName == "MultilineTextInputView" ||
  89. viewName == "SinglelineTextInputView") {
  90. return "TextInput";
  91. }
  92. return viewName;
  93. }
  94. ComponentDescriptor const &ComponentDescriptorRegistry::at(
  95. std::string const &componentName) const {
  96. std::shared_lock<better::shared_mutex> lock(mutex_);
  97. auto unifiedComponentName = componentNameByReactViewName(componentName);
  98. auto it = _registryByName.find(unifiedComponentName);
  99. if (it == _registryByName.end()) {
  100. mutex_.unlock_shared();
  101. providerRegistry_.request(unifiedComponentName.c_str());
  102. mutex_.lock_shared();
  103. it = _registryByName.find(unifiedComponentName);
  104. /*
  105. * TODO: T54849676
  106. * Uncomment the `assert` after the following block that checks
  107. * `_fallbackComponentDescriptor` is no longer needed. The assert assumes
  108. * that `componentDescriptorProviderRequest` is always not null and register
  109. * some component on every single request.
  110. */
  111. // assert(it != _registryByName.end());
  112. }
  113. if (it == _registryByName.end()) {
  114. if (_fallbackComponentDescriptor == nullptr) {
  115. throw std::invalid_argument(
  116. ("Unable to find componentDescriptor for " + unifiedComponentName)
  117. .c_str());
  118. }
  119. return *_fallbackComponentDescriptor.get();
  120. }
  121. return *it->second;
  122. }
  123. ComponentDescriptor const *ComponentDescriptorRegistry::
  124. findComponentDescriptorByHandle_DO_NOT_USE_THIS_IS_BROKEN(
  125. ComponentHandle componentHandle) const {
  126. std::shared_lock<better::shared_mutex> lock(mutex_);
  127. auto iterator = _registryByHandle.find(componentHandle);
  128. if (iterator == _registryByHandle.end()) {
  129. return nullptr;
  130. }
  131. return iterator->second.get();
  132. }
  133. ComponentDescriptor const &ComponentDescriptorRegistry::at(
  134. ComponentHandle componentHandle) const {
  135. std::shared_lock<better::shared_mutex> lock(mutex_);
  136. return *_registryByHandle.at(componentHandle);
  137. }
  138. SharedShadowNode ComponentDescriptorRegistry::createNode(
  139. Tag tag,
  140. std::string const &viewName,
  141. SurfaceId surfaceId,
  142. folly::dynamic const &propsDynamic,
  143. SharedEventTarget const &eventTarget) const {
  144. auto unifiedComponentName = componentNameByReactViewName(viewName);
  145. auto const &componentDescriptor = this->at(unifiedComponentName);
  146. auto family = componentDescriptor.createFamily(
  147. ShadowNodeFamilyFragment{tag, surfaceId, nullptr},
  148. std::move(eventTarget));
  149. auto const props =
  150. componentDescriptor.cloneProps(nullptr, RawProps(propsDynamic));
  151. auto const state =
  152. componentDescriptor.createInitialState(ShadowNodeFragment{props}, family);
  153. return componentDescriptor.createShadowNode(
  154. {
  155. /* .props = */ props,
  156. /* .children = */ ShadowNodeFragment::childrenPlaceholder(),
  157. /* .state = */ state,
  158. },
  159. family);
  160. }
  161. void ComponentDescriptorRegistry::setFallbackComponentDescriptor(
  162. SharedComponentDescriptor descriptor) {
  163. _fallbackComponentDescriptor = descriptor;
  164. registerComponentDescriptor(descriptor);
  165. }
  166. ComponentDescriptor::Shared
  167. ComponentDescriptorRegistry::getFallbackComponentDescriptor() const {
  168. return _fallbackComponentDescriptor;
  169. }
  170. } // namespace react
  171. } // namespace facebook