1010'use strict' ;
1111
1212let ReactScheduler ;
13+ type FrameTimeoutConfigType = {
14+ // should only specify one or the other
15+ timeLeftInFrame : ?number ,
16+ timePastFrameDeadline : ?number ,
17+ } ;
1318
1419describe ( 'ReactScheduler' , ( ) => {
1520 let rAFCallbacks = [ ] ;
1621 let postMessageCallback ;
1722 let postMessageEvents = [ ] ;
1823
19- function drainPostMessageQueue ( ) {
20- // default to this falling about 15 ms before next frame
21- currentTime = startOfLatestFrame + frameSize - 15 ;
24+ function runPostMessageCallbacks ( config : FrameTimeoutConfigType ) {
25+ let timeLeftInFrame = 0 ;
26+ if ( typeof config . timeLeftInFrame === 'number' ) {
27+ timeLeftInFrame = config . timeLeftInFrame ;
28+ } else if ( typeof config . timePastFrameDeadline === 'number' ) {
29+ timeLeftInFrame = - 1 * config . timePastFrameDeadline ;
30+ }
31+ currentTime = startOfLatestFrame + frameSize - timeLeftInFrame ;
2232 if ( postMessageCallback ) {
2333 while ( postMessageEvents . length ) {
2434 postMessageCallback ( postMessageEvents . shift ( ) ) ;
@@ -31,9 +41,9 @@ describe('ReactScheduler', () => {
3141 rAFCallbacks . forEach ( cb => cb ( ) ) ;
3242 rAFCallbacks = [ ] ;
3343 }
34- function advanceAll ( ) {
44+ function advanceOneFrame ( config : FrameTimeoutConfigType = { } ) {
3545 runRAFCallbacks ( ) ;
36- drainPostMessageQueue ( ) ;
46+ runPostMessageCallbacks ( config ) ;
3747 }
3848
3949 let frameSize = 33 ;
@@ -77,7 +87,7 @@ describe('ReactScheduler', () => {
7787 const { scheduleWork} = ReactScheduler ;
7888 const cb = jest . fn ( ) ;
7989 scheduleWork ( cb ) ;
80- advanceAll ( ) ;
90+ advanceOneFrame ( { timeLeftInFrame : 15 } ) ;
8191 expect ( cb . mock . calls . length ) . toBe ( 1 ) ;
8292 // should not have timed out and should include a timeRemaining method
8393 expect ( cb . mock . calls [ 0 ] [ 0 ] . didTimeout ) . toBe ( false ) ;
@@ -97,7 +107,7 @@ describe('ReactScheduler', () => {
97107 scheduleWork ( callbackB ) ;
98108 expect ( callbackLog ) . toEqual ( [ ] ) ;
99109 // after a delay, calls as many callbacks as it has time for
100- advanceAll ( ) ;
110+ advanceOneFrame ( { timeLeftInFrame : 15 } ) ;
101111 expect ( callbackLog ) . toEqual ( [ 'A' , 'B' ] ) ;
102112 // callbackA should not have timed out and should include a timeRemaining method
103113 expect ( callbackA . mock . calls [ 0 ] [ 0 ] . didTimeout ) . toBe ( false ) ;
@@ -125,16 +135,16 @@ describe('ReactScheduler', () => {
125135 scheduleWork ( callbackB ) ;
126136 expect ( callbackLog ) . toEqual ( [ ] ) ;
127137 // now it should drain the message queue and do all scheduled work
128- drainPostMessageQueue ( ) ;
138+ runPostMessageCallbacks ( { timeLeftInFrame : 15 } ) ;
129139 expect ( callbackLog ) . toEqual ( [ 'A' , 'B' ] ) ;
130140
131141 // advances timers, now with an empty queue of work (to ensure they don't deadlock)
132- advanceAll ( ) ;
142+ advanceOneFrame ( { timeLeftInFrame : 15 } ) ;
133143
134144 // see if more work can be done now.
135145 scheduleWork ( callbackC ) ;
136146 expect ( callbackLog ) . toEqual ( [ 'A' , 'B' ] ) ;
137- advanceAll ( ) ;
147+ advanceOneFrame ( { timeLeftInFrame : 15 } ) ;
138148 expect ( callbackLog ) . toEqual ( [ 'A' , 'B' , 'C' ] ) ;
139149 } ) ;
140150
@@ -163,7 +173,7 @@ describe('ReactScheduler', () => {
163173 expect ( callbackLog ) . toEqual ( [ ] ) ;
164174 // after a delay, calls the scheduled callbacks,
165175 // and also calls new callbacks scheduled by current callbacks
166- advanceAll ( ) ;
176+ advanceOneFrame ( { timeLeftInFrame : 15 } ) ;
167177 expect ( callbackLog ) . toEqual ( [ 'A' , 'B' , 'C' ] ) ;
168178 } ,
169179 ) ;
@@ -199,7 +209,7 @@ describe('ReactScheduler', () => {
199209 // initially waits to call the callback
200210 expect ( callbackLog ) . toEqual ( [ ] ) ;
201211 // while flushing callbacks, calls as many as it has time for
202- advanceAll ( ) ;
212+ advanceOneFrame ( { timeLeftInFrame : 15 } ) ;
203213 expect ( callbackLog ) . toEqual ( [ 'A' , 'B' , 'C' , 'D' , 'E' , 'F' ] ) ;
204214 } ) ;
205215
@@ -222,7 +232,7 @@ describe('ReactScheduler', () => {
222232 scheduleWork ( callbackB ) ;
223233 expect ( callbackLog ) . toEqual ( [ ] ) ;
224234 // after a delay, calls the latest callback passed
225- advanceAll ( ) ;
235+ advanceOneFrame ( { timeLeftInFrame : 15 } ) ;
226236 expect ( callbackLog ) . toEqual ( [ 'A0' , 'B' , 'A1' ] ) ;
227237 } ) ;
228238 } ) ;
@@ -248,24 +258,20 @@ describe('ReactScheduler', () => {
248258 scheduleWork ( callbackB , { timeout : 100 } ) ; // times out later
249259 scheduleWork ( callbackC , { timeout : 2 } ) ; // will time out fast
250260
251- runRAFCallbacks ( ) ; // runs rAF callback
252261 // push time ahead a bit so that we have no idle time
253- startOfLatestFrame += 16 ;
254- drainPostMessageQueue ( ) ; // runs postMessage callback, idleTick
262+ advanceOneFrame ( { timePastFrameDeadline : 16 } ) ;
255263
256264 // callbackC should have timed out
257265 expect ( callbackLog ) . toEqual ( [ 'C' ] ) ;
258266
259- runRAFCallbacks ( ) ; // runs rAF callback
260267 // push time ahead a bit so that we have no idle time
261- startOfLatestFrame += 16 ;
262- drainPostMessageQueue ( ) ; // runs postMessage callback, idleTick
268+ advanceOneFrame ( { timePastFrameDeadline : 16 } ) ;
263269
264270 // callbackB should have timed out
265271 expect ( callbackLog ) . toEqual ( [ 'C' , 'B' ] ) ;
266272
267- runRAFCallbacks ( ) ; // runs rAF callback
268- drainPostMessageQueue ( ) ; // runs postMessage callback, idleTick
273+ // let's give ourselves some idle time now
274+ advanceOneFrame ( { timeLeftInFrame : 16 } ) ;
269275
270276 // we should have run callbackA in the idle time
271277 expect ( callbackLog ) . toEqual ( [ 'C' , 'B' , 'A' ] ) ;
@@ -295,27 +301,25 @@ describe('ReactScheduler', () => {
295301 scheduleWork ( callbackC , { timeout : 2 } ) ; // will time out fast
296302 scheduleWork ( callbackD ) ; // won't time out
297303
298- advanceAll ( ) ; // runs rAF and postMessage callbacks
304+ advanceOneFrame ( { timeLeftInFrame : 15 } ) ; // runs rAF and postMessage callbacks
299305
300306 // callbackC should have timed out
301307 // we should have had time to call A also, then we run out of time
302308 expect ( callbackLog ) . toEqual ( [ 'C' , 'A' ] ) ;
303309
304- runRAFCallbacks ( ) ; // runs rAF callback
305310 // push time ahead a bit so that we have no idle time
306- startOfLatestFrame += 16 ;
307- drainPostMessageQueue ( ) ; // runs postMessage callback, idleTick
311+ advanceOneFrame ( { timePastFrameDeadline : 16 } ) ;
308312
309313 // callbackB should have timed out
310314 // but we should not run callbackD because we have no idle time
311315 expect ( callbackLog ) . toEqual ( [ 'C' , 'A' , 'B' ] ) ;
312316
313- advanceAll ( ) ; // runs rAF and postMessage callbacks
317+ advanceOneFrame ( { timeLeftInFrame : 15 } ) ; // runs rAF and postMessage callbacks
314318
315319 // we should have run callbackD in the idle time
316320 expect ( callbackLog ) . toEqual ( [ 'C' , 'A' , 'B' , 'D' ] ) ;
317321
318- advanceAll ( ) ; // runs rAF and postMessage callbacks
322+ advanceOneFrame ( { timeLeftInFrame : 15 } ) ; // runs rAF and postMessage callbacks
319323
320324 // we should not have run anything again, nothing is scheduled
321325 expect ( callbackLog ) . toEqual ( [ 'C' , 'A' , 'B' , 'D' ] ) ;
@@ -331,7 +335,7 @@ describe('ReactScheduler', () => {
331335 const callbackId = scheduleWork ( cb ) ;
332336 expect ( cb . mock . calls . length ) . toBe ( 0 ) ;
333337 cancelScheduledWork ( callbackId ) ;
334- advanceAll ( ) ;
338+ advanceOneFrame ( { timeLeftInFrame : 15 } ) ;
335339 expect ( cb . mock . calls . length ) . toBe ( 0 ) ;
336340 } ) ;
337341
@@ -349,7 +353,7 @@ describe('ReactScheduler', () => {
349353 callbackBId = scheduleWork ( callbackB ) ;
350354 // Initially doesn't call anything
351355 expect ( callbackLog ) . toEqual ( [ ] ) ;
352- advanceAll ( ) ;
356+ advanceOneFrame ( { timeLeftInFrame : 15 } ) ;
353357 // B should not get called because A cancelled B
354358 expect ( callbackLog ) . toEqual ( [ 'A' ] ) ;
355359 expect ( callbackB . mock . calls . length ) . toBe ( 0 ) ;
0 commit comments