@samitouri / QOS-React-2 / commits / d0eaf78293

Move priorities to separate import to break cycle (#21060)

The event priority constants exports by the reconciler package are meant to be used by the reconciler (host config) itself. So it doesn't make sense to export them from a module that requires them. To break the cycle, we can move them to a separate module and import that. This looks like a "deep import" of an internal module, which we try to avoid, but conceptually these are part of the public interface of the reconciler module. So, no different than importing from the main `react-reconciler`. We do need to be careful about not mixing these types of imports with implementation details. Those are the ones to really avoid. An unintended benefit of the reconciler fork infra is that it makes deep imports harder. Any module that we treat as "public", like this one, needs to account for the `enableNewReconciler` flag and forward to the correct implementation.

Andrew Clark committed Mar 23, 2021 at 15:57 UTC d0eaf782930b6e6c575f50bf688e667b9f6795b7
13 files changed +129 -86
packages/react-art/src/ReactARTHostConfig.js
+2 -8
@@ -7,17 +7,11 @@
7
8 import Transform from 'art/core/transform';
9 import Mode from 'art/modes/current';
10 -import {enableNewReconciler} from 'shared/ReactFeatureFlags';
10 import invariant from 'shared/invariant';
11
12 import {TYPES, EVENT_TYPES, childrenAsString} from './ReactARTInternals';
13
15 -import {DefaultLanePriority as DefaultLanePriority_old} from 'react-reconciler/src/ReactFiberLane.old';
16 -import {DefaultLanePriority as DefaultLanePriority_new} from 'react-reconciler/src/ReactFiberLane.new';
17 -
18 -const DefaultLanePriority = enableNewReconciler
19 - ? DefaultLanePriority_new
20 - : DefaultLanePriority_old;
14 +import {DefaultEventPriority} from 'react-reconciler/src/ReactEventPriorities';
15
16 const pooledTransform = new Transform();
17
@@ -347,7 +341,7 @@ export function shouldSetTextContent(type, props) {
341 }
342
343 export function getCurrentEventPriority() {
350 - return DefaultLanePriority;
344 + return DefaultEventPriority;
345 }
346
347 // The ART renderer is secondary to the React DOM renderer.
packages/react-dom/src/client/ReactDOMHostConfig.js
+2 -8
@@ -67,17 +67,11 @@ import {
67 enableSuspenseServerRenderer,
68 enableCreateEventHandleAPI,
69 enableScopeAPI,
70 - enableNewReconciler,
70 } from 'shared/ReactFeatureFlags';
71 import {HostComponent, HostText} from 'react-reconciler/src/ReactWorkTags';
72 import {listenToAllSupportedEvents} from '../events/DOMPluginEventSystem';
73
75 -import {DefaultLanePriority as DefaultLanePriority_old} from 'react-reconciler/src/ReactFiberLane.old';
76 -import {DefaultLanePriority as DefaultLanePriority_new} from 'react-reconciler/src/ReactFiberLane.new';
77 -
78 -const DefaultLanePriority = enableNewReconciler
79 - ? DefaultLanePriority_new
80 - : DefaultLanePriority_old;
74 +import {DefaultEventPriority} from 'react-reconciler/src/ReactEventPriorities';
75
76 export type Type = string;
77 export type Props = {
@@ -385,7 +379,7 @@ export function createTextInstance(
379 export function getCurrentEventPriority(): * {
380 const currentEvent = window.event;
381 if (currentEvent === undefined) {
388 - return DefaultLanePriority;
382 + return DefaultEventPriority;
383 }
384 return getEventPriority(currentEvent.type);
385 }
packages/react-dom/src/events/ReactDOMEventListener.js
+18 -20
@@ -14,6 +14,7 @@ import type {
14 } from 'react-reconciler/src/ReactInternalTypes';
15 import type {Container, SuspenseInstance} from '../client/ReactDOMHostConfig';
16 import type {DOMEventName} from '../events/DOMEventNames';
17 +import type {LanePriority} from 'react-reconciler/src/ReactFiberLane.new';
18
19 import {
20 isReplayableDiscreteEvent,
@@ -49,18 +50,13 @@ import {
50
51 import {
52 InputContinuousLanePriority as InputContinuousLanePriority_old,
52 - DefaultLanePriority as DefaultLanePriority_old,
53 getCurrentUpdateLanePriority as getCurrentUpdateLanePriority_old,
54 setCurrentUpdateLanePriority as setCurrentUpdateLanePriority_old,
55 } from 'react-reconciler/src/ReactFiberLane.old';
56 import {
57 InputContinuousLanePriority as InputContinuousLanePriority_new,
58 - DefaultLanePriority as DefaultLanePriority_new,
58 getCurrentUpdateLanePriority as getCurrentUpdateLanePriority_new,
59 setCurrentUpdateLanePriority as setCurrentUpdateLanePriority_new,
61 - SyncLanePriority,
62 - IdleLanePriority,
63 - NoLanePriority,
60 } from 'react-reconciler/src/ReactFiberLane.new';
61 import {getCurrentPriorityLevel as getCurrentPriorityLevel_old} from 'react-reconciler/src/SchedulerWithReactIntegration.old';
62 import {
@@ -71,14 +67,16 @@ import {
67 NormalPriority as NormalSchedulerPriority,
68 UserBlockingPriority as UserBlockingSchedulerPriority,
69 } from 'react-reconciler/src/SchedulerWithReactIntegration.new';
74 -import type {LanePriority} from 'react-reconciler/src/ReactFiberLane.new';
70 +import {
71 + DiscreteEventPriority,
72 + ContinuousEventPriority,
73 + DefaultEventPriority,
74 + IdleEventPriority,
75 +} from 'react-reconciler/src/ReactEventPriorities';
76
77 const InputContinuousLanePriority = enableNewReconciler
78 ? InputContinuousLanePriority_new
79 : InputContinuousLanePriority_old;
79 -const DefaultLanePriority = enableNewReconciler
80 - ? DefaultLanePriority_new
81 - : DefaultLanePriority_old;
80 const getCurrentUpdateLanePriority = enableNewReconciler
81 ? getCurrentUpdateLanePriority_new
82 : getCurrentUpdateLanePriority_old;
@@ -94,17 +92,17 @@ function schedulerPriorityToLanePriority(
92 ): LanePriority {
93 switch (schedulerPriorityLevel) {
94 case ImmediateSchedulerPriority:
97 - return SyncLanePriority;
95 + return DiscreteEventPriority;
96 case UserBlockingSchedulerPriority:
99 - return InputContinuousLanePriority;
97 + return ContinuousEventPriority;
98 case NormalSchedulerPriority:
99 case LowSchedulerPriority:
100 // TODO: Handle LowSchedulerPriority, somehow. Maybe the same lane as hydration.
103 - return DefaultLanePriority;
101 + return DefaultEventPriority;
102 case IdleSchedulerPriority:
105 - return IdleLanePriority;
103 + return IdleEventPriority;
104 default:
107 - return NoLanePriority;
105 + return DefaultEventPriority;
106 }
107 }
108
@@ -142,13 +140,13 @@ export function createEventListenerWrapperWithPriority(
140 const eventPriority = getEventPriority(domEventName);
141 let listenerWrapper;
142 switch (eventPriority) {
145 - case SyncLanePriority:
143 + case DiscreteEventPriority:
144 listenerWrapper = dispatchDiscreteEvent;
145 break;
148 - case InputContinuousLanePriority:
146 + case ContinuousEventPriority:
147 listenerWrapper = dispatchContinuousEvent;
148 break;
151 - case DefaultLanePriority:
149 + case DefaultEventPriority:
150 default:
151 listenerWrapper = dispatchEvent;
152 break;
@@ -407,7 +405,7 @@ export function getEventPriority(domEventName: DOMEventName): * {
405 case 'popstate':
406 case 'select':
407 case 'selectstart':
410 - return SyncLanePriority;
408 + return DiscreteEventPriority;
409 case 'drag':
410 case 'dragenter':
411 case 'dragexit':
@@ -427,7 +425,7 @@ export function getEventPriority(domEventName: DOMEventName): * {
425 // eslint-disable-next-line no-fallthrough
426 case 'mouseenter':
427 case 'mouseleave':
430 - return InputContinuousLanePriority;
428 + return ContinuousEventPriority;
429 case 'message': {
430 // We might be in the Scheduler callback.
431 // Eventually this mechanism will be replaced by a check
@@ -436,6 +434,6 @@ export function getEventPriority(domEventName: DOMEventName): * {
434 return schedulerPriorityToLanePriority(schedulerPriority);
435 }
436 default:
439 - return DefaultLanePriority;
437 + return DefaultEventPriority;
438 }
439 }
packages/react-native-renderer/src/ReactFabricHostConfig.js
+2 -8
@@ -21,17 +21,11 @@ import type {
21 import {mountSafeCallback_NOT_REALLY_SAFE} from './NativeMethodsMixinUtils';
22 import {create, diff} from './ReactNativeAttributePayload';
23
24 -import {enableNewReconciler} from 'shared/ReactFeatureFlags';
24 import invariant from 'shared/invariant';
25
26 import {dispatchEvent} from './ReactFabricEventEmitter';
27
29 -import {DefaultLanePriority as DefaultLanePriority_old} from 'react-reconciler/src/ReactFiberLane.old';
30 -import {DefaultLanePriority as DefaultLanePriority_new} from 'react-reconciler/src/ReactFiberLane.new';
31 -
32 -const DefaultLanePriority = enableNewReconciler
33 - ? DefaultLanePriority_new
34 - : DefaultLanePriority_old;
28 +import {DefaultEventPriority} from 'react-reconciler/src/ReactEventPriorities';
29
30 // Modules provided by RN:
31 import {
@@ -349,7 +343,7 @@ export function shouldSetTextContent(type: string, props: Props): boolean {
343 }
344
345 export function getCurrentEventPriority(): * {
352 - return DefaultLanePriority;
346 + return DefaultEventPriority;
347 }
348
349 // The Fabric renderer is secondary to the existing React Native renderer.
packages/react-native-renderer/src/ReactNativeHostConfig.js
+2 -8
@@ -10,7 +10,6 @@
10 import type {TouchedViewDataAtPoint} from './ReactNativeTypes';
11
12 import invariant from 'shared/invariant';
13 -import {enableNewReconciler} from 'shared/ReactFeatureFlags';
13
14 // Modules provided by RN:
15 import {
@@ -27,12 +26,7 @@ import {
26 } from './ReactNativeComponentTree';
27 import ReactNativeFiberHostComponent from './ReactNativeFiberHostComponent';
28
30 -import {DefaultLanePriority as DefaultLanePriority_old} from 'react-reconciler/src/ReactFiberLane.old';
31 -import {DefaultLanePriority as DefaultLanePriority_new} from 'react-reconciler/src/ReactFiberLane.new';
32 -
33 -const DefaultLanePriority = enableNewReconciler
34 - ? DefaultLanePriority_new
35 - : DefaultLanePriority_old;
29 +import {DefaultEventPriority} from 'react-reconciler/src/ReactEventPriorities';
30
31 const {get: getViewConfigForType} = ReactNativeViewConfigRegistry;
32
@@ -268,7 +262,7 @@ export function shouldSetTextContent(type: string, props: Props): boolean {
262 }
263
264 export function getCurrentEventPriority(): * {
271 - return DefaultLanePriority;
265 + return DefaultEventPriority;
266 }
267
268 // -------------------
packages/react-noop-renderer/src/createReactNoop.js
+4 -1
@@ -27,6 +27,9 @@ import ReactSharedInternals from 'shared/ReactSharedInternals';
27 import enqueueTask from 'shared/enqueueTask';
28 const {IsSomeRendererActing} = ReactSharedInternals;
29
30 +// TODO: Publish public entry point that exports the event priority constants
31 +const DefaultEventPriority = 8;
32 +
33 type Container = {
34 rootID: string,
35 children: Array<Instance | TextInstance>,
@@ -587,7 +590,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
590 const roots = new Map();
591 const DEFAULT_ROOT_ID = '<default>';
592
590 - let currentEventPriority = NoopRenderer.DefaultEventPriority;
593 + let currentEventPriority = DefaultEventPriority;
594
595 function childToJSX(child, text) {
596 if (text !== null) {
packages/react-reconciler/README.md
+10 -4
@@ -219,10 +219,16 @@ This is a property (not a function) that should be set to `true` if your rendere
219 To implement this method, you'll need some constants available on the _returned_ `Renderer` object:
220
221 ```js
222 +import {
223 + DiscreteEventPriority,
224 + ContinuousEventPriority,
225 + DefaultEventPriority,
226 +} from './ReactFiberReconciler/src/ReactEventPriorities';
227 +
228 const HostConfig = {
229 // ...
230 getCurrentEventPriority() {
225 - return MyRenderer.DefaultEventPriority;
231 + return DefaultEventPriority;
232 },
233 // ...
234 }
@@ -232,11 +238,11 @@ const MyRenderer = Reconciler(HostConfig);
238
239 The constant you return depends on which event, if any, is being handled right now. (In the browser, you can check this using `window.event && window.event.type`).
240
235 -* **Discrete events:** If the active event is _directly caused by the user_ (such as mouse and keyboard events) and _each event in a sequence is intentional_ (e.g. `click`), return `MyRenderer.DiscreteEventPriority`. This tells React that they should interrupt any background work and cannot be batched across time.
241 +* **Discrete events:** If the active event is _directly caused by the user_ (such as mouse and keyboard events) and _each event in a sequence is intentional_ (e.g. `click`), return `DiscreteEventPriority`. This tells React that they should interrupt any background work and cannot be batched across time.
242
237 -* **Continuous events:** If the active event is _directly caused by the user_ but _the user can't distinguish between individual events in a sequence_ (e.g. `mouseover`), return `MyRenderer.ContinuousEventPriority`. This tells React they should interrupt any background work but can be batched across time.
243 +* **Continuous events:** If the active event is _directly caused by the user_ but _the user can't distinguish between individual events in a sequence_ (e.g. `mouseover`), return `ContinuousEventPriority`. This tells React they should interrupt any background work but can be batched across time.
244
239 -* **Other events / No active event:** In all other cases, return `MyRenderer.DefaultEventPriority`. This tells React that this event is considered background work, and interactive events will be prioritized over it.
245 +* **Other events / No active event:** In all other cases, return `DefaultEventPriority`. This tells React that this event is considered background work, and interactive events will be prioritized over it.
246
247 You can consult the `getCurrentEventPriority()` implementation in `ReactDOMHostConfig.js` for a reference implementation.
248
packages/react-reconciler/src/ReactEventPriorities.js new
+37
@@ -0,0 +1,37 @@
1 +/**
2 + * Copyright (c) Facebook, Inc. and its affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + *
7 + * @flow
8 + */
9 +
10 +import {enableNewReconciler} from 'shared/ReactFeatureFlags';
11 +
12 +import {
13 + DiscreteEventPriority as DiscreteEventPriority_old,
14 + ContinuousEventPriority as ContinuousEventPriority_old,
15 + DefaultEventPriority as DefaultEventPriority_old,
16 + IdleEventPriority as IdleEventPriority_old,
17 +} from './ReactEventPriorities.old';
18 +
19 +import {
20 + DiscreteEventPriority as DiscreteEventPriority_new,
21 + ContinuousEventPriority as ContinuousEventPriority_new,
22 + DefaultEventPriority as DefaultEventPriority_new,
23 + IdleEventPriority as IdleEventPriority_new,
24 +} from './ReactEventPriorities.new';
25 +
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;
packages/react-reconciler/src/ReactEventPriorities.new.js new
+15
@@ -0,0 +1,15 @@
1 +/**
2 + * Copyright (c) Facebook, Inc. and its affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + *
7 + * @flow
8 + */
9 +
10 +export {
11 + SyncLanePriority as DiscreteEventPriority,
12 + InputContinuousLanePriority as ContinuousEventPriority,
13 + DefaultLanePriority as DefaultEventPriority,
14 + IdleLanePriority as IdleEventPriority,
15 +} from './ReactFiberLane.new';
packages/react-reconciler/src/ReactEventPriorities.old.js new
+15
@@ -0,0 +1,15 @@
1 +/**
2 + * Copyright (c) Facebook, Inc. and its affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + *
7 + * @flow
8 + */
9 +
10 +export {
11 + SyncLanePriority as DiscreteEventPriority,
12 + InputContinuousLanePriority as ContinuousEventPriority,
13 + DefaultLanePriority as DefaultEventPriority,
14 + IdleLanePriority as IdleEventPriority,
15 +} from './ReactFiberLane.old';
packages/react-reconciler/src/ReactFiberReconciler.js
-20
@@ -52,10 +52,6 @@ import {
52 registerMutableSourceForHydration as registerMutableSourceForHydration_old,
53 runWithPriority as runWithPriority_old,
54 getCurrentUpdateLanePriority as getCurrentUpdateLanePriority_old,
55 - DefaultEventPriority as DefaultEventPriority_old,
56 - DiscreteEventPriority as DiscreteEventPriority_old,
57 - ContinuousEventPriority as ContinuousEventPriority_old,
58 - IdleEventPriority as IdleEventPriority_old,
55 } from './ReactFiberReconciler.old';
56
57 import {
@@ -96,10 +92,6 @@ import {
92 registerMutableSourceForHydration as registerMutableSourceForHydration_new,
93 runWithPriority as runWithPriority_new,
94 getCurrentUpdateLanePriority as getCurrentUpdateLanePriority_new,
99 - DefaultEventPriority as DefaultEventPriority_new,
100 - DiscreteEventPriority as DiscreteEventPriority_new,
101 - ContinuousEventPriority as ContinuousEventPriority_new,
102 - IdleEventPriority as IdleEventPriority_new,
95 } from './ReactFiberReconciler.new';
96
97 export const createContainer = enableNewReconciler
@@ -176,18 +168,6 @@ export const createPortal = enableNewReconciler
168 export const createComponentSelector = enableNewReconciler
169 ? createComponentSelector_new
170 : createComponentSelector_old;
179 -export const DefaultEventPriority = enableNewReconciler
180 - ? DefaultEventPriority_new
181 - : DefaultEventPriority_old;
182 -export const DiscreteEventPriority = enableNewReconciler
183 - ? DiscreteEventPriority_new
184 - : DiscreteEventPriority_old;
185 -export const ContinuousEventPriority = enableNewReconciler
186 - ? ContinuousEventPriority_new
187 - : ContinuousEventPriority_old;
188 -export const IdleEventPriority = enableNewReconciler
189 - ? IdleEventPriority_new
190 - : IdleEventPriority_old;
171
172 //TODO: "psuedo" is spelled "pseudo"
173 export const createHasPseudoClassSelector = enableNewReconciler
packages/react-test-renderer/src/ReactTestHostConfig.js
+2 -9
@@ -8,14 +8,7 @@
8 */
9
10 import {REACT_OPAQUE_ID_TYPE} from 'shared/ReactSymbols';
11 -import {enableNewReconciler} from 'shared/ReactFeatureFlags';
12 -
13 -import {DefaultLanePriority as DefaultLanePriority_old} from 'react-reconciler/src/ReactFiberLane.old';
14 -import {DefaultLanePriority as DefaultLanePriority_new} from 'react-reconciler/src/ReactFiberLane.new';
15 -
16 -const DefaultLanePriority = enableNewReconciler
17 - ? DefaultLanePriority_new
18 - : DefaultLanePriority_old;
11 +import {DefaultEventPriority} from 'react-reconciler/src/ReactEventPriorities';
12
13 export type Type = string;
14 export type Props = Object;
@@ -223,7 +216,7 @@ export function createTextInstance(
216 }
217
218 export function getCurrentEventPriority(): * {
226 - return DefaultLanePriority;
219 + return DefaultEventPriority;
220 }
221
222 export const isPrimaryRenderer = false;
scripts/rollup/forks.js
+20
@@ -279,6 +279,26 @@ const forks = Object.freeze({
279 return 'react-reconciler/src/ReactFiberReconciler.old.js';
280 },
281
282 + 'react-reconciler/src/ReactEventPriorities': (
283 + bundleType,
284 + entry,
285 + dependencies,
286 + moduleType,
287 + bundle
288 + ) => {
289 + if (bundle.enableNewReconciler) {
290 + switch (bundleType) {
291 + case FB_WWW_DEV:
292 + case FB_WWW_PROD:
293 + case FB_WWW_PROFILING:
294 + // Use the forked version of the reconciler
295 + return 'react-reconciler/src/ReactEventPriorities.new.js';
296 + }
297 + }
298 + // Otherwise, use the non-forked version.
299 + return 'react-reconciler/src/ReactEventPriorities.old.js';
300 + },
301 +
302 'react-reconciler/src/ReactFiberHotReloading': (
303 bundleType,
304 entry,