8
8
9
9
/* eslint-disable no-var */
10
10
11
- import { enableSchedulerDebugging } from './SchedulerFeatureFlags' ;
12
11
import {
13
- requestHostCallback ,
12
+ enableSchedulerDebugging ,
13
+ enableProfiling ,
14
+ } from './SchedulerFeatureFlags' ;
15
+ import {
16
+ requestHostCallback as requestHostCallbackWithoutProfiling ,
14
17
requestHostTimeout ,
18
+ cancelHostCallback ,
15
19
cancelHostTimeout ,
16
20
shouldYieldToHost ,
17
21
getCurrentTime ,
@@ -21,11 +25,23 @@ import {
21
25
import { push , pop , peek } from './SchedulerMinHeap' ;
22
26
23
27
// TODO: Use symbols?
24
- var ImmediatePriority = 1 ;
25
- var UserBlockingPriority = 2 ;
26
- var NormalPriority = 3 ;
27
- var LowPriority = 4 ;
28
- var IdlePriority = 5 ;
28
+ import {
29
+ ImmediatePriority ,
30
+ UserBlockingPriority ,
31
+ NormalPriority ,
32
+ LowPriority ,
33
+ IdlePriority ,
34
+ } from './SchedulerPriorities' ;
35
+ import {
36
+ markTaskRun ,
37
+ markTaskYield ,
38
+ markTaskCompleted ,
39
+ markTaskCanceled ,
40
+ markTaskErrored ,
41
+ markSchedulerSuspended ,
42
+ markSchedulerUnsuspended ,
43
+ markTaskStart ,
44
+ } from './SchedulerProfiling' ;
29
45
30
46
// Max 31 bit integer. The max integer size in V8 for 32-bit systems.
31
47
// Math.pow(2, 30) - 1
@@ -60,13 +76,29 @@ var isPerformingWork = false;
60
76
var isHostCallbackScheduled = false ;
61
77
var isHostTimeoutScheduled = false ;
62
78
79
+ function requestHostCallbackWithProfiling ( cb ) {
80
+ if ( enableProfiling ) {
81
+ markSchedulerSuspended ( ) ;
82
+ requestHostCallbackWithoutProfiling ( cb ) ;
83
+ }
84
+ }
85
+
86
+ const requestHostCallback = enableProfiling
87
+ ? requestHostCallbackWithProfiling
88
+ : requestHostCallbackWithoutProfiling ;
89
+
63
90
function flushTask ( task , callback , currentTime ) {
64
91
currentPriorityLevel = task . priorityLevel ;
65
92
var didUserCallbackTimeout = task . expirationTime <= currentTime ;
93
+ markTaskRun ( task ) ;
66
94
var continuationCallback = callback ( didUserCallbackTimeout ) ;
67
- return typeof continuationCallback === 'function'
68
- ? continuationCallback
69
- : null ;
95
+ if ( typeof continuationCallback === 'function' ) {
96
+ markTaskYield ( task ) ;
97
+ return continuationCallback ;
98
+ } else {
99
+ markTaskCompleted ( task ) ;
100
+ return null ;
101
+ }
70
102
}
71
103
72
104
function advanceTimers ( currentTime ) {
@@ -81,6 +113,7 @@ function advanceTimers(currentTime) {
81
113
pop ( timerQueue ) ;
82
114
timer . sortIndex = timer . expirationTime ;
83
115
push ( taskQueue , timer ) ;
116
+ markTaskStart ( timer ) ;
84
117
} else {
85
118
// Remaining timers are pending.
86
119
return ;
@@ -107,6 +140,10 @@ function handleTimeout(currentTime) {
107
140
}
108
141
109
142
function flushWork ( hasTimeRemaining , initialTime ) {
143
+ if ( isHostCallbackScheduled ) {
144
+ markSchedulerUnsuspended ( ) ;
145
+ }
146
+
110
147
// We'll need a host callback the next time work is scheduled.
111
148
isHostCallbackScheduled = false ;
112
149
if ( isHostTimeoutScheduled ) {
@@ -152,6 +189,8 @@ function flushWork(hasTimeRemaining, initialTime) {
152
189
}
153
190
// Return whether there's additional work
154
191
if ( currentTask !== null ) {
192
+ markSchedulerSuspended ( ) ;
193
+ isHostCallbackScheduled = true ;
155
194
return true ;
156
195
} else {
157
196
let firstTimer = peek ( timerQueue ) ;
@@ -160,6 +199,14 @@ function flushWork(hasTimeRemaining, initialTime) {
160
199
}
161
200
return false ;
162
201
}
202
+ } catch ( error ) {
203
+ if ( currentTask !== null ) {
204
+ markTaskErrored ( currentTask ) ;
205
+ if ( currentTask === peek ( taskQueue ) ) {
206
+ pop ( taskQueue ) ;
207
+ }
208
+ }
209
+ throw error ;
163
210
} finally {
164
211
currentTask = null ;
165
212
currentPriorityLevel = previousPriorityLevel ;
@@ -250,6 +297,7 @@ function unstable_scheduleCallback(priorityLevel, callback, options) {
250
297
251
298
var startTime ;
252
299
var timeout ;
300
+ var label ;
253
301
if ( typeof options === 'object' && options !== null ) {
254
302
var delay = options . delay ;
255
303
if ( typeof delay === 'number' && delay > 0 ) {
@@ -261,6 +309,12 @@ function unstable_scheduleCallback(priorityLevel, callback, options) {
261
309
typeof options . timeout === 'number'
262
310
? options . timeout
263
311
: timeoutForPriorityLevel ( priorityLevel ) ;
312
+ if ( enableProfiling ) {
313
+ var _label = options . label ;
314
+ if ( typeof _label === 'string' ) {
315
+ label = _label ;
316
+ }
317
+ }
264
318
} else {
265
319
timeout = timeoutForPriorityLevel ( priorityLevel ) ;
266
320
startTime = currentTime ;
@@ -269,14 +323,20 @@ function unstable_scheduleCallback(priorityLevel, callback, options) {
269
323
var expirationTime = startTime + timeout ;
270
324
271
325
var newTask = {
272
- id : taskIdCounter ++ ,
326
+ id : ++ taskIdCounter ,
273
327
callback,
274
328
priorityLevel,
275
329
startTime,
276
330
expirationTime,
277
331
sortIndex : - 1 ,
278
332
} ;
279
333
334
+ if ( enableProfiling ) {
335
+ if ( typeof options === 'object' && options !== null ) {
336
+ newTask . label = label ;
337
+ }
338
+ }
339
+
280
340
if ( startTime > currentTime ) {
281
341
// This is a delayed task.
282
342
newTask . sortIndex = startTime ;
@@ -295,6 +355,7 @@ function unstable_scheduleCallback(priorityLevel, callback, options) {
295
355
} else {
296
356
newTask . sortIndex = expirationTime ;
297
357
push ( taskQueue , newTask ) ;
358
+ markTaskStart ( newTask ) ;
298
359
// Schedule a host callback, if needed. If we're already performing work,
299
360
// wait until the next time we yield.
300
361
if ( ! isHostCallbackScheduled && ! isPerformingWork ) {
@@ -323,10 +384,23 @@ function unstable_getFirstCallbackNode() {
323
384
}
324
385
325
386
function unstable_cancelCallback ( task ) {
326
- // Null out the callback to indicate the task has been canceled. (Can't remove
327
- // from the queue because you can't remove arbitrary nodes from an array based
328
- // heap, only the first one.)
329
- task . callback = null ;
387
+ if ( enableProfiling && task . callback !== null ) {
388
+ markTaskCanceled ( task ) ;
389
+ }
390
+ if ( task !== null && task === peek ( taskQueue ) ) {
391
+ pop ( taskQueue ) ;
392
+ if ( enableProfiling && ! isPerformingWork && taskQueue . length === 0 ) {
393
+ // The queue is now empty.
394
+ markSchedulerUnsuspended ( ) ;
395
+ isHostCallbackScheduled = false ;
396
+ cancelHostCallback ( ) ;
397
+ }
398
+ } else {
399
+ // Null out the callback to indicate the task has been canceled. (Can't
400
+ // remove from the queue because you can't remove arbitrary nodes from an
401
+ // array based heap, only the first one.)
402
+ task . callback = null ;
403
+ }
330
404
}
331
405
332
406
function unstable_getCurrentPriorityLevel ( ) {
0 commit comments