@@ -261,6 +261,7 @@ import {
261
261
suspendedThenableDidResolve ,
262
262
isTrackingSuspendedThenable ,
263
263
} from './ReactFiberWakeable.new' ;
264
+ import { schedulePostPaintCallback } from './ReactPostPaintCallback' ;
264
265
265
266
const ceil = Math . ceil ;
266
267
@@ -361,6 +362,7 @@ export function getWorkInProgressTransitions() {
361
362
}
362
363
363
364
let currentPendingTransitionCallbacks : PendingTransitionCallbacks | null = null ;
365
+ let currentEndTime : number | null = null ;
364
366
365
367
export function addTransitionStartCallbackToPendingTransition (
366
368
transition : Transition ,
@@ -2643,6 +2645,36 @@ function commitRootImpl(
2643
2645
markCommitStopped ( ) ;
2644
2646
}
2645
2647
2648
+ if ( enableTransitionTracing ) {
2649
+ // We process transitions during passive effects. However, passive effects can be
2650
+ // processed synchronously during the commit phase as well as asynchronously after
2651
+ // paint. At the end of the commit phase, we schedule a callback that will be called
2652
+ // after the next paint. If the transitions have already been processed (passive
2653
+ // effect phase happened synchronously), we will schedule a callback to process
2654
+ // the transitions. However, if we don't have any pending transition callbacks, this
2655
+ // means that the transitions have yet to be processed (passive effects processed after paint)
2656
+ // so we will store the end time of paint so that we can process the transitions
2657
+ // and then call the callback via the correct end time.
2658
+ const prevRootTransitionCallbacks = root . transitionCallbacks ;
2659
+ if ( prevRootTransitionCallbacks !== null ) {
2660
+ schedulePostPaintCallback ( endTime => {
2661
+ const prevPendingTransitionCallbacks = currentPendingTransitionCallbacks ;
2662
+ if ( prevPendingTransitionCallbacks !== null ) {
2663
+ currentPendingTransitionCallbacks = null ;
2664
+ scheduleCallback ( IdleSchedulerPriority , ( ) => {
2665
+ processTransitionCallbacks (
2666
+ prevPendingTransitionCallbacks ,
2667
+ endTime ,
2668
+ prevRootTransitionCallbacks ,
2669
+ ) ;
2670
+ } ) ;
2671
+ } else {
2672
+ currentEndTime = endTime ;
2673
+ }
2674
+ } ) ;
2675
+ }
2676
+ }
2677
+
2646
2678
return null ;
2647
2679
}
2648
2680
@@ -2784,28 +2816,21 @@ function flushPassiveEffectsImpl() {
2784
2816
if ( enableTransitionTracing ) {
2785
2817
const prevPendingTransitionCallbacks = currentPendingTransitionCallbacks ;
2786
2818
const prevRootTransitionCallbacks = root . transitionCallbacks ;
2819
+ const prevEndTime = currentEndTime ;
2787
2820
if (
2788
2821
prevPendingTransitionCallbacks !== null &&
2789
- prevRootTransitionCallbacks !== null
2822
+ prevRootTransitionCallbacks !== null &&
2823
+ prevEndTime !== null
2790
2824
) {
2791
- // TODO(luna) Refactor this code into the Host Config
2792
- // TODO(luna) The end time here is not necessarily accurate
2793
- // because passive effects could be called before paint
2794
- // (synchronously) or after paint (normally). We need
2795
- // to come up with a way to get the correct end time for both cases.
2796
- // One solution is in the host config, if the passive effects
2797
- // have not yet been run, make a call to flush the passive effects
2798
- // right after paint.
2799
- const endTime = now ( ) ;
2800
2825
currentPendingTransitionCallbacks = null ;
2801
-
2802
- scheduleCallback ( IdleSchedulerPriority , ( ) =>
2826
+ currentEndTime = null ;
2827
+ scheduleCallback ( IdleSchedulerPriority , ( ) => {
2803
2828
processTransitionCallbacks (
2804
2829
prevPendingTransitionCallbacks ,
2805
- endTime ,
2830
+ prevEndTime ,
2806
2831
prevRootTransitionCallbacks ,
2807
- ) ,
2808
- ) ;
2832
+ ) ;
2833
+ } ) ;
2809
2834
}
2810
2835
}
2811
2836
0 commit comments