Skip to content

Commit

Permalink
[Fiber] Use hydration lanes when scheduling hydration work (#31751)
Browse files Browse the repository at this point in the history
When scheduling the initial root and when using
`unstable_scheduleHydration` we should use the Hydration Lanes rather
than the raw update lane. This ensures that we're always hydrating using
a Hydration Lane or the Offscreen Lane rather than other lanes getting
some random hydration in it.

This fixes an issue where updating a root while it is still hydrating
causes it to trigger client rendering when it could just hydrate and
then apply the update on top of that.

It also fixes a potential performance issue where
`unstable_scheduleHydration` gets batched with an update that then ends
up forcing an update of a boundary that requires it to rewind to do the
hydration lane anyway. Might as well just start with the hydration
without the update applied first.

I added a kill switch (`enableHydrationLaneScheduling`) just in case but
seems very safe given that using `unstable_scheduleHydration` at all is
very rare and updating the root before the shell hydrates is extremely
rare (and used to trigger a recoverable error).

DiffTrain build for [d5e8f79](d5e8f79)
  • Loading branch information
sebmarkbage committed Dec 13, 2024
1 parent 0bcbbf0 commit 2a2d2f8
Show file tree
Hide file tree
Showing 34 changed files with 1,034 additions and 912 deletions.
2 changes: 1 addition & 1 deletion compiled/facebook-www/REVISION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
a4964987dc140526702e996223fe7ee293def8ac
d5e8f79cf4d11fa7eee263b3f937deecbe65ffd7
2 changes: 1 addition & 1 deletion compiled/facebook-www/REVISION_TRANSFORMS
Original file line number Diff line number Diff line change
@@ -1 +1 @@
a4964987dc140526702e996223fe7ee293def8ac
d5e8f79cf4d11fa7eee263b3f937deecbe65ffd7
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-dev.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -1954,7 +1954,7 @@ __DEV__ &&
exports.useTransition = function () {
return resolveDispatcher().useTransition();
};
exports.version = "19.0.0-www-classic-a4964987-20241211";
exports.version = "19.1.0-www-classic-d5e8f79c-20241212";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-dev.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -1954,7 +1954,7 @@ __DEV__ &&
exports.useTransition = function () {
return resolveDispatcher().useTransition();
};
exports.version = "19.0.0-www-modern-a4964987-20241211";
exports.version = "19.1.0-www-modern-d5e8f79c-20241212";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-prod.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -635,4 +635,4 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactSharedInternals.H.useTransition();
};
exports.version = "19.0.0-www-classic-a4964987-20241211";
exports.version = "19.1.0-www-classic-d5e8f79c-20241212";
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-prod.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -635,4 +635,4 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactSharedInternals.H.useTransition();
};
exports.version = "19.0.0-www-modern-a4964987-20241211";
exports.version = "19.1.0-www-modern-d5e8f79c-20241212";
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-profiling.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,7 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactSharedInternals.H.useTransition();
};
exports.version = "19.0.0-www-classic-a4964987-20241211";
exports.version = "19.1.0-www-classic-d5e8f79c-20241212";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-profiling.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,7 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactSharedInternals.H.useTransition();
};
exports.version = "19.0.0-www-modern-a4964987-20241211";
exports.version = "19.1.0-www-modern-d5e8f79c-20241212";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
6 changes: 3 additions & 3 deletions compiled/facebook-www/ReactART-dev.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -17237,10 +17237,10 @@ __DEV__ &&
(function () {
var internals = {
bundleType: 1,
version: "19.0.0-www-classic-a4964987-20241211",
version: "19.1.0-www-classic-d5e8f79c-20241212",
rendererPackageName: "react-art",
currentDispatcherRef: ReactSharedInternals,
reconcilerVersion: "19.0.0-www-classic-a4964987-20241211"
reconcilerVersion: "19.1.0-www-classic-d5e8f79c-20241212"
};
internals.overrideHookState = overrideHookState;
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
Expand Down Expand Up @@ -17274,7 +17274,7 @@ __DEV__ &&
exports.Shape = Shape;
exports.Surface = Surface;
exports.Text = Text;
exports.version = "19.0.0-www-classic-a4964987-20241211";
exports.version = "19.1.0-www-classic-d5e8f79c-20241212";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
6 changes: 3 additions & 3 deletions compiled/facebook-www/ReactART-dev.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -17000,10 +17000,10 @@ __DEV__ &&
(function () {
var internals = {
bundleType: 1,
version: "19.0.0-www-modern-a4964987-20241211",
version: "19.1.0-www-modern-d5e8f79c-20241212",
rendererPackageName: "react-art",
currentDispatcherRef: ReactSharedInternals,
reconcilerVersion: "19.0.0-www-modern-a4964987-20241211"
reconcilerVersion: "19.1.0-www-modern-d5e8f79c-20241212"
};
internals.overrideHookState = overrideHookState;
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
Expand Down Expand Up @@ -17037,7 +17037,7 @@ __DEV__ &&
exports.Shape = Shape;
exports.Surface = Surface;
exports.Text = Text;
exports.version = "19.0.0-www-modern-a4964987-20241211";
exports.version = "19.1.0-www-modern-d5e8f79c-20241212";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
6 changes: 3 additions & 3 deletions compiled/facebook-www/ReactART-prod.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -10827,10 +10827,10 @@ var slice = Array.prototype.slice,
})(React.Component);
var internals$jscomp$inline_1509 = {
bundleType: 0,
version: "19.0.0-www-classic-a4964987-20241211",
version: "19.1.0-www-classic-d5e8f79c-20241212",
rendererPackageName: "react-art",
currentDispatcherRef: ReactSharedInternals,
reconcilerVersion: "19.0.0-www-classic-a4964987-20241211"
reconcilerVersion: "19.1.0-www-classic-d5e8f79c-20241212"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1510 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
Expand All @@ -10856,4 +10856,4 @@ exports.RadialGradient = RadialGradient;
exports.Shape = TYPES.SHAPE;
exports.Surface = Surface;
exports.Text = Text;
exports.version = "19.0.0-www-classic-a4964987-20241211";
exports.version = "19.1.0-www-classic-d5e8f79c-20241212";
6 changes: 3 additions & 3 deletions compiled/facebook-www/ReactART-prod.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -10543,10 +10543,10 @@ var slice = Array.prototype.slice,
})(React.Component);
var internals$jscomp$inline_1488 = {
bundleType: 0,
version: "19.0.0-www-modern-a4964987-20241211",
version: "19.1.0-www-modern-d5e8f79c-20241212",
rendererPackageName: "react-art",
currentDispatcherRef: ReactSharedInternals,
reconcilerVersion: "19.0.0-www-modern-a4964987-20241211"
reconcilerVersion: "19.1.0-www-modern-d5e8f79c-20241212"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1489 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
Expand All @@ -10572,4 +10572,4 @@ exports.RadialGradient = RadialGradient;
exports.Shape = TYPES.SHAPE;
exports.Surface = Surface;
exports.Text = Text;
exports.version = "19.0.0-www-modern-a4964987-20241211";
exports.version = "19.1.0-www-modern-d5e8f79c-20241212";
153 changes: 82 additions & 71 deletions compiled/facebook-www/ReactDOM-dev.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -1193,6 +1193,46 @@ __DEV__ &&
rootEntangledLanes &= ~lane;
}
}
function getBumpedLaneForHydrationByLane(lane) {
switch (lane) {
case 2:
lane = 1;
break;
case 8:
lane = 4;
break;
case 32:
lane = 16;
break;
case 128:
case 256:
case 512:
case 1024:
case 2048:
case 4096:
case 8192:
case 16384:
case 32768:
case 65536:
case 131072:
case 262144:
case 524288:
case 1048576:
case 2097152:
case 4194304:
case 8388608:
case 16777216:
case 33554432:
lane = 64;
break;
case 268435456:
lane = 134217728;
break;
default:
lane = 0;
}
return lane;
}
function addFiberToLanesMap(root, fiber, lanes) {
if (isDevToolsPresent)
for (root = root.pendingUpdatersLaneMap; 0 < lanes; ) {
Expand Down Expand Up @@ -9656,73 +9696,38 @@ __DEV__ &&
didReceiveUpdate || JSCompiler_object_inline_digest_2503)
) {
JSCompiler_object_inline_digest_2503 = workInProgressRoot;
if (null !== JSCompiler_object_inline_digest_2503) {
JSCompiler_object_inline_stack_2504 = renderLanes & -renderLanes;
if (0 !== (JSCompiler_object_inline_stack_2504 & 42))
JSCompiler_object_inline_stack_2504 = 1;
else
switch (JSCompiler_object_inline_stack_2504) {
case 2:
JSCompiler_object_inline_stack_2504 = 1;
break;
case 8:
JSCompiler_object_inline_stack_2504 = 4;
break;
case 32:
JSCompiler_object_inline_stack_2504 = 16;
break;
case 128:
case 256:
case 512:
case 1024:
case 2048:
case 4096:
case 8192:
case 16384:
case 32768:
case 65536:
case 131072:
case 262144:
case 524288:
case 1048576:
case 2097152:
case 4194304:
case 8388608:
case 16777216:
case 33554432:
JSCompiler_object_inline_stack_2504 = 64;
break;
case 268435456:
JSCompiler_object_inline_stack_2504 = 134217728;
break;
default:
JSCompiler_object_inline_stack_2504 = 0;
}
JSCompiler_object_inline_stack_2504 =
if (
null !== JSCompiler_object_inline_digest_2503 &&
((JSCompiler_object_inline_stack_2504 = renderLanes & -renderLanes),
(JSCompiler_object_inline_stack_2504 =
0 !== (JSCompiler_object_inline_stack_2504 & 42)
? 1
: getBumpedLaneForHydrationByLane(
JSCompiler_object_inline_stack_2504
)),
(JSCompiler_object_inline_stack_2504 =
0 !==
(JSCompiler_object_inline_stack_2504 &
(JSCompiler_object_inline_digest_2503.suspendedLanes |
renderLanes))
? 0
: JSCompiler_object_inline_stack_2504;
if (
0 !== JSCompiler_object_inline_stack_2504 &&
JSCompiler_object_inline_stack_2504 !== prevState.retryLane
)
throw (
((prevState.retryLane = JSCompiler_object_inline_stack_2504),
enqueueConcurrentRenderForLane(
current,
JSCompiler_object_inline_stack_2504
),
scheduleUpdateOnFiber(
JSCompiler_object_inline_digest_2503,
current,
JSCompiler_object_inline_stack_2504
),
SelectiveHydrationException)
);
}
: JSCompiler_object_inline_stack_2504),
0 !== JSCompiler_object_inline_stack_2504 &&
JSCompiler_object_inline_stack_2504 !== prevState.retryLane)
)
throw (
((prevState.retryLane = JSCompiler_object_inline_stack_2504),
enqueueConcurrentRenderForLane(
current,
JSCompiler_object_inline_stack_2504
),
scheduleUpdateOnFiber(
JSCompiler_object_inline_digest_2503,
current,
JSCompiler_object_inline_stack_2504
),
SelectiveHydrationException)
);
JSCompiler_object_inline_message_2502.data ===
SUSPENSE_PENDING_START_DATA || renderDidSuspendDelayIfPossible();
workInProgress = retrySuspenseComponentWithoutHydrating(
Expand Down Expand Up @@ -23227,8 +23232,12 @@ __DEV__ &&
queuedTarget.blockedOn = targetInst;
runWithPriority(queuedTarget.priority, function () {
if (13 === nearestMounted.tag) {
var lane = requestUpdateLane(nearestMounted),
root = enqueueConcurrentRenderForLane(nearestMounted, lane);
var lane = requestUpdateLane(nearestMounted);
lane = getBumpedLaneForHydrationByLane(lane);
var root = enqueueConcurrentRenderForLane(
nearestMounted,
lane
);
null !== root &&
scheduleUpdateOnFiber(root, nearestMounted, lane);
markRetryLaneIfNotHydrated(nearestMounted, lane);
Expand Down Expand Up @@ -27711,11 +27720,11 @@ __DEV__ &&
return_targetInst = null;
(function () {
var isomorphicReactPackageVersion = React.version;
if ("19.0.0-www-classic-a4964987-20241211" !== isomorphicReactPackageVersion)
if ("19.1.0-www-classic-d5e8f79c-20241212" !== isomorphicReactPackageVersion)
throw Error(
'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' +
(isomorphicReactPackageVersion +
"\n - react-dom: 19.0.0-www-classic-a4964987-20241211\nLearn more: https://react.dev/warnings/version-mismatch")
"\n - react-dom: 19.1.0-www-classic-d5e8f79c-20241212\nLearn more: https://react.dev/warnings/version-mismatch")
);
})();
("function" === typeof Map &&
Expand Down Expand Up @@ -27758,10 +27767,10 @@ __DEV__ &&
!(function () {
var internals = {
bundleType: 1,
version: "19.0.0-www-classic-a4964987-20241211",
version: "19.1.0-www-classic-d5e8f79c-20241212",
rendererPackageName: "react-dom",
currentDispatcherRef: ReactSharedInternals,
reconcilerVersion: "19.0.0-www-classic-a4964987-20241211"
reconcilerVersion: "19.1.0-www-classic-d5e8f79c-20241212"
};
internals.overrideHookState = overrideHookState;
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
Expand Down Expand Up @@ -28035,11 +28044,13 @@ __DEV__ &&
initialChildren.context = getContextForSubtree(null);
options = initialChildren.current;
isStrictMode = requestUpdateLane(options);
isStrictMode = getBumpedLaneForHydrationByLane(isStrictMode);
identifierPrefix = createUpdate(isStrictMode);
identifierPrefix.callback = null;
enqueueUpdate(options, identifierPrefix, isStrictMode);
initialChildren.current.lanes = isStrictMode;
markRootUpdated(initialChildren, isStrictMode);
options = isStrictMode;
initialChildren.current.lanes = options;
markRootUpdated(initialChildren, options);
ensureRootIsScheduled(initialChildren);
container[internalContainerInstanceKey] = initialChildren.current;
listenToAllSupportedEvents(container);
Expand Down Expand Up @@ -28366,7 +28377,7 @@ __DEV__ &&
exports.useFormStatus = function () {
return resolveDispatcher().useHostTransitionStatus();
};
exports.version = "19.0.0-www-classic-a4964987-20241211";
exports.version = "19.1.0-www-classic-d5e8f79c-20241212";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
Loading

0 comments on commit 2a2d2f8

Please sign in to comment.