@samitouri / QOS-React / commits / 21fdf308a1

Use a shared noop function from shared/noop (#33154)

Stacked on #33150. We use `noop` functions in a lot of places as place holders. I don't think there's any real optimizations we get from having separate instances. This moves them to use a common instance in `shared/noop`.

Sebastian Markbåge committed May 8, 2025 at 21:33 UTC 21fdf308a1a01af69c28c00a70086aa1bd4c2411
15 files changed +48 -45
packages/react-dom-bindings/src/client/ReactDOMComponent.js
+2 -2
@@ -63,6 +63,8 @@ import {validateProperties as validateInputProperties} from '../shared/ReactDOMN
63 import {validateProperties as validateUnknownProperties} from '../shared/ReactDOMUnknownPropertyHook';
64 import sanitizeURL from '../shared/sanitizeURL';
65
66 +import noop from 'shared/noop';
67 +
68 import {trackHostMutation} from 'react-reconciler/src/ReactFiberMutationTracking';
69
70 import {
@@ -319,8 +321,6 @@ function checkForUnmatchedText(
321 return false;
322 }
323
322 -function noop() {}
323 -
324 export function trapClickOnNonInteractiveElement(node: HTMLElement) {
325 // Mobile Safari does not fire properly bubble click events on
326 // non-interactive elements, which means delegated click listeners do not
packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
+7 -6
@@ -139,6 +139,9 @@ import {requestFormReset as requestFormResetOnFiber} from 'react-reconciler/src/
139 import ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals';
140
141 export {default as rendererVersion} from 'shared/ReactVersion';
142 +
143 +import noop from 'shared/noop';
144 +
145 export const rendererPackageName = 'react-dom';
146 export const extraDevToolsConfig = null;
147
@@ -5628,16 +5631,14 @@ type SuspendedState = {
5631 };
5632 let suspendedState: null | SuspendedState = null;
5633
5631 -// We use a noop function when we begin suspending because if possible we want the
5632 -// waitfor step to finish synchronously. If it doesn't we'll return a function to
5633 -// provide the actual unsuspend function and that will get completed when the count
5634 -// hits zero or it will get cancelled if the root starts new work.
5635 -function noop() {}
5636 -
5634 export function startSuspendingCommit(): void {
5635 suspendedState = {
5636 stylesheets: null,
5637 count: 0,
5638 + // We use a noop function when we begin suspending because if possible we want the
5639 + // waitfor step to finish synchronously. If it doesn't we'll return a function to
5640 + // provide the actual unsuspend function and that will get completed when the count
5641 + // hits zero or it will get cancelled if the root starts new work.
5642 unsuspend: noop,
5643 };
5644 }
packages/react-dom/src/ReactDOMSharedInternals.js
+2 -2
@@ -10,6 +10,8 @@
10 import type {EventPriority} from 'react-reconciler/src/ReactEventPriorities';
11 import type {HostDispatcher} from './shared/ReactDOMTypes';
12
13 +import noop from 'shared/noop';
14 +
15 // This should line up with NoEventPriority from react-reconciler/src/ReactEventPriorities
16 // but we can't depend on the react-reconciler from this isomorphic code.
17 export const NoEventPriority: EventPriority = (0: any);
@@ -24,8 +26,6 @@ type ReactDOMInternals = {
26 ) => null | Element | Text),
27 };
28
27 -function noop() {}
28 -
29 function requestFormReset(element: HTMLFormElement) {
30 throw new Error(
31 'Invalid form element. requestFormReset must be passed a form that was ' +
packages/react-dom/src/ReactDOMSharedInternalsFB.js
+2 -2
@@ -12,6 +12,8 @@ import type {HostDispatcher} from './shared/ReactDOMTypes';
12
13 import {NoEventPriority} from 'react-reconciler/src/ReactEventPriorities';
14
15 +import noop from 'shared/noop';
16 +
17 type ReactDOMInternals = {
18 Events: [any, any, any, any, any, any],
19 d /* ReactDOMCurrentDispatcher */: HostDispatcher,
@@ -23,8 +25,6 @@ type ReactDOMInternals = {
25 ) => null | Element | Text),
26 };
27
26 -function noop() {}
27 -
28 const DefaultDispatcher: HostDispatcher = {
29 f /* flushSyncWork */: noop,
30 r /* requestFormReset */: noop,
packages/react-dom/src/client/ReactDOMRootFB.js
+6 -8
@@ -70,6 +70,8 @@ import {
70
71 import assign from 'shared/assign';
72
73 +import noop from 'shared/noop';
74 +
75 // Provided by www
76 const ReactFiberErrorDialogWWW = require('ReactFiberErrorDialog');
77
@@ -206,14 +208,10 @@ function getReactRootElementInContainer(container: any) {
208 }
209 }
210
209 -function noopOnRecoverableError() {
210 - // This isn't reachable because onRecoverableError isn't called in the
211 - // legacy API.
212 -}
213 -
214 -function noopOnDefaultTransitionIndicator() {
215 - // Noop
216 -}
211 +// This isn't reachable because onRecoverableError isn't called in the
212 +// legacy API.
213 +const noopOnRecoverableError = noop;
214 +const noopOnDefaultTransitionIndicator = noop;
215
216 function legacyCreateRootFromDOMContainer(
217 container: Container,
packages/react-reconciler/src/ReactFiberThenable.js
+2 -2
@@ -18,6 +18,8 @@ import {getWorkInProgressRoot} from './ReactFiberWorkLoop';
18
19 import ReactSharedInternals from 'shared/ReactSharedInternals';
20
21 +import noop from 'shared/noop';
22 +
23 opaque type ThenableStateDev = {
24 didWarnAboutUncachedPromise: boolean,
25 thenables: Array<Thenable<any>>,
@@ -95,8 +97,6 @@ export function isThenableResolved(thenable: Thenable<mixed>): boolean {
97 return status === 'fulfilled' || status === 'rejected';
98 }
99
98 -function noop(): void {}
99 -
100 export function trackUsedThenable<T>(
101 thenableState: ThenableState,
102 thenable: Thenable<T>,
packages/react-server/src/ReactFizzHooks.js
+2 -2
@@ -47,6 +47,8 @@ import {
47 import {checkAttributeStringCoercion} from 'shared/CheckStringCoercion';
48 import {getFormState} from './ReactFizzServer';
49
50 +import noop from 'shared/noop';
51 +
52 type BasicStateAction<S> = (S => S) | S;
53 type Dispatch<A> = A => void;
54
@@ -795,8 +797,6 @@ function useMemoCache(size: number): Array<mixed> {
797 return data;
798 }
799
798 -function noop(): void {}
799 -
800 function clientHookNotSupported() {
801 throw new Error(
802 'Cannot use state or effect Hooks in renderToHTML because ' +
packages/react-server/src/ReactFizzServer.js
+1 -2
@@ -176,6 +176,7 @@ import {
176 } from 'shared/ReactFeatureFlags';
177
178 import assign from 'shared/assign';
179 +import noop from 'shared/noop';
180 import getComponentNameFromType from 'shared/getComponentNameFromType';
181 import isArray from 'shared/isArray';
182 import {SuspenseException, getSuspendedThenable} from './ReactFizzThenable';
@@ -425,8 +426,6 @@ function defaultErrorHandler(error: mixed) {
426 return null;
427 }
428
428 -function noop(): void {}
429 -
429 function RequestInstance(
430 this: $FlowFixMe,
431 resumableState: ResumableState,
packages/react-server/src/ReactFizzThenable.js
+2 -2
@@ -20,6 +20,8 @@ import type {
20 RejectedThenable,
21 } from 'shared/ReactTypes';
22
23 +import noop from 'shared/noop';
24 +
25 export opaque type ThenableState = Array<Thenable<any>>;
26
27 // An error that is thrown (e.g. by `use`) to trigger Suspense. If we
@@ -40,8 +42,6 @@ export function createThenableState(): ThenableState {
42 return [];
43 }
44
43 -function noop(): void {}
44 -
45 export function trackUsedThenable<T>(
46 thenableState: ThenableState,
47 thenable: Thenable<T>,
packages/react-server/src/ReactFlightServer.js
+3 -5
@@ -105,6 +105,8 @@ import {resolveOwner, setCurrentOwner} from './flight/ReactFlightCurrentOwner';
105 import {getOwnerStackByComponentInfoInDev} from 'shared/ReactComponentInfoStack';
106 import {resetOwnerStackLimit} from 'shared/ReactOwnerStackReset';
107
108 +import noop from 'shared/noop';
109 +
110 import {
111 callComponentInDEV,
112 callLazyInitInDEV,
@@ -443,9 +445,7 @@ function defaultErrorHandler(error: mixed) {
445 // Don't transform to our wrapper
446 }
447
446 -function defaultPostponeHandler(reason: string) {
447 - // Noop
448 -}
448 +const defaultPostponeHandler: (reason: string) => void = noop;
449
450 function RequestInstance(
451 this: $FlowFixMe,
@@ -558,8 +558,6 @@ function RequestInstance(
558 pingedTasks.push(rootTask);
559 }
560
561 -function noop() {}
562 -
561 export function createRequest(
562 model: ReactClientValue,
563 bundlerConfig: ClientManifest,
packages/react-server/src/ReactFlightThenable.js
+2 -2
@@ -20,6 +20,8 @@ import type {
20 RejectedThenable,
21 } from 'shared/ReactTypes';
22
23 +import noop from 'shared/noop';
24 +
25 export opaque type ThenableState = Array<Thenable<any>>;
26
27 // An error that is thrown (e.g. by `use`) to trigger Suspense. If we
@@ -40,8 +42,6 @@ export function createThenableState(): ThenableState {
42 return [];
43 }
44
43 -function noop(): void {}
44 -
45 export function trackUsedThenable<T>(
46 thenableState: ThenableState,
47 thenable: Thenable<T>,
packages/react-test-renderer/src/ReactTestRenderer.js
+3 -3
@@ -60,9 +60,9 @@ import {
60 disableLegacyMode,
61 } from 'shared/ReactFeatureFlags';
62
63 -function defaultOnDefaultTransitionIndicator(): void | (() => void) {
64 - // Noop
65 -}
63 +import noop from 'shared/noop';
64 +
65 +const defaultOnDefaultTransitionIndicator: () => void | (() => void) = noop;
66
67 // $FlowFixMe[prop-missing]: This is only in the development export.
68 const act = React.act;
packages/react/src/ReactChildren.js
+1 -2
@@ -16,6 +16,7 @@ import type {
16 } from 'shared/ReactTypes';
17
18 import isArray from 'shared/isArray';
19 +import noop from 'shared/noop';
20 import {
21 getIteratorFn,
22 REACT_ELEMENT_TYPE,
@@ -82,8 +83,6 @@ function getElementKey(element: any, index: number): string {
83 return index.toString(36);
84 }
85
85 -function noop() {}
86 -
86 function resolveThenable<T>(thenable: Thenable<T>): T {
87 switch (thenable.status) {
88 case 'fulfilled': {
packages/react/src/ReactStartTransition.js
+3 -5
@@ -25,6 +25,8 @@ import {
25
26 import reportGlobalError from 'shared/reportGlobalError';
27
28 +import noop from 'shared/noop';
29 +
30 export type Transition = {
31 types: null | TransitionTypes, // enableViewTransition
32 gesture: null | GestureProvider, // enableGestureTransition
@@ -177,9 +179,7 @@ export function startGestureTransition(
179 } finally {
180 ReactSharedInternals.T = prevTransition;
181 }
180 - return function cancelGesture() {
181 - // Noop
182 - };
182 + return noop;
183 }
184
185 function warnAboutTransitionSubscriptions(
@@ -200,5 +200,3 @@ function warnAboutTransitionSubscriptions(
200 }
201 }
202 }
203 -
204 -function noop() {}
packages/shared/noop.js new
+10
@@ -0,0 +1,10 @@
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 +export default function noop() {}