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 './ReactFabricInjection';
    
  15. 
    
  16. import {
    
  17.   batchedUpdates as batchedUpdatesImpl,
    
  18.   discreteUpdates,
    
  19.   createContainer,
    
  20.   updateContainer,
    
  21.   injectIntoDevTools,
    
  22.   getPublicRootInstance,
    
  23. } from 'react-reconciler/src/ReactFiberReconciler';
    
  24. 
    
  25. import {createPortal as createPortalImpl} from 'react-reconciler/src/ReactPortal';
    
  26. import {setBatchingImplementation} from './legacy-events/ReactGenericBatching';
    
  27. import ReactVersion from 'shared/ReactVersion';
    
  28. 
    
  29. import {getClosestInstanceFromNode} from './ReactFabricComponentTree';
    
  30. import {
    
  31.   getInspectorDataForViewTag,
    
  32.   getInspectorDataForViewAtPoint,
    
  33.   getInspectorDataForInstance,
    
  34. } from './ReactNativeFiberInspector';
    
  35. import {LegacyRoot, ConcurrentRoot} from 'react-reconciler/src/ReactRootTags';
    
  36. import {
    
  37.   findHostInstance_DEPRECATED,
    
  38.   findNodeHandle,
    
  39.   dispatchCommand,
    
  40.   sendAccessibilityEvent,
    
  41.   getNodeFromInternalInstanceHandle,
    
  42. } from './ReactNativePublicCompat';
    
  43. import {getPublicInstanceFromInternalInstanceHandle} from './ReactFiberConfigFabric';
    
  44. 
    
  45. // $FlowFixMe[missing-local-annot]
    
  46. function onRecoverableError(error) {
    
  47.   // TODO: Expose onRecoverableError option to userspace
    
  48.   // eslint-disable-next-line react-internal/no-production-logging, react-internal/warning-args
    
  49.   console.error(error);
    
  50. }
    
  51. 
    
  52. function render(
    
  53.   element: Element<ElementType>,
    
  54.   containerTag: number,
    
  55.   callback: ?() => void,
    
  56.   concurrentRoot: ?boolean,
    
  57. ): ?ElementRef<ElementType> {
    
  58.   let root = roots.get(containerTag);
    
  59. 
    
  60.   if (!root) {
    
  61.     // TODO (bvaughn): If we decide to keep the wrapper component,
    
  62.     // We could create a wrapper for containerTag as well to reduce special casing.
    
  63.     root = createContainer(
    
  64.       containerTag,
    
  65.       concurrentRoot ? ConcurrentRoot : LegacyRoot,
    
  66.       null,
    
  67.       false,
    
  68.       null,
    
  69.       '',
    
  70.       onRecoverableError,
    
  71.       null,
    
  72.     );
    
  73.     roots.set(containerTag, root);
    
  74.   }
    
  75.   updateContainer(element, root, null, callback);
    
  76. 
    
  77.   return getPublicRootInstance(root);
    
  78. }
    
  79. 
    
  80. // $FlowFixMe[missing-this-annot]
    
  81. function unmountComponentAtNode(containerTag: number) {
    
  82.   this.stopSurface(containerTag);
    
  83. }
    
  84. 
    
  85. function stopSurface(containerTag: number) {
    
  86.   const root = roots.get(containerTag);
    
  87.   if (root) {
    
  88.     // TODO: Is it safe to reset this now or should I wait since this unmount could be deferred?
    
  89.     updateContainer(null, root, null, () => {
    
  90.       roots.delete(containerTag);
    
  91.     });
    
  92.   }
    
  93. }
    
  94. 
    
  95. function createPortal(
    
  96.   children: ReactNodeList,
    
  97.   containerTag: number,
    
  98.   key: ?string = null,
    
  99. ): ReactPortal {
    
  100.   return createPortalImpl(children, containerTag, null, key);
    
  101. }
    
  102. 
    
  103. setBatchingImplementation(batchedUpdatesImpl, discreteUpdates);
    
  104. 
    
  105. const roots = new Map<number, FiberRoot>();
    
  106. 
    
  107. export {
    
  108.   // This is needed for implementation details of TouchableNativeFeedback
    
  109.   // Remove this once TouchableNativeFeedback doesn't use cloneElement
    
  110.   findHostInstance_DEPRECATED,
    
  111.   findNodeHandle,
    
  112.   dispatchCommand,
    
  113.   sendAccessibilityEvent,
    
  114.   render,
    
  115.   // Deprecated - this function is being renamed to stopSurface, use that instead.
    
  116.   // TODO (T47576999): Delete this once it's no longer called from native code.
    
  117.   unmountComponentAtNode,
    
  118.   stopSurface,
    
  119.   createPortal,
    
  120.   // This export is typically undefined in production builds.
    
  121.   // See the "enableGetInspectorDataForInstanceInProduction" flag.
    
  122.   getInspectorDataForInstance,
    
  123.   // The public instance has a reference to the internal instance handle.
    
  124.   // This method allows it to acess the most recent shadow node for
    
  125.   // the instance (it's only accessible through it).
    
  126.   getNodeFromInternalInstanceHandle,
    
  127.   // Fabric native methods to traverse the host tree return the same internal
    
  128.   // instance handles we use to dispatch events. This provides a way to access
    
  129.   // the public instances we created from them (potentially created lazily).
    
  130.   getPublicInstanceFromInternalInstanceHandle,
    
  131. };
    
  132. 
    
  133. injectIntoDevTools({
    
  134.   // $FlowExpectedError[incompatible-call] The type of `Instance` in `getClosestInstanceFromNode` does not match in Fabric and the legacy renderer, so it fails to typecheck here.
    
  135.   findFiberByHostInstance: getClosestInstanceFromNode,
    
  136.   bundleType: __DEV__ ? 1 : 0,
    
  137.   version: ReactVersion,
    
  138.   rendererPackageName: 'react-native-renderer',
    
  139.   rendererConfig: {
    
  140.     getInspectorDataForInstance,
    
  141.     getInspectorDataForViewTag: getInspectorDataForViewTag,
    
  142.     getInspectorDataForViewAtPoint: getInspectorDataForViewAtPoint.bind(
    
  143.       null,
    
  144.       findNodeHandle,
    
  145.     ),
    
  146.   },
    
  147. });