mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
61777a78f6
* [schedule] Use linked list instead of queue and map for storing cbs NOTE: This PR depends on https://github.com/facebook/react/pull/12880 and https://github.com/facebook/react/pull/12884 Please review those first, and after they land Flarnie will rebase on top of them. --- **what is the change?:** See title **why make this change?:** This seems to make the code simpler, and potentially saves space of having an array and object around holding references to the callbacks. **test plan:** Run existing tests * minor style improvements * refactor conditionals in cancelScheduledWork for increased clarity * Remove 'canUseDOM' condition and fix some flow issues w/callbackID type **what is the change?:** - Removed conditional which fell back to 'setTimeout' when the environment doesn't have DOM. This appears to be an old polyfill used for test environments and we don't use it any more. - Fixed type definitions around the callbackID to be more accurate in the scheduler itself, and more loose in the React code. **why make this change?:** To get Flow passing, simplify the scheduler code, make things accurate. **test plan:** Run tests and flow. * Rewrite 'cancelScheduledWork' so that Flow accepts it **what is the change?:** Adding verification that 'previousCallbackConfig' and 'nextCallbackConfig' are not null before accessing properties on them. Slightly concerned because this implementation relies on these properties being untouched and correct on the config which is passed to 'cancelScheduledWork' but I guess we already rely heavily on that for this whole approach. :\ **why make this change?:** To get Flow passing. Not sure why it passed earlier and in CI, but now it's not. **test plan:** `yarn flow dom` and other flow tests, lint, tests, etc. * ran prettier * Put back the fallback implementation of scheduler for node environment **what is the change?:** We had tried removing the fallback implementation of `scheduler` but tests reminded us that this is important for supporting isomorphic uses of React. Long term we will move this out of the `schedule` module but for now let's keep things simple. **why make this change?:** Keep things working! **test plan:** Ran tests and flow * Shorten properties stored in objects by sheduler **what is the change?:** `previousScheduledCallback` -> `prev` `nextScheduledCallback` -> `next` **why make this change?:** We want this package to be smaller, and less letters means less code means smaller! **test plan:** ran existing tests * further remove extra lines in scheduler
117 lines
3.2 KiB
JavaScript
117 lines
3.2 KiB
JavaScript
/**
|
|
* Copyright (c) 2013-present, Facebook, Inc.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @flow
|
|
*/
|
|
|
|
import type {Deadline} from 'react-reconciler/src/ReactFiberScheduler';
|
|
|
|
// Current virtual time
|
|
export let nowImplementation = () => 0;
|
|
export let scheduledCallback: ((deadline: Deadline) => mixed) | null = null;
|
|
export let yieldedValues: Array<mixed> | null = null;
|
|
|
|
export function scheduleDeferredCallback(
|
|
callback: (deadline: Deadline) => mixed,
|
|
options?: {timeout: number},
|
|
): number {
|
|
scheduledCallback = callback;
|
|
const fakeCallbackId = 0;
|
|
return fakeCallbackId;
|
|
}
|
|
|
|
export function cancelDeferredCallback(timeoutID: number): void {
|
|
scheduledCallback = null;
|
|
}
|
|
|
|
export function setNowImplementation(implementation: () => number): void {
|
|
nowImplementation = implementation;
|
|
}
|
|
|
|
export function flushAll(): Array<mixed> {
|
|
yieldedValues = null;
|
|
while (scheduledCallback !== null) {
|
|
const cb = scheduledCallback;
|
|
scheduledCallback = null;
|
|
cb({
|
|
timeRemaining() {
|
|
// Keep rendering until there's no more work
|
|
return 999;
|
|
},
|
|
// React's scheduler has its own way of keeping track of expired
|
|
// work and doesn't read this, so don't bother setting it to the
|
|
// correct value.
|
|
didTimeout: false,
|
|
});
|
|
}
|
|
if (yieldedValues === null) {
|
|
// Always return an array.
|
|
return [];
|
|
}
|
|
return yieldedValues;
|
|
}
|
|
|
|
export function flushThrough(expectedValues: Array<mixed>): Array<mixed> {
|
|
let didStop = false;
|
|
yieldedValues = null;
|
|
while (scheduledCallback !== null && !didStop) {
|
|
const cb = scheduledCallback;
|
|
scheduledCallback = null;
|
|
cb({
|
|
timeRemaining() {
|
|
if (
|
|
yieldedValues !== null &&
|
|
yieldedValues.length >= expectedValues.length
|
|
) {
|
|
// We at least as many values as expected. Stop rendering.
|
|
didStop = true;
|
|
return 0;
|
|
}
|
|
// Keep rendering.
|
|
return 999;
|
|
},
|
|
// React's scheduler has its own way of keeping track of expired
|
|
// work and doesn't read this, so don't bother setting it to the
|
|
// correct value.
|
|
didTimeout: false,
|
|
});
|
|
}
|
|
if (yieldedValues === null) {
|
|
// Always return an array.
|
|
yieldedValues = [];
|
|
}
|
|
for (let i = 0; i < expectedValues.length; i++) {
|
|
const expectedValue = `"${(expectedValues[i]: any)}"`;
|
|
const yieldedValue =
|
|
i < yieldedValues.length ? `"${(yieldedValues[i]: any)}"` : 'nothing';
|
|
if (yieldedValue !== expectedValue) {
|
|
const error = new Error(
|
|
`flushThrough expected to yield ${(expectedValue: any)}, but ${(yieldedValue: any)} was yielded`,
|
|
);
|
|
// Attach expected and yielded arrays,
|
|
// So the caller could pretty print the diff (if desired).
|
|
(error: any).expectedValues = expectedValues;
|
|
(error: any).actualValues = yieldedValues;
|
|
throw error;
|
|
}
|
|
}
|
|
return yieldedValues;
|
|
}
|
|
|
|
export function yieldValue(value: mixed): void {
|
|
if (yieldedValues === null) {
|
|
yieldedValues = [value];
|
|
} else {
|
|
yieldedValues.push(value);
|
|
}
|
|
}
|
|
|
|
export function withCleanYields(fn: Function) {
|
|
yieldedValues = [];
|
|
fn();
|
|
return yieldedValues;
|
|
}
|