15
import type {Flags} from './ReactFiberFlags';
16
import type {FunctionComponentUpdateQueue} from './ReactFiberHooks.new';
17
import type {EventPriority} from './ReactEventPriorities.new';
18
+import type {
19
+ PendingTransitionCallbacks,
20
+ TransitionObject,
21
+ Transitions,
22
+} from './ReactFiberTracingMarkerComponent.new';
23
24
import {
25
warnAboutDeprecatedLifecycles,
37
enableStrictEffects,
38
enableUpdaterTracking,
39
enableCache,
40
+ enableTransitionTracing,
41
} from 'shared/ReactFeatureFlags';
42
import ReactSharedInternals from 'shared/ReactSharedInternals';
43
import is from 'shared/objectIs';
144
getHighestPriorityLane,
145
addFiberToLanesMap,
146
movePendingFibersToMemoized,
147
+ addTransitionToLanesMap,
148
+ getTransitionsForLanes,
149
} from './ReactFiberLane.new';
150
import {
151
DiscreteEventPriority,
239
isLegacyActEnvironment,
240
isConcurrentActEnvironment,
241
} from './ReactFiberAct.new';
242
+import {processTransitionCallbacks} from './ReactFiberTracingMarkerComponent.new';
243
244
const ceil = Math.ceil;
245
322
// suspense heuristics and opt out of rendering more content.
323
const RENDER_TIMEOUT_MS = 500;
324
325
+let workInProgressTransitions: Transitions | null = null;
326
+export function getWorkInProgressTransitions() {
327
+ return workInProgressTransitions;
328
+}
329
+
330
+let currentPendingTransitionCallbacks: PendingTransitionCallbacks | null = null;
331
+
332
+export function addTransitionStartCallbackToPendingTransition(
333
+ transition: TransitionObject,
334
+) {
335
+ if (enableTransitionTracing) {
336
+ if (currentPendingTransitionCallbacks === null) {
337
+ currentPendingTransitionCallbacks = {
338
+ transitionStart: [],
339
+ transitionComplete: null,
340
+ };
341
+ }
342
+
343
+ if (currentPendingTransitionCallbacks.transitionStart === null) {
344
+ currentPendingTransitionCallbacks.transitionStart = [];
345
+ }
346
+
347
+ currentPendingTransitionCallbacks.transitionStart.push(transition);
348
+ }
349
+}
350
+
351
+export function addTransitionCompleteCallbackToPendingTransition(
352
+ transition: TransitionObject,
353
+) {
354
+ if (enableTransitionTracing) {
355
+ if (currentPendingTransitionCallbacks === null) {
356
+ currentPendingTransitionCallbacks = {
357
+ transitionStart: null,
358
+ transitionComplete: [],
359
+ };
360
+ }
361
+
362
+ if (currentPendingTransitionCallbacks.transitionComplete === null) {
363
+ currentPendingTransitionCallbacks.transitionComplete = [];
364
+ }
365
+
366
+ currentPendingTransitionCallbacks.transitionComplete.push(transition);
367
+ }
368
+}
369
+
370
function resetRenderTimer() {
371
workInProgressRootRenderTargetTime = now() + RENDER_TIMEOUT_MS;
372
}
569
}
570
}
571
572
+ if (enableTransitionTracing) {
573
+ const transition = ReactCurrentBatchConfig.transition;
574
+ if (transition !== null) {
575
+ if (transition.startTime === -1) {
576
+ transition.startTime = now();
577
+ }
578
+
579
+ addTransitionToLanesMap(root, transition, lane);
580
+ }
581
+ }
582
+
583
if (root.isDehydrated && root.tag !== LegacyRoot) {
584
// This root's shell hasn't hydrated yet. Revert to client rendering.
585
if (workInProgressRoot === root) {
1309
export function deferredUpdates<A>(fn: () => A): A {
1310
const previousPriority = getCurrentUpdatePriority();
1311
const prevTransition = ReactCurrentBatchConfig.transition;
1312
+
1313
try {
1314
ReactCurrentBatchConfig.transition = null;
1315
setCurrentUpdatePriority(DefaultEventPriority);
1384
1385
const prevTransition = ReactCurrentBatchConfig.transition;
1386
const previousPriority = getCurrentUpdatePriority();
1387
+
1388
try {
1389
ReactCurrentBatchConfig.transition = null;
1390
setCurrentUpdatePriority(DiscreteEventPriority);
1396
} finally {
1397
setCurrentUpdatePriority(previousPriority);
1398
ReactCurrentBatchConfig.transition = prevTransition;
1399
+
1400
executionContext = prevExecutionContext;
1401
// Flush the immediate callbacks that were scheduled during this batch.
1402
// Note that this will happen even if batchedUpdates is higher up
1685
}
1686
}
1687
1688
+ workInProgressTransitions = getTransitionsForLanes(root, lanes);
1689
prepareFreshStack(root, lanes);
1690
}
1691
1770
}
1771
}
1772
1773
+ workInProgressTransitions = getTransitionsForLanes(root, lanes);
1774
resetRenderTimer();
1775
prepareFreshStack(root, lanes);
1776
}
1966
// layout phases. Should be able to remove.
1967
const previousUpdateLanePriority = getCurrentUpdatePriority();
1968
const prevTransition = ReactCurrentBatchConfig.transition;
1969
+
1970
try {
1971
ReactCurrentBatchConfig.transition = null;
1972
setCurrentUpdatePriority(DiscreteEventPriority);
2308
// If layout work was scheduled, flush it now.
2309
flushSyncCallbacks();
2310
2311
+ if (enableTransitionTracing) {
2312
+ const prevPendingTransitionCallbacks = currentPendingTransitionCallbacks;
2313
+ const prevRootTransitionCallbacks = root.transitionCallbacks;
2314
+ if (
2315
+ prevPendingTransitionCallbacks !== null &&
2316
+ prevRootTransitionCallbacks !== null
2317
+ ) {
2318
+ // TODO(luna) Refactor this code into the Host Config
2319
+ const endTime = now();
2320
+ currentPendingTransitionCallbacks = null;
2321
+
2322
+ scheduleCallback(IdleSchedulerPriority, () =>
2323
+ processTransitionCallbacks(
2324
+ prevPendingTransitionCallbacks,
2325
+ endTime,
2326
+ prevRootTransitionCallbacks,
2327
+ ),
2328
+ );
2329
+ }
2330
+ }
2331
+
2332
if (__DEV__) {
2333
if (enableDebugTracing) {
2334
logCommitStopped();
2378
const priority = lowerEventPriority(DefaultEventPriority, renderPriority);
2379
const prevTransition = ReactCurrentBatchConfig.transition;
2380
const previousPriority = getCurrentUpdatePriority();
2381
+
2382
try {
2383
ReactCurrentBatchConfig.transition = null;
2384
setCurrentUpdatePriority(priority);