@@ -33,6 +33,7 @@ import {getCurrentRootHostContainer} from 'react-reconciler/src/ReactFiberHostCo
33
33
import { DefaultEventPriority } from 'react-reconciler/src/ReactEventPriorities' ;
34
34
// TODO: Remove this deep import when we delete the legacy root API
35
35
import { ConcurrentMode , NoMode } from 'react-reconciler/src/ReactTypeOfMode' ;
36
+ import * as Scheduler from 'scheduler' ;
36
37
37
38
import hasOwnProperty from 'shared/hasOwnProperty' ;
38
39
import { checkAttributeStringCoercion } from 'shared/CheckStringCoercion' ;
@@ -623,6 +624,11 @@ const localRequestAnimationFrame =
623
624
typeof requestAnimationFrame === 'function'
624
625
? requestAnimationFrame
625
626
: scheduleTimeout ;
627
+ const localCancelAnimationFrame =
628
+ typeof window !== 'undefined' &&
629
+ typeof window . cancelAnimationFrame === 'function'
630
+ ? window . cancelAnimationFrame
631
+ : cancelTimeout ;
626
632
627
633
export function getInstanceFromNode ( node : HTMLElement ) : null | Object {
628
634
return getClosestInstanceFromNode ( node ) || null ;
@@ -668,6 +674,68 @@ function handleErrorInNextTick(error: any) {
668
674
} ) ;
669
675
}
670
676
677
+ // -------------------
678
+ // Animation Frame
679
+ // -------------------
680
+ export const supportsFrameAlignedTask = true ;
681
+
682
+ type FrameAlignedTask = { |
683
+ rafNode : AnimationFrameID ,
684
+ schedulerNode : number | null ,
685
+ task : Function ,
686
+ | } ;
687
+
688
+ let currentTask : FrameAlignedTask | null = null ;
689
+ function performFrameAlignedWork ( ) {
690
+ if ( currentTask != null ) {
691
+ const currentTaskForFlow = currentTask ;
692
+ const task = currentTask . task ;
693
+ localCancelAnimationFrame ( currentTaskForFlow . rafNode ) ;
694
+ if ( currentTaskForFlow . schedulerNode !== null ) {
695
+ Scheduler . unstable_cancelCallback ( currentTaskForFlow . schedulerNode ) ;
696
+ }
697
+ currentTask = null ;
698
+ if ( task != null ) {
699
+ task ( ) ;
700
+ }
701
+ }
702
+ }
703
+
704
+ export function scheduleFrameAlignedTask ( task : any ) : any {
705
+ if ( currentTask === null ) {
706
+ const rafNode = localRequestAnimationFrame ( performFrameAlignedWork ) ;
707
+
708
+ const schedulerNode = Scheduler . unstable_scheduleCallback (
709
+ Scheduler . unstable_NormalPriority ,
710
+ performFrameAlignedWork ,
711
+ ) ;
712
+
713
+ currentTask = {
714
+ rafNode,
715
+ schedulerNode,
716
+ task,
717
+ } ;
718
+ } else {
719
+ currentTask . task = task ;
720
+ currentTask . schedulerNode = Scheduler . unstable_scheduleCallback (
721
+ Scheduler . unstable_NormalPriority ,
722
+ performFrameAlignedWork ,
723
+ ) ;
724
+ }
725
+
726
+ return currentTask ;
727
+ }
728
+
729
+ export function cancelFrameAlignedTask ( task : any ) {
730
+ if ( task . schedulerNode ) {
731
+ Scheduler . unstable_cancelCallback ( task . schedulerNode ) ;
732
+ task . schedulerNode = null ;
733
+ }
734
+ // We don't cancel the rAF in case it gets re-used later.
735
+ // But clear the task so if it fires and shouldn't run, it won't.
736
+ task . task = null ;
737
+ }
738
+
671
739
// -------------------
672
740
// Mutation
673
741
// -------------------
0 commit comments