41
NormalPriority,
42
LowPriority,
43
IdlePriority,
44
- flushImmediateQueue,
44
+ flushSyncCallbackQueue,
45
+ scheduleSyncCallback,
46
} from './SchedulerWithReactIntegration';
47
48
import {__interactionsRef, __subscriberRef} from 'scheduler/tracing';
56
} from './ReactFiberHostConfig';
57
58
import {createWorkInProgress, assignFiberPropertiesInDEV} from './ReactFiber';
58
-import {NoContext, ConcurrentMode, ProfileMode} from './ReactTypeOfMode';
59
+import {
60
+ NoMode,
61
+ ProfileMode,
62
+ BatchedMode,
63
+ ConcurrentMode,
64
+} from './ReactTypeOfMode';
65
import {
66
HostRoot,
67
ClassComponent,
97
computeAsyncExpiration,
98
inferPriorityFromExpirationTime,
99
LOW_PRIORITY_EXPIRATION,
100
+ Batched,
101
} from './ReactFiberExpirationTime';
102
import {beginWork as originalBeginWork} from './ReactFiberBeginWork';
103
import {completeWork} from './ReactFiberCompleteWork';
262
currentTime: ExpirationTime,
263
fiber: Fiber,
264
): ExpirationTime {
258
- if ((fiber.mode & ConcurrentMode) === NoContext) {
265
+ const mode = fiber.mode;
266
+ if ((mode & BatchedMode) === NoMode) {
267
return Sync;
268
}
269
270
+ const priorityLevel = getCurrentPriorityLevel();
271
+ if ((mode & ConcurrentMode) === NoMode) {
272
+ return priorityLevel === ImmediatePriority ? Sync : Batched;
273
+ }
274
+
275
if (workPhase === RenderPhase) {
276
// Use whatever time we're already rendering
277
return renderExpirationTime;
279
280
// Compute an expiration time based on the Scheduler priority.
281
let expirationTime;
269
- const priorityLevel = getCurrentPriorityLevel();
282
switch (priorityLevel) {
283
case ImmediatePriority:
284
expirationTime = Sync;
361
// scheduleCallbackForFiber to preserve the ability to schedule a callback
362
// without immediately flushing it. We only do this for user-initated
363
// updates, to preserve historical behavior of sync mode.
352
- flushImmediateQueue();
364
+ flushSyncCallbackQueue();
365
}
366
}
367
} else {
468
}
469
root.callbackExpirationTime = expirationTime;
470
459
- let options = null;
460
- if (expirationTime !== Sync && expirationTime !== Never) {
461
- let timeout = expirationTimeToMs(expirationTime) - now();
462
- if (timeout > 5000) {
463
- // Sanity check. Should never take longer than 5 seconds.
464
- // TODO: Add internal warning?
465
- timeout = 5000;
471
+ if (expirationTime === Sync) {
472
+ // Sync React callbacks are scheduled on a special internal queue
473
+ root.callbackNode = scheduleSyncCallback(
474
+ runRootCallback.bind(
475
+ null,
476
+ root,
477
+ renderRoot.bind(null, root, expirationTime),
478
+ ),
479
+ );
480
+ } else {
481
+ let options = null;
482
+ if (expirationTime !== Sync && expirationTime !== Never) {
483
+ let timeout = expirationTimeToMs(expirationTime) - now();
484
+ if (timeout > 5000) {
485
+ // Sanity check. Should never take longer than 5 seconds.
486
+ // TODO: Add internal warning?
487
+ timeout = 5000;
488
+ }
489
+ options = {timeout};
490
}
467
- options = {timeout};
468
- }
491
470
- root.callbackNode = scheduleCallback(
471
- priorityLevel,
472
- runRootCallback.bind(
473
- null,
474
- root,
475
- renderRoot.bind(null, root, expirationTime),
476
- ),
477
- options,
478
- );
479
- if (
480
- enableUserTimingAPI &&
481
- expirationTime !== Sync &&
482
- workPhase !== RenderPhase &&
483
- workPhase !== CommitPhase
484
- ) {
485
- // Scheduled an async callback, and we're not already working. Add an
486
- // entry to the flamegraph that shows we're waiting for a callback
487
- // to fire.
488
- startRequestCallbackTimer();
492
+ root.callbackNode = scheduleCallback(
493
+ priorityLevel,
494
+ runRootCallback.bind(
495
+ null,
496
+ root,
497
+ renderRoot.bind(null, root, expirationTime),
498
+ ),
499
+ options,
500
+ );
501
+ if (
502
+ enableUserTimingAPI &&
503
+ expirationTime !== Sync &&
504
+ workPhase !== RenderPhase &&
505
+ workPhase !== CommitPhase
506
+ ) {
507
+ // Scheduled an async callback, and we're not already working. Add an
508
+ // entry to the flamegraph that shows we're waiting for a callback
509
+ // to fire.
510
+ startRequestCallbackTimer();
511
+ }
512
}
513
}
514
547
'means you attempted to commit from inside a lifecycle method.',
548
);
549
}
527
- scheduleCallback(
528
- ImmediatePriority,
529
- renderRoot.bind(null, root, expirationTime),
530
- );
531
- flushImmediateQueue();
550
+ scheduleSyncCallback(renderRoot.bind(null, root, expirationTime));
551
+ flushSyncCallbackQueue();
552
}
553
554
export function flushInteractiveUpdates() {
616
const roots = rootsWithPendingDiscreteUpdates;
617
rootsWithPendingDiscreteUpdates = null;
618
roots.forEach((expirationTime, root) => {
599
- scheduleCallback(
600
- ImmediatePriority,
601
- renderRoot.bind(null, root, expirationTime),
602
- );
619
+ scheduleSyncCallback(renderRoot.bind(null, root, expirationTime));
620
});
621
// Now flush the immediate queue.
605
- flushImmediateQueue();
622
+ flushSyncCallbackQueue();
623
}
624
}
625
634
} finally {
635
workPhase = NotWorking;
636
// Flush the immediate callbacks that were scheduled during this batch
620
- flushImmediateQueue();
637
+ flushSyncCallbackQueue();
638
}
639
}
640
670
// Flush the immediate callbacks that were scheduled during this batch.
671
// Note that this will happen even if batchedUpdates is higher up
672
// the stack.
656
- flushImmediateQueue();
673
+ flushSyncCallbackQueue();
674
}
675
}
676
683
workPhase = prevWorkPhase;
684
if (workPhase === NotWorking) {
685
// Flush the immediate callbacks that were scheduled during this batch
669
- flushImmediateQueue();
686
+ flushSyncCallbackQueue();
687
}
688
}
689
}
900
// caused by tearing due to a mutation during an event. Try rendering
901
// one more time without yiedling to events.
902
prepareFreshStack(root, expirationTime);
886
- scheduleCallback(
887
- ImmediatePriority,
888
- renderRoot.bind(null, root, expirationTime),
889
- );
903
+ scheduleSyncCallback(renderRoot.bind(null, root, expirationTime));
904
return null;
905
}
906
// If we're already rendering synchronously, commit the root in its
1004
setCurrentDebugFiberInDEV(unitOfWork);
1005
1006
let next;
993
- if (enableProfilerTimer && (unitOfWork.mode & ProfileMode) !== NoContext) {
1007
+ if (enableProfilerTimer && (unitOfWork.mode & ProfileMode) !== NoMode) {
1008
startProfilerTimer(unitOfWork);
1009
next = beginWork(current, unitOfWork, renderExpirationTime);
1010
stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true);
1040
let next;
1041
if (
1042
!enableProfilerTimer ||
1029
- (workInProgress.mode & ProfileMode) === NoContext
1043
+ (workInProgress.mode & ProfileMode) === NoMode
1044
) {
1045
next = completeWork(current, workInProgress, renderExpirationTime);
1046
} else {
1106
1107
if (
1108
enableProfilerTimer &&
1095
- (workInProgress.mode & ProfileMode) !== NoContext
1109
+ (workInProgress.mode & ProfileMode) !== NoMode
1110
) {
1111
// Record the render duration for the fiber that errored.
1112
stopProfilerTimerIfRunningAndRecordDelta(workInProgress, false);
1170
let newChildExpirationTime = NoWork;
1171
1172
// Bubble up the earliest expiration time.
1159
- if (enableProfilerTimer && (completedWork.mode & ProfileMode) !== NoContext) {
1173
+ if (enableProfilerTimer && (completedWork.mode & ProfileMode) !== NoMode) {
1174
// In profiling mode, resetChildExpirationTime is also used to reset
1175
// profiler durations.
1176
let actualDuration = completedWork.actualDuration;
1501
}
1502
1503
// If layout work was scheduled, flush it now.
1490
- flushImmediateQueue();
1504
+ flushSyncCallbackQueue();
1505
return null;
1506
}
1507
1672
}
1673
1674
workPhase = prevWorkPhase;
1661
- flushImmediateQueue();
1675
+ flushSyncCallbackQueue();
1676
1677
// If additional passive effects were scheduled, increment a counter. If this
1678
// exceeds the limit, we'll fire a warning.