From b09af77b8295486b210a2c99a9d2104c73632cbc Mon Sep 17 00:00:00 2001 From: Andrew Clark Date: Sun, 28 Mar 2021 16:13:38 -0500 Subject: [PATCH] Remove Scheduler indirection (#21107) * Bump version number * Remove Scheduler indirection I originally kept the React PriorityLevel and Scheduler PriorityLevel types separate in case there was a versioning mismatch between the two modules. However, it looks like we're going to keep the Scheduler module private in the short to medium term, and longer term the public interface will match postTask. So, I've removed the extra indirection (the switch statements that convert between the two types). --- packages/react-art/package.json | 4 +- .../__tests__/preprocessData-test.internal.js | 2 +- .../src/backend/renderer.js | 13 +- packages/react-dom/package.json | 4 +- packages/react-is/package.json | 2 +- packages/react-reconciler/package.json | 2 +- .../src/ReactFiberHooks.new.js | 2 - .../src/ReactFiberHooks.old.js | 2 - .../src/ReactInternalTypes.js | 2 - .../src/SchedulerWithReactIntegration.new.js | 115 +++--------------- .../src/SchedulerWithReactIntegration.old.js | 115 +++--------------- packages/react-test-renderer/package.json | 6 +- packages/react/package.json | 2 +- packages/shared/ReactVersion.js | 6 +- 14 files changed, 62 insertions(+), 215 deletions(-) diff --git a/packages/react-art/package.json b/packages/react-art/package.json index ae977717034e8..00b1c30d982fe 100644 --- a/packages/react-art/package.json +++ b/packages/react-art/package.json @@ -1,7 +1,7 @@ { "name": "react-art", "description": "React ART is a JavaScript library for drawing vector graphics using React. It provides declarative and reactive bindings to the ART library. Using the same declarative API you can render the output to either Canvas, SVG or VML (IE8).", - "version": "17.0.2", + "version": "17.0.3", "main": "index.js", "repository": { "type": "git", @@ -29,7 +29,7 @@ "scheduler": "^0.20.1" }, "peerDependencies": { - "react": "17.0.2" + "react": "17.0.3" }, "files": [ "LICENSE", diff --git a/packages/react-devtools-scheduling-profiler/src/import-worker/__tests__/preprocessData-test.internal.js b/packages/react-devtools-scheduling-profiler/src/import-worker/__tests__/preprocessData-test.internal.js index 4945b5fdb4d54..59933cf6900b0 100644 --- a/packages/react-devtools-scheduling-profiler/src/import-worker/__tests__/preprocessData-test.internal.js +++ b/packages/react-devtools-scheduling-profiler/src/import-worker/__tests__/preprocessData-test.internal.js @@ -517,7 +517,7 @@ describe(preprocessData, () => { timestamp: 0.003, }, { - name: '--react-init-17.0.2', + name: '--react-init-17.0.3', timestamp: 0.004, }, ], diff --git a/packages/react-devtools-shared/src/backend/renderer.js b/packages/react-devtools-shared/src/backend/renderer.js index 3bc2abe46a912..050a4e709ab32 100644 --- a/packages/react-devtools-shared/src/backend/renderer.js +++ b/packages/react-devtools-shared/src/backend/renderer.js @@ -159,7 +159,7 @@ export function getInternalReactConstants( // Technically these priority levels are invalid for versions before 16.9, // but 16.9 is the first version to report priority level to DevTools, // so we can avoid checking for earlier versions and support pre-16.9 canary releases in the process. - const ReactPriorityLevels: ReactPriorityLevelsType = { + let ReactPriorityLevels: ReactPriorityLevelsType = { ImmediatePriority: 99, UserBlockingPriority: 98, NormalPriority: 97, @@ -168,6 +168,17 @@ export function getInternalReactConstants( NoPriority: 90, }; + if (gt(version, '17.0.2')) { + ReactPriorityLevels = { + ImmediatePriority: 1, + UserBlockingPriority: 2, + NormalPriority: 3, + LowPriority: 4, + IdlePriority: 5, + NoPriority: 0, + }; + } + let ReactTypeOfWork: WorkTagMap = ((null: any): WorkTagMap); // ********************************************************** diff --git a/packages/react-dom/package.json b/packages/react-dom/package.json index 5e8991e898772..b5fdf2c991ac7 100644 --- a/packages/react-dom/package.json +++ b/packages/react-dom/package.json @@ -1,6 +1,6 @@ { "name": "react-dom", - "version": "17.0.2", + "version": "17.0.3", "description": "React package for working with the DOM.", "main": "index.js", "repository": { @@ -22,7 +22,7 @@ "scheduler": "^0.20.1" }, "peerDependencies": { - "react": "17.0.2" + "react": "17.0.3" }, "files": [ "LICENSE", diff --git a/packages/react-is/package.json b/packages/react-is/package.json index 1a6567dcff5e9..0637792729f18 100644 --- a/packages/react-is/package.json +++ b/packages/react-is/package.json @@ -1,6 +1,6 @@ { "name": "react-is", - "version": "17.0.2", + "version": "17.0.3", "description": "Brand checking of React Elements.", "main": "index.js", "repository": { diff --git a/packages/react-reconciler/package.json b/packages/react-reconciler/package.json index 7a681953eeb2e..14ca5c03670e8 100644 --- a/packages/react-reconciler/package.json +++ b/packages/react-reconciler/package.json @@ -27,7 +27,7 @@ "node": ">=0.10.0" }, "peerDependencies": { - "react": "^17.0.2" + "react": "^17.0.3" }, "dependencies": { "loose-envify": "^1.1.0", diff --git a/packages/react-reconciler/src/ReactFiberHooks.new.js b/packages/react-reconciler/src/ReactFiberHooks.new.js index f47627053fc9a..0c7e2e4846d8f 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.new.js +++ b/packages/react-reconciler/src/ReactFiberHooks.new.js @@ -16,7 +16,6 @@ import type { import type {Fiber, Dispatcher, HookType} from './ReactInternalTypes'; import type {Lanes, Lane} from './ReactFiberLane.new'; import type {HookFlags} from './ReactHookEffectTags'; -import type {ReactPriorityLevel} from './ReactInternalTypes'; import type {FiberRoot} from './ReactInternalTypes'; import type {OpaqueIDType} from './ReactFiberHostConfig'; import type {Cache} from './ReactFiberCacheComponent.new'; @@ -120,7 +119,6 @@ type Update = {| eagerReducer: ((S, A) => S) | null, eagerState: S | null, next: Update, - priority?: ReactPriorityLevel, |}; export type UpdateQueue = {| diff --git a/packages/react-reconciler/src/ReactFiberHooks.old.js b/packages/react-reconciler/src/ReactFiberHooks.old.js index 7673d88caecdb..6d5d355f0d711 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.old.js +++ b/packages/react-reconciler/src/ReactFiberHooks.old.js @@ -16,7 +16,6 @@ import type { import type {Fiber, Dispatcher, HookType} from './ReactInternalTypes'; import type {Lanes, Lane} from './ReactFiberLane.old'; import type {HookFlags} from './ReactHookEffectTags'; -import type {ReactPriorityLevel} from './ReactInternalTypes'; import type {FiberRoot} from './ReactInternalTypes'; import type {OpaqueIDType} from './ReactFiberHostConfig'; import type {Cache} from './ReactFiberCacheComponent.old'; @@ -120,7 +119,6 @@ type Update = {| eagerReducer: ((S, A) => S) | null, eagerState: S | null, next: Update, - priority?: ReactPriorityLevel, |}; export type UpdateQueue = {| diff --git a/packages/react-reconciler/src/ReactInternalTypes.js b/packages/react-reconciler/src/ReactInternalTypes.js index 93305e156abcf..53d3203439314 100644 --- a/packages/react-reconciler/src/ReactInternalTypes.js +++ b/packages/react-reconciler/src/ReactInternalTypes.js @@ -45,8 +45,6 @@ export type HookType = | 'useOpaqueIdentifier' | 'useCacheRefresh'; -export type ReactPriorityLevel = 99 | 98 | 97 | 96 | 95 | 90; - export type ContextDependency = { context: ReactContext, next: ContextDependency | null, diff --git a/packages/react-reconciler/src/SchedulerWithReactIntegration.new.js b/packages/react-reconciler/src/SchedulerWithReactIntegration.new.js index 685285dffd808..c686cfe12aac6 100644 --- a/packages/react-reconciler/src/SchedulerWithReactIntegration.new.js +++ b/packages/react-reconciler/src/SchedulerWithReactIntegration.new.js @@ -7,10 +7,10 @@ * @flow */ -import type {ReactPriorityLevel} from './ReactInternalTypes'; - -// Intentionally not named imports because Rollup would use dynamic dispatch for -// CommonJS interop named imports. +// This module only exists as an ESM wrapper around the external CommonJS +// Scheduler dependency. Notice that we're intentionally not using named imports +// because Rollup would use dynamic dispatch for CommonJS interop named imports. +// When we switch to ESM, we can delete this module. import * as Scheduler from 'scheduler'; import {__interactionsRef} from 'scheduler/tracing'; import {enableSchedulerTracing} from 'shared/ReactFeatureFlags'; @@ -21,19 +21,18 @@ import { setCurrentUpdatePriority, } from './ReactEventPriorities.new'; -const { - unstable_scheduleCallback: Scheduler_scheduleCallback, - unstable_cancelCallback: Scheduler_cancelCallback, - unstable_shouldYield: Scheduler_shouldYield, - unstable_requestPaint: Scheduler_requestPaint, - unstable_now: Scheduler_now, - unstable_getCurrentPriorityLevel: Scheduler_getCurrentPriorityLevel, - unstable_ImmediatePriority: Scheduler_ImmediatePriority, - unstable_UserBlockingPriority: Scheduler_UserBlockingPriority, - unstable_NormalPriority: Scheduler_NormalPriority, - unstable_LowPriority: Scheduler_LowPriority, - unstable_IdlePriority: Scheduler_IdlePriority, -} = Scheduler; +export const scheduleCallback = Scheduler.unstable_scheduleCallback; +export const cancelCallback = Scheduler.unstable_cancelCallback; +export const shouldYield = Scheduler.unstable_shouldYield; +export const requestPaint = Scheduler.unstable_requestPaint; +export const now = Scheduler.unstable_now; +export const getCurrentPriorityLevel = + Scheduler.unstable_getCurrentPriorityLevel; +export const ImmediatePriority = Scheduler.unstable_ImmediatePriority; +export const UserBlockingPriority = Scheduler.unstable_UserBlockingPriority; +export const NormalPriority = Scheduler.unstable_NormalPriority; +export const LowPriority = Scheduler.unstable_LowPriority; +export const IdlePriority = Scheduler.unstable_IdlePriority; if (enableSchedulerTracing) { // Provide explicit error message when production+profiling bundle of e.g. @@ -51,80 +50,9 @@ if (enableSchedulerTracing) { export type SchedulerCallback = (isSync: boolean) => SchedulerCallback | null; -type SchedulerCallbackOptions = {timeout?: number, ...}; - -// Except for NoPriority, these correspond to Scheduler priorities. We use -// ascending numbers so we can compare them like numbers. They start at 90 to -// avoid clashing with Scheduler's priorities. -export const ImmediatePriority: ReactPriorityLevel = 99; -export const UserBlockingPriority: ReactPriorityLevel = 98; -export const NormalPriority: ReactPriorityLevel = 97; -export const LowPriority: ReactPriorityLevel = 96; -export const IdlePriority: ReactPriorityLevel = 95; -// NoPriority is the absence of priority. Also React-only. -export const NoPriority: ReactPriorityLevel = 90; - -export const shouldYield = Scheduler_shouldYield; -export const requestPaint = - // Fall back gracefully if we're running an older version of Scheduler. - Scheduler_requestPaint !== undefined ? Scheduler_requestPaint : () => {}; - +// TODO: Move sync task queue to its own module. let syncQueue: Array | null = null; let isFlushingSyncQueue: boolean = false; -const initialTimeMs: number = Scheduler_now(); - -// If the initial timestamp is reasonably small, use Scheduler's `now` directly. -// This will be the case for modern browsers that support `performance.now`. In -// older browsers, Scheduler falls back to `Date.now`, which returns a Unix -// timestamp. In that case, subtract the module initialization time to simulate -// the behavior of performance.now and keep our times small enough to fit -// within 32 bits. -// TODO: Consider lifting this into Scheduler. -export const now = - initialTimeMs < 10000 ? Scheduler_now : () => Scheduler_now() - initialTimeMs; - -export function getCurrentPriorityLevel(): ReactPriorityLevel { - switch (Scheduler_getCurrentPriorityLevel()) { - case Scheduler_ImmediatePriority: - return ImmediatePriority; - case Scheduler_UserBlockingPriority: - return UserBlockingPriority; - case Scheduler_NormalPriority: - return NormalPriority; - case Scheduler_LowPriority: - return LowPriority; - case Scheduler_IdlePriority: - return IdlePriority; - default: - invariant(false, 'Unknown priority level.'); - } -} - -function reactPriorityToSchedulerPriority(reactPriorityLevel) { - switch (reactPriorityLevel) { - case ImmediatePriority: - return Scheduler_ImmediatePriority; - case UserBlockingPriority: - return Scheduler_UserBlockingPriority; - case NormalPriority: - return Scheduler_NormalPriority; - case LowPriority: - return Scheduler_LowPriority; - case IdlePriority: - return Scheduler_IdlePriority; - default: - invariant(false, 'Unknown priority level.'); - } -} - -export function scheduleCallback( - reactPriorityLevel: ReactPriorityLevel, - callback: SchedulerCallback, - options: SchedulerCallbackOptions | void | null, -) { - const priorityLevel = reactPriorityToSchedulerPriority(reactPriorityLevel); - return Scheduler_scheduleCallback(priorityLevel, callback, options); -} export function scheduleSyncCallback(callback: SchedulerCallback) { // Push this callback into an internal queue. We'll flush these either in @@ -138,10 +66,6 @@ export function scheduleSyncCallback(callback: SchedulerCallback) { } } -export function cancelCallback(callbackNode: mixed) { - Scheduler_cancelCallback(callbackNode); -} - export function flushSyncCallbackQueue() { if (!isFlushingSyncQueue && syncQueue !== null) { // Prevent re-entrancy. @@ -167,10 +91,7 @@ export function flushSyncCallbackQueue() { syncQueue = syncQueue.slice(i + 1); } // Resume flushing in the next tick - Scheduler_scheduleCallback( - Scheduler_ImmediatePriority, - flushSyncCallbackQueue, - ); + scheduleCallback(ImmediatePriority, flushSyncCallbackQueue); throw error; } finally { setCurrentUpdatePriority(previousUpdatePriority); diff --git a/packages/react-reconciler/src/SchedulerWithReactIntegration.old.js b/packages/react-reconciler/src/SchedulerWithReactIntegration.old.js index 142b04333adbf..9a57e77cb89fe 100644 --- a/packages/react-reconciler/src/SchedulerWithReactIntegration.old.js +++ b/packages/react-reconciler/src/SchedulerWithReactIntegration.old.js @@ -7,10 +7,10 @@ * @flow */ -import type {ReactPriorityLevel} from './ReactInternalTypes'; - -// Intentionally not named imports because Rollup would use dynamic dispatch for -// CommonJS interop named imports. +// This module only exists as an ESM wrapper around the external CommonJS +// Scheduler dependency. Notice that we're intentionally not using named imports +// because Rollup would use dynamic dispatch for CommonJS interop named imports. +// When we switch to ESM, we can delete this module. import * as Scheduler from 'scheduler'; import {__interactionsRef} from 'scheduler/tracing'; import {enableSchedulerTracing} from 'shared/ReactFeatureFlags'; @@ -21,19 +21,18 @@ import { setCurrentUpdatePriority, } from './ReactEventPriorities.old'; -const { - unstable_scheduleCallback: Scheduler_scheduleCallback, - unstable_cancelCallback: Scheduler_cancelCallback, - unstable_shouldYield: Scheduler_shouldYield, - unstable_requestPaint: Scheduler_requestPaint, - unstable_now: Scheduler_now, - unstable_getCurrentPriorityLevel: Scheduler_getCurrentPriorityLevel, - unstable_ImmediatePriority: Scheduler_ImmediatePriority, - unstable_UserBlockingPriority: Scheduler_UserBlockingPriority, - unstable_NormalPriority: Scheduler_NormalPriority, - unstable_LowPriority: Scheduler_LowPriority, - unstable_IdlePriority: Scheduler_IdlePriority, -} = Scheduler; +export const scheduleCallback = Scheduler.unstable_scheduleCallback; +export const cancelCallback = Scheduler.unstable_cancelCallback; +export const shouldYield = Scheduler.unstable_shouldYield; +export const requestPaint = Scheduler.unstable_requestPaint; +export const now = Scheduler.unstable_now; +export const getCurrentPriorityLevel = + Scheduler.unstable_getCurrentPriorityLevel; +export const ImmediatePriority = Scheduler.unstable_ImmediatePriority; +export const UserBlockingPriority = Scheduler.unstable_UserBlockingPriority; +export const NormalPriority = Scheduler.unstable_NormalPriority; +export const LowPriority = Scheduler.unstable_LowPriority; +export const IdlePriority = Scheduler.unstable_IdlePriority; if (enableSchedulerTracing) { // Provide explicit error message when production+profiling bundle of e.g. @@ -51,80 +50,9 @@ if (enableSchedulerTracing) { export type SchedulerCallback = (isSync: boolean) => SchedulerCallback | null; -type SchedulerCallbackOptions = {timeout?: number, ...}; - -// Except for NoPriority, these correspond to Scheduler priorities. We use -// ascending numbers so we can compare them like numbers. They start at 90 to -// avoid clashing with Scheduler's priorities. -export const ImmediatePriority: ReactPriorityLevel = 99; -export const UserBlockingPriority: ReactPriorityLevel = 98; -export const NormalPriority: ReactPriorityLevel = 97; -export const LowPriority: ReactPriorityLevel = 96; -export const IdlePriority: ReactPriorityLevel = 95; -// NoPriority is the absence of priority. Also React-only. -export const NoPriority: ReactPriorityLevel = 90; - -export const shouldYield = Scheduler_shouldYield; -export const requestPaint = - // Fall back gracefully if we're running an older version of Scheduler. - Scheduler_requestPaint !== undefined ? Scheduler_requestPaint : () => {}; - +// TODO: Move sync task queue to its own module. let syncQueue: Array | null = null; let isFlushingSyncQueue: boolean = false; -const initialTimeMs: number = Scheduler_now(); - -// If the initial timestamp is reasonably small, use Scheduler's `now` directly. -// This will be the case for modern browsers that support `performance.now`. In -// older browsers, Scheduler falls back to `Date.now`, which returns a Unix -// timestamp. In that case, subtract the module initialization time to simulate -// the behavior of performance.now and keep our times small enough to fit -// within 32 bits. -// TODO: Consider lifting this into Scheduler. -export const now = - initialTimeMs < 10000 ? Scheduler_now : () => Scheduler_now() - initialTimeMs; - -export function getCurrentPriorityLevel(): ReactPriorityLevel { - switch (Scheduler_getCurrentPriorityLevel()) { - case Scheduler_ImmediatePriority: - return ImmediatePriority; - case Scheduler_UserBlockingPriority: - return UserBlockingPriority; - case Scheduler_NormalPriority: - return NormalPriority; - case Scheduler_LowPriority: - return LowPriority; - case Scheduler_IdlePriority: - return IdlePriority; - default: - invariant(false, 'Unknown priority level.'); - } -} - -function reactPriorityToSchedulerPriority(reactPriorityLevel) { - switch (reactPriorityLevel) { - case ImmediatePriority: - return Scheduler_ImmediatePriority; - case UserBlockingPriority: - return Scheduler_UserBlockingPriority; - case NormalPriority: - return Scheduler_NormalPriority; - case LowPriority: - return Scheduler_LowPriority; - case IdlePriority: - return Scheduler_IdlePriority; - default: - invariant(false, 'Unknown priority level.'); - } -} - -export function scheduleCallback( - reactPriorityLevel: ReactPriorityLevel, - callback: SchedulerCallback, - options: SchedulerCallbackOptions | void | null, -) { - const priorityLevel = reactPriorityToSchedulerPriority(reactPriorityLevel); - return Scheduler_scheduleCallback(priorityLevel, callback, options); -} export function scheduleSyncCallback(callback: SchedulerCallback) { // Push this callback into an internal queue. We'll flush these either in @@ -138,10 +66,6 @@ export function scheduleSyncCallback(callback: SchedulerCallback) { } } -export function cancelCallback(callbackNode: mixed) { - Scheduler_cancelCallback(callbackNode); -} - export function flushSyncCallbackQueue() { if (!isFlushingSyncQueue && syncQueue !== null) { // Prevent re-entrancy. @@ -167,10 +91,7 @@ export function flushSyncCallbackQueue() { syncQueue = syncQueue.slice(i + 1); } // Resume flushing in the next tick - Scheduler_scheduleCallback( - Scheduler_ImmediatePriority, - flushSyncCallbackQueue, - ); + scheduleCallback(ImmediatePriority, flushSyncCallbackQueue); throw error; } finally { setCurrentUpdatePriority(previousUpdatePriority); diff --git a/packages/react-test-renderer/package.json b/packages/react-test-renderer/package.json index ea62201e24b1a..1daa2c54308f1 100644 --- a/packages/react-test-renderer/package.json +++ b/packages/react-test-renderer/package.json @@ -1,6 +1,6 @@ { "name": "react-test-renderer", - "version": "17.0.2", + "version": "17.0.3", "description": "React package for snapshot testing.", "main": "index.js", "repository": { @@ -20,12 +20,12 @@ "homepage": "https://reactjs.org/", "dependencies": { "object-assign": "^4.1.1", - "react-is": "^17.0.2", + "react-is": "^17.0.3", "react-shallow-renderer": "^16.13.1", "scheduler": "^0.20.1" }, "peerDependencies": { - "react": "17.0.2" + "react": "17.0.3" }, "files": [ "LICENSE", diff --git a/packages/react/package.json b/packages/react/package.json index 311982f5c3544..0ab41de16ca59 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -4,7 +4,7 @@ "keywords": [ "react" ], - "version": "17.0.2", + "version": "17.0.3", "homepage": "https://reactjs.org/", "bugs": "https://github.com/facebook/react/issues", "license": "MIT", diff --git a/packages/shared/ReactVersion.js b/packages/shared/ReactVersion.js index 0404e3972272e..69b37a19f0379 100644 --- a/packages/shared/ReactVersion.js +++ b/packages/shared/ReactVersion.js @@ -7,7 +7,7 @@ // TODO: this is special because it gets imported during build. // -// TODO: 17.0.2 has not been released to NPM; +// TODO: 17.0.3 has not been released to NPM; // It exists as a placeholder so that DevTools can support work tag changes between releases. -// When we next publish a release (either 17.0.2 or 17.1.0), update the matching TODO in backend/renderer.js -export default '17.0.2'; +// When we next publish a release (either 17.0.3 or 17.1.0), update the matching TODO in backend/renderer.js +export default '17.0.3';