Skip to content

Commit a57f40d

Browse files
authored
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.
1 parent d310d65 commit a57f40d

File tree

5 files changed

+25
-112
lines changed

5 files changed

+25
-112
lines changed

packages/react-dom-bindings/src/events/ReactDOMControlledComponent.js

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ import {
1212
getFiberCurrentPropsFromNode,
1313
} from '../client/ReactDOMComponentTree';
1414

15+
import {restoreControlledState} from 'react-dom-bindings/src/client/ReactDOMComponent';
16+
1517
// Use to restore controlled state after a change event has fired.
1618

17-
let restoreImpl = null;
1819
let restoreTarget = null;
1920
let restoreQueue = null;
2021

@@ -27,27 +28,18 @@ function restoreStateOfTarget(target: Node) {
2728
return;
2829
}
2930

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-
3731
const stateNode = internalInstance.stateNode;
3832
// Guard against Fiber being unmounted.
3933
if (stateNode) {
4034
const props = getFiberCurrentPropsFromNode(stateNode);
41-
restoreImpl(internalInstance.stateNode, internalInstance.type, props);
35+
restoreControlledState(
36+
internalInstance.stateNode,
37+
internalInstance.type,
38+
props,
39+
);
4240
}
4341
}
4442

45-
export function setRestoreImplementation(
46-
impl: (domElement: Element, tag: string, props: Object) => void,
47-
): void {
48-
restoreImpl = impl;
49-
}
50-
5143
export function enqueueStateRestore(target: Node): void {
5244
if (restoreTarget) {
5345
if (restoreQueue) {

packages/react-dom-bindings/src/events/ReactDOMEventListener.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ import {
1919
hasQueuedDiscreteEvents,
2020
clearIfContinuousEvent,
2121
queueIfContinuousEvent,
22-
attemptSynchronousHydration,
2322
} from './ReactDOMEventReplaying';
23+
import {attemptSynchronousHydration} from 'react-reconciler/src/ReactFiberReconciler';
2424
import {
2525
getNearestMountedFiber,
2626
getContainerFromFiber,

packages/react-dom-bindings/src/events/ReactDOMEventReplaying.js

Lines changed: 10 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -38,49 +38,16 @@ import {HostRoot, SuspenseComponent} from 'react-reconciler/src/ReactWorkTags';
3838
import {isHigherEventPriority} from 'react-reconciler/src/ReactEventPriorities';
3939
import {isRootDehydrated} from 'react-reconciler/src/ReactFiberShellHydration';
4040

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';
8451

8552
// TODO: Upgrade this definition once we're on a newer version of Flow that
8653
// has this definition built-in.

packages/react-dom-bindings/src/events/ReactDOMUpdateBatching.js

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,18 @@ import {
1010
restoreStateIfNeeded,
1111
} from './ReactDOMControlledComponent';
1212

13+
import {
14+
batchedUpdates as batchedUpdatesImpl,
15+
discreteUpdates as discreteUpdatesImpl,
16+
flushSync as flushSyncImpl,
17+
} from 'react-reconciler/src/ReactFiberReconciler';
18+
1319
// Used as a way to call batchedUpdates when we don't have a reference to
1420
// the renderer. Such as when we're dispatching events or if third party
1521
// libraries need to call batchedUpdates. Eventually, this API will go away when
1622
// everything is batched by default. We'll then have a similar API to opt-out of
1723
// scheduled work and instead do synchronous work.
1824

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-
2825
let isInsideEventHandler = false;
2926

3027
function finishEventHandler() {
@@ -63,13 +60,3 @@ export function batchedUpdates(fn, a, b) {
6360
export function discreteUpdates(fn, a, b, c, d) {
6461
return discreteUpdatesImpl(fn, a, b, c, d);
6562
}
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

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -34,20 +34,12 @@ import {createEventHandle} from 'react-dom-bindings/src/client/ReactDOMEventHand
3434

3535
import {
3636
batchedUpdates,
37-
discreteUpdates,
3837
flushSync as flushSyncWithoutWarningIfAlreadyRendering,
3938
isAlreadyRendering,
4039
flushControlled,
4140
injectIntoDevTools,
42-
attemptSynchronousHydration,
43-
attemptDiscreteHydration,
44-
attemptContinuousHydration,
45-
attemptHydrationAtCurrentPriority,
4641
} 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';
5143
import {createPortal as createPortalImpl} from 'react-reconciler/src/ReactPortal';
5244
import {canUseDOM} from 'shared/ExecutionEnvironment';
5345
import ReactVersion from 'shared/ReactVersion';
@@ -58,18 +50,7 @@ import {
5850
getNodeFromInstance,
5951
getFiberCurrentPropsFromNode,
6052
} 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';
7153
import {
72-
setRestoreImplementation,
7354
enqueueStateRestore,
7455
restoreStateIfNeeded,
7556
} from 'react-dom-bindings/src/events/ReactDOMControlledComponent';
@@ -82,13 +63,6 @@ export {
8263
preinit,
8364
} from 'react-dom-bindings/src/shared/ReactDOMFloat';
8465

85-
setAttemptSynchronousHydration(attemptSynchronousHydration);
86-
setAttemptDiscreteHydration(attemptDiscreteHydration);
87-
setAttemptContinuousHydration(attemptContinuousHydration);
88-
setAttemptHydrationAtCurrentPriority(attemptHydrationAtCurrentPriority);
89-
setGetCurrentUpdatePriority(getCurrentUpdatePriority);
90-
setAttemptHydrationAtPriority(runWithPriority);
91-
9266
if (__DEV__) {
9367
if (
9468
typeof Map !== 'function' ||
@@ -108,13 +82,6 @@ if (__DEV__) {
10882
}
10983
}
11084

111-
setRestoreImplementation(restoreControlledState);
112-
setBatchingImplementation(
113-
batchedUpdates,
114-
discreteUpdates,
115-
flushSyncWithoutWarningIfAlreadyRendering,
116-
);
117-
11885
function createPortal(
11986
children: ReactNodeList,
12087
container: Element | DocumentFragment,

0 commit comments

Comments
 (0)