Repository: facebook/react
Pull request: Extract duplicated methods in Fabric and the legacy renderer to a shared module

## Summary

The following methods have exactly the same implementation on Fabric and the legacy renderer:
* `findHostInstance_DEPRECATED`
* `findNodeHandle`
* `dispatchCommand`
* `sendAccessibilityEvent`

This just extracts those functions to a common module so they're easier to change (no need to sync changes in 2 files).

## How did you test this change?

Existing tests (this is a refactor).

Changed files:
filename: packages/react-native-renderer/src/ReactFabric.js
patch: @@ -7,16 +7,13 @@
  * @flow
  */
 
-import type {HostComponent} from './ReactNativeTypes';
 import type {ReactPortal, ReactNodeList} from 'shared/ReactTypes';
 import type {ElementRef, Element, ElementType} from 'react';
 import type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
 
 import './ReactFabricInjection';
 
 import {
-  findHostInstance,
-  findHostInstanceWithWarning,
   batchedUpdates as batchedUpdatesImpl,
   discreteUpdates,
   createContainer,
@@ -29,159 +26,19 @@ import {createPortal as createPortalImpl} from 'react-reconciler/src/ReactPortal
 import {setBatchingImplementation} from './legacy-events/ReactGenericBatching';
 import ReactVersion from 'shared/ReactVersion';
 
-// Modules provided by RN:
-import {
-  UIManager,
-  legacySendAccessibilityEvent,
-} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
-
 import {getClosestInstanceFromNode} from './ReactFabricComponentTree';
 import {
   getInspectorDataForViewTag,
   getInspectorDataForViewAtPoint,
   getInspectorDataForInstance,
 } from './ReactNativeFiberInspector';
 import {LegacyRoot, ConcurrentRoot} from 'react-reconciler/src/ReactRootTags';
-import ReactSharedInternals from 'shared/ReactSharedInternals';
-import getComponentNameFromType from 'shared/getComponentNameFromType';
-
-const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
-
-function findHostInstance_DEPRECATED<TElementType: ElementType>(
-  componentOrHandle: ?(ElementRef<TElementType> | number),
-): ?ElementRef<HostComponent<mixed>> {
-  if (__DEV__) {
-    const owner = ReactCurrentOwner.current;
-    if (owner !== null && owner.stateNode !== null) {
-      if (!owner.stateNode._warnedAboutRefsInRender) {
-        console.error(
-          '%s is accessing findNodeHandle inside its render(). ' +
-            'render() should be a pure function of props and state. It should ' +
-            'never access something that requires stale data from the previous ' +
-            'render, such as refs. Move this logic to componentDidMount and ' +
-            'componentDidUpdate instead.',
-          getComponentNameFromType(owner.type) || 'A component',
-        );
-      }
-
-      owner.stateNode._warnedAboutRefsInRender = true;
-    }
-  }
-  if (componentOrHandle == null) {
-    return null;
-  }
-  // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN
-  if (componentOrHandle._nativeTag) {
-    // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN
-    return componentOrHandle;
-  }
-  // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN
-  if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) {
-    // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN
-    return componentOrHandle.canonical;
-  }
-  let hostInstance;
-  if (__DEV__) {
-    hostInstance = findHostInstanceWithWarning(
-      componentOrHandle,
-      'findHostInstance_DEPRECATED',
-    );
-  } else {
-    hostInstance = findHostInstance(componentOrHandle);
-  }
-
-  return hostInstance;
-}
-
-function findNodeHandle(componentOrHandle: any): ?number {
-  if (__DEV__) {
-    const owner = ReactCurrentOwner.current;
-    if (owner !== null && owner.stateNode !== null) {
-      if (!owner.stateNode._warnedAboutRefsInRender) {
-        console.error(
-          '%s is accessing findNodeHandle inside its render(). ' +
-            'render() should be a pure function of props and state. It should ' +
-            'never access something that requires stale data from the previous ' +
-            'render, such as refs. Move this logic to componentDidMount and ' +
-            'componentDidUpdate instead.',
-          getComponentNameFromType(owner.type) || 'A component',
-        );
-      }
-
-      owner.stateNode._warnedAboutRefsInRender = true;
-    }
-  }
-  if (componentOrHandle == null) {
-    return null;
-  }
-  if (typeof componentOrHandle === 'number') {
-    // Already a node handle
-    return componentOrHandle;
-  }
-  if (componentOrHandle._nativeTag) {
-    return componentOrHandle._nativeTag;
-  }
-  if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) {
-    return componentOrHandle.canonical._nativeTag;
-  }
-  let hostInstance;
-  if (__DEV__) {
-    hostInstance = findHostInstanceWithWarning(
-      componentOrHandle,
-      'findNodeHandle',
-    );
-  } else {
-    hostInstance = findHostInstance(componentOrHandle);
-  }
-
-  if (hostInstance == null) {
-    return hostInstance;
-  }
-
-  return hostInstance._nativeTag;
-}
-
-function dispatchCommand(handle: any, command: string, args: Array<any>) {
-  if (handle._nativeTag == null) {
-    if (__DEV__) {
-      console.error(
-        "dispatchCommand was called with a ref that isn't a " +
-          'native component. Use React.forwardRef to get access to the underlying native component',
-      );
-    }
-    return;
-  }
-
-  if (handle._internalInstanceHandle != null) {
-    const {stateNode} = handle._internalInstanceHandle;
-    if (stateNode != null) {
-      nativeFabricUIManager.dispatchCommand(stateNode.node, command, args);
-    }
-  } else {
-    UIManager.dispatchViewManagerCommand(handle._nativeTag, command, args);
-  }
-}
-
-function sendAccessibilityEvent(handle: any, eventType: string) {
-  if (handle._nativeTag == null) {
-    if (__DEV__) {
-      console.error(
-        "sendAccessibilityEvent was called with a ref that isn't a " +
-          'native component. Use React.forwardRef to get access to the underlying native component',
-      );
-    }
-    return;
-  }
-
-  if (handle._internalInstanceHandle != null) {
-    const {stateNode} = handle._internalInstanceHandle;
-    if (stateNode != null) {
-      nativeFabricUIManager.sendAccessibilityEvent(stateNode.node, eventType);
-    }
-  } else {
-    legacySendAccessibilityEvent(handle._nativeTag, eventType);
-  }
-}
+import {
+  findHostInstance_DEPRECATED,
+  findNodeHandle,
+  dispatchCommand,
+  sendAccessibilityEvent,
+} from './ReactNativePublicCompat';
 
 // $FlowFixMe[missing-local-annot]
 function onRecoverableError(error) {

filename: packages/react-native-renderer/src/ReactNativePublicCompat.js
patch: @@ -0,0 +1,166 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @flow
+ */
+
+import type {HostComponent} from './ReactNativeTypes';
+import type {ElementRef, ElementType} from 'react';
+
+// Modules provided by RN:
+import {
+  UIManager,
+  legacySendAccessibilityEvent,
+} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
+
+import {
+  findHostInstance,
+  findHostInstanceWithWarning,
+} from 'react-reconciler/src/ReactFiberReconciler';
+import ReactSharedInternals from 'shared/ReactSharedInternals';
+import getComponentNameFromType from 'shared/getComponentNameFromType';
+
+const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
+
+export function findHostInstance_DEPRECATED<TElementType: ElementType>(
+  componentOrHandle: ?(ElementRef<TElementType> | number),
+): ?ElementRef<HostComponent<mixed>> {
+  if (__DEV__) {
+    const owner = ReactCurrentOwner.current;
+    if (owner !== null && owner.stateNode !== null) {
+      if (!owner.stateNode._warnedAboutRefsInRender) {
+        console.error(
+          '%s is accessing findNodeHandle inside its render(). ' +
+            'render() should be a pure function of props and state. It should ' +
+            'never access something that requires stale data from the previous ' +
+            'render, such as refs. Move this logic to componentDidMount and ' +
+            'componentDidUpdate instead.',
+          getComponentNameFromType(owner.type) || 'A component',
+        );
+      }
+
+      owner.stateNode._warnedAboutRefsInRender = true;
+    }
+  }
+  if (componentOrHandle == null) {
+    return null;
+  }
+  // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN
+  if (componentOrHandle._nativeTag) {
+    // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN
+    return componentOrHandle;
+  }
+  // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN
+  if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) {
+    // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN
+    return componentOrHandle.canonical;
+  }
+  let hostInstance;
+  if (__DEV__) {
+    hostInstance = findHostInstanceWithWarning(
+      componentOrHandle,
+      'findHostInstance_DEPRECATED',
+    );
+  } else {
+    hostInstance = findHostInstance(componentOrHandle);
+  }
+
+  return hostInstance;
+}
+
+export function findNodeHandle(componentOrHandle: any): ?number {
+  if (__DEV__) {
+    const owner = ReactCurrentOwner.current;
+    if (owner !== null && owner.stateNode !== null) {
+      if (!owner.stateNode._warnedAboutRefsInRender) {
+        console.error(
+          '%s is accessing findNodeHandle inside its render(). ' +
+            'render() should be a pure function of props and state. It should ' +
+            'never access something that requires stale data from the previous ' +
+            'render, such as refs. Move this logic to componentDidMount and ' +
+            'componentDidUpdate instead.',
+          getComponentNameFromType(owner.type) || 'A component',
+        );
+      }
+
+      owner.stateNode._warnedAboutRefsInRender = true;
+    }
+  }
+  if (componentOrHandle == null) {
+    return null;
+  }
+  if (typeof componentOrHandle === 'number') {
+    // Already a node handle
+    return componentOrHandle;
+  }
+  if (componentOrHandle._nativeTag) {
+    return componentOrHandle._nativeTag;
+  }
+  if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) {
+    return componentOrHandle.canonical._nativeTag;
+  }
+  let hostInstance;
+  if (__DEV__) {
+    hostInstance = findHostInstanceWithWarning(
+      componentOrHandle,
+      'findNodeHandle',
+    );
+  } else {
+    hostInstance = findHostInstance(componentOrHandle);
+  }
+
+  if (hostInstance == null) {
+    return hostInstance;
+  }
+
+  return hostInstance._nativeTag;
+}
+
+export function dispatchCommand(
+  handle: any,
+  command: string,
+  args: Array<any>,
+) {
+  if (handle._nativeTag == null) {
+    if (__DEV__) {
+      console.error(
+        "dispatchCommand was called with a ref that isn't a " +
+          'native component. Use React.forwardRef to get access to the underlying native component',
+      );
+    }
+    return;
+  }
+
+  if (handle._internalInstanceHandle != null) {
+    const {stateNode} = handle._internalInstanceHandle;
+    if (stateNode != null) {
+      nativeFabricUIManager.dispatchCommand(stateNode.node, command, args);
+    }
+  } else {
+    UIManager.dispatchViewManagerCommand(handle._nativeTag, command, args);
+  }
+}
+
+export function sendAccessibilityEvent(handle: any, eventType: string) {
+  if (handle._nativeTag == null) {
+    if (__DEV__) {
+      console.error(
+        "sendAccessibilityEvent was called with a ref that isn't a " +
+          'native component. Use React.forwardRef to get access to the underlying native component',
+      );
+    }
+    return;
+  }
+
+  if (handle._internalInstanceHandle != null) {
+    const {stateNode} = handle._internalInstanceHandle;
+    if (stateNode != null) {
+      nativeFabricUIManager.sendAccessibilityEvent(stateNode.node, eventType);
+    }
+  } else {
+    legacySendAccessibilityEvent(handle._nativeTag, eventType);
+  }
+}

filename: packages/react-native-renderer/src/ReactNativeRenderer.js
patch: @@ -7,16 +7,13 @@
  * @flow
  */
 
-import type {HostComponent} from './ReactNativeTypes';
 import type {ReactPortal, ReactNodeList} from 'shared/ReactTypes';
 import type {ElementRef, Element, ElementType} from 'react';
 import type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
 
 import './ReactNativeInjection';
 
 import {
-  findHostInstance,
-  findHostInstanceWithWarning,
   batchedUpdates as batchedUpdatesImpl,
   discreteUpdates,
   createContainer,
@@ -33,10 +30,7 @@ import {
 } from './legacy-events/ReactGenericBatching';
 import ReactVersion from 'shared/ReactVersion';
 // Modules provided by RN:
-import {
-  UIManager,
-  legacySendAccessibilityEvent,
-} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
+import {UIManager} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
 
 import {getClosestInstanceFromNode} from './ReactNativeComponentTree';
 import {
@@ -45,142 +39,12 @@ import {
   getInspectorDataForInstance,
 } from './ReactNativeFiberInspector';
 import {LegacyRoot} from 'react-reconciler/src/ReactRootTags';
-import ReactSharedInternals from 'shared/ReactSharedInternals';
-import getComponentNameFromType from 'shared/getComponentNameFromType';
-
-const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
-
-function findHostInstance_DEPRECATED(
-  componentOrHandle: any,
-): ?React$ElementRef<HostComponent<mixed>> {
-  if (__DEV__) {
-    const owner = ReactCurrentOwner.current;
-    if (owner !== null && owner.stateNode !== null) {
-      if (!owner.stateNode._warnedAboutRefsInRender) {
-        console.error(
-          '%s is accessing findNodeHandle inside its render(). ' +
-            'render() should be a pure function of props and state. It should ' +
-            'never access something that requires stale data from the previous ' +
-            'render, such as refs. Move this logic to componentDidMount and ' +
-            'componentDidUpdate instead.',
-          getComponentNameFromType(owner.type) || 'A component',
-        );
-      }
-
-      owner.stateNode._warnedAboutRefsInRender = true;
-    }
-  }
-  if (componentOrHandle == null) {
-    return null;
-  }
-  if (componentOrHandle._nativeTag) {
-    return componentOrHandle;
-  }
-  if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) {
-    return componentOrHandle.canonical;
-  }
-  let hostInstance;
-  if (__DEV__) {
-    hostInstance = findHostInstanceWithWarning(
-      componentOrHandle,
-      'findHostInstance_DEPRECATED',
-    );
-  } else {
-    hostInstance = findHostInstance(componentOrHandle);
-  }
-
-  return hostInstance;
-}
-
-function findNodeHandle(componentOrHandle: any): ?number {
-  if (__DEV__) {
-    const owner = ReactCurrentOwner.current;
-    if (owner !== null && owner.stateNode !== null) {
-      if (!owner.stateNode._warnedAboutRefsInRender) {
-        console.error(
-          '%s is accessing findNodeHandle inside its render(). ' +
-            'render() should be a pure function of props and state. It should ' +
-            'never access something that requires stale data from the previous ' +
-            'render, such as refs. Move this logic to componentDidMount and ' +
-            'componentDidUpdate instead.',
-          getComponentNameFromType(owner.type) || 'A component',
-        );
-      }
-
-      owner.stateNode._warnedAboutRefsInRender = true;
-    }
-  }
-  if (componentOrHandle == null) {
-    return null;
-  }
-  if (typeof componentOrHandle === 'number') {
-    // Already a node handle
-    return componentOrHandle;
-  }
-  if (componentOrHandle._nativeTag) {
-    return componentOrHandle._nativeTag;
-  }
-  if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) {
-    return componentOrHandle.canonical._nativeTag;
-  }
-  let hostInstance;
-  if (__DEV__) {
-    hostInstance = findHostInstanceWithWarning(
-      componentOrHandle,
-      'findNodeHandle',
-    );
-  } else {
-    hostInstance = findHostInstance(componentOrHandle);
-  }
-
-  if (hostInstance == null) {
-    return hostInstance;
-  }
-
-  return hostInstance._nativeTag;
-}
-
-function dispatchCommand(handle: any, command: string, args: Array<any>) {
-  if (handle._nativeTag == null) {
-    if (__DEV__) {
-      console.error(
-        "dispatchCommand was called with a ref that isn't a " +
-          'native component. Use React.forwardRef to get access to the underlying native component',
-      );
-    }
-    return;
-  }
-
-  if (handle._internalInstanceHandle != null) {
-    const {stateNode} = handle._internalInstanceHandle;
-    if (stateNode != null) {
-      nativeFabricUIManager.dispatchCommand(stateNode.node, command, args);
-    }
-  } else {
-    UIManager.dispatchViewManagerCommand(handle._nativeTag, command, args);
-  }
-}
-
-function sendAccessibilityEvent(handle: any, eventType: string) {
-  if (handle._nativeTag == null) {
-    if (__DEV__) {
-      console.error(
-        "sendAccessibilityEvent was called with a ref that isn't a " +
-          'native component. Use React.forwardRef to get access to the underlying native component',
-      );
-    }
-    return;
-  }
-
-  if (handle._internalInstanceHandle != null) {
-    const {stateNode} = handle._internalInstanceHandle;
-    if (stateNode != null) {
-      nativeFabricUIManager.sendAccessibilityEvent(stateNode.node, eventType);
-    }
-  } else {
-    legacySendAccessibilityEvent(handle._nativeTag, eventType);
-  }
-}
+import {
+  findHostInstance_DEPRECATED,
+  findNodeHandle,
+  dispatchCommand,
+  sendAccessibilityEvent,
+} from './ReactNativePublicCompat';
 
 // $FlowFixMe[missing-local-annot]
 function onRecoverableError(error) {