Skip to content

Commit 91a2e81

Browse files
authored
Decouple update priority tracking from Scheduler package (#19121)
* Initial currentLanePriority implementation * Minor updates from review * Fix typos and enable flag * Fix feature flags and lint * Fix simple event tests by switching to withSuspenseConfig * Don't lower the priority of setPending in startTransition below InputContinuous * Move currentUpdateLanePriority in commit root into the first effect block * Refactor requestUpdateLane to log for priority mismatches Also verifies that the update lane priority matches the scheduler lane priority before using it * Fix four tests by adding ReactDOM.unstable_runWithPriority * Fix partial hydration when using update lane priority * Fix partial hydration when using update lane priority * Rename feature flag and only log for now * Move unstable_runWithPriority to ReactFiberReconciler * Add unstable_runWithPriority to ReactNoopPersistent too * Bug fixes and performance improvements * Initial currentLanePriority implementation * Minor updates from review * Fix typos and enable flag * Remove higherLanePriority from ReactDOMEventReplaying.js * Change warning implementation and startTransition update lane priority * Inject reconciler functions to avoid importing src/ * Fix feature flags and lint * Fix simple event tests by switching to withSuspenseConfig * Don't lower the priority of setPending in startTransition below InputContinuous * Move currentUpdateLanePriority in commit root into the first effect block * Refactor requestUpdateLane to log for priority mismatches Also verifies that the update lane priority matches the scheduler lane priority before using it * Fix four tests by adding ReactDOM.unstable_runWithPriority * Fix partial hydration when using update lane priority * Fix partial hydration when using update lane priority * Rename feature flag and only log for now * Move unstable_runWithPriority to ReactFiberReconciler * Bug fixes and performance improvements * Remove higherLanePriority from ReactDOMEventReplaying.js * Change warning implementation and startTransition update lane priority * Inject reconciler functions to avoid importing src/ * Fixes from bad rebase
1 parent c3e42a9 commit 91a2e81

31 files changed

Lines changed: 394 additions & 65 deletions

packages/react-dom/index.classic.fb.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export {
3434
createBlockingRoot as unstable_createBlockingRoot,
3535
unstable_flushControlled,
3636
unstable_scheduleHydration,
37+
unstable_runWithPriority,
3738
unstable_renderSubtreeIntoContainer,
3839
unstable_createPortal,
3940
unstable_createEventHandle,

packages/react-dom/index.experimental.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ export {
2323
createBlockingRoot as unstable_createBlockingRoot,
2424
unstable_flushControlled,
2525
unstable_scheduleHydration,
26+
// DO NOT USE: Temporarily exposing this to migrate off of Scheduler.runWithPriority.
27+
unstable_runWithPriority,
2628
// Disabled behind disableUnstableRenderSubtreeIntoContainer
2729
unstable_renderSubtreeIntoContainer,
2830
// Disabled behind disableUnstableCreatePortal

packages/react-dom/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export {
2525
createBlockingRoot as unstable_createBlockingRoot,
2626
unstable_flushControlled,
2727
unstable_scheduleHydration,
28+
unstable_runWithPriority,
2829
unstable_renderSubtreeIntoContainer,
2930
unstable_createPortal,
3031
unstable_createEventHandle,

packages/react-dom/index.modern.fb.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export {
1919
createBlockingRoot as unstable_createBlockingRoot,
2020
unstable_flushControlled,
2121
unstable_scheduleHydration,
22+
unstable_runWithPriority,
2223
unstable_createEventHandle,
2324
unstable_isNewReconciler,
2425
} from './src/client/ReactDOM';

packages/react-dom/src/client/ReactDOM.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ import {
3535
attemptUserBlockingHydration,
3636
attemptContinuousHydration,
3737
attemptHydrationAtCurrentPriority,
38+
runWithPriority,
39+
getCurrentUpdatePriority,
3840
} from 'react-reconciler/src/ReactFiberReconciler';
3941
import {createPortal as createPortalImpl} from 'react-reconciler/src/ReactPortal';
4042
import {canUseDOM} from 'shared/ExecutionEnvironment';
@@ -58,6 +60,8 @@ import {
5860
setAttemptContinuousHydration,
5961
setAttemptHydrationAtCurrentPriority,
6062
queueExplicitHydrationTarget,
63+
setGetCurrentUpdatePriority,
64+
setAttemptHydrationAtPriority,
6165
} from '../events/ReactDOMEventReplaying';
6266
import {setBatchingImplementation} from '../events/ReactDOMUpdateBatching';
6367
import {
@@ -70,6 +74,8 @@ setAttemptSynchronousHydration(attemptSynchronousHydration);
7074
setAttemptUserBlockingHydration(attemptUserBlockingHydration);
7175
setAttemptContinuousHydration(attemptContinuousHydration);
7276
setAttemptHydrationAtCurrentPriority(attemptHydrationAtCurrentPriority);
77+
setGetCurrentUpdatePriority(getCurrentUpdatePriority);
78+
setAttemptHydrationAtPriority(runWithPriority);
7379

7480
let didWarnAboutUnstableCreatePortal = false;
7581
let didWarnAboutUnstableRenderSubtreeIntoContainer = false;
@@ -205,6 +211,9 @@ export {
205211
unstable_createPortal,
206212
// enableCreateEventHandleAPI
207213
createEventHandle as unstable_createEventHandle,
214+
// TODO: Remove this once callers migrate to alternatives.
215+
// This should only be used by React internals.
216+
runWithPriority as unstable_runWithPriority,
208217
};
209218

210219
const foundDevTools = injectIntoDevTools({

packages/react-dom/src/events/ReactDOMEventReplaying.js

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ import type {Container, SuspenseInstance} from '../client/ReactDOMHostConfig';
1212
import type {DOMTopLevelEventType} from '../events/TopLevelEventTypes';
1313
import type {ElementListenerMap} from '../client/ReactDOMComponentTree';
1414
import type {EventSystemFlags} from './EventSystemFlags';
15-
import type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
15+
import type {
16+
FiberRoot,
17+
ReactPriorityLevel,
18+
} from 'react-reconciler/src/ReactInternalTypes';
1619

1720
import {
1821
enableDeprecatedFlareAPI,
@@ -64,6 +67,23 @@ export function setAttemptHydrationAtCurrentPriority(
6467
attemptHydrationAtCurrentPriority = fn;
6568
}
6669

70+
let getCurrentUpdatePriority: () => ReactPriorityLevel;
71+
72+
export function setGetCurrentUpdatePriority(fn: () => ReactPriorityLevel) {
73+
getCurrentUpdatePriority = fn;
74+
}
75+
76+
let attemptHydrationAtPriority: <T>(
77+
priority: ReactPriorityLevel,
78+
fn: () => T,
79+
) => T;
80+
81+
export function setAttemptHydrationAtPriority(
82+
fn: <T>(priority: ReactPriorityLevel, fn: () => T) => T,
83+
) {
84+
attemptHydrationAtPriority = fn;
85+
}
86+
6787
// TODO: Upgrade this definition once we're on a newer version of Flow that
6888
// has this definition built-in.
6989
type PointerEvent = Event & {
@@ -147,6 +167,7 @@ type QueuedHydrationTarget = {|
147167
blockedOn: null | Container | SuspenseInstance,
148168
target: Node,
149169
priority: number,
170+
lanePriority: ReactPriorityLevel,
150171
|};
151172
const queuedExplicitHydrationTargets: Array<QueuedHydrationTarget> = [];
152173

@@ -508,9 +529,12 @@ function attemptExplicitHydrationTarget(
508529
// We're blocked on hydrating this boundary.
509530
// Increase its priority.
510531
queuedTarget.blockedOn = instance;
511-
runWithPriority(queuedTarget.priority, () => {
512-
attemptHydrationAtCurrentPriority(nearestMounted);
532+
attemptHydrationAtPriority(queuedTarget.lanePriority, () => {
533+
runWithPriority(queuedTarget.priority, () => {
534+
attemptHydrationAtCurrentPriority(nearestMounted);
535+
});
513536
});
537+
514538
return;
515539
}
516540
} else if (tag === HostRoot) {
@@ -529,15 +553,17 @@ function attemptExplicitHydrationTarget(
529553

530554
export function queueExplicitHydrationTarget(target: Node): void {
531555
if (enableSelectiveHydration) {
532-
const priority = getCurrentPriorityLevel();
556+
const schedulerPriority = getCurrentPriorityLevel();
557+
const updateLanePriority = getCurrentUpdatePriority();
533558
const queuedTarget: QueuedHydrationTarget = {
534559
blockedOn: null,
535560
target: target,
536-
priority: priority,
561+
priority: schedulerPriority,
562+
lanePriority: updateLanePriority,
537563
};
538564
let i = 0;
539565
for (; i < queuedExplicitHydrationTargets.length; i++) {
540-
if (priority <= queuedExplicitHydrationTargets[i].priority) {
566+
if (schedulerPriority <= queuedExplicitHydrationTargets[i].priority) {
541567
break;
542568
}
543569
}

packages/react-dom/src/events/plugins/__tests__/ModernSimpleEventPlugin-test.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,8 @@ describe('SimpleEventPlugin', function() {
231231
describe('interactive events, in concurrent mode', () => {
232232
beforeEach(() => {
233233
jest.resetModules();
234+
235+
React = require('react');
234236
ReactDOM = require('react-dom');
235237
Scheduler = require('scheduler');
236238
});
@@ -377,11 +379,14 @@ describe('SimpleEventPlugin', function() {
377379
<button
378380
ref={el => (button = el)}
379381
onClick={() => {
380-
Scheduler.unstable_next(() => {
381-
this.setState(state => ({
382-
lowPriCount: state.lowPriCount + 1,
383-
}));
384-
});
382+
React.unstable_withSuspenseConfig(
383+
() => {
384+
this.setState(state => ({
385+
lowPriCount: state.lowPriCount + 1,
386+
}));
387+
},
388+
{timeoutMs: 5000},
389+
);
385390
}}>
386391
{text}
387392
</button>

packages/react-noop-renderer/src/ReactNoop.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ export const {
4747
act,
4848
dumpTree,
4949
getRoot,
50+
// TODO: Remove this once callers migrate to alternatives.
51+
// This should only be used by React internals.
52+
unstable_runWithPriority,
5053
} = createReactNoop(
5154
ReactFiberReconciler, // reconciler
5255
true, // useMutation

packages/react-noop-renderer/src/ReactNoopPersistent.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ export const {
4747
act,
4848
dumpTree,
4949
getRoot,
50+
// TODO: Remove this once callers migrate to alternatives.
51+
// This should only be used by React internals.
52+
unstable_runWithPriority,
5053
} = createReactNoop(
5154
ReactFiberReconciler, // reconciler
5255
false, // useMutation

packages/react-noop-renderer/src/createReactNoop.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,8 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
954954
return Scheduler.unstable_flushExpired();
955955
},
956956

957+
unstable_runWithPriority: NoopRenderer.runWithPriority,
958+
957959
batchedUpdates: NoopRenderer.batchedUpdates,
958960

959961
deferredUpdates: NoopRenderer.deferredUpdates,

0 commit comments

Comments
 (0)