Skip to content

Commit 62bd6d7

Browse files
author
Brian Vaughn
committed
Revert "Replace unbatchedUpdates with flushSync (facebook#21776)"
This reverts commit ed6c091.
1 parent b6258b0 commit 62bd6d7

File tree

12 files changed

+239
-59
lines changed

12 files changed

+239
-59
lines changed

packages/react-devtools-shared/src/__tests__/__snapshots__/profilingCache-test.js.snap

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ Object {
4040
6 => 1,
4141
},
4242
"passiveEffectDuration": null,
43-
"priorityLevel": "Immediate",
43+
"priorityLevel": "Normal",
4444
"timestamp": 16,
4545
"updaters": Array [
4646
Object {
@@ -87,7 +87,7 @@ Object {
8787
4 => 2,
8888
},
8989
"passiveEffectDuration": null,
90-
"priorityLevel": "Immediate",
90+
"priorityLevel": "Normal",
9191
"timestamp": 15,
9292
"updaters": Array [
9393
Object {
@@ -186,7 +186,7 @@ Object {
186186
6 => 1,
187187
},
188188
"passiveEffectDuration": null,
189-
"priorityLevel": "Immediate",
189+
"priorityLevel": "Normal",
190190
"timestamp": 12,
191191
"updaters": Array [
192192
Object {
@@ -445,7 +445,7 @@ Object {
445445
],
446446
],
447447
"passiveEffectDuration": null,
448-
"priorityLevel": "Immediate",
448+
"priorityLevel": "Normal",
449449
"timestamp": 12,
450450
"updaters": Array [
451451
Object {
@@ -938,7 +938,7 @@ Object {
938938
],
939939
],
940940
"passiveEffectDuration": null,
941-
"priorityLevel": "Immediate",
941+
"priorityLevel": "Normal",
942942
"timestamp": 11,
943943
"updaters": Array [
944944
Object {
@@ -1597,7 +1597,7 @@ Object {
15971597
17 => 1,
15981598
},
15991599
"passiveEffectDuration": null,
1600-
"priorityLevel": "Immediate",
1600+
"priorityLevel": "Normal",
16011601
"timestamp": 24,
16021602
"updaters": Array [
16031603
Object {
@@ -1687,7 +1687,7 @@ Object {
16871687
"fiberActualDurations": Map {},
16881688
"fiberSelfDurations": Map {},
16891689
"passiveEffectDuration": 0,
1690-
"priorityLevel": "Immediate",
1690+
"priorityLevel": "Normal",
16911691
"timestamp": 34,
16921692
"updaters": Array [
16931693
Object {
@@ -2223,7 +2223,7 @@ Object {
22232223
],
22242224
],
22252225
"passiveEffectDuration": null,
2226-
"priorityLevel": "Immediate",
2226+
"priorityLevel": "Normal",
22272227
"timestamp": 24,
22282228
"updaters": Array [
22292229
Object {
@@ -2310,7 +2310,7 @@ Object {
23102310
"fiberActualDurations": Array [],
23112311
"fiberSelfDurations": Array [],
23122312
"passiveEffectDuration": 0,
2313-
"priorityLevel": "Immediate",
2313+
"priorityLevel": "Normal",
23142314
"timestamp": 34,
23152315
"updaters": Array [
23162316
Object {
@@ -2431,7 +2431,7 @@ Object {
24312431
2 => 0,
24322432
},
24332433
"passiveEffectDuration": null,
2434-
"priorityLevel": "Immediate",
2434+
"priorityLevel": "Normal",
24352435
"timestamp": 0,
24362436
"updaters": Array [
24372437
Object {
@@ -2506,7 +2506,7 @@ Object {
25062506
3 => 0,
25072507
},
25082508
"passiveEffectDuration": 0,
2509-
"priorityLevel": "Immediate",
2509+
"priorityLevel": "Normal",
25102510
"timestamp": 0,
25112511
"updaters": Array [
25122512
Object {
@@ -2715,7 +2715,7 @@ Object {
27152715
],
27162716
],
27172717
"passiveEffectDuration": 0,
2718-
"priorityLevel": "Immediate",
2718+
"priorityLevel": "Normal",
27192719
"timestamp": 0,
27202720
"updaters": Array [
27212721
Object {
@@ -3071,7 +3071,7 @@ Object {
30713071
7 => 0,
30723072
},
30733073
"passiveEffectDuration": null,
3074-
"priorityLevel": "Immediate",
3074+
"priorityLevel": "Normal",
30753075
"timestamp": 0,
30763076
"updaters": Array [
30773077
Object {
@@ -3515,7 +3515,7 @@ Object {
35153515
],
35163516
],
35173517
"passiveEffectDuration": null,
3518-
"priorityLevel": "Immediate",
3518+
"priorityLevel": "Normal",
35193519
"timestamp": 0,
35203520
"updaters": Array [
35213521
Object {

packages/react-dom/src/__tests__/ReactMount-test.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ describe('ReactMount', () => {
277277
expect(calls).toBe(5);
278278
});
279279

280-
it('initial mount of legacy root is sync inside batchedUpdates, as if it were wrapped in flushSync', () => {
280+
it('initial mount is sync inside batchedUpdates, but task work is deferred until the end of the batch', () => {
281281
const container1 = document.createElement('div');
282282
const container2 = document.createElement('div');
283283

@@ -302,12 +302,12 @@ describe('ReactMount', () => {
302302

303303
// Initial mount on another root. Should flush immediately.
304304
ReactDOM.render(<Foo>a</Foo>, container2);
305-
// The earlier update also flushed, since flushSync flushes all pending
306-
// sync work across all roots.
307-
expect(container1.textContent).toEqual('2');
308-
// Layout updates are also flushed synchronously
309-
expect(container2.textContent).toEqual('a!');
305+
// The update did not flush yet.
306+
expect(container1.textContent).toEqual('1');
307+
// The initial mount flushed, but not the update scheduled in cDM.
308+
expect(container2.textContent).toEqual('a');
310309
});
310+
// All updates have flushed.
311311
expect(container1.textContent).toEqual('2');
312312
expect(container2.textContent).toEqual('a!');
313313
});

packages/react-dom/src/client/ReactDOMLegacy.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import {
2929
createContainer,
3030
findHostInstanceWithNoPortals,
3131
updateContainer,
32-
flushSyncWithoutWarningIfAlreadyRendering,
32+
unbatchedUpdates,
3333
getPublicRootInstance,
3434
findHostInstance,
3535
findHostInstanceWithWarning,
@@ -174,7 +174,7 @@ function legacyRenderSubtreeIntoContainer(
174174
};
175175
}
176176
// Initial mount should not be batched.
177-
flushSyncWithoutWarningIfAlreadyRendering(() => {
177+
unbatchedUpdates(() => {
178178
updateContainer(children, fiberRoot, parentComponent, callback);
179179
});
180180
} else {
@@ -357,7 +357,7 @@ export function unmountComponentAtNode(container: Container) {
357357
}
358358

359359
// Unmount should not be batched.
360-
flushSyncWithoutWarningIfAlreadyRendering(() => {
360+
unbatchedUpdates(() => {
361361
legacyRenderSubtreeIntoContainer(null, null, container, false, () => {
362362
// $FlowFixMe This should probably use `delete container._reactRootContainer`
363363
container._reactRootContainer = null;

packages/react-noop-renderer/src/ReactNoop.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export const {
3838
flushExpired,
3939
batchedUpdates,
4040
deferredUpdates,
41+
unbatchedUpdates,
4142
discreteUpdates,
4243
idleUpdates,
4344
flushSync,

packages/react-noop-renderer/src/ReactNoopPersistent.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export const {
3838
flushExpired,
3939
batchedUpdates,
4040
deferredUpdates,
41+
unbatchedUpdates,
4142
discreteUpdates,
4243
idleUpdates,
4344
flushDiscreteUpdates,

packages/react-noop-renderer/src/createReactNoop.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,8 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
901901

902902
deferredUpdates: NoopRenderer.deferredUpdates,
903903

904+
unbatchedUpdates: NoopRenderer.unbatchedUpdates,
905+
904906
discreteUpdates: NoopRenderer.discreteUpdates,
905907

906908
idleUpdates<T>(fn: () => T): T {

packages/react-reconciler/src/ReactFiberReconciler.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
createContainer as createContainer_old,
1919
updateContainer as updateContainer_old,
2020
batchedUpdates as batchedUpdates_old,
21+
unbatchedUpdates as unbatchedUpdates_old,
2122
deferredUpdates as deferredUpdates_old,
2223
discreteUpdates as discreteUpdates_old,
2324
flushControlled as flushControlled_old,
@@ -55,6 +56,7 @@ import {
5556
createContainer as createContainer_new,
5657
updateContainer as updateContainer_new,
5758
batchedUpdates as batchedUpdates_new,
59+
unbatchedUpdates as unbatchedUpdates_new,
5860
deferredUpdates as deferredUpdates_new,
5961
discreteUpdates as discreteUpdates_new,
6062
flushControlled as flushControlled_new,
@@ -97,6 +99,9 @@ export const updateContainer = enableNewReconciler
9799
export const batchedUpdates = enableNewReconciler
98100
? batchedUpdates_new
99101
: batchedUpdates_old;
102+
export const unbatchedUpdates = enableNewReconciler
103+
? unbatchedUpdates_new
104+
: unbatchedUpdates_old;
100105
export const deferredUpdates = enableNewReconciler
101106
? deferredUpdates_new
102107
: deferredUpdates_old;

packages/react-reconciler/src/ReactFiberReconciler.new.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import {
5252
scheduleUpdateOnFiber,
5353
flushRoot,
5454
batchedUpdates,
55+
unbatchedUpdates,
5556
flushSync,
5657
flushControlled,
5758
deferredUpdates,
@@ -326,6 +327,7 @@ export function updateContainer(
326327

327328
export {
328329
batchedUpdates,
330+
unbatchedUpdates,
329331
deferredUpdates,
330332
discreteUpdates,
331333
flushControlled,

packages/react-reconciler/src/ReactFiberReconciler.old.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import {
5252
scheduleUpdateOnFiber,
5353
flushRoot,
5454
batchedUpdates,
55+
unbatchedUpdates,
5556
flushSync,
5657
flushControlled,
5758
deferredUpdates,
@@ -326,6 +327,7 @@ export function updateContainer(
326327

327328
export {
328329
batchedUpdates,
330+
unbatchedUpdates,
329331
deferredUpdates,
330332
discreteUpdates,
331333
flushControlled,

packages/react-reconciler/src/ReactFiberWorkLoop.new.js

Lines changed: 72 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -246,11 +246,12 @@ const {
246246

247247
type ExecutionContext = number;
248248

249-
export const NoContext = /* */ 0b0000;
250-
const BatchedContext = /* */ 0b0001;
251-
const RenderContext = /* */ 0b0010;
252-
const CommitContext = /* */ 0b0100;
253-
export const RetryAfterError = /* */ 0b1000;
249+
export const NoContext = /* */ 0b00000;
250+
const BatchedContext = /* */ 0b00001;
251+
const LegacyUnbatchedContext = /* */ 0b00010;
252+
const RenderContext = /* */ 0b00100;
253+
const CommitContext = /* */ 0b01000;
254+
export const RetryAfterError = /* */ 0b10000;
254255

255256
type RootExitStatus = 0 | 1 | 2 | 3 | 4 | 5;
256257
const RootIncomplete = 0;
@@ -514,19 +515,35 @@ export function scheduleUpdateOnFiber(
514515
}
515516
}
516517

517-
ensureRootIsScheduled(root, eventTime);
518-
if (
519-
lane === SyncLane &&
520-
executionContext === NoContext &&
521-
(fiber.mode & ConcurrentMode) === NoMode
522-
) {
523-
// Flush the synchronous work now, unless we're already working or inside
524-
// a batch. This is intentionally inside scheduleUpdateOnFiber instead of
525-
// scheduleCallbackForFiber to preserve the ability to schedule a callback
526-
// without immediately flushing it. We only do this for user-initiated
527-
// updates, to preserve historical behavior of legacy mode.
528-
resetRenderTimer();
529-
flushSyncCallbacksOnlyInLegacyMode();
518+
if (lane === SyncLane) {
519+
if (
520+
// Check if we're inside unbatchedUpdates
521+
(executionContext & LegacyUnbatchedContext) !== NoContext &&
522+
// Check if we're not already rendering
523+
(executionContext & (RenderContext | CommitContext)) === NoContext
524+
) {
525+
// This is a legacy edge case. The initial mount of a ReactDOM.render-ed
526+
// root inside of batchedUpdates should be synchronous, but layout updates
527+
// should be deferred until the end of the batch.
528+
performSyncWorkOnRoot(root);
529+
} else {
530+
ensureRootIsScheduled(root, eventTime);
531+
if (
532+
executionContext === NoContext &&
533+
(fiber.mode & ConcurrentMode) === NoMode
534+
) {
535+
// Flush the synchronous work now, unless we're already working or inside
536+
// a batch. This is intentionally inside scheduleUpdateOnFiber instead of
537+
// scheduleCallbackForFiber to preserve the ability to schedule a callback
538+
// without immediately flushing it. We only do this for user-initiated
539+
// updates, to preserve historical behavior of legacy mode.
540+
resetRenderTimer();
541+
flushSyncCallbacksOnlyInLegacyMode();
542+
}
543+
}
544+
} else {
545+
// Schedule other updates after in case the callback is sync.
546+
ensureRootIsScheduled(root, eventTime);
530547
}
531548

532549
return root;
@@ -1078,6 +1095,25 @@ export function discreteUpdates<A, B, C, D, R>(
10781095
}
10791096
}
10801097

1098+
export function unbatchedUpdates<A, R>(fn: (a: A) => R, a: A): R {
1099+
const prevExecutionContext = executionContext;
1100+
executionContext &= ~BatchedContext;
1101+
executionContext |= LegacyUnbatchedContext;
1102+
try {
1103+
return fn(a);
1104+
} finally {
1105+
executionContext = prevExecutionContext;
1106+
// If there were legacy sync updates, flush them at the end of the outer
1107+
// most batchedUpdates-like method.
1108+
if (executionContext === NoContext) {
1109+
resetRenderTimer();
1110+
// TODO: I think this call is redundant, because we flush inside
1111+
// scheduleUpdateOnFiber when LegacyUnbatchedContext is set.
1112+
flushSyncCallbacksOnlyInLegacyMode();
1113+
}
1114+
}
1115+
}
1116+
10811117
export function flushSyncWithoutWarningIfAlreadyRendering<A, R>(
10821118
fn: A => R,
10831119
a: A,
@@ -1918,6 +1954,24 @@ function commitRootImpl(root, renderPriorityLevel) {
19181954
throw error;
19191955
}
19201956

1957+
if ((executionContext & LegacyUnbatchedContext) !== NoContext) {
1958+
if (__DEV__) {
1959+
if (enableDebugTracing) {
1960+
logCommitStopped();
1961+
}
1962+
}
1963+
1964+
if (enableSchedulingProfiler) {
1965+
markCommitStopped();
1966+
}
1967+
1968+
// This is a legacy edge case. We just committed the initial mount of
1969+
// a ReactDOM.render-ed root inside of batchedUpdates. The commit fired
1970+
// synchronously, but layout updates should be deferred until the end
1971+
// of the batch.
1972+
return null;
1973+
}
1974+
19211975
// If the passive effects are the result of a discrete render, flush them
19221976
// synchronously at the end of the current task so that the result is
19231977
// immediately observable. Otherwise, we assume that they are not

0 commit comments

Comments
 (0)