Skip to content

Commit 8d3e7a7

Browse files
committed
Prerendering support for useDeferredValue (#27512)
### Based on #27509 Revealing a prerendered tree (hidden -> visible) is considered the same as mounting a brand new tree. So, when an initialValue argument is passed to useDeferredValue, and it's prerendered inside a hidden tree, we should first prerender the initial value. After the initial value has been prerendered, we switch to prerendering the final one. This is the same sequence that we use when mounting new visible tree. Depending on how much prerendering work has been finished by the time the tree is revealed, we may or may not be able to skip all the way to the final value. This means we get the benefits of both prerendering and preview states: if we have enough resources to prerender the whole thing, we do that. If we don't, we have a preview state to show for immediate feedback. DiffTrain build for commit 75c1bd7.
1 parent b763135 commit 8d3e7a7

File tree

13 files changed

+342
-295
lines changed

13 files changed

+342
-295
lines changed

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-dev.js

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<e2046f4b72996278b314c5849a8eb848>>
10+
* @generated SignedSource<<4d9878b267a005902b63980f6c367201>>
1111
*/
1212

1313
'use strict';
@@ -8580,46 +8580,49 @@ function mountDeferredValueImpl(hook, value, initialValue) {
85808580
}
85818581

85828582
function updateDeferredValueImpl(hook, prevValue, value, initialValue) {
8583-
// TODO: We should also check if this component is going from
8584-
// hidden -> visible. If so, it should use the initialValue arg.
8585-
var shouldDeferValue = !includesOnlyNonUrgentLanes(renderLanes);
8586-
8587-
if (shouldDeferValue) {
8588-
// This is an urgent update. If the value has changed, keep using the
8589-
// previous value and spawn a deferred render to update it later.
8590-
if (!objectIs(value, prevValue)) {
8583+
if (objectIs(value, prevValue)) {
8584+
// The incoming value is referentially identical to the currently rendered
8585+
// value, so we can bail out quickly.
8586+
return value;
8587+
} else {
8588+
// Received a new value that's different from the current value.
8589+
// Check if we're inside a hidden tree
8590+
if (isCurrentTreeHidden()) {
8591+
// Revealing a prerendered tree is considered the same as mounting new
8592+
// one, so we reuse the "mount" path in this case.
8593+
var resultValue = mountDeferredValueImpl(hook, value); // Unlike during an actual mount, we need to mark this as an update if
8594+
// the value changed.
8595+
8596+
if (!objectIs(resultValue, prevValue)) {
8597+
markWorkInProgressReceivedUpdate();
8598+
}
8599+
8600+
return resultValue;
8601+
}
8602+
8603+
var shouldDeferValue = !includesOnlyNonUrgentLanes(renderLanes);
8604+
8605+
if (shouldDeferValue) {
8606+
// This is an urgent update. Since the value has changed, keep using the
8607+
// previous value and spawn a deferred render to update it later.
85918608
// Schedule a deferred render
85928609
var deferredLane = requestDeferredLane();
85938610
currentlyRenderingFiber$1.lanes = mergeLanes(
85948611
currentlyRenderingFiber$1.lanes,
85958612
deferredLane
85968613
);
8597-
markSkippedUpdateLanes(deferredLane); // Set this to true to indicate that the rendered value is inconsistent
8598-
// from the latest value. The name "baseState" doesn't really match how we
8599-
// use it because we're reusing a state hook field instead of creating a
8600-
// new one.
8614+
markSkippedUpdateLanes(deferredLane); // Reuse the previous value. We do not need to mark this as an update,
8615+
// because we did not render a new value.
86018616

8602-
hook.baseState = true;
8603-
} // Reuse the previous value
8604-
8605-
return prevValue;
8606-
} else {
8607-
// This is not an urgent update, so we can use the latest value regardless
8608-
// of what it is. No need to defer it.
8609-
// However, if we're currently inside a spawned render, then we need to mark
8610-
// this as an update to prevent the fiber from bailing out.
8611-
//
8612-
// `baseState` is true when the current value is different from the rendered
8613-
// value. The name doesn't really match how we use it because we're reusing
8614-
// a state hook field instead of creating a new one.
8615-
if (hook.baseState) {
8616-
// Flip this back to false.
8617-
hook.baseState = false;
8617+
return prevValue;
8618+
} else {
8619+
// This is not an urgent update, so we can use the latest value regardless
8620+
// of what it is. No need to defer it.
8621+
// Mark this as an update to prevent the fiber from bailing out.
86188622
markWorkInProgressReceivedUpdate();
8623+
hook.memoizedState = value;
8624+
return value;
86198625
}
8620-
8621-
hook.memoizedState = value;
8622-
return value;
86238626
}
86248627
}
86258628

@@ -24875,7 +24878,7 @@ function createFiberRoot(
2487524878
return root;
2487624879
}
2487724880

24878-
var ReactVersion = "18.3.0-canary-b2a68a65c-20231017";
24881+
var ReactVersion = "18.3.0-canary-75c1bd7ee-20231017";
2487924882

2488024883
// Might add PROFILE later.
2488124884

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-prod.js

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<d2181e69a294cf0b50b846b598547492>>
10+
* @generated SignedSource<<ed6d8869c24db97c9d90eec277215874>>
1111
*/
1212

1313
"use strict";
@@ -2849,21 +2849,23 @@ function updateMemo(nextCreate, deps) {
28492849
return nextCreate;
28502850
}
28512851
function updateDeferredValueImpl(hook, prevValue, value) {
2852-
if (0 === (renderLanes & 42))
2852+
if (objectIs(value, prevValue)) return value;
2853+
if (null !== currentTreeHiddenStackCursor.current)
28532854
return (
2854-
hook.baseState && ((hook.baseState = !1), (didReceiveUpdate = !0)),
2855-
(hook.memoizedState = value)
2855+
(hook.memoizedState = value),
2856+
objectIs(value, prevValue) || (didReceiveUpdate = !0),
2857+
value
28562858
);
2857-
objectIs(value, prevValue) ||
2858-
(0 === workInProgressDeferredLane &&
2859-
(workInProgressDeferredLane =
2860-
0 !== (workInProgressRootRenderLanes & 536870912)
2861-
? 536870912
2862-
: requestTransitionLane()),
2863-
(value = workInProgressDeferredLane),
2864-
(currentlyRenderingFiber$1.lanes |= value),
2865-
(workInProgressRootSkippedLanes |= value),
2866-
(hook.baseState = !0));
2859+
if (0 === (renderLanes & 42))
2860+
return (didReceiveUpdate = !0), (hook.memoizedState = value);
2861+
0 === workInProgressDeferredLane &&
2862+
(workInProgressDeferredLane =
2863+
0 !== (workInProgressRootRenderLanes & 536870912)
2864+
? 536870912
2865+
: requestTransitionLane());
2866+
hook = workInProgressDeferredLane;
2867+
currentlyRenderingFiber$1.lanes |= hook;
2868+
workInProgressRootSkippedLanes |= hook;
28672869
return prevValue;
28682870
}
28692871
function startTransition(fiber, queue, pendingState, finishedState, callback) {
@@ -9015,19 +9017,19 @@ function wrapFiber(fiber) {
90159017
fiberToWrapper.set(fiber, wrapper));
90169018
return wrapper;
90179019
}
9018-
var devToolsConfig$jscomp$inline_1025 = {
9020+
var devToolsConfig$jscomp$inline_1031 = {
90199021
findFiberByHostInstance: function () {
90209022
throw Error("TestRenderer does not support findFiberByHostInstance()");
90219023
},
90229024
bundleType: 0,
9023-
version: "18.3.0-canary-b2a68a65c-20231017",
9025+
version: "18.3.0-canary-75c1bd7ee-20231017",
90249026
rendererPackageName: "react-test-renderer"
90259027
};
9026-
var internals$jscomp$inline_1218 = {
9027-
bundleType: devToolsConfig$jscomp$inline_1025.bundleType,
9028-
version: devToolsConfig$jscomp$inline_1025.version,
9029-
rendererPackageName: devToolsConfig$jscomp$inline_1025.rendererPackageName,
9030-
rendererConfig: devToolsConfig$jscomp$inline_1025.rendererConfig,
9028+
var internals$jscomp$inline_1224 = {
9029+
bundleType: devToolsConfig$jscomp$inline_1031.bundleType,
9030+
version: devToolsConfig$jscomp$inline_1031.version,
9031+
rendererPackageName: devToolsConfig$jscomp$inline_1031.rendererPackageName,
9032+
rendererConfig: devToolsConfig$jscomp$inline_1031.rendererConfig,
90319033
overrideHookState: null,
90329034
overrideHookStateDeletePath: null,
90339035
overrideHookStateRenamePath: null,
@@ -9044,26 +9046,26 @@ var internals$jscomp$inline_1218 = {
90449046
return null === fiber ? null : fiber.stateNode;
90459047
},
90469048
findFiberByHostInstance:
9047-
devToolsConfig$jscomp$inline_1025.findFiberByHostInstance ||
9049+
devToolsConfig$jscomp$inline_1031.findFiberByHostInstance ||
90489050
emptyFindFiberByHostInstance,
90499051
findHostInstancesForRefresh: null,
90509052
scheduleRefresh: null,
90519053
scheduleRoot: null,
90529054
setRefreshHandler: null,
90539055
getCurrentFiber: null,
9054-
reconcilerVersion: "18.3.0-canary-b2a68a65c-20231017"
9056+
reconcilerVersion: "18.3.0-canary-75c1bd7ee-20231017"
90559057
};
90569058
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
9057-
var hook$jscomp$inline_1219 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
9059+
var hook$jscomp$inline_1225 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
90589060
if (
9059-
!hook$jscomp$inline_1219.isDisabled &&
9060-
hook$jscomp$inline_1219.supportsFiber
9061+
!hook$jscomp$inline_1225.isDisabled &&
9062+
hook$jscomp$inline_1225.supportsFiber
90619063
)
90629064
try {
9063-
(rendererID = hook$jscomp$inline_1219.inject(
9064-
internals$jscomp$inline_1218
9065+
(rendererID = hook$jscomp$inline_1225.inject(
9066+
internals$jscomp$inline_1224
90659067
)),
9066-
(injectedHook = hook$jscomp$inline_1219);
9068+
(injectedHook = hook$jscomp$inline_1225);
90679069
} catch (err) {}
90689070
}
90699071
exports._Scheduler = Scheduler;

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-profiling.js

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<efc6d41dec65b2187ec52681d760c9b7>>
10+
* @generated SignedSource<<c3d1140631a9ffbb19f029e3ecdb90fc>>
1111
*/
1212

1313
"use strict";
@@ -2869,21 +2869,23 @@ function updateMemo(nextCreate, deps) {
28692869
return nextCreate;
28702870
}
28712871
function updateDeferredValueImpl(hook, prevValue, value) {
2872-
if (0 === (renderLanes & 42))
2872+
if (objectIs(value, prevValue)) return value;
2873+
if (null !== currentTreeHiddenStackCursor.current)
28732874
return (
2874-
hook.baseState && ((hook.baseState = !1), (didReceiveUpdate = !0)),
2875-
(hook.memoizedState = value)
2875+
(hook.memoizedState = value),
2876+
objectIs(value, prevValue) || (didReceiveUpdate = !0),
2877+
value
28762878
);
2877-
objectIs(value, prevValue) ||
2878-
(0 === workInProgressDeferredLane &&
2879-
(workInProgressDeferredLane =
2880-
0 !== (workInProgressRootRenderLanes & 536870912)
2881-
? 536870912
2882-
: requestTransitionLane()),
2883-
(value = workInProgressDeferredLane),
2884-
(currentlyRenderingFiber$1.lanes |= value),
2885-
(workInProgressRootSkippedLanes |= value),
2886-
(hook.baseState = !0));
2879+
if (0 === (renderLanes & 42))
2880+
return (didReceiveUpdate = !0), (hook.memoizedState = value);
2881+
0 === workInProgressDeferredLane &&
2882+
(workInProgressDeferredLane =
2883+
0 !== (workInProgressRootRenderLanes & 536870912)
2884+
? 536870912
2885+
: requestTransitionLane());
2886+
hook = workInProgressDeferredLane;
2887+
currentlyRenderingFiber$1.lanes |= hook;
2888+
workInProgressRootSkippedLanes |= hook;
28872889
return prevValue;
28882890
}
28892891
function startTransition(fiber, queue, pendingState, finishedState, callback) {
@@ -9441,19 +9443,19 @@ function wrapFiber(fiber) {
94419443
fiberToWrapper.set(fiber, wrapper));
94429444
return wrapper;
94439445
}
9444-
var devToolsConfig$jscomp$inline_1067 = {
9446+
var devToolsConfig$jscomp$inline_1073 = {
94459447
findFiberByHostInstance: function () {
94469448
throw Error("TestRenderer does not support findFiberByHostInstance()");
94479449
},
94489450
bundleType: 0,
9449-
version: "18.3.0-canary-b2a68a65c-20231017",
9451+
version: "18.3.0-canary-75c1bd7ee-20231017",
94509452
rendererPackageName: "react-test-renderer"
94519453
};
9452-
var internals$jscomp$inline_1259 = {
9453-
bundleType: devToolsConfig$jscomp$inline_1067.bundleType,
9454-
version: devToolsConfig$jscomp$inline_1067.version,
9455-
rendererPackageName: devToolsConfig$jscomp$inline_1067.rendererPackageName,
9456-
rendererConfig: devToolsConfig$jscomp$inline_1067.rendererConfig,
9454+
var internals$jscomp$inline_1265 = {
9455+
bundleType: devToolsConfig$jscomp$inline_1073.bundleType,
9456+
version: devToolsConfig$jscomp$inline_1073.version,
9457+
rendererPackageName: devToolsConfig$jscomp$inline_1073.rendererPackageName,
9458+
rendererConfig: devToolsConfig$jscomp$inline_1073.rendererConfig,
94579459
overrideHookState: null,
94589460
overrideHookStateDeletePath: null,
94599461
overrideHookStateRenamePath: null,
@@ -9470,26 +9472,26 @@ var internals$jscomp$inline_1259 = {
94709472
return null === fiber ? null : fiber.stateNode;
94719473
},
94729474
findFiberByHostInstance:
9473-
devToolsConfig$jscomp$inline_1067.findFiberByHostInstance ||
9475+
devToolsConfig$jscomp$inline_1073.findFiberByHostInstance ||
94749476
emptyFindFiberByHostInstance,
94759477
findHostInstancesForRefresh: null,
94769478
scheduleRefresh: null,
94779479
scheduleRoot: null,
94789480
setRefreshHandler: null,
94799481
getCurrentFiber: null,
9480-
reconcilerVersion: "18.3.0-canary-b2a68a65c-20231017"
9482+
reconcilerVersion: "18.3.0-canary-75c1bd7ee-20231017"
94819483
};
94829484
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
9483-
var hook$jscomp$inline_1260 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
9485+
var hook$jscomp$inline_1266 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
94849486
if (
9485-
!hook$jscomp$inline_1260.isDisabled &&
9486-
hook$jscomp$inline_1260.supportsFiber
9487+
!hook$jscomp$inline_1266.isDisabled &&
9488+
hook$jscomp$inline_1266.supportsFiber
94879489
)
94889490
try {
9489-
(rendererID = hook$jscomp$inline_1260.inject(
9490-
internals$jscomp$inline_1259
9491+
(rendererID = hook$jscomp$inline_1266.inject(
9492+
internals$jscomp$inline_1265
94919493
)),
9492-
(injectedHook = hook$jscomp$inline_1260);
9494+
(injectedHook = hook$jscomp$inline_1266);
94939495
} catch (err) {}
94949496
}
94959497
exports._Scheduler = Scheduler;

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-dev.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ if (
2727
}
2828
"use strict";
2929

30-
var ReactVersion = "18.3.0-canary-b2a68a65c-20231017";
30+
var ReactVersion = "18.3.0-canary-75c1bd7ee-20231017";
3131

3232
// ATTENTION
3333
// When adding new symbols to this file,

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-prod.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,4 +580,4 @@ exports.useSyncExternalStore = function (
580580
exports.useTransition = function () {
581581
return ReactCurrentDispatcher.current.useTransition();
582582
};
583-
exports.version = "18.3.0-canary-b2a68a65c-20231017";
583+
exports.version = "18.3.0-canary-75c1bd7ee-20231017";

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-profiling.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,7 @@ exports.useSyncExternalStore = function (
583583
exports.useTransition = function () {
584584
return ReactCurrentDispatcher.current.useTransition();
585585
};
586-
exports.version = "18.3.0-canary-b2a68a65c-20231017";
586+
exports.version = "18.3.0-canary-75c1bd7ee-20231017";
587587

588588
/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
589589
if (
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
b2a68a65c84b63ac86930d88ae5c84380cbbdeb6
1+
75c1bd7ee7e4a87a4dd0f560e157c57957ef823b

0 commit comments

Comments
 (0)