@samitouri / QOS-React / commits / 88ee14ffa5

[Devtools] Ensure initial read of `useFormStatus` returns `NotPendingTransition` (#28728)

Sebastian Silbermann committed Aug 1, 2024 at 10:55 UTC 88ee14ffa57beb0689f26f0c52c357e3ac446af8
11 files changed +72 -36
packages/react-art/src/ReactFiberConfigART.js
+12
@@ -16,6 +16,8 @@ import {
16 DefaultEventPriority,
17 NoEventPriority,
18 } from 'react-reconciler/src/ReactEventPriorities';
19 +import type {ReactContext} from 'shared/ReactTypes';
20 +import {REACT_CONTEXT_TYPE} from 'shared/ReactSymbols';
21
22 export {default as rendererVersion} from 'shared/ReactVersion';
23 export const rendererPackageName = 'react-art';
@@ -28,6 +30,8 @@ if (__DEV__) {
30 Object.freeze(NO_CONTEXT);
31 }
32
33 +export type TransitionStatus = mixed;
34 +
35 /** Helper Methods */
36
37 function addEventListeners(instance, type, listener) {
@@ -488,4 +492,12 @@ export function waitForCommitToBeReady() {
492 }
493
494 export const NotPendingTransition = null;
495 +export const HostTransitionContext: ReactContext<TransitionStatus> = {
496 + $$typeof: REACT_CONTEXT_TYPE,
497 + Provider: (null: any),
498 + Consumer: (null: any),
499 + _currentValue: NotPendingTransition,
500 + _currentValue2: NotPendingTransition,
501 + _threadCount: 0,
502 +};
503 export function resetFormInstance() {}
packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegrationDOM-test.js
+6 -1
@@ -119,7 +119,12 @@ describe('ReactHooksInspectionIntegration', () => {
119 isStateEditable: false,
120 name: 'FormStatus',
121 subHooks: [],
122 - value: null,
122 + value: {
123 + action: null,
124 + data: null,
125 + method: null,
126 + pending: false,
127 + },
128 },
129 {
130 debugInfo: null,
packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
+10 -1
@@ -14,7 +14,7 @@ import type {
14 IntersectionObserverOptions,
15 ObserveVisibleRectsCallback,
16 } from 'react-reconciler/src/ReactTestSelectors';
17 -import type {ReactScopeInstance} from 'shared/ReactTypes';
17 +import type {ReactContext, ReactScopeInstance} from 'shared/ReactTypes';
18 import type {AncestorInfoDev} from './validateDOMNesting';
19 import type {FormStatus} from 'react-dom-bindings/src/shared/ReactDOMFormActions';
20 import type {
@@ -32,6 +32,7 @@ import {getCurrentRootHostContainer} from 'react-reconciler/src/ReactFiberHostCo
32
33 import hasOwnProperty from 'shared/hasOwnProperty';
34 import {checkAttributeStringCoercion} from 'shared/CheckStringCoercion';
35 +import {REACT_CONTEXT_TYPE} from 'shared/ReactSymbols';
36
37 export {
38 setCurrentUpdatePriority,
@@ -3564,6 +3565,14 @@ function insertStylesheetIntoRoot(
3565 }
3566
3567 export const NotPendingTransition: TransitionStatus = NotPending;
3568 +export const HostTransitionContext: ReactContext<TransitionStatus> = {
3569 + $$typeof: REACT_CONTEXT_TYPE,
3570 + Provider: (null: any),
3571 + Consumer: (null: any),
3572 + _currentValue: NotPendingTransition,
3573 + _currentValue2: NotPendingTransition,
3574 + _threadCount: 0,
3575 +};
3576
3577 export type FormInstance = HTMLFormElement;
3578 export function resetFormInstance(form: FormInstance): void {
packages/react-native-renderer/src/ReactFiberConfigFabric.js
+10
@@ -60,6 +60,8 @@ import {
60 enableFabricCompleteRootInCommitPhase,
61 passChildrenWhenCloningPersistedNodes,
62 } from 'shared/ReactFeatureFlags';
63 +import {REACT_CONTEXT_TYPE} from 'shared/ReactSymbols';
64 +import type {ReactContext} from 'shared/ReactTypes';
65
66 export {default as rendererVersion} from 'shared/ReactVersion'; // TODO: Consider exporting the react-native version.
67 export const rendererPackageName = 'react-native-renderer';
@@ -544,6 +546,14 @@ export function waitForCommitToBeReady(): null {
546 }
547
548 export const NotPendingTransition: TransitionStatus = null;
549 +export const HostTransitionContext: ReactContext<TransitionStatus> = {
550 + $$typeof: REACT_CONTEXT_TYPE,
551 + Provider: (null: any),
552 + Consumer: (null: any),
553 + _currentValue: NotPendingTransition,
554 + _currentValue2: NotPendingTransition,
555 + _threadCount: 0,
556 +};
557
558 export type FormInstance = Instance;
559 export function resetFormInstance(form: Instance): void {}
packages/react-native-renderer/src/ReactFiberConfigNative.js
+11
@@ -32,6 +32,9 @@ import {
32 } from 'react-reconciler/src/ReactEventPriorities';
33 import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
34
35 +import {REACT_CONTEXT_TYPE} from 'shared/ReactSymbols';
36 +import type {ReactContext} from 'shared/ReactTypes';
37 +
38 import {
39 getInspectorDataForViewTag,
40 getInspectorDataForViewAtPoint,
@@ -561,6 +564,14 @@ export function waitForCommitToBeReady(): null {
564 }
565
566 export const NotPendingTransition: TransitionStatus = null;
567 +export const HostTransitionContext: ReactContext<TransitionStatus> = {
568 + $$typeof: REACT_CONTEXT_TYPE,
569 + Provider: (null: any),
570 + Consumer: (null: any),
571 + _currentValue: NotPendingTransition,
572 + _currentValue2: NotPendingTransition,
573 + _threadCount: 0,
574 +};
575
576 export type FormInstance = Instance;
577 export function resetFormInstance(form: Instance): void {}
packages/react-reconciler/src/ReactFiberBeginWork.js
+1 -1
@@ -178,6 +178,7 @@ import {
178 isPrimaryRenderer,
179 getResource,
180 createHoistableInstance,
181 + HostTransitionContext,
182 } from './ReactFiberConfig';
183 import type {SuspenseInstance} from './ReactFiberConfig';
184 import {shouldError, shouldSuspend} from './ReactFiberReconciler';
@@ -185,7 +186,6 @@ import {
186 pushHostContext,
187 pushHostContainer,
188 getRootHostContainer,
188 - HostTransitionContext,
189 } from './ReactFiberHostContext';
190 import {
191 suspenseStackCursor,
packages/react-reconciler/src/ReactFiberHooks.js
+2 -3
@@ -28,6 +28,7 @@ import type {Flags} from './ReactFiberFlags';
28 import type {TransitionStatus} from './ReactFiberConfig';
29
30 import {
31 + HostTransitionContext,
32 NotPendingTransition as NoPendingHostTransition,
33 setCurrentUpdatePriority,
34 getCurrentUpdatePriority,
@@ -156,7 +157,6 @@ import {
157 peekEntangledActionThenable,
158 chainThenableValue,
159 } from './ReactFiberAsyncAction';
159 -import {HostTransitionContext} from './ReactFiberHostContext';
160 import {requestTransitionLane} from './ReactFiberRootScheduler';
161 import {isCurrentTreeHidden} from './ReactFiberHiddenContext';
162 import {requestCurrentTransition} from './ReactFiberTransition';
@@ -3276,8 +3276,7 @@ function useHostTransitionStatus(): TransitionStatus {
3276 if (!enableAsyncActions) {
3277 throw new Error('Not implemented.');
3278 }
3279 - const status: TransitionStatus | null = readContext(HostTransitionContext);
3280 - return status !== null ? status : NoPendingHostTransition;
3279 + return readContext(HostTransitionContext);
3280 }
3281
3282 function mountId(): string {
packages/react-reconciler/src/ReactFiberHostContext.js
+6 -25
@@ -9,21 +9,17 @@
9
10 import type {Fiber} from './ReactInternalTypes';
11 import type {StackCursor} from './ReactFiberStack';
12 -import type {
13 - Container,
14 - HostContext,
15 - TransitionStatus,
16 -} from './ReactFiberConfig';
12 +import type {Container, HostContext} from './ReactFiberConfig';
13 import type {Hook} from './ReactFiberHooks';
18 -import type {ReactContext} from 'shared/ReactTypes';
14
15 import {
16 getChildHostContext,
17 getRootHostContext,
18 + HostTransitionContext,
19 + NotPendingTransition,
20 isPrimaryRenderer,
21 } from './ReactFiberConfig';
22 import {createCursor, push, pop} from './ReactFiberStack';
26 -import {REACT_CONTEXT_TYPE} from 'shared/ReactSymbols';
23 import {enableAsyncActions} from 'shared/ReactFeatureFlags';
24
25 const contextStackCursor: StackCursor<HostContext | null> = createCursor(null);
@@ -38,21 +34,6 @@ const rootInstanceStackCursor: StackCursor<Container | null> =
34 const hostTransitionProviderCursor: StackCursor<Fiber | null> =
35 createCursor(null);
36
41 -// TODO: This should initialize to NotPendingTransition, a constant
42 -// imported from the fiber config. However, because of a cycle in the module
43 -// graph, that value isn't defined during this module's initialization. I can't
44 -// think of a way to work around this without moving that value out of the
45 -// fiber config. For now, the "no provider" case is handled when reading,
46 -// inside useHostTransitionStatus.
47 -export const HostTransitionContext: ReactContext<TransitionStatus | null> = {
48 - $$typeof: REACT_CONTEXT_TYPE,
49 - Provider: (null: any),
50 - Consumer: (null: any),
51 - _currentValue: null,
52 - _currentValue2: null,
53 - _threadCount: 0,
54 -};
55 -
37 function requiredContext<Value>(c: Value | null): Value {
38 if (__DEV__) {
39 if (c === null) {
@@ -150,13 +131,13 @@ function popHostContext(fiber: Fiber): void {
131 pop(hostTransitionProviderCursor, fiber);
132
133 // When popping the transition provider, we reset the context value back
153 - // to `null`. We can do this because you're not allowd to nest forms. If
134 + // to `NotPendingTransition`. We can do this because you're not allowed to nest forms. If
135 // we allowed for multiple nested host transition providers, then we'd
136 // need to reset this to the parent provider's status.
137 if (isPrimaryRenderer) {
157 - HostTransitionContext._currentValue = null;
138 + HostTransitionContext._currentValue = NotPendingTransition;
139 } else {
159 - HostTransitionContext._currentValue2 = null;
140 + HostTransitionContext._currentValue2 = NotPendingTransition;
141 }
142 }
143 }
packages/react-reconciler/src/ReactFiberNewContext.js
+2 -5
@@ -20,7 +20,7 @@ import type {SharedQueue} from './ReactFiberClassUpdateQueue';
20 import type {TransitionStatus} from './ReactFiberConfig';
21 import type {Hook} from './ReactFiberHooks';
22
23 -import {isPrimaryRenderer} from './ReactFiberConfig';
23 +import {isPrimaryRenderer, HostTransitionContext} from './ReactFiberConfig';
24 import {createCursor, push, pop} from './ReactFiberStack';
25 import {
26 ContextProvider,
@@ -48,10 +48,7 @@ import {
48 enableAsyncActions,
49 enableRenderableContext,
50 } from 'shared/ReactFeatureFlags';
51 -import {
52 - getHostTransitionProvider,
53 - HostTransitionContext,
54 -} from './ReactFiberHostContext';
51 +import {getHostTransitionProvider} from './ReactFiberHostContext';
52 import isArray from '../../shared/isArray';
53 import {enableContextProfiling} from '../../shared/ReactFeatureFlags';
54
packages/react-reconciler/src/forks/ReactFiberConfig.custom.js
+1
@@ -83,6 +83,7 @@ export const startSuspendingCommit = $$$config.startSuspendingCommit;
83 export const suspendInstance = $$$config.suspendInstance;
84 export const waitForCommitToBeReady = $$$config.waitForCommitToBeReady;
85 export const NotPendingTransition = $$$config.NotPendingTransition;
86 +export const HostTransitionContext = $$$config.HostTransitionContext;
87 export const resetFormInstance = $$$config.resetFormInstance;
88 export const bindToConsole = $$$config.bindToConsole;
89
packages/react-test-renderer/src/ReactFiberConfigTestHost.js
+11
@@ -7,7 +7,10 @@
7 * @flow
8 */
9
10 +import type {ReactContext} from 'shared/ReactTypes';
11 +
12 import isArray from 'shared/isArray';
13 +import {REACT_CONTEXT_TYPE} from 'shared/ReactSymbols';
14 import {
15 DefaultEventPriority,
16 NoEventPriority,
@@ -352,6 +355,14 @@ export function waitForCommitToBeReady(): null {
355 }
356
357 export const NotPendingTransition: TransitionStatus = null;
358 +export const HostTransitionContext: ReactContext<TransitionStatus> = {
359 + $$typeof: REACT_CONTEXT_TYPE,
360 + Provider: (null: any),
361 + Consumer: (null: any),
362 + _currentValue: NotPendingTransition,
363 + _currentValue2: NotPendingTransition,
364 + _threadCount: 0,
365 +};
366
367 export type FormInstance = Instance;
368 export function resetFormInstance(form: Instance): void {}