1. /**
    
  2.  * Copyright (c) Meta Platforms, Inc. and 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.  * @flow
    
  8.  */
    
  9. 
    
  10. import type {ReactPortal, ReactNodeList} from 'shared/ReactTypes';
    
  11. import type {ElementRef, Element, ElementType} from 'react';
    
  12. import type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
    
  13. 
    
  14. import './ReactNativeInjection';
    
  15. 
    
  16. import {
    
  17.   batchedUpdates as batchedUpdatesImpl,
    
  18.   discreteUpdates,
    
  19.   createContainer,
    
  20.   updateContainer,
    
  21.   injectIntoDevTools,
    
  22.   getPublicRootInstance,
    
  23. } from 'react-reconciler/src/ReactFiberReconciler';
    
  24. // TODO: direct imports like some-package/src/* are bad. Fix me.
    
  25. import {getStackByFiberInDevAndProd} from 'react-reconciler/src/ReactFiberComponentStack';
    
  26. import {createPortal as createPortalImpl} from 'react-reconciler/src/ReactPortal';
    
  27. import {
    
  28.   setBatchingImplementation,
    
  29.   batchedUpdates,
    
  30. } from './legacy-events/ReactGenericBatching';
    
  31. import ReactVersion from 'shared/ReactVersion';
    
  32. // Modules provided by RN:
    
  33. import {UIManager} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
    
  34. 
    
  35. import {getClosestInstanceFromNode} from './ReactNativeComponentTree';
    
  36. import {
    
  37.   getInspectorDataForViewTag,
    
  38.   getInspectorDataForViewAtPoint,
    
  39.   getInspectorDataForInstance,
    
  40. } from './ReactNativeFiberInspector';
    
  41. import {LegacyRoot} from 'react-reconciler/src/ReactRootTags';
    
  42. import {
    
  43.   findHostInstance_DEPRECATED,
    
  44.   findNodeHandle,
    
  45.   dispatchCommand,
    
  46.   sendAccessibilityEvent,
    
  47. } from './ReactNativePublicCompat';
    
  48. 
    
  49. // $FlowFixMe[missing-local-annot]
    
  50. function onRecoverableError(error) {
    
  51.   // TODO: Expose onRecoverableError option to userspace
    
  52.   // eslint-disable-next-line react-internal/no-production-logging, react-internal/warning-args
    
  53.   console.error(error);
    
  54. }
    
  55. 
    
  56. function render(
    
  57.   element: Element<ElementType>,
    
  58.   containerTag: number,
    
  59.   callback: ?() => void,
    
  60. ): ?ElementRef<ElementType> {
    
  61.   let root = roots.get(containerTag);
    
  62. 
    
  63.   if (!root) {
    
  64.     // TODO (bvaughn): If we decide to keep the wrapper component,
    
  65.     // We could create a wrapper for containerTag as well to reduce special casing.
    
  66.     root = createContainer(
    
  67.       containerTag,
    
  68.       LegacyRoot,
    
  69.       null,
    
  70.       false,
    
  71.       null,
    
  72.       '',
    
  73.       onRecoverableError,
    
  74.       null,
    
  75.     );
    
  76.     roots.set(containerTag, root);
    
  77.   }
    
  78.   updateContainer(element, root, null, callback);
    
  79. 
    
  80.   return getPublicRootInstance(root);
    
  81. }
    
  82. 
    
  83. function unmountComponentAtNode(containerTag: number) {
    
  84.   const root = roots.get(containerTag);
    
  85.   if (root) {
    
  86.     // TODO: Is it safe to reset this now or should I wait since this unmount could be deferred?
    
  87.     updateContainer(null, root, null, () => {
    
  88.       roots.delete(containerTag);
    
  89.     });
    
  90.   }
    
  91. }
    
  92. 
    
  93. function unmountComponentAtNodeAndRemoveContainer(containerTag: number) {
    
  94.   unmountComponentAtNode(containerTag);
    
  95. 
    
  96.   // Call back into native to remove all of the subviews from this container
    
  97.   UIManager.removeRootView(containerTag);
    
  98. }
    
  99. 
    
  100. function createPortal(
    
  101.   children: ReactNodeList,
    
  102.   containerTag: number,
    
  103.   key: ?string = null,
    
  104. ): ReactPortal {
    
  105.   return createPortalImpl(children, containerTag, null, key);
    
  106. }
    
  107. 
    
  108. setBatchingImplementation(batchedUpdatesImpl, discreteUpdates);
    
  109. 
    
  110. function computeComponentStackForErrorReporting(reactTag: number): string {
    
  111.   const fiber = getClosestInstanceFromNode(reactTag);
    
  112.   if (!fiber) {
    
  113.     return '';
    
  114.   }
    
  115.   return getStackByFiberInDevAndProd(fiber);
    
  116. }
    
  117. 
    
  118. const roots = new Map<number, FiberRoot>();
    
  119. 
    
  120. const Internals = {
    
  121.   computeComponentStackForErrorReporting,
    
  122. };
    
  123. 
    
  124. export {
    
  125.   // This is needed for implementation details of TouchableNativeFeedback
    
  126.   // Remove this once TouchableNativeFeedback doesn't use cloneElement
    
  127.   findHostInstance_DEPRECATED,
    
  128.   findNodeHandle,
    
  129.   dispatchCommand,
    
  130.   sendAccessibilityEvent,
    
  131.   render,
    
  132.   unmountComponentAtNode,
    
  133.   unmountComponentAtNodeAndRemoveContainer,
    
  134.   createPortal,
    
  135.   batchedUpdates as unstable_batchedUpdates,
    
  136.   Internals as __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
    
  137.   // This export is typically undefined in production builds.
    
  138.   // See the "enableGetInspectorDataForInstanceInProduction" flag.
    
  139.   getInspectorDataForInstance,
    
  140. };
    
  141. 
    
  142. injectIntoDevTools({
    
  143.   findFiberByHostInstance: getClosestInstanceFromNode,
    
  144.   bundleType: __DEV__ ? 1 : 0,
    
  145.   version: ReactVersion,
    
  146.   rendererPackageName: 'react-native-renderer',
    
  147.   rendererConfig: {
    
  148.     getInspectorDataForInstance,
    
  149.     getInspectorDataForViewTag: getInspectorDataForViewTag,
    
  150.     getInspectorDataForViewAtPoint: getInspectorDataForViewAtPoint.bind(
    
  151.       null,
    
  152.       findNodeHandle,
    
  153.     ),
    
  154.   },
    
  155. });