mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Flow: typing of Scheduler (#25317)
Enables well formed exports for /scheduler. Some of the modules there were missing `@flow` and were therefore completely unchecked (despite some spurious types sprinkled around).
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict
|
||||
*/
|
||||
|
||||
export const enableSchedulerDebugging = false;
|
||||
|
||||
@@ -7,23 +7,24 @@
|
||||
* @flow strict
|
||||
*/
|
||||
|
||||
type Heap = Array<Node>;
|
||||
type Heap<T: Node> = Array<T>;
|
||||
type Node = {
|
||||
id: number,
|
||||
sortIndex: number,
|
||||
...
|
||||
};
|
||||
|
||||
export function push(heap: Heap, node: Node): void {
|
||||
export function push<T: Node>(heap: Heap<T>, node: T): void {
|
||||
const index = heap.length;
|
||||
heap.push(node);
|
||||
siftUp(heap, node, index);
|
||||
}
|
||||
|
||||
export function peek(heap: Heap): Node | null {
|
||||
export function peek<T: Node>(heap: Heap<T>): T | null {
|
||||
return heap.length === 0 ? null : heap[0];
|
||||
}
|
||||
|
||||
export function pop(heap: Heap): Node | null {
|
||||
export function pop<T: Node>(heap: Heap<T>): T | null {
|
||||
if (heap.length === 0) {
|
||||
return null;
|
||||
}
|
||||
@@ -36,7 +37,7 @@ export function pop(heap: Heap): Node | null {
|
||||
return first;
|
||||
}
|
||||
|
||||
function siftUp(heap, node, i) {
|
||||
function siftUp<T: Node>(heap: Heap<T>, node: T, i: number): void {
|
||||
let index = i;
|
||||
while (index > 0) {
|
||||
const parentIndex = (index - 1) >>> 1;
|
||||
@@ -53,7 +54,7 @@ function siftUp(heap, node, i) {
|
||||
}
|
||||
}
|
||||
|
||||
function siftDown(heap, node, i) {
|
||||
function siftDown<T: Node>(heap: Heap<T>, node: T, i: number): void {
|
||||
let index = i;
|
||||
const length = heap.length;
|
||||
const halfLength = length >>> 1;
|
||||
@@ -85,7 +86,7 @@ function siftDown(heap, node, i) {
|
||||
}
|
||||
}
|
||||
|
||||
function compare(a, b) {
|
||||
function compare(a: Node, b: Node) {
|
||||
// Compare sort index first, then task id.
|
||||
const diff = a.sortIndex - b.sortIndex;
|
||||
return diff !== 0 ? diff : a.id - b.id;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @flow strict
|
||||
*/
|
||||
|
||||
export type PriorityLevel = 0 | 1 | 2 | 3 | 4 | 5;
|
||||
|
||||
@@ -4,10 +4,13 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
|
||||
/* eslint-disable no-var */
|
||||
|
||||
import type {PriorityLevel} from '../SchedulerPriorities';
|
||||
|
||||
import {
|
||||
enableSchedulerDebugging,
|
||||
enableProfiling,
|
||||
@@ -41,7 +44,19 @@ import {
|
||||
startLoggingProfilingEvents,
|
||||
} from '../SchedulerProfiling';
|
||||
|
||||
let getCurrentTime;
|
||||
export type Callback = boolean => ?Callback;
|
||||
|
||||
type Task = {
|
||||
id: number,
|
||||
callback: Callback | null,
|
||||
priorityLevel: PriorityLevel,
|
||||
startTime: number,
|
||||
expirationTime: number,
|
||||
sortIndex: number,
|
||||
isQueued?: boolean,
|
||||
};
|
||||
|
||||
let getCurrentTime: () => number | DOMHighResTimeStamp;
|
||||
const hasPerformanceNow =
|
||||
typeof performance === 'object' && typeof performance.now === 'function';
|
||||
|
||||
@@ -96,7 +111,9 @@ const localSetImmediate =
|
||||
|
||||
const isInputPending =
|
||||
typeof navigator !== 'undefined' &&
|
||||
// $FlowFixMe[prop-missing]
|
||||
navigator.scheduling !== undefined &&
|
||||
// $FlowFixMe[incompatible-type]
|
||||
navigator.scheduling.isInputPending !== undefined
|
||||
? navigator.scheduling.isInputPending.bind(navigator.scheduling)
|
||||
: null;
|
||||
@@ -247,7 +264,10 @@ function workLoop(hasTimeRemaining, initialTime) {
|
||||
}
|
||||
}
|
||||
|
||||
function unstable_runWithPriority(priorityLevel, eventHandler) {
|
||||
function unstable_runWithPriority<T>(
|
||||
priorityLevel: PriorityLevel,
|
||||
eventHandler: () => T,
|
||||
): T {
|
||||
switch (priorityLevel) {
|
||||
case ImmediatePriority:
|
||||
case UserBlockingPriority:
|
||||
@@ -269,7 +289,7 @@ function unstable_runWithPriority(priorityLevel, eventHandler) {
|
||||
}
|
||||
}
|
||||
|
||||
function unstable_next(eventHandler) {
|
||||
function unstable_next<T>(eventHandler: () => T): T {
|
||||
var priorityLevel;
|
||||
switch (currentPriorityLevel) {
|
||||
case ImmediatePriority:
|
||||
@@ -294,8 +314,9 @@ function unstable_next(eventHandler) {
|
||||
}
|
||||
}
|
||||
|
||||
function unstable_wrapCallback(callback) {
|
||||
function unstable_wrapCallback<T: (...Array<mixed>) => mixed>(callback: T): T {
|
||||
var parentPriorityLevel = currentPriorityLevel;
|
||||
// $FlowFixMe[incompatible-return]
|
||||
return function() {
|
||||
// This is a fork of runWithPriority, inlined for performance.
|
||||
var previousPriorityLevel = currentPriorityLevel;
|
||||
@@ -309,7 +330,11 @@ function unstable_wrapCallback(callback) {
|
||||
};
|
||||
}
|
||||
|
||||
function unstable_scheduleCallback(priorityLevel, callback, options) {
|
||||
function unstable_scheduleCallback(
|
||||
priorityLevel: PriorityLevel,
|
||||
callback: Callback,
|
||||
options?: {delay: number},
|
||||
): Task {
|
||||
var currentTime = getCurrentTime();
|
||||
|
||||
var startTime;
|
||||
@@ -346,7 +371,7 @@ function unstable_scheduleCallback(priorityLevel, callback, options) {
|
||||
|
||||
var expirationTime = startTime + timeout;
|
||||
|
||||
var newTask = {
|
||||
var newTask: Task = {
|
||||
id: taskIdCounter++,
|
||||
callback,
|
||||
priorityLevel,
|
||||
@@ -403,11 +428,11 @@ function unstable_continueExecution() {
|
||||
}
|
||||
}
|
||||
|
||||
function unstable_getFirstCallbackNode() {
|
||||
function unstable_getFirstCallbackNode(): Task | null {
|
||||
return peek(taskQueue);
|
||||
}
|
||||
|
||||
function unstable_cancelCallback(task) {
|
||||
function unstable_cancelCallback(task: Task) {
|
||||
if (enableProfiling) {
|
||||
if (task.isQueued) {
|
||||
const currentTime = getCurrentTime();
|
||||
@@ -422,13 +447,18 @@ function unstable_cancelCallback(task) {
|
||||
task.callback = null;
|
||||
}
|
||||
|
||||
function unstable_getCurrentPriorityLevel() {
|
||||
function unstable_getCurrentPriorityLevel(): PriorityLevel {
|
||||
return currentPriorityLevel;
|
||||
}
|
||||
|
||||
let isMessageLoopRunning = false;
|
||||
let scheduledHostCallback = null;
|
||||
let taskTimeoutID = -1;
|
||||
let scheduledHostCallback:
|
||||
| null
|
||||
| ((
|
||||
hasTimeRemaining: boolean,
|
||||
initialTime: DOMHighResTimeStamp | number,
|
||||
) => boolean) = null;
|
||||
let taskTimeoutID: TimeoutID = (-1: any);
|
||||
|
||||
// Scheduler periodically yields in case there is other work on the main
|
||||
// thread, like user events. By default, it yields multiple times per frame.
|
||||
@@ -441,7 +471,7 @@ let startTime = -1;
|
||||
|
||||
let needsPaint = false;
|
||||
|
||||
function shouldYieldToHost() {
|
||||
function shouldYieldToHost(): boolean {
|
||||
const timeElapsed = getCurrentTime() - startTime;
|
||||
if (timeElapsed < frameInterval) {
|
||||
// The main thread has only been blocked for a really short amount of time;
|
||||
@@ -490,7 +520,9 @@ function requestPaint() {
|
||||
if (
|
||||
enableIsInputPending &&
|
||||
navigator !== undefined &&
|
||||
// $FlowFixMe[prop-missing]
|
||||
navigator.scheduling !== undefined &&
|
||||
// $FlowFixMe[incompatible-type]
|
||||
navigator.scheduling.isInputPending !== undefined
|
||||
) {
|
||||
needsPaint = true;
|
||||
@@ -499,7 +531,7 @@ function requestPaint() {
|
||||
// Since we yield every frame regardless, `requestPaint` has no effect.
|
||||
}
|
||||
|
||||
function forceFrameRate(fps) {
|
||||
function forceFrameRate(fps: number) {
|
||||
if (fps < 0 || fps > 125) {
|
||||
// Using console['error'] to evade Babel and ESLint
|
||||
console['error'](
|
||||
@@ -579,6 +611,7 @@ if (typeof localSetImmediate === 'function') {
|
||||
} else {
|
||||
// We should only fallback here in non-browser environments.
|
||||
schedulePerformWorkUntilDeadline = () => {
|
||||
// $FlowFixMe[not-a-function] nullable value
|
||||
localSetTimeout(performWorkUntilDeadline, 0);
|
||||
};
|
||||
}
|
||||
@@ -592,14 +625,16 @@ function requestHostCallback(callback) {
|
||||
}
|
||||
|
||||
function requestHostTimeout(callback, ms) {
|
||||
// $FlowFixMe[not-a-function] nullable value
|
||||
taskTimeoutID = localSetTimeout(() => {
|
||||
callback(getCurrentTime());
|
||||
}, ms);
|
||||
}
|
||||
|
||||
function cancelHostTimeout() {
|
||||
// $FlowFixMe[not-a-function] nullable value
|
||||
localClearTimeout(taskTimeoutID);
|
||||
taskTimeoutID = -1;
|
||||
taskTimeoutID = ((-1: any): TimeoutID);
|
||||
}
|
||||
|
||||
export {
|
||||
@@ -623,7 +658,10 @@ export {
|
||||
forceFrameRate as unstable_forceFrameRate,
|
||||
};
|
||||
|
||||
export const unstable_Profiling = enableProfiling
|
||||
export const unstable_Profiling: {
|
||||
startLoggingProfilingEvents(): void,
|
||||
stopLoggingProfilingEvents(): ArrayBuffer | null,
|
||||
} | null = enableProfiling
|
||||
? {
|
||||
startLoggingProfilingEvents,
|
||||
stopLoggingProfilingEvents,
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
*/
|
||||
|
||||
// In www, these flags are controlled by GKs. Because most GKs have some
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
|
||||
// $FlowFixMe[cannot-resolve-module]
|
||||
const dynamicFeatureFlags = require('SchedulerFeatureFlags');
|
||||
|
||||
// Re-export dynamic flags from the www version.
|
||||
@@ -19,4 +21,5 @@ export const {
|
||||
maxYieldMs,
|
||||
} = dynamicFeatureFlags;
|
||||
|
||||
export const enableProfiling = __PROFILE__ && enableProfilingFeatureFlag;
|
||||
export const enableProfiling: boolean =
|
||||
__PROFILE__ && enableProfilingFeatureFlag;
|
||||
|
||||
@@ -4,11 +4,14 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
|
||||
/* eslint-disable no-var */
|
||||
/* eslint-disable react-internal/prod-error-codes */
|
||||
|
||||
import type {PriorityLevel} from '../SchedulerPriorities';
|
||||
|
||||
import {
|
||||
enableSchedulerDebugging,
|
||||
enableProfiling,
|
||||
@@ -36,6 +39,18 @@ import {
|
||||
startLoggingProfilingEvents,
|
||||
} from '../SchedulerProfiling';
|
||||
|
||||
type Callback = boolean => ?Callback;
|
||||
|
||||
type Task = {
|
||||
id: number,
|
||||
callback: Callback | null,
|
||||
priorityLevel: PriorityLevel,
|
||||
startTime: number,
|
||||
expirationTime: number,
|
||||
sortIndex: number,
|
||||
isQueued?: boolean,
|
||||
};
|
||||
|
||||
// Max 31 bit integer. The max integer size in V8 for 32-bit systems.
|
||||
// Math.pow(2, 30) - 1
|
||||
// 0b111111111111111111111111111111
|
||||
@@ -52,7 +67,7 @@ var IDLE_PRIORITY_TIMEOUT = maxSigned31BitInt;
|
||||
|
||||
// Tasks are stored on a min heap
|
||||
var taskQueue = [];
|
||||
var timerQueue = [];
|
||||
var timerQueue: Array<Task> = [];
|
||||
|
||||
// Incrementing id counter. Used to maintain insertion order.
|
||||
var taskIdCounter = 1;
|
||||
@@ -70,7 +85,12 @@ var isHostCallbackScheduled = false;
|
||||
var isHostTimeoutScheduled = false;
|
||||
|
||||
let currentMockTime: number = 0;
|
||||
let scheduledCallback: ((boolean, number) => void) | null = null;
|
||||
let scheduledCallback:
|
||||
| null
|
||||
| ((
|
||||
hasTimeRemaining: boolean,
|
||||
initialTime: DOMHighResTimeStamp | number,
|
||||
) => boolean) = null;
|
||||
let scheduledTimeout: (number => void) | null = null;
|
||||
let timeoutTime: number = -1;
|
||||
let yieldedValues: Array<mixed> | null = null;
|
||||
@@ -82,11 +102,11 @@ let shouldYieldForPaint: boolean = false;
|
||||
|
||||
var disableYieldValue = false;
|
||||
|
||||
function setDisableYieldValue(newValue) {
|
||||
function setDisableYieldValue(newValue: boolean) {
|
||||
disableYieldValue = newValue;
|
||||
}
|
||||
|
||||
function advanceTimers(currentTime) {
|
||||
function advanceTimers(currentTime: number) {
|
||||
// Check for tasks that are no longer delayed and add them to the queue.
|
||||
let timer = peek(timerQueue);
|
||||
while (timer !== null) {
|
||||
@@ -110,7 +130,7 @@ function advanceTimers(currentTime) {
|
||||
}
|
||||
}
|
||||
|
||||
function handleTimeout(currentTime) {
|
||||
function handleTimeout(currentTime: number) {
|
||||
isHostTimeoutScheduled = false;
|
||||
advanceTimers(currentTime);
|
||||
|
||||
@@ -127,7 +147,7 @@ function handleTimeout(currentTime) {
|
||||
}
|
||||
}
|
||||
|
||||
function flushWork(hasTimeRemaining, initialTime) {
|
||||
function flushWork(hasTimeRemaining: boolean, initialTime: number) {
|
||||
if (enableProfiling) {
|
||||
markSchedulerUnsuspended(initialTime);
|
||||
}
|
||||
@@ -169,7 +189,7 @@ function flushWork(hasTimeRemaining, initialTime) {
|
||||
}
|
||||
}
|
||||
|
||||
function workLoop(hasTimeRemaining, initialTime) {
|
||||
function workLoop(hasTimeRemaining, initialTime: number): boolean {
|
||||
let currentTime = initialTime;
|
||||
advanceTimers(currentTime);
|
||||
currentTask = peek(taskQueue);
|
||||
@@ -238,7 +258,10 @@ function workLoop(hasTimeRemaining, initialTime) {
|
||||
}
|
||||
}
|
||||
|
||||
function unstable_runWithPriority(priorityLevel, eventHandler) {
|
||||
function unstable_runWithPriority<T>(
|
||||
priorityLevel: PriorityLevel,
|
||||
eventHandler: () => T,
|
||||
): T {
|
||||
switch (priorityLevel) {
|
||||
case ImmediatePriority:
|
||||
case UserBlockingPriority:
|
||||
@@ -260,7 +283,7 @@ function unstable_runWithPriority(priorityLevel, eventHandler) {
|
||||
}
|
||||
}
|
||||
|
||||
function unstable_next(eventHandler) {
|
||||
function unstable_next<T>(eventHandler: () => T): T {
|
||||
var priorityLevel;
|
||||
switch (currentPriorityLevel) {
|
||||
case ImmediatePriority:
|
||||
@@ -285,8 +308,9 @@ function unstable_next(eventHandler) {
|
||||
}
|
||||
}
|
||||
|
||||
function unstable_wrapCallback(callback) {
|
||||
function unstable_wrapCallback<T: (...Array<mixed>) => mixed>(callback: T): T {
|
||||
var parentPriorityLevel = currentPriorityLevel;
|
||||
// $FlowFixMe[incompatible-return]
|
||||
return function() {
|
||||
// This is a fork of runWithPriority, inlined for performance.
|
||||
var previousPriorityLevel = currentPriorityLevel;
|
||||
@@ -300,7 +324,11 @@ function unstable_wrapCallback(callback) {
|
||||
};
|
||||
}
|
||||
|
||||
function unstable_scheduleCallback(priorityLevel, callback, options) {
|
||||
function unstable_scheduleCallback(
|
||||
priorityLevel: PriorityLevel,
|
||||
callback: Callback,
|
||||
options?: {delay: number},
|
||||
): Task {
|
||||
var currentTime = getCurrentTime();
|
||||
|
||||
var startTime;
|
||||
@@ -337,7 +365,7 @@ function unstable_scheduleCallback(priorityLevel, callback, options) {
|
||||
|
||||
var expirationTime = startTime + timeout;
|
||||
|
||||
var newTask = {
|
||||
var newTask: Task = {
|
||||
id: taskIdCounter++,
|
||||
callback,
|
||||
priorityLevel,
|
||||
@@ -394,11 +422,11 @@ function unstable_continueExecution() {
|
||||
}
|
||||
}
|
||||
|
||||
function unstable_getFirstCallbackNode() {
|
||||
function unstable_getFirstCallbackNode(): Task | null {
|
||||
return peek(taskQueue);
|
||||
}
|
||||
|
||||
function unstable_cancelCallback(task) {
|
||||
function unstable_cancelCallback(task: Task) {
|
||||
if (enableProfiling) {
|
||||
if (task.isQueued) {
|
||||
const currentTime = getCurrentTime();
|
||||
@@ -413,11 +441,11 @@ function unstable_cancelCallback(task) {
|
||||
task.callback = null;
|
||||
}
|
||||
|
||||
function unstable_getCurrentPriorityLevel() {
|
||||
function unstable_getCurrentPriorityLevel(): PriorityLevel {
|
||||
return currentPriorityLevel;
|
||||
}
|
||||
|
||||
function requestHostCallback(callback: boolean => void) {
|
||||
function requestHostCallback(callback: (boolean, number) => boolean) {
|
||||
scheduledCallback = callback;
|
||||
}
|
||||
|
||||
@@ -494,7 +522,7 @@ function unstable_flushNumberOfYields(count: number): void {
|
||||
}
|
||||
}
|
||||
|
||||
function unstable_flushUntilNextPaint(): void {
|
||||
function unstable_flushUntilNextPaint(): false {
|
||||
if (isFlushing) {
|
||||
throw new Error('Already flushing work.');
|
||||
}
|
||||
@@ -657,7 +685,10 @@ export {
|
||||
setDisableYieldValue as unstable_setDisableYieldValue,
|
||||
};
|
||||
|
||||
export const unstable_Profiling = enableProfiling
|
||||
export const unstable_Profiling: {
|
||||
startLoggingProfilingEvents(): void,
|
||||
stopLoggingProfilingEvents(): ArrayBuffer | null,
|
||||
} | null = enableProfiling
|
||||
? {
|
||||
startLoggingProfilingEvents,
|
||||
stopLoggingProfilingEvents,
|
||||
|
||||
@@ -44,7 +44,7 @@ const setTimeout = window.setTimeout;
|
||||
// Use experimental Chrome Scheduler postTask API.
|
||||
const scheduler = global.scheduler;
|
||||
|
||||
const getCurrentTime = perf.now.bind(perf);
|
||||
const getCurrentTime: () => DOMHighResTimeStamp = perf.now.bind(perf);
|
||||
|
||||
export const unstable_now = getCurrentTime;
|
||||
|
||||
@@ -193,7 +193,7 @@ export function unstable_runWithPriority<T>(
|
||||
}
|
||||
}
|
||||
|
||||
export function unstable_getCurrentPriorityLevel() {
|
||||
export function unstable_getCurrentPriorityLevel(): PriorityLevel {
|
||||
return currentPriorityLevel_DEPRECATED;
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ export function unstable_pauseExecution() {}
|
||||
|
||||
export function unstable_continueExecution() {}
|
||||
|
||||
export function unstable_getFirstCallbackNode() {
|
||||
export function unstable_getFirstCallbackNode(): null {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ well_formed_exports=true
|
||||
well_formed_exports.includes=<PROJECT_ROOT>/packages/react-devtools-shared
|
||||
well_formed_exports.includes=<PROJECT_ROOT>/packages/react-devtools-shell
|
||||
well_formed_exports.includes=<PROJECT_ROOT>/packages/react-devtools-timeline
|
||||
well_formed_exports.includes=<PROJECT_ROOT>/packages/scheduler
|
||||
|
||||
# Substituted by createFlowConfig.js:
|
||||
%REACT_RENDERER_FLOW_OPTIONS%
|
||||
|
||||
Reference in New Issue
Block a user