@samitouri / QOS-React / commits / 83b941a519

Add isRootDehydrated function

Currently this does nothing except read a boolean field, but I'm about to change this logic. Since this is accessed by React DOM, too, I put the function in a separate module that can be deep imported. Previously, it was accessing the FiberRoot directly. The reason it's a separate module is to break a circular dependency between React DOM and the reconciler.

Andrew Clark committed Mar 4, 2022 at 12:37 UTC 83b941a519f0528f3c7938f2bc6094a8de60c21e
13 files changed +45 -16
packages/react-dom/src/events/ReactDOMEventListener.js
+2 -1
@@ -53,6 +53,7 @@ import {
53 setCurrentUpdatePriority,
54 } from 'react-reconciler/src/ReactEventPriorities';
55 import ReactSharedInternals from 'shared/ReactSharedInternals';
56 +import {isRootDehydrated} from 'react-reconciler/src/ReactFiberShellHydration';
57
58 const {ReactCurrentBatchConfig} = ReactSharedInternals;
59
@@ -386,7 +387,7 @@ export function findInstanceBlockingEvent(
387 targetInst = null;
388 } else if (tag === HostRoot) {
389 const root: FiberRoot = nearestMounted.stateNode;
389 - if (root.isDehydrated) {
390 + if (isRootDehydrated(root)) {
391 // If this happens during a replay something went wrong and it might block
392 // the whole system.
393 return getContainerFromFiber(nearestMounted);
packages/react-dom/src/events/ReactDOMEventReplaying.js
+2 -1
@@ -39,6 +39,7 @@ import {
39 } from '../client/ReactDOMComponentTree';
40 import {HostRoot, SuspenseComponent} from 'react-reconciler/src/ReactWorkTags';
41 import {isHigherEventPriority} from 'react-reconciler/src/ReactEventPriorities';
42 +import {isRootDehydrated} from 'react-reconciler/src/ReactFiberShellHydration';
43
44 let _attemptSynchronousHydration: (fiber: Object) => void;
45
@@ -414,7 +415,7 @@ function attemptExplicitHydrationTarget(
415 }
416 } else if (tag === HostRoot) {
417 const root: FiberRoot = nearestMounted.stateNode;
417 - if (root.isDehydrated) {
418 + if (isRootDehydrated(root)) {
419 queuedTarget.blockedOn = getContainerFromFiber(nearestMounted);
420 // We don't currently have a way to increase the priority of
421 // a root other than sync.
packages/react-reconciler/src/ReactFiberBeginWork.new.js
+2 -1
@@ -223,6 +223,7 @@ import {
223 createOffscreenHostContainerFiber,
224 isSimpleFunctionComponent,
225 } from './ReactFiber.new';
226 +import {isRootDehydrated} from './ReactFiberShellHydration';
227 import {
228 retryDehydratedSuspenseBoundary,
229 scheduleUpdateOnFiber,
@@ -1351,7 +1352,7 @@ function updateHostRoot(current, workInProgress, renderLanes) {
1352 resetHydrationState();
1353 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
1354 }
1354 - if (root.isDehydrated && enterHydrationState(workInProgress)) {
1355 + if (isRootDehydrated(root) && enterHydrationState(workInProgress)) {
1356 // If we don't have any current children this might be the first pass.
1357 // We always try to hydrate. If this isn't a hydration pass there won't
1358 // be any children to hydrate which is effectively the same thing as
packages/react-reconciler/src/ReactFiberBeginWork.old.js
+2 -1
@@ -223,6 +223,7 @@ import {
223 createOffscreenHostContainerFiber,
224 isSimpleFunctionComponent,
225 } from './ReactFiber.old';
226 +import {isRootDehydrated} from './ReactFiberShellHydration';
227 import {
228 retryDehydratedSuspenseBoundary,
229 scheduleUpdateOnFiber,
@@ -1351,7 +1352,7 @@ function updateHostRoot(current, workInProgress, renderLanes) {
1352 resetHydrationState();
1353 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
1354 }
1354 - if (root.isDehydrated && enterHydrationState(workInProgress)) {
1355 + if (isRootDehydrated(root) && enterHydrationState(workInProgress)) {
1356 // If we don't have any current children this might be the first pass.
1357 // We always try to hydrate. If this isn't a hydration pass there won't
1358 // be any children to hydrate which is effectively the same thing as
packages/react-reconciler/src/ReactFiberCommitWork.new.js
+3 -2
@@ -82,6 +82,7 @@ import {
82 Visibility,
83 } from './ReactFiberFlags';
84 import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';
85 +import {isRootDehydrated} from './ReactFiberShellHydration';
86 import {
87 resetCurrentFiber as resetCurrentDebugFiberInDEV,
88 setCurrentFiber as setCurrentDebugFiberInDEV,
@@ -1878,7 +1879,7 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
1879 case HostRoot: {
1880 if (supportsHydration) {
1881 const root: FiberRoot = finishedWork.stateNode;
1881 - if (root.isDehydrated) {
1882 + if (isRootDehydrated(root)) {
1883 // We've just hydrated. No need to hydrate again.
1884 root.isDehydrated = false;
1885 commitHydratedContainer(root.containerInfo);
@@ -1986,7 +1987,7 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
1987 case HostRoot: {
1988 if (supportsHydration) {
1989 const root: FiberRoot = finishedWork.stateNode;
1989 - if (root.isDehydrated) {
1990 + if (isRootDehydrated(root)) {
1991 // We've just hydrated. No need to hydrate again.
1992 root.isDehydrated = false;
1993 commitHydratedContainer(root.containerInfo);
packages/react-reconciler/src/ReactFiberCommitWork.old.js
+3 -2
@@ -82,6 +82,7 @@ import {
82 Visibility,
83 } from './ReactFiberFlags';
84 import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';
85 +import {isRootDehydrated} from './ReactFiberShellHydration';
86 import {
87 resetCurrentFiber as resetCurrentDebugFiberInDEV,
88 setCurrentFiber as setCurrentDebugFiberInDEV,
@@ -1878,7 +1879,7 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
1879 case HostRoot: {
1880 if (supportsHydration) {
1881 const root: FiberRoot = finishedWork.stateNode;
1881 - if (root.isDehydrated) {
1882 + if (isRootDehydrated(root)) {
1883 // We've just hydrated. No need to hydrate again.
1884 root.isDehydrated = false;
1885 commitHydratedContainer(root.containerInfo);
@@ -1986,7 +1987,7 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
1987 case HostRoot: {
1988 if (supportsHydration) {
1989 const root: FiberRoot = finishedWork.stateNode;
1989 - if (root.isDehydrated) {
1990 + if (isRootDehydrated(root)) {
1991 // We've just hydrated. No need to hydrate again.
1992 root.isDehydrated = false;
1993 commitHydratedContainer(root.containerInfo);
packages/react-reconciler/src/ReactFiberCompleteWork.new.js
+2 -1
@@ -160,6 +160,7 @@ import {
160 includesSomeLane,
161 mergeLanes,
162 } from './ReactFiberLane.new';
163 +import {isRootDehydrated} from './ReactFiberShellHydration';
164 import {resetChildFibers} from './ReactChildFiber.new';
165 import {createScopeInstance} from './ReactFiberScope.new';
166 import {transferActualDuration} from './ReactProfilerTimer.new';
@@ -890,7 +891,7 @@ function completeWork(
891 // If we hydrated, then we'll need to schedule an update for
892 // the commit side-effects on the root.
893 markUpdate(workInProgress);
893 - } else if (!fiberRoot.isDehydrated) {
894 + } else if (!isRootDehydrated(fiberRoot)) {
895 // Schedule an effect to clear this container at the start of the next commit.
896 // This handles the case of React rendering into a container with previous children.
897 // It's also safe to do for updates too, because current.child would only be null
packages/react-reconciler/src/ReactFiberCompleteWork.old.js
+2 -1
@@ -160,6 +160,7 @@ import {
160 includesSomeLane,
161 mergeLanes,
162 } from './ReactFiberLane.old';
163 +import {isRootDehydrated} from './ReactFiberShellHydration';
164 import {resetChildFibers} from './ReactChildFiber.old';
165 import {createScopeInstance} from './ReactFiberScope.old';
166 import {transferActualDuration} from './ReactProfilerTimer.old';
@@ -890,7 +891,7 @@ function completeWork(
891 // If we hydrated, then we'll need to schedule an update for
892 // the commit side-effects on the root.
893 markUpdate(workInProgress);
893 - } else if (!fiberRoot.isDehydrated) {
894 + } else if (!isRootDehydrated(fiberRoot)) {
895 // Schedule an effect to clear this container at the start of the next commit.
896 // This handles the case of React rendering into a container with previous children.
897 // It's also safe to do for updates too, because current.child would only be null
packages/react-reconciler/src/ReactFiberReconciler.new.js
+2 -1
@@ -48,6 +48,7 @@ import {
48 isContextProvider as isLegacyContextProvider,
49 } from './ReactFiberContext.new';
50 import {createFiberRoot} from './ReactFiberRoot.new';
51 +import {isRootDehydrated} from './ReactFiberShellHydration';
52 import {
53 injectInternals,
54 markRenderScheduled,
@@ -411,7 +412,7 @@ export function attemptSynchronousHydration(fiber: Fiber): void {
412 switch (fiber.tag) {
413 case HostRoot:
414 const root: FiberRoot = fiber.stateNode;
414 - if (root.isDehydrated) {
415 + if (isRootDehydrated(root)) {
416 // Flush the first scheduled "update".
417 const lanes = getHighestPriorityPendingLanes(root);
418 flushRoot(root, lanes);
packages/react-reconciler/src/ReactFiberReconciler.old.js
+2 -1
@@ -48,6 +48,7 @@ import {
48 isContextProvider as isLegacyContextProvider,
49 } from './ReactFiberContext.old';
50 import {createFiberRoot} from './ReactFiberRoot.old';
51 +import {isRootDehydrated} from './ReactFiberShellHydration';
52 import {
53 injectInternals,
54 markRenderScheduled,
@@ -411,7 +412,7 @@ export function attemptSynchronousHydration(fiber: Fiber): void {
412 switch (fiber.tag) {
413 case HostRoot:
414 const root: FiberRoot = fiber.stateNode;
414 - if (root.isDehydrated) {
415 + if (isRootDehydrated(root)) {
416 // Flush the first scheduled "update".
417 const lanes = getHighestPriorityPendingLanes(root);
418 flushRoot(root, lanes);
packages/react-reconciler/src/ReactFiberShellHydration.js new
+17
@@ -0,0 +1,17 @@
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 type {FiberRoot} from './ReactInternalTypes';
11 +
12 +// This is imported by the event replaying implementation in React DOM. It's
13 +// in a separate file to break a circular dependency between the renderer and
14 +// the reconciler.
15 +export function isRootDehydrated(root: FiberRoot) {
16 + return root.isDehydrated;
17 +}
packages/react-reconciler/src/ReactFiberWorkLoop.new.js
+3 -2
@@ -88,6 +88,7 @@ import {
88 createWorkInProgress,
89 assignFiberPropertiesInDEV,
90 } from './ReactFiber.new';
91 +import {isRootDehydrated} from './ReactFiberShellHydration';
92 import {NoMode, ProfileMode, ConcurrentMode} from './ReactTypeOfMode';
93 import {
94 HostRoot,
@@ -581,7 +582,7 @@ export function scheduleUpdateOnFiber(
582 }
583 }
584
584 - if (root.isDehydrated && root.tag !== LegacyRoot) {
585 + if (isRootDehydrated(root) && root.tag !== LegacyRoot) {
586 // This root's shell hasn't hydrated yet. Revert to client rendering.
587 if (workInProgressRoot === root) {
588 // If this happened during an interleaved event, interrupt the
@@ -1016,7 +1017,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
1017 function recoverFromConcurrentError(root, errorRetryLanes) {
1018 // If an error occurred during hydration, discard server response and fall
1019 // back to client side render.
1019 - if (root.isDehydrated) {
1020 + if (isRootDehydrated(root)) {
1021 root.isDehydrated = false;
1022 if (__DEV__) {
1023 errorHydratingContainer(root.containerInfo);
packages/react-reconciler/src/ReactFiberWorkLoop.old.js
+3 -2
@@ -88,6 +88,7 @@ import {
88 createWorkInProgress,
89 assignFiberPropertiesInDEV,
90 } from './ReactFiber.old';
91 +import {isRootDehydrated} from './ReactFiberShellHydration';
92 import {NoMode, ProfileMode, ConcurrentMode} from './ReactTypeOfMode';
93 import {
94 HostRoot,
@@ -581,7 +582,7 @@ export function scheduleUpdateOnFiber(
582 }
583 }
584
584 - if (root.isDehydrated && root.tag !== LegacyRoot) {
585 + if (isRootDehydrated(root) && root.tag !== LegacyRoot) {
586 // This root's shell hasn't hydrated yet. Revert to client rendering.
587 if (workInProgressRoot === root) {
588 // If this happened during an interleaved event, interrupt the
@@ -1016,7 +1017,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
1017 function recoverFromConcurrentError(root, errorRetryLanes) {
1018 // If an error occurred during hydration, discard server response and fall
1019 // back to client side render.
1019 - if (root.isDehydrated) {
1020 + if (isRootDehydrated(root)) {
1021 root.isDehydrated = false;
1022 if (__DEV__) {
1023 errorHydratingContainer(root.containerInfo);