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 {Node, HostComponent} from './ReactNativeTypes';
    
  11. import type {ElementRef, ElementType} from 'react';
    
  12. 
    
  13. // Modules provided by RN:
    
  14. import {
    
  15.   UIManager,
    
  16.   legacySendAccessibilityEvent,
    
  17.   getNodeFromPublicInstance,
    
  18.   getNativeTagFromPublicInstance,
    
  19. } from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
    
  20. 
    
  21. import {
    
  22.   findHostInstance,
    
  23.   findHostInstanceWithWarning,
    
  24. } from 'react-reconciler/src/ReactFiberReconciler';
    
  25. import ReactSharedInternals from 'shared/ReactSharedInternals';
    
  26. import getComponentNameFromType from 'shared/getComponentNameFromType';
    
  27. 
    
  28. const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
    
  29. 
    
  30. export function findHostInstance_DEPRECATED<TElementType: ElementType>(
    
  31.   componentOrHandle: ?(ElementRef<TElementType> | number),
    
  32. ): ?ElementRef<HostComponent<mixed>> {
    
  33.   if (__DEV__) {
    
  34.     const owner = ReactCurrentOwner.current;
    
  35.     if (owner !== null && owner.stateNode !== null) {
    
  36.       if (!owner.stateNode._warnedAboutRefsInRender) {
    
  37.         console.error(
    
  38.           '%s is accessing findNodeHandle inside its render(). ' +
    
  39.             'render() should be a pure function of props and state. It should ' +
    
  40.             'never access something that requires stale data from the previous ' +
    
  41.             'render, such as refs. Move this logic to componentDidMount and ' +
    
  42.             'componentDidUpdate instead.',
    
  43.           getComponentNameFromType(owner.type) || 'A component',
    
  44.         );
    
  45.       }
    
  46. 
    
  47.       owner.stateNode._warnedAboutRefsInRender = true;
    
  48.     }
    
  49.   }
    
  50. 
    
  51.   if (componentOrHandle == null) {
    
  52.     return null;
    
  53.   }
    
  54. 
    
  55.   // For compatibility with Fabric instances
    
  56.   if (
    
  57.     componentOrHandle.canonical &&
    
  58.     componentOrHandle.canonical.publicInstance
    
  59.   ) {
    
  60.     // $FlowExpectedError[incompatible-return] Can't refine componentOrHandle as a Fabric instance
    
  61.     return componentOrHandle.canonical.publicInstance;
    
  62.   }
    
  63. 
    
  64.   // For compatibility with legacy renderer instances
    
  65.   if (componentOrHandle._nativeTag) {
    
  66.     // $FlowFixMe[incompatible-exact] Necessary when running Flow on Fabric
    
  67.     // $FlowFixMe[incompatible-return]
    
  68.     return componentOrHandle;
    
  69.   }
    
  70. 
    
  71.   let hostInstance;
    
  72.   if (__DEV__) {
    
  73.     hostInstance = findHostInstanceWithWarning(
    
  74.       componentOrHandle,
    
  75.       'findHostInstance_DEPRECATED',
    
  76.     );
    
  77.   } else {
    
  78.     hostInstance = findHostInstance(componentOrHandle);
    
  79.   }
    
  80. 
    
  81.   // findHostInstance handles legacy vs. Fabric differences correctly
    
  82.   // $FlowFixMe[incompatible-exact] we need to fix the definition of `HostComponent` to use NativeMethods as an interface, not as a type.
    
  83.   // $FlowFixMe[incompatible-return]
    
  84.   return hostInstance;
    
  85. }
    
  86. 
    
  87. export function findNodeHandle(componentOrHandle: any): ?number {
    
  88.   if (__DEV__) {
    
  89.     const owner = ReactCurrentOwner.current;
    
  90.     if (owner !== null && owner.stateNode !== null) {
    
  91.       if (!owner.stateNode._warnedAboutRefsInRender) {
    
  92.         console.error(
    
  93.           '%s is accessing findNodeHandle inside its render(). ' +
    
  94.             'render() should be a pure function of props and state. It should ' +
    
  95.             'never access something that requires stale data from the previous ' +
    
  96.             'render, such as refs. Move this logic to componentDidMount and ' +
    
  97.             'componentDidUpdate instead.',
    
  98.           getComponentNameFromType(owner.type) || 'A component',
    
  99.         );
    
  100.       }
    
  101. 
    
  102.       owner.stateNode._warnedAboutRefsInRender = true;
    
  103.     }
    
  104.   }
    
  105. 
    
  106.   if (componentOrHandle == null) {
    
  107.     return null;
    
  108.   }
    
  109. 
    
  110.   if (typeof componentOrHandle === 'number') {
    
  111.     // Already a node handle
    
  112.     return componentOrHandle;
    
  113.   }
    
  114. 
    
  115.   // For compatibility with legacy renderer instances
    
  116.   if (componentOrHandle._nativeTag) {
    
  117.     return componentOrHandle._nativeTag;
    
  118.   }
    
  119. 
    
  120.   // For compatibility with Fabric instances
    
  121.   if (
    
  122.     componentOrHandle.canonical != null &&
    
  123.     componentOrHandle.canonical.nativeTag != null
    
  124.   ) {
    
  125.     return componentOrHandle.canonical.nativeTag;
    
  126.   }
    
  127. 
    
  128.   // For compatibility with Fabric public instances
    
  129.   const nativeTag = getNativeTagFromPublicInstance(componentOrHandle);
    
  130.   if (nativeTag) {
    
  131.     return nativeTag;
    
  132.   }
    
  133. 
    
  134.   let hostInstance;
    
  135.   if (__DEV__) {
    
  136.     hostInstance = findHostInstanceWithWarning(
    
  137.       componentOrHandle,
    
  138.       'findNodeHandle',
    
  139.     );
    
  140.   } else {
    
  141.     hostInstance = findHostInstance(componentOrHandle);
    
  142.   }
    
  143. 
    
  144.   if (hostInstance == null) {
    
  145.     return hostInstance;
    
  146.   }
    
  147. 
    
  148.   // $FlowFixMe[incompatible-type] For compatibility with legacy renderer instances
    
  149.   if (hostInstance._nativeTag != null) {
    
  150.     return hostInstance._nativeTag;
    
  151.   }
    
  152. 
    
  153.   // $FlowFixMe[incompatible-call] Necessary when running Flow on the legacy renderer
    
  154.   return getNativeTagFromPublicInstance(hostInstance);
    
  155. }
    
  156. 
    
  157. export function dispatchCommand(
    
  158.   handle: any,
    
  159.   command: string,
    
  160.   args: Array<any>,
    
  161. ) {
    
  162.   const nativeTag =
    
  163.     handle._nativeTag != null
    
  164.       ? handle._nativeTag
    
  165.       : getNativeTagFromPublicInstance(handle);
    
  166.   if (nativeTag == null) {
    
  167.     if (__DEV__) {
    
  168.       console.error(
    
  169.         "dispatchCommand was called with a ref that isn't a " +
    
  170.           'native component. Use React.forwardRef to get access to the underlying native component',
    
  171.       );
    
  172.     }
    
  173.     return;
    
  174.   }
    
  175. 
    
  176.   const node = getNodeFromPublicInstance(handle);
    
  177. 
    
  178.   if (node != null) {
    
  179.     nativeFabricUIManager.dispatchCommand(node, command, args);
    
  180.   } else {
    
  181.     UIManager.dispatchViewManagerCommand(nativeTag, command, args);
    
  182.   }
    
  183. }
    
  184. 
    
  185. export function sendAccessibilityEvent(handle: any, eventType: string) {
    
  186.   const nativeTag =
    
  187.     handle._nativeTag != null
    
  188.       ? handle._nativeTag
    
  189.       : getNativeTagFromPublicInstance(handle);
    
  190.   if (nativeTag == null) {
    
  191.     if (__DEV__) {
    
  192.       console.error(
    
  193.         "sendAccessibilityEvent was called with a ref that isn't a " +
    
  194.           'native component. Use React.forwardRef to get access to the underlying native component',
    
  195.       );
    
  196.     }
    
  197.     return;
    
  198.   }
    
  199. 
    
  200.   const node = getNodeFromPublicInstance(handle);
    
  201.   if (node != null) {
    
  202.     nativeFabricUIManager.sendAccessibilityEvent(node, eventType);
    
  203.   } else {
    
  204.     legacySendAccessibilityEvent(nativeTag, eventType);
    
  205.   }
    
  206. }
    
  207. 
    
  208. export function getNodeFromInternalInstanceHandle(
    
  209.   internalInstanceHandle: mixed,
    
  210. ): ?Node {
    
  211.   return (
    
  212.     // $FlowExpectedError[incompatible-return] internalInstanceHandle is opaque but we need to make an exception here.
    
  213.     internalInstanceHandle &&
    
  214.     // $FlowExpectedError[incompatible-return]
    
  215.     internalInstanceHandle.stateNode &&
    
  216.     // $FlowExpectedError[incompatible-use]
    
  217.     internalInstanceHandle.stateNode.node
    
  218.   );
    
  219. }