Skip to content

Commit

Permalink
clean up isInputPending
Browse files Browse the repository at this point in the history
  • Loading branch information
noahlemen committed Feb 26, 2024
1 parent 8fb0233 commit 02543f6
Show file tree
Hide file tree
Showing 5 changed files with 6 additions and 115 deletions.
4 changes: 0 additions & 4 deletions packages/scheduler/src/SchedulerFeatureFlags.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,8 @@
*/

export const enableSchedulerDebugging = false;
export const enableIsInputPending = false;
export const enableProfiling = false;
export const enableIsInputPendingContinuous = false;
export const frameYieldMs = 5;
export const continuousYieldMs = 50;
export const maxYieldMs = 300;

export const userBlockingPriorityTimeout = 250;
export const normalPriorityTimeout = 5000;
Expand Down
36 changes: 4 additions & 32 deletions packages/scheduler/src/__tests__/Scheduler-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -339,15 +339,7 @@ describe('SchedulerBrowser', () => {
runtime.assertLog([
'Message Event',
'Task with no pending input',
// Even though there's no input, eventually Scheduler will yield
// regardless in case there's a pending main thread task we don't know
// about, like a network event.
gate(flags =>
flags.enableIsInputPending
? 'Yield at 10ms'
: // When isInputPending is disabled, we always yield quickly
'Yield at 5ms',
),
'Yield at 5ms',
]);

runtime.resetTime();
Expand Down Expand Up @@ -393,15 +385,7 @@ describe('SchedulerBrowser', () => {
runtime.assertLog([
'Message Event',
'Task with no pending input',
// Even though there's no input, eventually Scheduler will yield
// regardless in case there's a pending main thread task we don't know
// about, like a network event.
gate(flags =>
flags.enableIsInputPending
? 'Yield at 10ms'
: // When isInputPending is disabled, we always yield quickly
'Yield at 5ms',
),
'Yield at 5ms',
]);

runtime.resetTime();
Expand All @@ -419,14 +403,7 @@ describe('SchedulerBrowser', () => {
runtime.assertLog([
'Message Event',
'Task with continuous input',
// This time we yielded quickly to unblock the continuous event. But not
// as quickly as for a discrete event.
gate(flags =>
flags.enableIsInputPending
? 'Yield at 10ms'
: // When isInputPending is disabled, we always yield quickly
'Yield at 5ms',
),
'Yield at 5ms',
'Continuous Event',
]);
},
Expand All @@ -451,12 +428,7 @@ describe('SchedulerBrowser', () => {
runtime.assertLog([
'Message Event',
'Task with no paint',
gate(flags =>
flags.enableIsInputPending
? 'Yield at 10ms'
: // When isInputPending is disabled, we always yield quickly
'Yield at 5ms',
),
'Yield at 5ms',
]);

runtime.resetTime();
Expand Down
73 changes: 2 additions & 71 deletions packages/scheduler/src/forks/Scheduler.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,7 @@ import type {PriorityLevel} from '../SchedulerPriorities';
import {
enableSchedulerDebugging,
enableProfiling,
enableIsInputPending,
enableIsInputPendingContinuous,
frameYieldMs,
continuousYieldMs,
maxYieldMs,
userBlockingPriorityTimeout,
lowPriorityTimeout,
normalPriorityTimeout,
Expand Down Expand Up @@ -104,17 +100,6 @@ const localClearTimeout =
const localSetImmediate =
typeof setImmediate !== 'undefined' ? setImmediate : null; // IE and Node.js + jsdom

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;

const continuousOptions = {includeContinuous: enableIsInputPendingContinuous};

function advanceTimers(currentTime: number) {
// Check for tasks that are no longer delayed and add them to the queue.
let timer = peek(timerQueue);
Expand Down Expand Up @@ -468,71 +453,20 @@ let taskTimeoutID: TimeoutID = (-1: any);
// It does not attempt to align with frame boundaries, since most tasks don't
// need to be frame aligned; for those that do, use requestAnimationFrame.
let frameInterval = frameYieldMs;
const continuousInputInterval = continuousYieldMs;
const maxInterval = maxYieldMs;
let startTime = -1;

let needsPaint = false;

function shouldYieldToHost(): boolean {
const timeElapsed = getCurrentTime() - startTime;
if (timeElapsed < frameInterval) {
// The main thread has only been blocked for a really short amount of time;
// smaller than a single frame. Don't yield yet.
return false;
}

// The main thread has been blocked for a non-negligible amount of time. We
// may want to yield control of the main thread, so the browser can perform
// high priority tasks. The main ones are painting and user input. If there's
// a pending paint or a pending input, then we should yield. But if there's
// neither, then we can yield less often while remaining responsive. We'll
// eventually yield regardless, since there could be a pending paint that
// wasn't accompanied by a call to `requestPaint`, or other main thread tasks
// like network events.
if (enableIsInputPending) {
if (needsPaint) {
// There's a pending paint (signaled by `requestPaint`). Yield now.
return true;
}
if (timeElapsed < continuousInputInterval) {
// We haven't blocked the thread for that long. Only yield if there's a
// pending discrete input (e.g. click). It's OK if there's pending
// continuous input (e.g. mouseover).
if (isInputPending !== null) {
return isInputPending();
}
} else if (timeElapsed < maxInterval) {
// Yield if there's either a pending discrete or continuous input.
if (isInputPending !== null) {
return isInputPending(continuousOptions);
}
} else {
// We've blocked the thread for a long time. Even if there's no pending
// input, there may be some other scheduled work that we don't know about,
// like a network event. Yield now.
return true;
}
}

// `isInputPending` isn't available. Yield now.
// Yield now.
return true;
}

function requestPaint() {
if (
enableIsInputPending &&
navigator !== undefined &&
// $FlowFixMe[prop-missing]
navigator.scheduling !== undefined &&
// $FlowFixMe[incompatible-type]
navigator.scheduling.isInputPending !== undefined
) {
needsPaint = true;
}

// Since we yield every frame regardless, `requestPaint` has no effect.
}
function requestPaint() {}

function forceFrameRate(fps: number) {
if (fps < 0 || fps > 125) {
Expand Down Expand Up @@ -577,9 +511,6 @@ const performWorkUntilDeadline = () => {
}
}
}
// Yielding to the browser will give it a chance to paint, so we can
// reset this.
needsPaint = false;
};

let schedulePerformWorkUntilDeadline;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,7 @@

export const enableProfiling = __VARIANT__;

export const enableIsInputPending = __VARIANT__;
export const enableIsInputPendingContinuous = __VARIANT__;
export const frameYieldMs = 5;
export const continuousYieldMs = 10;
export const maxYieldMs = 10;

export const userBlockingPriorityTimeout = 250;
export const normalPriorityTimeout = 5000;
Expand Down
4 changes: 0 additions & 4 deletions packages/scheduler/src/forks/SchedulerFeatureFlags.www.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,7 @@ export const {
userBlockingPriorityTimeout,
normalPriorityTimeout,
lowPriorityTimeout,
enableIsInputPending,
enableIsInputPendingContinuous,
frameYieldMs,
continuousYieldMs,
maxYieldMs,
} = dynamicFeatureFlags;
export const enableSchedulerDebugging = true;
export const enableProfiling: boolean =
Expand Down

0 comments on commit 02543f6

Please sign in to comment.