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 95e5f95 commit 40363db
Show file tree
Hide file tree
Showing 23 changed files with 496 additions and 438 deletions.
2 changes: 1 addition & 1 deletion compiled-rn/VERSION_NATIVE_FB
Original file line number Diff line number Diff line change
@@ -1 +1 @@
19.0.0-native-fb-a4964987-20241211
19.1.0-native-fb-d5e8f79c-20241212
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<ccf476a715066d778df0505049a54566>>
* @generated SignedSource<<ab939ae8d8627b0b15a910117e30c826>>
*/

"use strict";
Expand Down Expand Up @@ -420,5 +420,5 @@ __DEV__ &&
exports.useFormStatus = function () {
return resolveDispatcher().useHostTransitionStatus();
};
exports.version = "19.0.0-native-fb-a4964987-20241211";
exports.version = "19.1.0-native-fb-d5e8f79c-20241212";
})();
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<9a6ddd03ad59bffae1400d7817440da9>>
* @generated SignedSource<<bc8b32405f408ad4311ddb0630ac1b1e>>
*/

"use strict";
Expand Down Expand Up @@ -203,4 +203,4 @@ exports.useFormState = function (action, initialState, permalink) {
exports.useFormStatus = function () {
return ReactSharedInternals.H.useHostTransitionStatus();
};
exports.version = "19.0.0-native-fb-a4964987-20241211";
exports.version = "19.1.0-native-fb-d5e8f79c-20241212";
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<9a6ddd03ad59bffae1400d7817440da9>>
* @generated SignedSource<<bc8b32405f408ad4311ddb0630ac1b1e>>
*/

"use strict";
Expand Down Expand Up @@ -203,4 +203,4 @@ exports.useFormState = function (action, initialState, permalink) {
exports.useFormStatus = function () {
return ReactSharedInternals.H.useHostTransitionStatus();
};
exports.version = "19.0.0-native-fb-a4964987-20241211";
exports.version = "19.1.0-native-fb-d5e8f79c-20241212";
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<9daf013310978cac03378fd9f0c4e4d2>>
* @generated SignedSource<<e6ba74922114eb45cd14230675a1821d>>
*/

/*
Expand Down Expand Up @@ -1310,6 +1310,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 @@ -9526,73 +9566,38 @@ __DEV__ &&
didReceiveUpdate || JSCompiler_object_inline_digest_2369)
) {
JSCompiler_object_inline_digest_2369 = workInProgressRoot;
if (null !== JSCompiler_object_inline_digest_2369) {
JSCompiler_object_inline_stack_2370 = renderLanes & -renderLanes;
if (0 !== (JSCompiler_object_inline_stack_2370 & 42))
JSCompiler_object_inline_stack_2370 = 1;
else
switch (JSCompiler_object_inline_stack_2370) {
case 2:
JSCompiler_object_inline_stack_2370 = 1;
break;
case 8:
JSCompiler_object_inline_stack_2370 = 4;
break;
case 32:
JSCompiler_object_inline_stack_2370 = 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_2370 = 64;
break;
case 268435456:
JSCompiler_object_inline_stack_2370 = 134217728;
break;
default:
JSCompiler_object_inline_stack_2370 = 0;
}
JSCompiler_object_inline_stack_2370 =
if (
null !== JSCompiler_object_inline_digest_2369 &&
((JSCompiler_object_inline_stack_2370 = renderLanes & -renderLanes),
(JSCompiler_object_inline_stack_2370 =
0 !== (JSCompiler_object_inline_stack_2370 & 42)
? 1
: getBumpedLaneForHydrationByLane(
JSCompiler_object_inline_stack_2370
)),
(JSCompiler_object_inline_stack_2370 =
0 !==
(JSCompiler_object_inline_stack_2370 &
(JSCompiler_object_inline_digest_2369.suspendedLanes |
renderLanes))
? 0
: JSCompiler_object_inline_stack_2370;
if (
0 !== JSCompiler_object_inline_stack_2370 &&
JSCompiler_object_inline_stack_2370 !== prevState.retryLane
)
throw (
((prevState.retryLane = JSCompiler_object_inline_stack_2370),
enqueueConcurrentRenderForLane(
current,
JSCompiler_object_inline_stack_2370
),
scheduleUpdateOnFiber(
JSCompiler_object_inline_digest_2369,
current,
JSCompiler_object_inline_stack_2370
),
SelectiveHydrationException)
);
}
: JSCompiler_object_inline_stack_2370),
0 !== JSCompiler_object_inline_stack_2370 &&
JSCompiler_object_inline_stack_2370 !== prevState.retryLane)
)
throw (
((prevState.retryLane = JSCompiler_object_inline_stack_2370),
enqueueConcurrentRenderForLane(
current,
JSCompiler_object_inline_stack_2370
),
scheduleUpdateOnFiber(
JSCompiler_object_inline_digest_2369,
current,
JSCompiler_object_inline_stack_2370
),
SelectiveHydrationException)
);
JSCompiler_object_inline_message_2368.data ===
SUSPENSE_PENDING_START_DATA || renderDidSuspendDelayIfPossible();
workInProgress = retrySuspenseComponentWithoutHydrating(
Expand Down Expand Up @@ -21917,8 +21922,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 @@ -25936,11 +25945,11 @@ __DEV__ &&
};
(function () {
var isomorphicReactPackageVersion = React.version;
if ("19.0.0-native-fb-a4964987-20241211" !== isomorphicReactPackageVersion)
if ("19.1.0-native-fb-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-native-fb-a4964987-20241211\nLearn more: https://react.dev/warnings/version-mismatch")
"\n - react-dom: 19.1.0-native-fb-d5e8f79c-20241212\nLearn more: https://react.dev/warnings/version-mismatch")
);
})();
("function" === typeof Map &&
Expand Down Expand Up @@ -25977,10 +25986,10 @@ __DEV__ &&
!(function () {
var internals = {
bundleType: 1,
version: "19.0.0-native-fb-a4964987-20241211",
version: "19.1.0-native-fb-d5e8f79c-20241212",
rendererPackageName: "react-dom",
currentDispatcherRef: ReactSharedInternals,
reconcilerVersion: "19.0.0-native-fb-a4964987-20241211"
reconcilerVersion: "19.1.0-native-fb-d5e8f79c-20241212"
};
internals.overrideHookState = overrideHookState;
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
Expand Down Expand Up @@ -26114,15 +26123,17 @@ __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$1(initialChildren, isStrictMode);
options = isStrictMode;
initialChildren.current.lanes = options;
markRootUpdated$1(initialChildren, options);
ensureRootIsScheduled(initialChildren);
container[internalContainerInstanceKey] = initialChildren.current;
listenToAllSupportedEvents(container);
return new ReactDOMHydrationRoot(initialChildren);
};
exports.version = "19.0.0-native-fb-a4964987-20241211";
exports.version = "19.1.0-native-fb-d5e8f79c-20241212";
})();
Loading

0 comments on commit 40363db

Please sign in to comment.