@@ -83,6 +83,7 @@ import {
8383 supportsMicrotasks ,
8484 errorHydratingContainer ,
8585 scheduleMicrotask ,
86+ requestPostPaintCallback ,
8687} from './ReactFiberHostConfig' ;
8788
8889import {
@@ -360,6 +361,7 @@ export function getWorkInProgressTransitions() {
360361}
361362
362363let currentPendingTransitionCallbacks : PendingTransitionCallbacks | null = null ;
364+ let currentEndTime : number | null = null ;
363365
364366export function addTransitionStartCallbackToPendingTransition (
365367 transition : Transition ,
@@ -2639,6 +2641,36 @@ function commitRootImpl(
26392641 markCommitStopped ( ) ;
26402642 }
26412643
2644+ if ( enableTransitionTracing ) {
2645+ // We process transitions during passive effects. However, passive effects can be
2646+ // processed synchronously during the commit phase as well as asynchronously after
2647+ // paint. At the end of the commit phase, we schedule a callback that will be called
2648+ // after the next paint. If the transitions have already been processed (passive
2649+ // effect phase happened synchronously), we will schedule a callback to process
2650+ // the transitions. However, if we don't have any pending transition callbacks, this
2651+ // means that the transitions have yet to be processed (passive effects processed after paint)
2652+ // so we will store the end time of paint so that we can process the transitions
2653+ // and then call the callback via the correct end time.
2654+ const prevRootTransitionCallbacks = root . transitionCallbacks ;
2655+ if ( prevRootTransitionCallbacks !== null ) {
2656+ requestPostPaintCallback ( endTime => {
2657+ const prevPendingTransitionCallbacks = currentPendingTransitionCallbacks ;
2658+ if ( prevPendingTransitionCallbacks !== null ) {
2659+ currentPendingTransitionCallbacks = null ;
2660+ scheduleCallback ( IdleSchedulerPriority , ( ) => {
2661+ processTransitionCallbacks (
2662+ prevPendingTransitionCallbacks ,
2663+ endTime ,
2664+ prevRootTransitionCallbacks ,
2665+ ) ;
2666+ } ) ;
2667+ } else {
2668+ currentEndTime = endTime ;
2669+ }
2670+ } ) ;
2671+ }
2672+ }
2673+
26422674 return null ;
26432675}
26442676
@@ -2780,28 +2812,21 @@ function flushPassiveEffectsImpl() {
27802812 if ( enableTransitionTracing ) {
27812813 const prevPendingTransitionCallbacks = currentPendingTransitionCallbacks ;
27822814 const prevRootTransitionCallbacks = root . transitionCallbacks ;
2815+ const prevEndTime = currentEndTime ;
27832816 if (
27842817 prevPendingTransitionCallbacks !== null &&
2785- prevRootTransitionCallbacks !== null
2818+ prevRootTransitionCallbacks !== null &&
2819+ prevEndTime !== null
27862820 ) {
2787- // TODO(luna) Refactor this code into the Host Config
2788- // TODO(luna) The end time here is not necessarily accurate
2789- // because passive effects could be called before paint
2790- // (synchronously) or after paint (normally). We need
2791- // to come up with a way to get the correct end time for both cases.
2792- // One solution is in the host config, if the passive effects
2793- // have not yet been run, make a call to flush the passive effects
2794- // right after paint.
2795- const endTime = now ( ) ;
27962821 currentPendingTransitionCallbacks = null ;
2797-
2798- scheduleCallback ( IdleSchedulerPriority , ( ) =>
2822+ currentEndTime = null ;
2823+ scheduleCallback ( IdleSchedulerPriority , ( ) => {
27992824 processTransitionCallbacks (
28002825 prevPendingTransitionCallbacks ,
2801- endTime ,
2826+ prevEndTime ,
28022827 prevRootTransitionCallbacks ,
2803- ) ,
2804- ) ;
2828+ ) ;
2829+ } ) ;
28052830 }
28062831 }
28072832
0 commit comments