@@ -261,6 +261,7 @@ import {
261261 suspendedThenableDidResolve ,
262262 isTrackingSuspendedThenable ,
263263} from './ReactFiberWakeable.new' ;
264+ import { schedulePostPaintCallback } from './ReactPostPaintCallback' ;
264265
265266const ceil = Math . ceil ;
266267
@@ -361,6 +362,7 @@ export function getWorkInProgressTransitions() {
361362}
362363
363364let currentPendingTransitionCallbacks : PendingTransitionCallbacks | null = null ;
365+ let currentEndTime : number | null = null ;
364366
365367export function addTransitionStartCallbackToPendingTransition (
366368 transition : Transition ,
@@ -2643,6 +2645,36 @@ function commitRootImpl(
26432645 markCommitStopped ( ) ;
26442646 }
26452647
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+
26462678 return null ;
26472679}
26482680
@@ -2784,28 +2816,21 @@ function flushPassiveEffectsImpl() {
27842816 if ( enableTransitionTracing ) {
27852817 const prevPendingTransitionCallbacks = currentPendingTransitionCallbacks ;
27862818 const prevRootTransitionCallbacks = root . transitionCallbacks ;
2819+ const prevEndTime = currentEndTime ;
27872820 if (
27882821 prevPendingTransitionCallbacks !== null &&
2789- prevRootTransitionCallbacks !== null
2822+ prevRootTransitionCallbacks !== null &&
2823+ prevEndTime !== null
27902824 ) {
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 ( ) ;
28002825 currentPendingTransitionCallbacks = null ;
2801-
2802- scheduleCallback ( IdleSchedulerPriority , ( ) =>
2826+ currentEndTime = null ;
2827+ scheduleCallback ( IdleSchedulerPriority , ( ) => {
28032828 processTransitionCallbacks (
28042829 prevPendingTransitionCallbacks ,
2805- endTime ,
2830+ prevEndTime ,
28062831 prevRootTransitionCallbacks ,
2807- ) ,
2808- ) ;
2832+ ) ;
2833+ } ) ;
28092834 }
28102835 }
28112836
0 commit comments