Skip to content

Commit

Permalink
Flow: typing of Scheduler (#25317)
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
kassens authored Sep 23, 2022
1 parent cc8cb14 commit 135e33c
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 46 deletions.
1 change: 1 addition & 0 deletions packages/scheduler/src/SchedulerFeatureFlags.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
15 changes: 8 additions & 7 deletions packages/scheduler/src/SchedulerMinHeap.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion packages/scheduler/src/SchedulerPriorities.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
68 changes: 53 additions & 15 deletions packages/scheduler/src/forks/Scheduler.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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';

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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:
Expand All @@ -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:
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -346,7 +371,7 @@ function unstable_scheduleCallback(priorityLevel, callback, options) {

var expirationTime = startTime + timeout;

var newTask = {
var newTask: Task = {
id: taskIdCounter++,
callback,
priorityLevel,
Expand Down Expand Up @@ -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();
Expand All @@ -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.
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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'](
Expand Down Expand Up @@ -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);
};
}
Expand All @@ -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 {
Expand All @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 4 additions & 1 deletion packages/scheduler/src/forks/SchedulerFeatureFlags.www.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -19,4 +21,5 @@ export const {
maxYieldMs,
} = dynamicFeatureFlags;

export const enableProfiling = __PROFILE__ && enableProfilingFeatureFlag;
export const enableProfiling: boolean =
__PROFILE__ && enableProfilingFeatureFlag;
Loading

0 comments on commit 135e33c

Please sign in to comment.