@samitouri / QOS-React / commits / 96f3093bec

Remove RefreshRuntime.findAffectedHostInstances (#30538)

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.

dan committed Jul 30, 2024 at 22:06 UTC 96f3093becc1f26e06549b9a54b93db9df8f5689
4 files changed -300
packages/react-reconciler/src/ReactFiberHotReloading.js
-159
@@ -11,7 +11,6 @@
11
12 import type {ReactElement} from 'shared/ReactElementType';
13 import type {Fiber, FiberRoot} from './ReactInternalTypes';
14 -import type {Instance} from './ReactFiberConfig';
14 import type {ReactNodeList} from 'shared/ReactTypes';
15
16 import {
@@ -27,11 +26,6 @@ import {
26 ClassComponent,
27 FunctionComponent,
28 ForwardRef,
30 - HostComponent,
31 - HostHoistable,
32 - HostSingleton,
33 - HostPortal,
34 - HostRoot,
29 MemoComponent,
30 SimpleMemoComponent,
31 } from './ReactWorkTags';
@@ -40,7 +34,6 @@ import {
34 REACT_MEMO_TYPE,
35 REACT_LAZY_TYPE,
36 } from 'shared/ReactSymbols';
43 -import {supportsSingletons} from './ReactFiberConfig';
37
38 export type Family = {
39 current: any,
@@ -58,10 +51,6 @@ type RefreshHandler = any => Family | void;
51 export type SetRefreshHandler = (handler: RefreshHandler | null) => void;
52 export type ScheduleRefresh = (root: FiberRoot, update: RefreshUpdate) => void;
53 export type ScheduleRoot = (root: FiberRoot, element: ReactNodeList) => void;
61 -export type FindHostInstancesForRefresh = (
62 - root: FiberRoot,
63 - families: Array<Family>,
64 -) => Set<Instance>;
54
55 let resolveFamily: RefreshHandler | null = null;
56 let failedBoundaries: WeakSet<Fiber> | null = null;
@@ -343,151 +332,3 @@ function scheduleFibersWithFamiliesRecursively(
332 }
333 }
334 }
346 -
347 -export const findHostInstancesForRefresh: FindHostInstancesForRefresh = (
348 - root: FiberRoot,
349 - families: Array<Family>,
350 -): Set<Instance> => {
351 - if (__DEV__) {
352 - const hostInstances = new Set<Instance>();
353 - const types = new Set(families.map(family => family.current));
354 - findHostInstancesForMatchingFibersRecursively(
355 - root.current,
356 - types,
357 - hostInstances,
358 - );
359 - return hostInstances;
360 - } else {
361 - throw new Error(
362 - 'Did not expect findHostInstancesForRefresh to be called in production.',
363 - );
364 - }
365 -};
366 -
367 -function findHostInstancesForMatchingFibersRecursively(
368 - fiber: Fiber,
369 - types: Set<any>,
370 - hostInstances: Set<Instance>,
371 -) {
372 - if (__DEV__) {
373 - const {child, sibling, tag, type} = fiber;
374 -
375 - let candidateType = null;
376 - switch (tag) {
377 - case FunctionComponent:
378 - case SimpleMemoComponent:
379 - case ClassComponent:
380 - candidateType = type;
381 - break;
382 - case ForwardRef:
383 - candidateType = type.render;
384 - break;
385 - default:
386 - break;
387 - }
388 -
389 - let didMatch = false;
390 - if (candidateType !== null) {
391 - if (types.has(candidateType)) {
392 - didMatch = true;
393 - }
394 - }
395 -
396 - if (didMatch) {
397 - // We have a match. This only drills down to the closest host components.
398 - // There's no need to search deeper because for the purpose of giving
399 - // visual feedback, "flashing" outermost parent rectangles is sufficient.
400 - findHostInstancesForFiberShallowly(fiber, hostInstances);
401 - } else {
402 - // If there's no match, maybe there will be one further down in the child tree.
403 - if (child !== null) {
404 - findHostInstancesForMatchingFibersRecursively(
405 - child,
406 - types,
407 - hostInstances,
408 - );
409 - }
410 - }
411 -
412 - if (sibling !== null) {
413 - findHostInstancesForMatchingFibersRecursively(
414 - sibling,
415 - types,
416 - hostInstances,
417 - );
418 - }
419 - }
420 -}
421 -
422 -function findHostInstancesForFiberShallowly(
423 - fiber: Fiber,
424 - hostInstances: Set<Instance>,
425 -): void {
426 - if (__DEV__) {
427 - const foundHostInstances = findChildHostInstancesForFiberShallowly(
428 - fiber,
429 - hostInstances,
430 - );
431 - if (foundHostInstances) {
432 - return;
433 - }
434 - // If we didn't find any host children, fallback to closest host parent.
435 - let node = fiber;
436 - while (true) {
437 - switch (node.tag) {
438 - case HostSingleton:
439 - case HostComponent:
440 - hostInstances.add(node.stateNode);
441 - return;
442 - case HostPortal:
443 - hostInstances.add(node.stateNode.containerInfo);
444 - return;
445 - case HostRoot:
446 - hostInstances.add(node.stateNode.containerInfo);
447 - return;
448 - }
449 - if (node.return === null) {
450 - throw new Error('Expected to reach root first.');
451 - }
452 - node = node.return;
453 - }
454 - }
455 -}
456 -
457 -function findChildHostInstancesForFiberShallowly(
458 - fiber: Fiber,
459 - hostInstances: Set<Instance>,
460 -): boolean {
461 - if (__DEV__) {
462 - let node: Fiber = fiber;
463 - let foundHostInstances = false;
464 - while (true) {
465 - if (
466 - node.tag === HostComponent ||
467 - node.tag === HostHoistable ||
468 - (supportsSingletons ? node.tag === HostSingleton : false)
469 - ) {
470 - // We got a match.
471 - foundHostInstances = true;
472 - hostInstances.add(node.stateNode);
473 - // There may still be more, so keep searching.
474 - } else if (node.child !== null) {
475 - node.child.return = node;
476 - node = node.child;
477 - continue;
478 - }
479 - if (node === fiber) {
480 - return foundHostInstances;
481 - }
482 - while (node.sibling === null) {
483 - if (node.return === null || node.return === fiber) {
484 - return foundHostInstances;
485 - }
486 - node = node.return;
487 - }
488 - node.sibling.return = node.return;
489 - node = node.sibling;
490 - }
491 - }
492 - return false;
493 -}
packages/react-reconciler/src/ReactFiberReconciler.js
-2
@@ -96,7 +96,6 @@ import {
96 scheduleRefresh,
97 scheduleRoot,
98 setRefreshHandler,
99 - findHostInstancesForRefresh,
99 } from './ReactFiberHotReloading';
100 import ReactVersion from 'shared/ReactVersion';
101 export {createPortal} from './ReactPortal';
@@ -865,7 +864,6 @@ export function injectIntoDevTools(): boolean {
864 internals.setErrorHandler = setErrorHandler;
865 internals.setSuspenseHandler = setSuspenseHandler;
866 // React Refresh
868 - internals.findHostInstancesForRefresh = findHostInstancesForRefresh;
867 internals.scheduleRefresh = scheduleRefresh;
868 internals.scheduleRoot = scheduleRoot;
869 internals.setRefreshHandler = setRefreshHandler;
packages/react-refresh/src/ReactFreshRuntime.js
-31
@@ -7,14 +7,12 @@
7 * @flow
8 */
9
10 -import type {Instance} from 'react-reconciler/src/ReactFiberConfig';
10 import type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
11 import type {
12 Family,
13 RefreshUpdate,
14 ScheduleRefresh,
15 ScheduleRoot,
17 - FindHostInstancesForRefresh,
16 SetRefreshHandler,
17 } from 'react-reconciler/src/ReactFiberHotReloading';
18 import type {ReactNodeList} from 'shared/ReactTypes';
@@ -29,7 +27,6 @@ type Signature = {
27 };
28
29 type RendererHelpers = {
32 - findHostInstancesForRefresh: FindHostInstancesForRefresh,
30 scheduleRefresh: ScheduleRefresh,
31 scheduleRoot: ScheduleRoot,
32 setRefreshHandler: SetRefreshHandler,
@@ -414,34 +411,6 @@ export function getFamilyByType(type: any): Family | void {
411 }
412 }
413
417 -export function findAffectedHostInstances(
418 - families: Array<Family>,
419 -): Set<Instance> {
420 - if (__DEV__) {
421 - const affectedInstances = new Set<Instance>();
422 - mountedRoots.forEach(root => {
423 - const helpers = helpersByRoot.get(root);
424 - if (helpers === undefined) {
425 - throw new Error(
426 - 'Could not find helpers for a root. This is a bug in React Refresh.',
427 - );
428 - }
429 - const instancesForRoot = helpers.findHostInstancesForRefresh(
430 - root,
431 - families,
432 - );
433 - instancesForRoot.forEach(inst => {
434 - affectedInstances.add(inst);
435 - });
436 - });
437 - return affectedInstances;
438 - } else {
439 - throw new Error(
440 - 'Unexpected call to React Refresh in a production environment.',
441 - );
442 - }
443 -}
444 -
414 export function injectIntoGlobalHook(globalObject: any): void {
415 if (__DEV__) {
416 // For React Native, the global hook will be set up by require('react-devtools-core').
packages/react-refresh/src/__tests__/ReactFresh-test.js
-108
@@ -3407,114 +3407,6 @@ describe('ReactFresh', () => {
3407 }
3408 });
3409
3410 - it('can find host instances for a family', async () => {
3411 - if (__DEV__) {
3412 - await render(() => {
3413 - function Child({children}) {
3414 - return <div className="Child">{children}</div>;
3415 - }
3416 - $RefreshReg$(Child, 'Child');
3417 -
3418 - function Parent({children}) {
3419 - return (
3420 - <div className="Parent">
3421 - <div>
3422 - <Child />
3423 - </div>
3424 - <div>
3425 - <Child />
3426 - </div>
3427 - </div>
3428 - );
3429 - }
3430 - $RefreshReg$(Parent, 'Parent');
3431 -
3432 - function App() {
3433 - return (
3434 - <div className="App">
3435 - <Parent />
3436 - <Cls>
3437 - <Parent />
3438 - </Cls>
3439 - <Indirection>
3440 - <Empty />
3441 - </Indirection>
3442 - </div>
3443 - );
3444 - }
3445 - $RefreshReg$(App, 'App');
3446 -
3447 - class Cls extends React.Component {
3448 - render() {
3449 - return this.props.children;
3450 - }
3451 - }
3452 -
3453 - function Indirection({children}) {
3454 - return children;
3455 - }
3456 -
3457 - function Empty() {
3458 - return null;
3459 - }
3460 - $RefreshReg$(Empty, 'Empty');
3461 -
3462 - function Frag() {
3463 - return (
3464 - <>
3465 - <div className="Frag">
3466 - <div />
3467 - </div>
3468 - <div className="Frag">
3469 - <div />
3470 - </div>
3471 - </>
3472 - );
3473 - }
3474 - $RefreshReg$(Frag, 'Frag');
3475 -
3476 - return App;
3477 - });
3478 -
3479 - const parentFamily = ReactFreshRuntime.getFamilyByID('Parent');
3480 - const childFamily = ReactFreshRuntime.getFamilyByID('Child');
3481 - const emptyFamily = ReactFreshRuntime.getFamilyByID('Empty');
3482 -
3483 - testFindHostInstancesForFamilies(
3484 - [parentFamily],
3485 - container.querySelectorAll('.Parent'),
3486 - );
3487 -
3488 - testFindHostInstancesForFamilies(
3489 - [childFamily],
3490 - container.querySelectorAll('.Child'),
3491 - );
3492 -
3493 - // When searching for both Parent and Child,
3494 - // we'll stop visual highlighting at the Parent.
3495 - testFindHostInstancesForFamilies(
3496 - [parentFamily, childFamily],
3497 - container.querySelectorAll('.Parent'),
3498 - );
3499 -
3500 - // When we can't find host nodes, use the closest parent.
3501 - testFindHostInstancesForFamilies(
3502 - [emptyFamily],
3503 - container.querySelectorAll('.App'),
3504 - );
3505 - }
3506 - });
3507 -
3508 - function testFindHostInstancesForFamilies(families, expectedNodes) {
3509 - const foundInstances = Array.from(
3510 - ReactFreshRuntime.findAffectedHostInstances(families),
3511 - );
3512 - expect(foundInstances.length).toEqual(expectedNodes.length);
3513 - foundInstances.forEach((node, i) => {
3514 - expect(node).toBe(expectedNodes[i]);
3515 - });
3516 - }
3517 -
3410 it('can update multiple roots independently', async () => {
3411 if (__DEV__) {
3412 // Declare the first version.