Repository: facebook/react
Pull request: Remove RefreshRuntime.findAffectedHostInstances

I originally added this with a plan to visualize which nodes got updated after a Fast Refresh. I didn't end up implementing that part, and to my knowledge, no actively used integration actually does that or use this method.

- [Webpack plugin doesn't use it](https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/f1c8b9a44198449093ca95f85af5df97925e1cfc/lib/runtime/RefreshUtils.js)
- [RN doesn't use it](https://github.com/facebook/react-native/blob/23c5c42de01953ed7b8e8938c2d3a8fac82250a0/packages/react-native/Libraries/Core/setUpReactRefresh.js)
- [Global GitHub code search](https://github.com/search?q=findAffectedHostInstances&type=code&p=1) only shows copies of this code and the type definition based on it, but not actual calls to it

We should be able to delete this without a problem.

Changed files:
filename: packages/react-reconciler/src/ReactFiberHotReloading.js
patch: @@ -11,7 +11,6 @@
 
 import type {ReactElement} from 'shared/ReactElementType';
 import type {Fiber, FiberRoot} from './ReactInternalTypes';
-import type {Instance} from './ReactFiberConfig';
 import type {ReactNodeList} from 'shared/ReactTypes';
 
 import {
@@ -27,11 +26,6 @@ import {
   ClassComponent,
   FunctionComponent,
   ForwardRef,
-  HostComponent,
-  HostHoistable,
-  HostSingleton,
-  HostPortal,
-  HostRoot,
   MemoComponent,
   SimpleMemoComponent,
 } from './ReactWorkTags';
@@ -40,7 +34,6 @@ import {
   REACT_MEMO_TYPE,
   REACT_LAZY_TYPE,
 } from 'shared/ReactSymbols';
-import {supportsSingletons} from './ReactFiberConfig';
 
 export type Family = {
   current: any,
@@ -58,10 +51,6 @@ type RefreshHandler = any => Family | void;
 export type SetRefreshHandler = (handler: RefreshHandler | null) => void;
 export type ScheduleRefresh = (root: FiberRoot, update: RefreshUpdate) => void;
 export type ScheduleRoot = (root: FiberRoot, element: ReactNodeList) => void;
-export type FindHostInstancesForRefresh = (
-  root: FiberRoot,
-  families: Array<Family>,
-) => Set<Instance>;
 
 let resolveFamily: RefreshHandler | null = null;
 let failedBoundaries: WeakSet<Fiber> | null = null;
@@ -343,151 +332,3 @@ function scheduleFibersWithFamiliesRecursively(
     }
   }
 }
-
-export const findHostInstancesForRefresh: FindHostInstancesForRefresh = (
-  root: FiberRoot,
-  families: Array<Family>,
-): Set<Instance> => {
-  if (__DEV__) {
-    const hostInstances = new Set<Instance>();
-    const types = new Set(families.map(family => family.current));
-    findHostInstancesForMatchingFibersRecursively(
-      root.current,
-      types,
-      hostInstances,
-    );
-    return hostInstances;
-  } else {
-    throw new Error(
-      'Did not expect findHostInstancesForRefresh to be called in production.',
-    );
-  }
-};
-
-function findHostInstancesForMatchingFibersRecursively(
-  fiber: Fiber,
-  types: Set<any>,
-  hostInstances: Set<Instance>,
-) {
-  if (__DEV__) {
-    const {child, sibling, tag, type} = fiber;
-
-    let candidateType = null;
-    switch (tag) {
-      case FunctionComponent:
-      case SimpleMemoComponent:
-      case ClassComponent:
-        candidateType = type;
-        break;
-      case ForwardRef:
-        candidateType = type.render;
-        break;
-      default:
-        break;
-    }
-
-    let didMatch = false;
-    if (candidateType !== null) {
-      if (types.has(candidateType)) {
-        didMatch = true;
-      }
-    }
-
-    if (didMatch) {
-      // We have a match. This only drills down to the closest host components.
-      // There's no need to search deeper because for the purpose of giving
-      // visual feedback, "flashing" outermost parent rectangles is sufficient.
-      findHostInstancesForFiberShallowly(fiber, hostInstances);
-    } else {
-      // If there's no match, maybe there will be one further down in the child tree.
-      if (child !== null) {
-        findHostInstancesForMatchingFibersRecursively(
-          child,
-          types,
-          hostInstances,
-        );
-      }
-    }
-
-    if (sibling !== null) {
-      findHostInstancesForMatchingFibersRecursively(
-        sibling,
-        types,
-        hostInstances,
-      );
-    }
-  }
-}
-
-function findHostInstancesForFiberShallowly(
-  fiber: Fiber,
-  hostInstances: Set<Instance>,
-): void {
-  if (__DEV__) {
-    const foundHostInstances = findChildHostInstancesForFiberShallowly(
-      fiber,
-      hostInstances,
-    );
-    if (foundHostInstances) {
-      return;
-    }
-    // If we didn't find any host children, fallback to closest host parent.
-    let node = fiber;
-    while (true) {
-      switch (node.tag) {
-        case HostSingleton:
-        case HostComponent:
-          hostInstances.add(node.stateNode);
-          return;
-        case HostPortal:
-          hostInstances.add(node.stateNode.containerInfo);
-          return;
-        case HostRoot:
-          hostInstances.add(node.stateNode.containerInfo);
-          return;
-      }
-      if (node.return === null) {
-        throw new Error('Expected to reach root first.');
-      }
-      node = node.return;
-    }
-  }
-}
-
-function findChildHostInstancesForFiberShallowly(
-  fiber: Fiber,
-  hostInstances: Set<Instance>,
-): boolean {
-  if (__DEV__) {
-    let node: Fiber = fiber;
-    let foundHostInstances = false;
-    while (true) {
-      if (
-        node.tag === HostComponent ||
-        node.tag === HostHoistable ||
-        (supportsSingletons ? node.tag === HostSingleton : false)
-      ) {
-        // We got a match.
-        foundHostInstances = true;
-        hostInstances.add(node.stateNode);
-        // There may still be more, so keep searching.
-      } else if (node.child !== null) {
-        node.child.return = node;
-        node = node.child;
-        continue;
-      }
-      if (node === fiber) {
-        return foundHostInstances;
-      }
-      while (node.sibling === null) {
-        if (node.return === null || node.return === fiber) {
-          return foundHostInstances;
-        }
-        node = node.return;
-      }
-      node.sibling.return = node.return;
-      node = node.sibling;
-    }
-  }
-  return false;
-}

filename: packages/react-reconciler/src/ReactFiberReconciler.js
patch: @@ -96,7 +96,6 @@ import {
   scheduleRefresh,
   scheduleRoot,
   setRefreshHandler,
-  findHostInstancesForRefresh,
 } from './ReactFiberHotReloading';
 import ReactVersion from 'shared/ReactVersion';
 export {createPortal} from './ReactPortal';
@@ -865,7 +864,6 @@ export function injectIntoDevTools(): boolean {
     internals.setErrorHandler = setErrorHandler;
     internals.setSuspenseHandler = setSuspenseHandler;
     // React Refresh
-    internals.findHostInstancesForRefresh = findHostInstancesForRefresh;
     internals.scheduleRefresh = scheduleRefresh;
     internals.scheduleRoot = scheduleRoot;
     internals.setRefreshHandler = setRefreshHandler;

filename: packages/react-refresh/src/ReactFreshRuntime.js
patch: @@ -7,14 +7,12 @@
  * @flow
  */
 
-import type {Instance} from 'react-reconciler/src/ReactFiberConfig';
 import type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
 import type {
   Family,
   RefreshUpdate,
   ScheduleRefresh,
   ScheduleRoot,
-  FindHostInstancesForRefresh,
   SetRefreshHandler,
 } from 'react-reconciler/src/ReactFiberHotReloading';
 import type {ReactNodeList} from 'shared/ReactTypes';
@@ -29,7 +27,6 @@ type Signature = {
 };
 
 type RendererHelpers = {
-  findHostInstancesForRefresh: FindHostInstancesForRefresh,
   scheduleRefresh: ScheduleRefresh,
   scheduleRoot: ScheduleRoot,
   setRefreshHandler: SetRefreshHandler,
@@ -414,34 +411,6 @@ export function getFamilyByType(type: any): Family | void {
   }
 }
 
-export function findAffectedHostInstances(
-  families: Array<Family>,
-): Set<Instance> {
-  if (__DEV__) {
-    const affectedInstances = new Set<Instance>();
-    mountedRoots.forEach(root => {
-      const helpers = helpersByRoot.get(root);
-      if (helpers === undefined) {
-        throw new Error(
-          'Could not find helpers for a root. This is a bug in React Refresh.',
-        );
-      }
-      const instancesForRoot = helpers.findHostInstancesForRefresh(
-        root,
-        families,
-      );
-      instancesForRoot.forEach(inst => {
-        affectedInstances.add(inst);
-      });
-    });
-    return affectedInstances;
-  } else {
-    throw new Error(
-      'Unexpected call to React Refresh in a production environment.',
-    );
-  }
-}
-
 export function injectIntoGlobalHook(globalObject: any): void {
   if (__DEV__) {
     // For React Native, the global hook will be set up by require('react-devtools-core').

filename: packages/react-refresh/src/__tests__/ReactFresh-test.js
patch: @@ -3407,114 +3407,6 @@ describe('ReactFresh', () => {
     }
   });
 
-  it('can find host instances for a family', async () => {
-    if (__DEV__) {
-      await render(() => {
-        function Child({children}) {
-          return <div className="Child">{children}</div>;
-        }
-        $RefreshReg$(Child, 'Child');
-
-        function Parent({children}) {
-          return (
-            <div className="Parent">
-              <div>
-                <Child />
-              </div>
-              <div>
-                <Child />
-              </div>
-            </div>
-          );
-        }
-        $RefreshReg$(Parent, 'Parent');
-
-        function App() {
-          return (
-            <div className="App">
-              <Parent />
-              <Cls>
-                <Parent />
-              </Cls>
-              <Indirection>
-                <Empty />
-              </Indirection>
-            </div>
-          );
-        }
-        $RefreshReg$(App, 'App');
-
-        class Cls extends React.Component {
-          render() {
-            return this.props.children;
-          }
-        }
-
-        function Indirection({children}) {
-          return children;
-        }
-
-        function Empty() {
-          return null;
-        }
-        $RefreshReg$(Empty, 'Empty');
-
-        function Frag() {
-          return (
-            <>
-              <div className="Frag">
-                <div />
-              </div>
-              <div className="Frag">
-                <div />
-              </div>
-            </>
-          );
-        }
-        $RefreshReg$(Frag, 'Frag');
-
-        return App;
-      });
-
-      const parentFamily = ReactFreshRuntime.getFamilyByID('Parent');
-      const childFamily = ReactFreshRuntime.getFamilyByID('Child');
-      const emptyFamily = ReactFreshRuntime.getFamilyByID('Empty');
-
-      testFindHostInstancesForFamilies(
-        [parentFamily],
-        container.querySelectorAll('.Parent'),
-      );
-
-      testFindHostInstancesForFamilies(
-        [childFamily],
-        container.querySelectorAll('.Child'),
-      );
-
-      // When searching for both Parent and Child,
-      // we'll stop visual highlighting at the Parent.
-      testFindHostInstancesForFamilies(
-        [parentFamily, childFamily],
-        container.querySelectorAll('.Parent'),
-      );
-
-      // When we can't find host nodes, use the closest parent.
-      testFindHostInstancesForFamilies(
-        [emptyFamily],
-        container.querySelectorAll('.App'),
-      );
-    }
-  });
-
-  function testFindHostInstancesForFamilies(families, expectedNodes) {
-    const foundInstances = Array.from(
-      ReactFreshRuntime.findAffectedHostInstances(families),
-    );
-    expect(foundInstances.length).toEqual(expectedNodes.length);
-    foundInstances.forEach((node, i) => {
-      expect(node).toBe(expectedNodes[i]);
-    });
-  }
-
   it('can update multiple roots independently', async () => {
     if (__DEV__) {
       // Declare the first version.