Skip to content

Commit 530027a

Browse files
committed
Use EventPriority to track update priority (facebook#21082)
Instead of LanePriority. Internally, EventPriority is just a lane, so this skips an extra conversion. Since EventPriority is a "public" (to the host config) type, I was also able to remove some deep imports of the Lane module. This gets us most of the way to deleting the LanePriority entirely.
1 parent 6a589ad commit 530027a

25 files changed

+494
-479
lines changed

packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,7 @@ let ReactFeatureFlags;
1717
let Suspense;
1818
let SuspenseList;
1919
let act;
20-
21-
// Copied from ReactFiberLanes. Don't do this!
22-
// This is hard coded directly to avoid needing to import, and
23-
// we'll remove this as we replace runWithPriority with React APIs.
24-
export const IdleLanePriority = 2;
20+
let IdleEventPriority;
2521

2622
function dispatchMouseEvent(to, from) {
2723
if (!to) {
@@ -89,6 +85,8 @@ describe('ReactDOMServerPartialHydration', () => {
8985
Scheduler = require('scheduler');
9086
Suspense = React.Suspense;
9187
SuspenseList = React.SuspenseList;
88+
89+
IdleEventPriority = require('react-reconciler/constants').IdleEventPriority;
9290
});
9391

9492
// Note: This is based on a similar component we use in www. We can delete
@@ -628,7 +626,7 @@ describe('ReactDOMServerPartialHydration', () => {
628626
expect(span.textContent).toBe('Hello');
629627

630628
// Schedule an update at idle priority
631-
ReactDOM.unstable_runWithPriority(IdleLanePriority, () => {
629+
ReactDOM.unstable_runWithPriority(IdleEventPriority, () => {
632630
root.render(<App text="Hi" className="hi" />);
633631
});
634632

packages/react-dom/src/__tests__/ReactDOMServerSelectiveHydration-test.internal.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,7 @@ let Scheduler;
1919
let Suspense;
2020
let act;
2121

22-
// Copied from ReactFiberLanes. Don't do this!
23-
// This is hard coded directly to avoid needing to import, and
24-
// we'll remove this as we replace runWithPriority with React APIs.
25-
export const IdleLanePriority = 2;
22+
let IdleEventPriority;
2623

2724
function dispatchMouseHoverEvent(to, from) {
2825
if (!to) {
@@ -101,7 +98,7 @@ function dispatchClickEvent(target) {
10198
// and there's no native DOM event that maps to idle priority, so this is a
10299
// temporary workaround. Need something like ReactDOM.unstable_IdleUpdates.
103100
function TODO_scheduleIdleDOMSchedulerTask(fn) {
104-
ReactDOM.unstable_runWithPriority(IdleLanePriority, () => {
101+
ReactDOM.unstable_runWithPriority(IdleEventPriority, () => {
105102
const prevEvent = window.event;
106103
window.event = {type: 'message'};
107104
try {
@@ -125,6 +122,8 @@ describe('ReactDOMServerSelectiveHydration', () => {
125122
act = ReactTestUtils.unstable_concurrentAct;
126123
Scheduler = require('scheduler');
127124
Suspense = React.Suspense;
125+
126+
IdleEventPriority = require('react-reconciler/constants').IdleEventPriority;
128127
});
129128

130129
// @gate experimental

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@ import {
3535
attemptDiscreteHydration,
3636
attemptContinuousHydration,
3737
attemptHydrationAtCurrentPriority,
38-
runWithPriority,
39-
getCurrentUpdateLanePriority,
4038
} from 'react-reconciler/src/ReactFiberReconciler';
39+
import {
40+
runWithPriority,
41+
getCurrentUpdatePriority,
42+
} from 'react-reconciler/src/ReactEventPriorities';
4143
import {createPortal as createPortalImpl} from 'react-reconciler/src/ReactPortal';
4244
import {canUseDOM} from 'shared/ExecutionEnvironment';
4345
import ReactVersion from 'shared/ReactVersion';
@@ -74,7 +76,7 @@ setAttemptSynchronousHydration(attemptSynchronousHydration);
7476
setAttemptDiscreteHydration(attemptDiscreteHydration);
7577
setAttemptContinuousHydration(attemptContinuousHydration);
7678
setAttemptHydrationAtCurrentPriority(attemptHydrationAtCurrentPriority);
77-
setGetCurrentUpdatePriority(getCurrentUpdateLanePriority);
79+
setGetCurrentUpdatePriority(getCurrentUpdatePriority);
7880
setAttemptHydrationAtPriority(runWithPriority);
7981

8082
let didWarnAboutUnstableCreatePortal = false;

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

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,6 @@ import {
4444
discreteUpdates,
4545
} from './ReactDOMUpdateBatching';
4646

47-
import {
48-
InputContinuousLanePriority as InputContinuousLanePriority_old,
49-
getCurrentUpdateLanePriority as getCurrentUpdateLanePriority_old,
50-
setCurrentUpdateLanePriority as setCurrentUpdateLanePriority_old,
51-
} from 'react-reconciler/src/ReactFiberLane.old';
52-
import {
53-
InputContinuousLanePriority as InputContinuousLanePriority_new,
54-
getCurrentUpdateLanePriority as getCurrentUpdateLanePriority_new,
55-
setCurrentUpdateLanePriority as setCurrentUpdateLanePriority_new,
56-
} from 'react-reconciler/src/ReactFiberLane.new';
5747
import {getCurrentPriorityLevel as getCurrentPriorityLevel_old} from 'react-reconciler/src/SchedulerWithReactIntegration.old';
5848
import {
5949
getCurrentPriorityLevel as getCurrentPriorityLevel_new,
@@ -68,19 +58,10 @@ import {
6858
ContinuousEventPriority,
6959
DefaultEventPriority,
7060
IdleEventPriority,
61+
getCurrentUpdatePriority,
62+
setCurrentUpdatePriority,
7163
} from 'react-reconciler/src/ReactEventPriorities';
7264

73-
// TODO: These should use the opaque EventPriority type instead of LanePriority.
74-
// Then internally we can use a Lane.
75-
const InputContinuousLanePriority = enableNewReconciler
76-
? InputContinuousLanePriority_new
77-
: InputContinuousLanePriority_old;
78-
const getCurrentUpdateLanePriority = enableNewReconciler
79-
? getCurrentUpdateLanePriority_new
80-
: getCurrentUpdateLanePriority_old;
81-
const setCurrentUpdateLanePriority = enableNewReconciler
82-
? setCurrentUpdateLanePriority_new
83-
: setCurrentUpdateLanePriority_old;
8465
const getCurrentPriorityLevel = enableNewReconciler
8566
? getCurrentPriorityLevel_new
8667
: getCurrentPriorityLevel_old;
@@ -167,12 +148,12 @@ function dispatchContinuousEvent(
167148
container,
168149
nativeEvent,
169150
) {
170-
const previousPriority = getCurrentUpdateLanePriority();
151+
const previousPriority = getCurrentUpdatePriority();
171152
try {
172-
setCurrentUpdateLanePriority(InputContinuousLanePriority);
153+
setCurrentUpdatePriority(ContinuousEventPriority);
173154
dispatchEvent(domEventName, eventSystemFlags, container, nativeEvent);
174155
} finally {
175-
setCurrentUpdateLanePriority(previousPriority);
156+
setCurrentUpdatePriority(previousPriority);
176157
}
177158
}
178159

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

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import type {Container, SuspenseInstance} from '../client/ReactDOMHostConfig';
1212
import type {DOMEventName} from '../events/DOMEventNames';
1313
import type {EventSystemFlags} from './EventSystemFlags';
1414
import type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
15-
import type {LanePriority} from 'react-reconciler/src/ReactFiberLane.old';
15+
import type {EventPriority} from 'react-reconciler/src/ReactEventPriorities';
1616

1717
import {enableSelectiveHydration} from 'shared/ReactFeatureFlags';
1818
import {
@@ -30,6 +30,7 @@ import {
3030
getClosestInstanceFromNode,
3131
} from '../client/ReactDOMComponentTree';
3232
import {HostRoot, SuspenseComponent} from 'react-reconciler/src/ReactWorkTags';
33+
import {isHigherEventPriority} from 'react-reconciler/src/ReactEventPriorities';
3334

3435
let attemptSynchronousHydration: (fiber: Object) => void;
3536

@@ -57,16 +58,16 @@ export function setAttemptHydrationAtCurrentPriority(
5758
attemptHydrationAtCurrentPriority = fn;
5859
}
5960

60-
let getCurrentUpdatePriority: () => LanePriority;
61+
let getCurrentUpdatePriority: () => EventPriority;
6162

62-
export function setGetCurrentUpdatePriority(fn: () => LanePriority) {
63+
export function setGetCurrentUpdatePriority(fn: () => EventPriority) {
6364
getCurrentUpdatePriority = fn;
6465
}
6566

66-
let attemptHydrationAtPriority: <T>(priority: LanePriority, fn: () => T) => T;
67+
let attemptHydrationAtPriority: <T>(priority: EventPriority, fn: () => T) => T;
6768

6869
export function setAttemptHydrationAtPriority(
69-
fn: <T>(priority: LanePriority, fn: () => T) => T,
70+
fn: <T>(priority: EventPriority, fn: () => T) => T,
7071
) {
7172
attemptHydrationAtPriority = fn;
7273
}
@@ -109,7 +110,7 @@ const queuedPointerCaptures: Map<number, QueuedReplayableEvent> = new Map();
109110
type QueuedHydrationTarget = {|
110111
blockedOn: null | Container | SuspenseInstance,
111112
target: Node,
112-
lanePriority: LanePriority,
113+
priority: EventPriority,
113114
|};
114115
const queuedExplicitHydrationTargets: Array<QueuedHydrationTarget> = [];
115116

@@ -390,7 +391,7 @@ function attemptExplicitHydrationTarget(
390391
// We're blocked on hydrating this boundary.
391392
// Increase its priority.
392393
queuedTarget.blockedOn = instance;
393-
attemptHydrationAtPriority(queuedTarget.lanePriority, () => {
394+
attemptHydrationAtPriority(queuedTarget.priority, () => {
394395
attemptHydrationAtCurrentPriority(nearestMounted);
395396
});
396397

@@ -412,16 +413,23 @@ function attemptExplicitHydrationTarget(
412413

413414
export function queueExplicitHydrationTarget(target: Node): void {
414415
if (enableSelectiveHydration) {
415-
const updateLanePriority = getCurrentUpdatePriority();
416+
// TODO: This will read the priority if it's dispatched by the React
417+
// event system but not native events. Should read window.event.type, like
418+
// we do for updates (getCurrentEventPriority).
419+
const updatePriority = getCurrentUpdatePriority();
416420
const queuedTarget: QueuedHydrationTarget = {
417421
blockedOn: null,
418422
target: target,
419-
lanePriority: updateLanePriority,
423+
priority: updatePriority,
420424
};
421425
let i = 0;
422426
for (; i < queuedExplicitHydrationTargets.length; i++) {
427+
// Stop once we hit the first target with lower priority than
423428
if (
424-
updateLanePriority <= queuedExplicitHydrationTargets[i].lanePriority
429+
!isHigherEventPriority(
430+
updatePriority,
431+
queuedExplicitHydrationTargets[i].priority,
432+
)
425433
) {
426434
break;
427435
}

packages/react-reconciler/src/ReactEventPriorities.js

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,61 @@ import {
1414
ContinuousEventPriority as ContinuousEventPriority_old,
1515
DefaultEventPriority as DefaultEventPriority_old,
1616
IdleEventPriority as IdleEventPriority_old,
17+
getCurrentUpdatePriority as getCurrentUpdatePriority_old,
18+
setCurrentUpdatePriority as setCurrentUpdatePriority_old,
19+
runWithPriority as runWithPriority_old,
20+
isHigherEventPriority as isHigherEventPriority_old,
1721
} from './ReactEventPriorities.old';
1822

1923
import {
2024
DiscreteEventPriority as DiscreteEventPriority_new,
2125
ContinuousEventPriority as ContinuousEventPriority_new,
2226
DefaultEventPriority as DefaultEventPriority_new,
2327
IdleEventPriority as IdleEventPriority_new,
28+
getCurrentUpdatePriority as getCurrentUpdatePriority_new,
29+
setCurrentUpdatePriority as setCurrentUpdatePriority_new,
30+
runWithPriority as runWithPriority_new,
31+
isHigherEventPriority as isHigherEventPriority_new,
2432
} from './ReactEventPriorities.new';
2533

26-
export const DiscreteEventPriority = enableNewReconciler
27-
? DiscreteEventPriority_new
28-
: DiscreteEventPriority_old;
29-
export const ContinuousEventPriority = enableNewReconciler
30-
? ContinuousEventPriority_new
31-
: ContinuousEventPriority_old;
32-
export const DefaultEventPriority = enableNewReconciler
33-
? DefaultEventPriority_new
34-
: DefaultEventPriority_old;
35-
export const IdleEventPriority = enableNewReconciler
36-
? IdleEventPriority_new
37-
: IdleEventPriority_old;
34+
export opaque type EventPriority = number;
35+
36+
export const DiscreteEventPriority: EventPriority = enableNewReconciler
37+
? (DiscreteEventPriority_new: any)
38+
: (DiscreteEventPriority_old: any);
39+
export const ContinuousEventPriority: EventPriority = enableNewReconciler
40+
? (ContinuousEventPriority_new: any)
41+
: (ContinuousEventPriority_old: any);
42+
export const DefaultEventPriority: EventPriority = enableNewReconciler
43+
? (DefaultEventPriority_new: any)
44+
: (DefaultEventPriority_old: any);
45+
export const IdleEventPriority: EventPriority = enableNewReconciler
46+
? (IdleEventPriority_new: any)
47+
: (IdleEventPriority_old: any);
48+
49+
export function runWithPriority<T>(priority: EventPriority, fn: () => T): T {
50+
return enableNewReconciler
51+
? runWithPriority_new((priority: any), fn)
52+
: runWithPriority_old((priority: any), fn);
53+
}
54+
55+
export function getCurrentUpdatePriority(): EventPriority {
56+
return enableNewReconciler
57+
? (getCurrentUpdatePriority_new(): any)
58+
: (getCurrentUpdatePriority_old(): any);
59+
}
60+
61+
export function setCurrentUpdatePriority(priority: EventPriority) {
62+
return enableNewReconciler
63+
? setCurrentUpdatePriority_new((priority: any))
64+
: setCurrentUpdatePriority_old((priority: any));
65+
}
66+
67+
export function isHigherEventPriority(
68+
a: EventPriority,
69+
b: EventPriority,
70+
): boolean {
71+
return enableNewReconciler
72+
? isHigherEventPriority_new((a: any), (b: any))
73+
: isHigherEventPriority_old((a: any), (b: any));
74+
}

packages/react-reconciler/src/ReactEventPriorities.new.js

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,76 @@
77
* @flow
88
*/
99

10-
export {
11-
SyncLane as DiscreteEventPriority,
12-
InputContinuousLane as ContinuousEventPriority,
13-
DefaultLane as DefaultEventPriority,
14-
IdleLane as IdleEventPriority,
10+
import type {Lane, Lanes} from './ReactFiberLane.new';
11+
12+
import {
13+
NoLane,
14+
SyncLane,
15+
InputContinuousLane,
16+
DefaultLane,
17+
IdleLane,
18+
getHighestPriorityLane,
19+
includesNonIdleWork,
1520
} from './ReactFiberLane.new';
21+
22+
export opaque type EventPriority = Lane;
23+
24+
export const DiscreteEventPriority: EventPriority = SyncLane;
25+
export const ContinuousEventPriority: EventPriority = InputContinuousLane;
26+
export const DefaultEventPriority: EventPriority = DefaultLane;
27+
export const IdleEventPriority: EventPriority = IdleLane;
28+
29+
let currentUpdatePriority: EventPriority = NoLane;
30+
31+
export function getCurrentUpdatePriority(): EventPriority {
32+
return currentUpdatePriority;
33+
}
34+
35+
export function setCurrentUpdatePriority(newPriority: EventPriority) {
36+
currentUpdatePriority = newPriority;
37+
}
38+
39+
export function runWithPriority<T>(priority: EventPriority, fn: () => T): T {
40+
const previousPriority = currentUpdatePriority;
41+
try {
42+
currentUpdatePriority = priority;
43+
return fn();
44+
} finally {
45+
currentUpdatePriority = previousPriority;
46+
}
47+
}
48+
49+
export function higherEventPriority(
50+
a: EventPriority,
51+
b: EventPriority,
52+
): EventPriority {
53+
return a !== 0 && a < b ? a : b;
54+
}
55+
56+
export function lowerEventPriority(
57+
a: EventPriority,
58+
b: EventPriority,
59+
): EventPriority {
60+
return a === 0 || a > b ? a : b;
61+
}
62+
63+
export function isHigherEventPriority(
64+
a: EventPriority,
65+
b: EventPriority,
66+
): boolean {
67+
return a !== 0 && a < b;
68+
}
69+
70+
export function lanesToEventPriority(lanes: Lanes): EventPriority {
71+
const lane = getHighestPriorityLane(lanes);
72+
if (!isHigherEventPriority(DiscreteEventPriority, lane)) {
73+
return DiscreteEventPriority;
74+
}
75+
if (!isHigherEventPriority(ContinuousEventPriority, lane)) {
76+
return ContinuousEventPriority;
77+
}
78+
if (includesNonIdleWork(lane)) {
79+
return DefaultEventPriority;
80+
}
81+
return IdleEventPriority;
82+
}

0 commit comments

Comments
 (0)