Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flow: typing of Scheduler #25317

Merged
merged 1 commit into from
Sep 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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