@@ -534,13 +534,13 @@ if (typeof window !== 'undefined' && window._schedMock) {
534534 }
535535 }
536536
537- var scheduledCallback = null ;
538- var isIdleScheduled = false ;
537+ var scheduledHostCallback = null ;
538+ var isMessageEventScheduled = false ;
539539 var timeoutTime = - 1 ;
540540
541541 var isAnimationFrameScheduled = false ;
542542
543- var isPerformingIdleWork = false ;
543+ var isFlushingHostCallback = false ;
544544
545545 var frameDeadline = 0 ;
546546 // We start out assuming that we run at 30fps but then the heuristic tracking
@@ -564,15 +564,20 @@ if (typeof window !== 'undefined' && window._schedMock) {
564564 return ;
565565 }
566566
567- isIdleScheduled = false ;
567+ isMessageEventScheduled = false ;
568+
569+ var prevScheduledCallback = scheduledHostCallback ;
570+ var prevTimeoutTime = timeoutTime ;
571+ scheduledHostCallback = null ;
572+ timeoutTime = - 1 ;
568573
569574 var currentTime = getCurrentTime ( ) ;
570575
571576 var didTimeout = false ;
572577 if ( frameDeadline - currentTime <= 0 ) {
573578 // There's no time left in this idle period. Check if the callback has
574579 // a timeout and whether it's been exceeded.
575- if ( timeoutTime !== - 1 && timeoutTime <= currentTime ) {
580+ if ( prevTimeoutTime !== - 1 && prevTimeoutTime <= currentTime ) {
576581 // Exceeded the timeout. Invoke the callback even though there's no
577582 // time left.
578583 didTimeout = true ;
@@ -584,19 +589,18 @@ if (typeof window !== 'undefined' && window._schedMock) {
584589 requestAnimationFrameWithTimeout ( animationTick ) ;
585590 }
586591 // Exit without invoking the callback.
592+ scheduledHostCallback = prevScheduledCallback ;
593+ timeoutTime = prevTimeoutTime ;
587594 return ;
588595 }
589596 }
590597
591- timeoutTime = - 1 ;
592- var callback = scheduledCallback ;
593- scheduledCallback = null ;
594- if ( callback !== null ) {
595- isPerformingIdleWork = true ;
598+ if ( prevScheduledCallback !== null ) {
599+ isFlushingHostCallback = true ;
596600 try {
597- callback ( didTimeout ) ;
601+ prevScheduledCallback ( didTimeout ) ;
598602 } finally {
599- isPerformingIdleWork = false ;
603+ isFlushingHostCallback = false ;
600604 }
601605 }
602606 } ;
@@ -605,7 +609,22 @@ if (typeof window !== 'undefined' && window._schedMock) {
605609 window . addEventListener ( 'message' , idleTick , false ) ;
606610
607611 var animationTick = function ( rafTime ) {
608- isAnimationFrameScheduled = false ;
612+ if ( scheduledHostCallback !== null ) {
613+ // Eagerly schedule the next animation callback at the beginning of the
614+ // frame. If the scheduler queue is not empty at the end of the frame, it
615+ // will continue flushing inside that callback. If the queue *is* empty,
616+ // then it will exit immediately. Posting the callback at the start of the
617+ // frame ensures it's fired within the earliest possible frame. If we
618+ // waited until the end of the frame to post the callback, we risk the
619+ // browser skipping a frame and not firing the callback until the frame
620+ // after that.
621+ requestAnimationFrameWithTimeout ( animationTick ) ;
622+ } else {
623+ // No pending work. Exit.
624+ isAnimationFrameScheduled = false ;
625+ return ;
626+ }
627+
609628 var nextFrameTime = rafTime - frameDeadline + activeFrameTime ;
610629 if (
611630 nextFrameTime < activeFrameTime &&
@@ -629,16 +648,16 @@ if (typeof window !== 'undefined' && window._schedMock) {
629648 previousFrameTime = nextFrameTime ;
630649 }
631650 frameDeadline = rafTime + activeFrameTime ;
632- if ( ! isIdleScheduled ) {
633- isIdleScheduled = true ;
651+ if ( ! isMessageEventScheduled ) {
652+ isMessageEventScheduled = true ;
634653 window . postMessage ( messageKey , '*' ) ;
635654 }
636655 } ;
637656
638657 requestHostCallback = function ( callback , absoluteTimeout ) {
639- scheduledCallback = callback ;
658+ scheduledHostCallback = callback ;
640659 timeoutTime = absoluteTimeout ;
641- if ( isPerformingIdleWork || absoluteTimeout < 0 ) {
660+ if ( isFlushingHostCallback || absoluteTimeout < 0 ) {
642661 // Don't wait for the next frame. Continue working ASAP, in a new event.
643662 window . postMessage ( messageKey , '*' ) ;
644663 } else if ( ! isAnimationFrameScheduled ) {
@@ -652,8 +671,8 @@ if (typeof window !== 'undefined' && window._schedMock) {
652671 } ;
653672
654673 cancelHostCallback = function ( ) {
655- scheduledCallback = null ;
656- isIdleScheduled = false ;
674+ scheduledHostCallback = null ;
675+ isMessageEventScheduled = false ;
657676 timeoutTime = - 1 ;
658677 } ;
659678}
0 commit comments