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

[scheduler] Deadline object -> shouldYield #14025

Merged
merged 2 commits into from
Oct 30, 2018
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/react-art/src/ReactARTHostConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
export {
unstable_now as now,
unstable_scheduleCallback as scheduleDeferredCallback,
unstable_shouldYield as shouldYield,
unstable_cancelCallback as cancelDeferredCallback,
} from 'scheduler';
import Transform from 'art/core/transform';
Expand Down
1 change: 1 addition & 0 deletions packages/react-dom/src/client/ReactDOMHostConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export type NoTimeout = -1;
export {
unstable_now as now,
unstable_scheduleCallback as scheduleDeferredCallback,
unstable_shouldYield as shouldYield,
unstable_cancelCallback as cancelDeferredCallback,
} from 'scheduler';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ export const scheduleDeferredCallback =
ReactNativeFrameScheduling.scheduleDeferredCallback;
export const cancelDeferredCallback =
ReactNativeFrameScheduling.cancelDeferredCallback;
export const shouldYield = ReactNativeFrameScheduling.shouldYield;

export const scheduleTimeout = setTimeout;
export const cancelTimeout = clearTimeout;
Expand Down
21 changes: 8 additions & 13 deletions packages/react-native-renderer/src/ReactNativeFrameScheduling.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,16 @@
* @flow
*/

import type {Deadline} from 'react-reconciler/src/ReactFiberScheduler';

const hasNativePerformanceNow =
typeof performance === 'object' && typeof performance.now === 'function';

const now = hasNativePerformanceNow
? () => performance.now()
: () => Date.now();

type Callback = (deadline: Deadline) => void;

let scheduledCallback: Callback | null = null;
let scheduledCallback: (() => mixed) | null = null;
let frameDeadline: number = 0;

const frameDeadlineObject: Deadline = {
timeRemaining: () => frameDeadline - now(),
didTimeout: false,
};

function setTimeoutCallback() {
// TODO (bvaughn) Hard-coded 5ms unblocks initial async testing.
// React API probably changing to boolean rather than time remaining.
Expand All @@ -36,15 +27,15 @@ function setTimeoutCallback() {
const callback = scheduledCallback;
scheduledCallback = null;
if (callback !== null) {
callback(frameDeadlineObject);
callback();
}
}

// RN has a poor polyfill for requestIdleCallback so we aren't using it.
// This implementation is only intended for short-term use anyway.
// We also don't implement cancel functionality b'c Fiber doesn't currently need it.
function scheduleDeferredCallback(
callback: Callback,
callback: () => mixed,
options?: {timeout: number},
): number {
// We assume only one callback is scheduled at a time b'c that's how Fiber works.
Expand All @@ -58,4 +49,8 @@ function cancelDeferredCallback(callbackID: number) {
clearTimeout((callbackID: any)); // Timeouts are always numbers on RN
}

export {now, scheduleDeferredCallback, cancelDeferredCallback};
function shouldYield() {
return frameDeadline <= now();
}

export {now, scheduleDeferredCallback, cancelDeferredCallback, shouldYield};
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ export const scheduleDeferredCallback =
ReactNativeFrameScheduling.scheduleDeferredCallback;
export const cancelDeferredCallback =
ReactNativeFrameScheduling.cancelDeferredCallback;
export const shouldYield = ReactNativeFrameScheduling.shouldYield;

export const scheduleTimeout = setTimeout;
export const cancelTimeout = clearTimeout;
Expand Down
63 changes: 37 additions & 26 deletions packages/react-noop-renderer/src/createReactNoop.js
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
scheduledCallbackTimeout === -1 ||
scheduledCallbackTimeout > newTimeout
) {
scheduledCallbackTimeout = newTimeout;
scheduledCallbackTimeout = elapsedTimeInMs + newTimeout;
}
}
return 0;
Expand All @@ -285,6 +285,8 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
scheduledCallbackTimeout = -1;
},

shouldYield,

scheduleTimeout: setTimeout,
cancelTimeout: clearTimeout,
noTimeout: -1,
Expand Down Expand Up @@ -407,35 +409,44 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {

let yieldedValues = null;

let didYield;
let unitsRemaining;

function shouldYield() {
if (
scheduledCallbackTimeout === -1 ||
elapsedTimeInMs > scheduledCallbackTimeout
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's early and I'm probably being stupid, but shouldn't this be elapsedTimeInMs < scheduledCallbackTimeout ?

Edit Never mind. This is just saying that we should never yield if work has already timed out.

) {
return false;
} else {
if (didYield || yieldedValues !== null) {
return true;
}
if (unitsRemaining-- > 0) {
return false;
}
didYield = true;
return true;
}
}

function* flushUnitsOfWork(n: number): Generator<Array<mixed>, void, void> {
let didStop = false;
while (!didStop && scheduledCallback !== null) {
let cb = scheduledCallback;
scheduledCallback = null;
unitsRemaining = n;
cb({
timeRemaining() {
if (yieldedValues !== null) {
return 0;
}
if (unitsRemaining-- > 0) {
return 999;
}
didStop = true;
return 0;
},
didTimeout:
scheduledCallbackTimeout !== -1 &&
elapsedTimeInMs > scheduledCallbackTimeout,
});

if (yieldedValues !== null) {
const values = yieldedValues;
yieldedValues = null;
yield values;
unitsRemaining = n + 1;
didYield = false;
try {
while (!didYield && scheduledCallback !== null) {
let cb = scheduledCallback;
scheduledCallback = null;
cb();
if (yieldedValues !== null) {
const values = yieldedValues;
yieldedValues = null;
yield values;
}
}
} finally {
unitsRemaining = -1;
didYield = false;
}
}

Expand Down
Loading