Skip to content

Commit 9d756d9

Browse files
authored
Revert #14756 changes to ReactFiberScheduler (#14992)
* Revert #14756 changes to ReactFiberScheduler This PR introduced some bugs in concurrent mode during internal testing. Until we figure out a proper solution, I'm going to try reverting it. Not totally certain this is sufficient to unbreak the bugs we found, but I'm using this branch to determine that. * Add back commented out Scheduler import With a note not to use named imports next time we import Scheduler in this module.
1 parent f16442a commit 9d756d9

File tree

1 file changed

+81
-72
lines changed

1 file changed

+81
-72
lines changed

packages/react-reconciler/src/ReactFiberScheduler.js

Lines changed: 81 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,16 @@ import type {Batch, FiberRoot} from './ReactFiberRoot';
1212
import type {ExpirationTime} from './ReactFiberExpirationTime';
1313
import type {Interaction} from 'scheduler/src/Tracing';
1414

15+
// Intentionally not named imports because Rollup would use dynamic dispatch for
16+
// CommonJS interop named imports.
17+
// TODO: We're not using this import anymore, but I've left this here so we
18+
// don't accidentally use named imports when we add it back.
19+
// import * as Scheduler from 'scheduler';
1520
import {
1621
__interactionsRef,
1722
__subscriberRef,
1823
unstable_wrap as Scheduler_tracing_wrap,
1924
} from 'scheduler/tracing';
20-
import * as Scheduler from 'scheduler';
2125
import {
2226
invokeGuardedCallback,
2327
hasCaughtError,
@@ -126,7 +130,7 @@ import {
126130
computeAsyncExpiration,
127131
computeInteractiveExpiration,
128132
} from './ReactFiberExpirationTime';
129-
import {ConcurrentMode, ProfileMode, NoContext} from './ReactTypeOfMode';
133+
import {ConcurrentMode, ProfileMode} from './ReactTypeOfMode';
130134
import {enqueueUpdate, resetCurrentlyProcessingQueue} from './ReactUpdateQueue';
131135
import {createCapturedValue} from './ReactCapturedValue';
132136
import {
@@ -172,19 +176,6 @@ export type Thenable = {
172176
then(resolve: () => mixed, reject?: () => mixed): mixed,
173177
};
174178

175-
// Intentionally not named imports because Rollup would
176-
// use dynamic dispatch for CommonJS interop named imports.
177-
const {
178-
unstable_next: Scheduler_next,
179-
unstable_getCurrentPriorityLevel: getCurrentPriorityLevel,
180-
unstable_runWithPriority: runWithPriority,
181-
unstable_ImmediatePriority: ImmediatePriority,
182-
unstable_UserBlockingPriority: UserBlockingPriority,
183-
unstable_NormalPriority: NormalPriority,
184-
unstable_LowPriority: LowPriority,
185-
unstable_IdlePriority: IdlePriority,
186-
} = Scheduler;
187-
188179
const {ReactCurrentDispatcher, ReactCurrentOwner} = ReactSharedInternals;
189180

190181
let didWarnAboutStateTransition;
@@ -259,6 +250,11 @@ if (__DEV__) {
259250
// Used to ensure computeUniqueAsyncExpiration is monotonically decreasing.
260251
let lastUniqueAsyncExpiration: number = Sync - 1;
261252

253+
// Represents the expiration time that incoming updates should use. (If this
254+
// is NoWork, use the default strategy: async updates in async mode, sync
255+
// updates in sync mode.)
256+
let expirationContext: ExpirationTime = NoWork;
257+
262258
let isWorking: boolean = false;
263259

264260
// The next work in progress fiber that we're currently working on.
@@ -811,9 +807,7 @@ function commitRoot(root: FiberRoot, finishedWork: Fiber): void {
811807
// here because that code is still in flux.
812808
callback = Scheduler_tracing_wrap(callback);
813809
}
814-
passiveEffectCallbackHandle = runWithPriority(NormalPriority, () => {
815-
return schedulePassiveEffects(callback);
816-
});
810+
passiveEffectCallbackHandle = schedulePassiveEffects(callback);
817811
passiveEffectCallback = callback;
818812
}
819813

@@ -1597,58 +1591,52 @@ function computeUniqueAsyncExpiration(): ExpirationTime {
15971591
}
15981592

15991593
function computeExpirationForFiber(currentTime: ExpirationTime, fiber: Fiber) {
1600-
const priorityLevel = getCurrentPriorityLevel();
1601-
16021594
let expirationTime;
1603-
if ((fiber.mode & ConcurrentMode) === NoContext) {
1604-
// Outside of concurrent mode, updates are always synchronous.
1605-
expirationTime = Sync;
1606-
} else if (isWorking && !isCommitting) {
1607-
// During render phase, updates expire during as the current render.
1608-
expirationTime = nextRenderExpirationTime;
1595+
if (expirationContext !== NoWork) {
1596+
// An explicit expiration context was set;
1597+
expirationTime = expirationContext;
1598+
} else if (isWorking) {
1599+
if (isCommitting) {
1600+
// Updates that occur during the commit phase should have sync priority
1601+
// by default.
1602+
expirationTime = Sync;
1603+
} else {
1604+
// Updates during the render phase should expire at the same time as
1605+
// the work that is being rendered.
1606+
expirationTime = nextRenderExpirationTime;
1607+
}
16091608
} else {
1610-
switch (priorityLevel) {
1611-
case ImmediatePriority:
1612-
expirationTime = Sync;
1613-
break;
1614-
case UserBlockingPriority:
1609+
// No explicit expiration context was set, and we're not currently
1610+
// performing work. Calculate a new expiration time.
1611+
if (fiber.mode & ConcurrentMode) {
1612+
if (isBatchingInteractiveUpdates) {
1613+
// This is an interactive update
16151614
expirationTime = computeInteractiveExpiration(currentTime);
1616-
break;
1617-
case NormalPriority:
1618-
// This is a normal, concurrent update
1615+
} else {
1616+
// This is an async update
16191617
expirationTime = computeAsyncExpiration(currentTime);
1620-
break;
1621-
case LowPriority:
1622-
case IdlePriority:
1623-
expirationTime = Never;
1624-
break;
1625-
default:
1626-
invariant(
1627-
false,
1628-
'Unknown priority level. This error is likely caused by a bug in ' +
1629-
'React. Please file an issue.',
1630-
);
1631-
}
1632-
1633-
// If we're in the middle of rendering a tree, do not update at the same
1634-
// expiration time that is already rendering.
1635-
if (nextRoot !== null && expirationTime === nextRenderExpirationTime) {
1636-
expirationTime -= 1;
1618+
}
1619+
// If we're in the middle of rendering a tree, do not update at the same
1620+
// expiration time that is already rendering.
1621+
if (nextRoot !== null && expirationTime === nextRenderExpirationTime) {
1622+
expirationTime -= 1;
1623+
}
1624+
} else {
1625+
// This is a sync update
1626+
expirationTime = Sync;
16371627
}
16381628
}
1639-
1640-
// Keep track of the lowest pending interactive expiration time. This
1641-
// allows us to synchronously flush all interactive updates
1642-
// when needed.
1643-
// TODO: Move this to renderer?
1644-
if (
1645-
priorityLevel === UserBlockingPriority &&
1646-
(lowestPriorityPendingInteractiveExpirationTime === NoWork ||
1647-
expirationTime < lowestPriorityPendingInteractiveExpirationTime)
1648-
) {
1649-
lowestPriorityPendingInteractiveExpirationTime = expirationTime;
1629+
if (isBatchingInteractiveUpdates) {
1630+
// This is an interactive update. Keep track of the lowest pending
1631+
// interactive expiration time. This allows us to synchronously flush
1632+
// all interactive updates when needed.
1633+
if (
1634+
lowestPriorityPendingInteractiveExpirationTime === NoWork ||
1635+
expirationTime < lowestPriorityPendingInteractiveExpirationTime
1636+
) {
1637+
lowestPriorityPendingInteractiveExpirationTime = expirationTime;
1638+
}
16501639
}
1651-
16521640
return expirationTime;
16531641
}
16541642

@@ -1909,16 +1897,34 @@ function scheduleWork(fiber: Fiber, expirationTime: ExpirationTime) {
19091897
}
19101898
}
19111899

1900+
function deferredUpdates<A>(fn: () => A): A {
1901+
const currentTime = requestCurrentTime();
1902+
const previousExpirationContext = expirationContext;
1903+
const previousIsBatchingInteractiveUpdates = isBatchingInteractiveUpdates;
1904+
expirationContext = computeAsyncExpiration(currentTime);
1905+
isBatchingInteractiveUpdates = false;
1906+
try {
1907+
return fn();
1908+
} finally {
1909+
expirationContext = previousExpirationContext;
1910+
isBatchingInteractiveUpdates = previousIsBatchingInteractiveUpdates;
1911+
}
1912+
}
1913+
19121914
function syncUpdates<A, B, C0, D, R>(
19131915
fn: (A, B, C0, D) => R,
19141916
a: A,
19151917
b: B,
19161918
c: C0,
19171919
d: D,
19181920
): R {
1919-
return runWithPriority(ImmediatePriority, () => {
1921+
const previousExpirationContext = expirationContext;
1922+
expirationContext = Sync;
1923+
try {
19201924
return fn(a, b, c, d);
1921-
});
1925+
} finally {
1926+
expirationContext = previousExpirationContext;
1927+
}
19221928
}
19231929

19241930
// TODO: Everything below this is written as if it has been lifted to the
@@ -1939,6 +1945,7 @@ let unhandledError: mixed | null = null;
19391945

19401946
let isBatchingUpdates: boolean = false;
19411947
let isUnbatchingUpdates: boolean = false;
1948+
let isBatchingInteractiveUpdates: boolean = false;
19421949

19431950
let completedBatches: Array<Batch> | null = null;
19441951

@@ -2450,9 +2457,7 @@ function completeRoot(
24502457
lastCommittedRootDuringThisBatch = root;
24512458
nestedUpdateCount = 0;
24522459
}
2453-
runWithPriority(ImmediatePriority, () => {
2454-
commitRoot(root, finishedWork);
2455-
});
2460+
commitRoot(root, finishedWork);
24562461
}
24572462

24582463
function onUncaughtError(error: mixed) {
@@ -2518,6 +2523,9 @@ function flushSync<A, R>(fn: (a: A) => R, a: A): R {
25182523
}
25192524

25202525
function interactiveUpdates<A, B, R>(fn: (A, B) => R, a: A, b: B): R {
2526+
if (isBatchingInteractiveUpdates) {
2527+
return fn(a, b);
2528+
}
25212529
// If there are any pending interactive updates, synchronously flush them.
25222530
// This needs to happen before we read any handlers, because the effect of
25232531
// the previous event may influence which handlers are called during
@@ -2531,13 +2539,14 @@ function interactiveUpdates<A, B, R>(fn: (A, B) => R, a: A, b: B): R {
25312539
performWork(lowestPriorityPendingInteractiveExpirationTime, false);
25322540
lowestPriorityPendingInteractiveExpirationTime = NoWork;
25332541
}
2542+
const previousIsBatchingInteractiveUpdates = isBatchingInteractiveUpdates;
25342543
const previousIsBatchingUpdates = isBatchingUpdates;
2544+
isBatchingInteractiveUpdates = true;
25352545
isBatchingUpdates = true;
25362546
try {
2537-
return runWithPriority(UserBlockingPriority, () => {
2538-
return fn(a, b);
2539-
});
2547+
return fn(a, b);
25402548
} finally {
2549+
isBatchingInteractiveUpdates = previousIsBatchingInteractiveUpdates;
25412550
isBatchingUpdates = previousIsBatchingUpdates;
25422551
if (!isBatchingUpdates && !isRendering) {
25432552
performSyncWork();
@@ -2588,7 +2597,7 @@ export {
25882597
unbatchedUpdates,
25892598
flushSync,
25902599
flushControlled,
2591-
Scheduler_next as deferredUpdates,
2600+
deferredUpdates,
25922601
syncUpdates,
25932602
interactiveUpdates,
25942603
flushInteractiveUpdates,

0 commit comments

Comments
 (0)