Skip to content

Commit 6c99ba7

Browse files
committed
Fix: Synchronous popstate transitions (#30759)
This is a refactor of the fix in #27505. When a transition update is scheduled by a popstate event, (i.e. a back/ forward navigation) we attempt to render it synchronously even though it's a transition, since it's likely the previous page's data is cached. In #27505, I changed the implementation so that it only "upgrades" the priority of the transition for a single attempt. If the attempt suspends, say because the data is not cached after all, from then on it should be treated as a normal transition. But it turns out #27505 did not work as intended, because it relied on marking the root with pending synchronous work (root.pendingLanes), which was never cleared until the popstate update completed. The test scenarios I wrote accidentally worked for a different reason related to suspending the work loop, which I'm currently in the middle of refactoring. DiffTrain build for commit ee7f675.
1 parent 99d43a1 commit 6c99ba7

14 files changed

+890
-731
lines changed

compiled-rn/VERSION_NATIVE_FB

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
19.0.0-native-fb-85fb95cd-20240816
1+
19.0.0-native-fb-ee7f6757-20240823

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

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<7279cc9cb0c567689cd8628192884a45>>
10+
* @generated SignedSource<<487e4d25726d3b9452e5df47a0ff70f5>>
1111
*/
1212

1313
"use strict";
1414
__DEV__ &&
1515
(function () {
16-
function JSCompiler_object_inline_createNodeMock_1088() {
16+
function JSCompiler_object_inline_createNodeMock_1089() {
1717
return null;
1818
}
1919
function findHook(fiber, id) {
@@ -1789,28 +1789,41 @@ __DEV__ &&
17891789
0 === root.tag &&
17901790
(ReactSharedInternals.didScheduleLegacyUpdate = !0);
17911791
}
1792-
function flushSyncWorkAcrossRoots_impl(onlyLegacy) {
1792+
function flushSyncWorkAcrossRoots_impl(syncTransitionLanes, onlyLegacy) {
17931793
if (!isFlushingWork && mightHavePendingSyncWork) {
17941794
isFlushingWork = !0;
17951795
do {
17961796
var didPerformSomeWork = !1;
17971797
for (var root = firstScheduledRoot; null !== root; ) {
1798-
if (!onlyLegacy || 0 === root.tag) {
1799-
var workInProgressRootRenderLanes$jscomp$0 =
1800-
workInProgressRootRenderLanes;
1801-
workInProgressRootRenderLanes$jscomp$0 = getNextLanes(
1802-
root,
1803-
root === workInProgressRoot
1804-
? workInProgressRootRenderLanes$jscomp$0
1805-
: 0
1806-
);
1807-
0 !== (workInProgressRootRenderLanes$jscomp$0 & 3) &&
1808-
((didPerformSomeWork = !0),
1809-
performSyncWorkOnRoot(
1810-
root,
1811-
workInProgressRootRenderLanes$jscomp$0
1812-
));
1813-
}
1798+
if (!onlyLegacy || 0 === root.tag)
1799+
if (0 !== syncTransitionLanes) {
1800+
var pendingLanes = root.pendingLanes;
1801+
if (0 === pendingLanes) var nextLanes = 0;
1802+
else {
1803+
var suspendedLanes = root.suspendedLanes,
1804+
pingedLanes = root.pingedLanes;
1805+
nextLanes =
1806+
(1 << (31 - clz32(42 | syncTransitionLanes) + 1)) - 1;
1807+
nextLanes &= pendingLanes & ~(suspendedLanes & ~pingedLanes);
1808+
nextLanes =
1809+
nextLanes & 201326677
1810+
? (nextLanes & 201326677) | 1
1811+
: nextLanes
1812+
? nextLanes | 2
1813+
: 0;
1814+
}
1815+
0 !== nextLanes &&
1816+
((didPerformSomeWork = !0),
1817+
performSyncWorkOnRoot(root, nextLanes));
1818+
} else
1819+
(nextLanes = workInProgressRootRenderLanes),
1820+
(nextLanes = getNextLanes(
1821+
root,
1822+
root === workInProgressRoot ? nextLanes : 0
1823+
)),
1824+
0 !== (nextLanes & 3) &&
1825+
((didPerformSomeWork = !0),
1826+
performSyncWorkOnRoot(root, nextLanes));
18141827
root = root.next;
18151828
}
18161829
} while (didPerformSomeWork);
@@ -1822,6 +1835,7 @@ __DEV__ &&
18221835
didScheduleMicrotask_act =
18231836
didScheduleMicrotask =
18241837
!1;
1838+
0 !== currentEventTransitionLane && (currentEventTransitionLane = 0);
18251839
for (
18261840
var currentTime = now$1(), prev = null, root = firstScheduledRoot;
18271841
null !== root;
@@ -1837,8 +1851,7 @@ __DEV__ &&
18371851
0 !== (nextLanes & 3) && (mightHavePendingSyncWork = !0));
18381852
root = next;
18391853
}
1840-
currentEventTransitionLane = 0;
1841-
flushSyncWorkAcrossRoots_impl(!1);
1854+
flushSyncWorkAcrossRoots_impl(0, !1);
18421855
}
18431856
function scheduleTaskForRootDuringMicrotask(root, currentTime) {
18441857
for (
@@ -10536,7 +10549,7 @@ __DEV__ &&
1053610549
0 !== (fiber.mode & 1) ||
1053710550
ReactSharedInternals.isBatchingLegacy ||
1053810551
((workInProgressRootRenderTargetTime = now$1() + RENDER_TIMEOUT_MS),
10539-
flushSyncWorkAcrossRoots_impl(!0));
10552+
flushSyncWorkAcrossRoots_impl(0, !0));
1054010553
}
1054110554
function performConcurrentWorkOnRoot(root, didTimeout) {
1054210555
nestedUpdateScheduled = currentUpdateIsNested = !1;
@@ -10861,12 +10874,12 @@ __DEV__ &&
1086110874
(ReactSharedInternals.T = prevTransition),
1086210875
(executionContext = prevExecutionContext),
1086310876
(executionContext & (RenderContext | CommitContext)) === NoContext &&
10864-
flushSyncWorkAcrossRoots_impl(!1);
10877+
flushSyncWorkAcrossRoots_impl(0, !1);
1086510878
}
1086610879
}
1086710880
function flushSyncWork() {
1086810881
return (executionContext & (RenderContext | CommitContext)) === NoContext
10869-
? (flushSyncWorkAcrossRoots_impl(!1), !1)
10882+
? (flushSyncWorkAcrossRoots_impl(0, !1), !1)
1087010883
: !0;
1087110884
}
1087210885
function resetWorkInProgressStack() {
@@ -11549,7 +11562,7 @@ __DEV__ &&
1154911562
? nestedUpdateCount++
1155011563
: ((nestedUpdateCount = 0), (rootWithNestedUpdates = root)))
1155111564
: (nestedUpdateCount = 0);
11552-
flushSyncWorkAcrossRoots_impl(!1);
11565+
flushSyncWorkAcrossRoots_impl(0, !1);
1155311566
markCommitStopped();
1155411567
return null;
1155511568
}
@@ -11679,7 +11692,7 @@ __DEV__ &&
1167911692
injectedProfilingHooks.markPassiveEffectsStopped();
1168011693
commitDoubleInvokeEffectsInDEV(priority, !0);
1168111694
executionContext = prevExecutionContext;
11682-
flushSyncWorkAcrossRoots_impl(!1);
11695+
flushSyncWorkAcrossRoots_impl(0, !1);
1168311696
didScheduleUpdateDuringPassiveEffects
1168411697
? priority === rootWithPassiveNestedUpdates
1168511698
? nestedPassiveUpdateCount++
@@ -14925,11 +14938,11 @@ __DEV__ &&
1492514938
(function () {
1492614939
var internals = {
1492714940
bundleType: 1,
14928-
version: "19.0.0-native-fb-85fb95cd-20240816",
14941+
version: "19.0.0-native-fb-ee7f6757-20240823",
1492914942
rendererPackageName: "react-test-renderer",
1493014943
currentDispatcherRef: ReactSharedInternals,
1493114944
findFiberByHostInstance: getInstanceFromNode,
14932-
reconcilerVersion: "19.0.0-native-fb-85fb95cd-20240816"
14945+
reconcilerVersion: "19.0.0-native-fb-ee7f6757-20240823"
1493314946
};
1493414947
internals.overrideHookState = overrideHookState;
1493514948
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
@@ -14951,7 +14964,7 @@ __DEV__ &&
1495114964
exports._Scheduler = Scheduler;
1495214965
exports.act = act;
1495314966
exports.create = function (element, options) {
14954-
var createNodeMock = JSCompiler_object_inline_createNodeMock_1088,
14967+
var createNodeMock = JSCompiler_object_inline_createNodeMock_1089,
1495514968
isConcurrent = !1,
1495614969
isStrictMode = !1;
1495714970
"object" === typeof options &&
@@ -15071,8 +15084,8 @@ __DEV__ &&
1507115084
executionContext !== NoContext ||
1507215085
ReactSharedInternals.isBatchingLegacy ||
1507315086
((workInProgressRootRenderTargetTime = now$1() + RENDER_TIMEOUT_MS),
15074-
flushSyncWorkAcrossRoots_impl(!0));
15087+
flushSyncWorkAcrossRoots_impl(0, !0));
1507515088
}
1507615089
};
15077-
exports.version = "19.0.0-native-fb-85fb95cd-20240816";
15090+
exports.version = "19.0.0-native-fb-ee7f6757-20240823";
1507815091
})();

0 commit comments

Comments
 (0)