@samitouri / QOS-React-2 / commits / a57f40d839

Undo dependency injection of batching (#26389)

There's currently a giant cycle between the event system, through react-dom-bindings, reconciler and then react-dom. We resolve this cycle using dependency injection. However, this all ends up in the same bundle. It can be reordered to resolve the cycles. If we avoid side-effects and avoid reading from module exports during initialization, this should be resolvable in a more optimal way by the compiler.

Sebastian Markbåge committed Mar 14, 2023 at 21:40 UTC a57f40d839bf055f910cc20d7e501a10df92db98
5 files changed +25 -112
packages/react-dom-bindings/src/events/ReactDOMControlledComponent.js
+7 -15
@@ -12,9 +12,10 @@ import {
12 getFiberCurrentPropsFromNode,
13 } from '../client/ReactDOMComponentTree';
14
15 +import {restoreControlledState} from 'react-dom-bindings/src/client/ReactDOMComponent';
16 +
17 // Use to restore controlled state after a change event has fired.
18
17 -let restoreImpl = null;
19 let restoreTarget = null;
20 let restoreQueue = null;
21
@@ -27,27 +28,18 @@ function restoreStateOfTarget(target: Node) {
28 return;
29 }
30
30 - if (typeof restoreImpl !== 'function') {
31 - throw new Error(
32 - 'setRestoreImplementation() needs to be called to handle a target for controlled ' +
33 - 'events. This error is likely caused by a bug in React. Please file an issue.',
34 - );
35 - }
36 -
31 const stateNode = internalInstance.stateNode;
32 // Guard against Fiber being unmounted.
33 if (stateNode) {
34 const props = getFiberCurrentPropsFromNode(stateNode);
41 - restoreImpl(internalInstance.stateNode, internalInstance.type, props);
35 + restoreControlledState(
36 + internalInstance.stateNode,
37 + internalInstance.type,
38 + props,
39 + );
40 }
41 }
42
45 -export function setRestoreImplementation(
46 - impl: (domElement: Element, tag: string, props: Object) => void,
47 -): void {
48 - restoreImpl = impl;
49 -}
50 -
43 export function enqueueStateRestore(target: Node): void {
44 if (restoreTarget) {
45 if (restoreQueue) {
packages/react-dom-bindings/src/events/ReactDOMEventListener.js
+1 -1
@@ -19,8 +19,8 @@ import {
19 hasQueuedDiscreteEvents,
20 clearIfContinuousEvent,
21 queueIfContinuousEvent,
22 - attemptSynchronousHydration,
22 } from './ReactDOMEventReplaying';
23 +import {attemptSynchronousHydration} from 'react-reconciler/src/ReactFiberReconciler';
24 import {
25 getNearestMountedFiber,
26 getContainerFromFiber,
packages/react-dom-bindings/src/events/ReactDOMEventReplaying.js
+10 -43
@@ -38,49 +38,16 @@ import {HostRoot, SuspenseComponent} from 'react-reconciler/src/ReactWorkTags';
38 import {isHigherEventPriority} from 'react-reconciler/src/ReactEventPriorities';
39 import {isRootDehydrated} from 'react-reconciler/src/ReactFiberShellHydration';
40
41 -let _attemptSynchronousHydration: (fiber: Object) => void;
42 -
43 -export function setAttemptSynchronousHydration(fn: (fiber: Object) => void) {
44 - _attemptSynchronousHydration = fn;
45 -}
46 -
47 -export function attemptSynchronousHydration(fiber: Object) {
48 - _attemptSynchronousHydration(fiber);
49 -}
50 -
51 -let attemptDiscreteHydration: (fiber: Object) => void;
52 -
53 -export function setAttemptDiscreteHydration(fn: (fiber: Object) => void) {
54 - attemptDiscreteHydration = fn;
55 -}
56 -
57 -let attemptContinuousHydration: (fiber: Object) => void;
58 -
59 -export function setAttemptContinuousHydration(fn: (fiber: Object) => void) {
60 - attemptContinuousHydration = fn;
61 -}
62 -
63 -let attemptHydrationAtCurrentPriority: (fiber: Object) => void;
64 -
65 -export function setAttemptHydrationAtCurrentPriority(
66 - fn: (fiber: Object) => void,
67 -) {
68 - attemptHydrationAtCurrentPriority = fn;
69 -}
70 -
71 -let getCurrentUpdatePriority: () => EventPriority;
72 -
73 -export function setGetCurrentUpdatePriority(fn: () => EventPriority) {
74 - getCurrentUpdatePriority = fn;
75 -}
76 -
77 -let attemptHydrationAtPriority: <T>(priority: EventPriority, fn: () => T) => T;
78 -
79 -export function setAttemptHydrationAtPriority(
80 - fn: <T>(priority: EventPriority, fn: () => T) => T,
81 -) {
82 - attemptHydrationAtPriority = fn;
83 -}
41 +import {
42 + attemptSynchronousHydration,
43 + attemptDiscreteHydration,
44 + attemptContinuousHydration,
45 + attemptHydrationAtCurrentPriority,
46 +} from 'react-reconciler/src/ReactFiberReconciler';
47 +import {
48 + runWithPriority as attemptHydrationAtPriority,
49 + getCurrentUpdatePriority,
50 +} from 'react-reconciler/src/ReactEventPriorities';
51
52 // TODO: Upgrade this definition once we're on a newer version of Flow that
53 // has this definition built-in.
packages/react-dom-bindings/src/events/ReactDOMUpdateBatching.js
+6 -19
@@ -10,21 +10,18 @@ import {
10 restoreStateIfNeeded,
11 } from './ReactDOMControlledComponent';
12
13 +import {
14 + batchedUpdates as batchedUpdatesImpl,
15 + discreteUpdates as discreteUpdatesImpl,
16 + flushSync as flushSyncImpl,
17 +} from 'react-reconciler/src/ReactFiberReconciler';
18 +
19 // Used as a way to call batchedUpdates when we don't have a reference to
20 // the renderer. Such as when we're dispatching events or if third party
21 // libraries need to call batchedUpdates. Eventually, this API will go away when
22 // everything is batched by default. We'll then have a similar API to opt-out of
23 // scheduled work and instead do synchronous work.
24
19 -// Defaults
20 -let batchedUpdatesImpl = function (fn, bookkeeping) {
21 - return fn(bookkeeping);
22 -};
23 -let discreteUpdatesImpl = function (fn, a, b, c, d) {
24 - return fn(a, b, c, d);
25 -};
26 -let flushSyncImpl = function () {};
27 -
25 let isInsideEventHandler = false;
26
27 function finishEventHandler() {
@@ -63,13 +60,3 @@ export function batchedUpdates(fn, a, b) {
60 export function discreteUpdates(fn, a, b, c, d) {
61 return discreteUpdatesImpl(fn, a, b, c, d);
62 }
66 -
67 -export function setBatchingImplementation(
68 - _batchedUpdatesImpl,
69 - _discreteUpdatesImpl,
70 - _flushSyncImpl,
71 -) {
72 - batchedUpdatesImpl = _batchedUpdatesImpl;
73 - discreteUpdatesImpl = _discreteUpdatesImpl;
74 - flushSyncImpl = _flushSyncImpl;
75 -}
packages/react-dom/src/client/ReactDOM.js
+1 -34
@@ -34,20 +34,12 @@ import {createEventHandle} from 'react-dom-bindings/src/client/ReactDOMEventHand
34
35 import {
36 batchedUpdates,
37 - discreteUpdates,
37 flushSync as flushSyncWithoutWarningIfAlreadyRendering,
38 isAlreadyRendering,
39 flushControlled,
40 injectIntoDevTools,
42 - attemptSynchronousHydration,
43 - attemptDiscreteHydration,
44 - attemptContinuousHydration,
45 - attemptHydrationAtCurrentPriority,
41 } from 'react-reconciler/src/ReactFiberReconciler';
47 -import {
48 - runWithPriority,
49 - getCurrentUpdatePriority,
50 -} from 'react-reconciler/src/ReactEventPriorities';
42 +import {runWithPriority} from 'react-reconciler/src/ReactEventPriorities';
43 import {createPortal as createPortalImpl} from 'react-reconciler/src/ReactPortal';
44 import {canUseDOM} from 'shared/ExecutionEnvironment';
45 import ReactVersion from 'shared/ReactVersion';
@@ -58,18 +50,7 @@ import {
50 getNodeFromInstance,
51 getFiberCurrentPropsFromNode,
52 } from 'react-dom-bindings/src/client/ReactDOMComponentTree';
61 -import {restoreControlledState} from 'react-dom-bindings/src/client/ReactDOMComponent';
62 -import {
63 - setAttemptSynchronousHydration,
64 - setAttemptDiscreteHydration,
65 - setAttemptContinuousHydration,
66 - setAttemptHydrationAtCurrentPriority,
67 - setGetCurrentUpdatePriority,
68 - setAttemptHydrationAtPriority,
69 -} from 'react-dom-bindings/src/events/ReactDOMEventReplaying';
70 -import {setBatchingImplementation} from 'react-dom-bindings/src/events/ReactDOMUpdateBatching';
53 import {
72 - setRestoreImplementation,
54 enqueueStateRestore,
55 restoreStateIfNeeded,
56 } from 'react-dom-bindings/src/events/ReactDOMControlledComponent';
@@ -82,13 +63,6 @@ export {
63 preinit,
64 } from 'react-dom-bindings/src/shared/ReactDOMFloat';
65
85 -setAttemptSynchronousHydration(attemptSynchronousHydration);
86 -setAttemptDiscreteHydration(attemptDiscreteHydration);
87 -setAttemptContinuousHydration(attemptContinuousHydration);
88 -setAttemptHydrationAtCurrentPriority(attemptHydrationAtCurrentPriority);
89 -setGetCurrentUpdatePriority(getCurrentUpdatePriority);
90 -setAttemptHydrationAtPriority(runWithPriority);
91 -
66 if (__DEV__) {
67 if (
68 typeof Map !== 'function' ||
@@ -108,13 +82,6 @@ if (__DEV__) {
82 }
83 }
84
111 -setRestoreImplementation(restoreControlledState);
112 -setBatchingImplementation(
113 - batchedUpdates,
114 - discreteUpdates,
115 - flushSyncWithoutWarningIfAlreadyRendering,
116 -);
117 -
85 function createPortal(
86 children: ReactNodeList,
87 container: Element | DocumentFragment,