Skip to content

Commit 9e0082b

Browse files
committed
Synchronously flush the transition lane scheduled in a popstate event (#26025)
<!-- Thanks for submitting a pull request! We appreciate you spending the time to work on these changes. Please provide enough information so that others can review your pull request. The three fields below are mandatory. Before submitting a pull request, please make sure the following is done: 1. Fork [the repository](https://github.com/facebook/react) and create your branch from `main`. 2. Run `yarn` in the repository root. 3. If you've fixed a bug or added code that should be tested, add tests! 4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch TestName` is helpful in development. 5. Run `yarn test --prod` to test in the production environment. It supports the same options as `yarn test`. 6. If you need a debugger, run `yarn debug-test --watch TestName`, open `chrome://inspect`, and press "Inspect". 7. Format your code with [prettier](https://github.com/prettier/prettier) (`yarn prettier`). 8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only check changed files. 9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`). 10. If you haven't already, complete the CLA. Learn more about contributing: https://reactjs.org/docs/how-to-contribute.html --> ## Summary Browsers restore state like forms and scroll position right after the popstate event. To make sure the page work as expected on back or forward button, we need to flush transitions scheduled in a popstate synchronously, and only yields if it suspends. This PR adds a new HostConfig method to check if `window.event === 'popstate'`, and `scheduleMicrotask` if a transition is scheduled in a `PopStateEvent`. ## How did you test this change? yarn test DiffTrain build for commit d121c67.
1 parent 79f5d01 commit 9e0082b

File tree

13 files changed

+182
-128
lines changed

13 files changed

+182
-128
lines changed

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

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1947,6 +1947,9 @@ function createTextInstance(
19471947
function getCurrentEventPriority() {
19481948
return DefaultEventPriority;
19491949
}
1950+
function shouldAttemptEagerTransition() {
1951+
return false;
1952+
}
19501953
var scheduleTimeout = setTimeout;
19511954
var cancelTimeout = clearTimeout;
19521955
var noTimeout = -1; // -------------------
@@ -19378,6 +19381,7 @@ var didScheduleMicrotask_act = false; // Used to quickly bail out of flushSync i
1937819381

1937919382
var mightHavePendingSyncWork = false;
1938019383
var isFlushingWork = false;
19384+
var currentEventTransitionLane = NoLanes;
1938119385
function ensureRootIsScheduled(root) {
1938219386
// This function is called whenever a root receives an update. It does two
1938319387
// things 1) it ensures the root is in the root schedule, and 2) it ensures
@@ -19528,6 +19532,14 @@ function processRootScheduleInMicrotask() {
1952819532

1952919533
while (root !== null) {
1953019534
var next = root.next;
19535+
19536+
if (
19537+
currentEventTransitionLane !== NoLane &&
19538+
shouldAttemptEagerTransition()
19539+
) {
19540+
markRootEntangled(root, mergeLanes(currentEventTransitionLane, SyncLane));
19541+
}
19542+
1953119543
var nextLanes = scheduleTaskForRootDuringMicrotask(root, currentTime);
1953219544

1953319545
if (nextLanes === NoLane) {
@@ -19559,7 +19571,9 @@ function processRootScheduleInMicrotask() {
1955919571
}
1956019572

1956119573
root = next;
19562-
} // At the end of the microtask, flush any pending synchronous work. This has
19574+
}
19575+
19576+
currentEventTransitionLane = NoLane; // At the end of the microtask, flush any pending synchronous work. This has
1956319577
// to come at the end, because it does actual rendering work that might throw.
1956419578

1956519579
flushSyncWorkOnAllRoots();
@@ -19732,6 +19746,13 @@ function scheduleImmediateTask(cb) {
1973219746
}
1973319747
}
1973419748

19749+
function getCurrentEventTransitionLane() {
19750+
return currentEventTransitionLane;
19751+
}
19752+
function setCurrentEventTransitionLane(lane) {
19753+
currentEventTransitionLane = lane;
19754+
}
19755+
1973519756
var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map;
1973619757
var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher,
1973719758
ReactCurrentCache = ReactSharedInternals.ReactCurrentCache,
@@ -19846,7 +19867,6 @@ var didScheduleUpdateDuringPassiveEffects = false;
1984619867
var NESTED_PASSIVE_UPDATE_LIMIT = 50;
1984719868
var nestedPassiveUpdateCount = 0;
1984819869
var rootWithPassiveNestedUpdates = null;
19849-
var currentEventTransitionLane = NoLanes;
1985019870
var isRunningInsertionEffect = false;
1985119871
function getWorkInProgressRoot() {
1985219872
return workInProgressRoot;
@@ -19898,12 +19918,12 @@ function requestUpdateLane(fiber) {
1989819918
// event. Then reset the cached values once we can be sure the event is
1989919919
// over. Our heuristic for that is whenever we enter a concurrent work loop.
1990019920

19901-
if (currentEventTransitionLane === NoLane) {
19921+
if (getCurrentEventTransitionLane() === NoLane) {
1990219922
// All transitions within the same event are assigned the same lane.
19903-
currentEventTransitionLane = claimNextTransitionLane();
19923+
setCurrentEventTransitionLane(claimNextTransitionLane());
1990419924
}
1990519925

19906-
return currentEventTransitionLane;
19926+
return getCurrentEventTransitionLane();
1990719927
} // Updates originating inside certain React methods, like flushSync, have
1990819928
// their priority set by tracking it with a context variable.
1990919929
//
@@ -20034,8 +20054,6 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
2003420054
resetNestedUpdateFlag();
2003520055
}
2003620056

20037-
currentEventTransitionLane = NoLanes;
20038-
2003920057
if ((executionContext & (RenderContext | CommitContext)) !== NoContext) {
2004020058
throw new Error("Should not already be working.");
2004120059
} // Flush any pending passive effects before deciding which lanes to work on,
@@ -23727,7 +23745,7 @@ function createFiberRoot(
2372723745
return root;
2372823746
}
2372923747

23730-
var ReactVersion = "18.3.0-next-7b0642bb9-20230412";
23748+
var ReactVersion = "18.3.0-next-d121c6700-20230413";
2373123749

2373223750
// Might add PROFILE later.
2373323751

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

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6165,7 +6165,8 @@ var DefaultCacheDispatcher = {
61656165
lastScheduledRoot = null,
61666166
didScheduleMicrotask = !1,
61676167
mightHavePendingSyncWork = !1,
6168-
isFlushingWork = !1;
6168+
isFlushingWork = !1,
6169+
currentEventTransitionLane = 0;
61696170
function ensureRootIsScheduled(root) {
61706171
root !== lastScheduledRoot &&
61716172
null === root.next &&
@@ -6282,6 +6283,7 @@ function processRootScheduleInMicrotask() {
62826283
0 !== (nextLanes & 3) && (mightHavePendingSyncWork = !0));
62836284
root = next;
62846285
}
6286+
currentEventTransitionLane = 0;
62856287
flushSyncWorkAcrossRoots_impl(!1);
62866288
}
62876289
function scheduleTaskForRootDuringMicrotask(root, currentTime) {
@@ -6387,8 +6389,7 @@ var PossiblyWeakMap = "function" === typeof WeakMap ? WeakMap : Map,
63876389
pendingPassiveEffectsRemainingLanes = 0,
63886390
pendingPassiveTransitions = null,
63896391
nestedUpdateCount = 0,
6390-
rootWithNestedUpdates = null,
6391-
currentEventTransitionLane = 0;
6392+
rootWithNestedUpdates = null;
63926393
function requestUpdateLane(fiber) {
63936394
if (0 === (fiber.mode & 1)) return 2;
63946395
if (0 !== (executionContext & 2) && 0 !== workInProgressRootRenderLanes)
@@ -6424,7 +6425,6 @@ function scheduleUpdateOnFiber(root, fiber, lane) {
64246425
flushSyncWorkAcrossRoots_impl(!0));
64256426
}
64266427
function performConcurrentWorkOnRoot(root, didTimeout) {
6427-
currentEventTransitionLane = 0;
64286428
if (0 !== (executionContext & 6))
64296429
throw Error("Should not already be working.");
64306430
var originalCallbackNode = root.callbackNode;
@@ -8582,19 +8582,19 @@ function wrapFiber(fiber) {
85828582
fiberToWrapper.set(fiber, wrapper));
85838583
return wrapper;
85848584
}
8585-
var devToolsConfig$jscomp$inline_1021 = {
8585+
var devToolsConfig$jscomp$inline_1023 = {
85868586
findFiberByHostInstance: function () {
85878587
throw Error("TestRenderer does not support findFiberByHostInstance()");
85888588
},
85898589
bundleType: 0,
8590-
version: "18.3.0-next-7b0642bb9-20230412",
8590+
version: "18.3.0-next-d121c6700-20230413",
85918591
rendererPackageName: "react-test-renderer"
85928592
};
8593-
var internals$jscomp$inline_1204 = {
8594-
bundleType: devToolsConfig$jscomp$inline_1021.bundleType,
8595-
version: devToolsConfig$jscomp$inline_1021.version,
8596-
rendererPackageName: devToolsConfig$jscomp$inline_1021.rendererPackageName,
8597-
rendererConfig: devToolsConfig$jscomp$inline_1021.rendererConfig,
8593+
var internals$jscomp$inline_1206 = {
8594+
bundleType: devToolsConfig$jscomp$inline_1023.bundleType,
8595+
version: devToolsConfig$jscomp$inline_1023.version,
8596+
rendererPackageName: devToolsConfig$jscomp$inline_1023.rendererPackageName,
8597+
rendererConfig: devToolsConfig$jscomp$inline_1023.rendererConfig,
85988598
overrideHookState: null,
85998599
overrideHookStateDeletePath: null,
86008600
overrideHookStateRenamePath: null,
@@ -8611,26 +8611,26 @@ var internals$jscomp$inline_1204 = {
86118611
return null === fiber ? null : fiber.stateNode;
86128612
},
86138613
findFiberByHostInstance:
8614-
devToolsConfig$jscomp$inline_1021.findFiberByHostInstance ||
8614+
devToolsConfig$jscomp$inline_1023.findFiberByHostInstance ||
86158615
emptyFindFiberByHostInstance,
86168616
findHostInstancesForRefresh: null,
86178617
scheduleRefresh: null,
86188618
scheduleRoot: null,
86198619
setRefreshHandler: null,
86208620
getCurrentFiber: null,
8621-
reconcilerVersion: "18.3.0-next-7b0642bb9-20230412"
8621+
reconcilerVersion: "18.3.0-next-d121c6700-20230413"
86228622
};
86238623
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
8624-
var hook$jscomp$inline_1205 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
8624+
var hook$jscomp$inline_1207 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
86258625
if (
8626-
!hook$jscomp$inline_1205.isDisabled &&
8627-
hook$jscomp$inline_1205.supportsFiber
8626+
!hook$jscomp$inline_1207.isDisabled &&
8627+
hook$jscomp$inline_1207.supportsFiber
86288628
)
86298629
try {
8630-
(rendererID = hook$jscomp$inline_1205.inject(
8631-
internals$jscomp$inline_1204
8630+
(rendererID = hook$jscomp$inline_1207.inject(
8631+
internals$jscomp$inline_1206
86328632
)),
8633-
(injectedHook = hook$jscomp$inline_1205);
8633+
(injectedHook = hook$jscomp$inline_1207);
86348634
} catch (err) {}
86358635
}
86368636
exports._Scheduler = Scheduler;

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

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6501,7 +6501,8 @@ var DefaultCacheDispatcher = {
65016501
lastScheduledRoot = null,
65026502
didScheduleMicrotask = !1,
65036503
mightHavePendingSyncWork = !1,
6504-
isFlushingWork = !1;
6504+
isFlushingWork = !1,
6505+
currentEventTransitionLane = 0;
65056506
function ensureRootIsScheduled(root) {
65066507
root !== lastScheduledRoot &&
65076508
null === root.next &&
@@ -6620,6 +6621,7 @@ function processRootScheduleInMicrotask() {
66206621
0 !== (nextLanes & 3) && (mightHavePendingSyncWork = !0));
66216622
root = next;
66226623
}
6624+
currentEventTransitionLane = 0;
66236625
flushSyncWorkAcrossRoots_impl(!1);
66246626
}
66256627
function scheduleTaskForRootDuringMicrotask(root, currentTime) {
@@ -6726,8 +6728,7 @@ var PossiblyWeakMap = "function" === typeof WeakMap ? WeakMap : Map,
67266728
pendingPassiveEffectsRemainingLanes = 0,
67276729
pendingPassiveTransitions = null,
67286730
nestedUpdateCount = 0,
6729-
rootWithNestedUpdates = null,
6730-
currentEventTransitionLane = 0;
6731+
rootWithNestedUpdates = null;
67316732
function requestUpdateLane(fiber) {
67326733
if (0 === (fiber.mode & 1)) return 2;
67336734
if (0 !== (executionContext & 2) && 0 !== workInProgressRootRenderLanes)
@@ -6764,7 +6765,6 @@ function scheduleUpdateOnFiber(root, fiber, lane) {
67646765
}
67656766
function performConcurrentWorkOnRoot(root, didTimeout) {
67666767
nestedUpdateScheduled = currentUpdateIsNested = !1;
6767-
currentEventTransitionLane = 0;
67686768
if (0 !== (executionContext & 6))
67696769
throw Error("Should not already be working.");
67706770
var originalCallbackNode = root.callbackNode;
@@ -9008,19 +9008,19 @@ function wrapFiber(fiber) {
90089008
fiberToWrapper.set(fiber, wrapper));
90099009
return wrapper;
90109010
}
9011-
var devToolsConfig$jscomp$inline_1063 = {
9011+
var devToolsConfig$jscomp$inline_1065 = {
90129012
findFiberByHostInstance: function () {
90139013
throw Error("TestRenderer does not support findFiberByHostInstance()");
90149014
},
90159015
bundleType: 0,
9016-
version: "18.3.0-next-7b0642bb9-20230412",
9016+
version: "18.3.0-next-d121c6700-20230413",
90179017
rendererPackageName: "react-test-renderer"
90189018
};
9019-
var internals$jscomp$inline_1245 = {
9020-
bundleType: devToolsConfig$jscomp$inline_1063.bundleType,
9021-
version: devToolsConfig$jscomp$inline_1063.version,
9022-
rendererPackageName: devToolsConfig$jscomp$inline_1063.rendererPackageName,
9023-
rendererConfig: devToolsConfig$jscomp$inline_1063.rendererConfig,
9019+
var internals$jscomp$inline_1247 = {
9020+
bundleType: devToolsConfig$jscomp$inline_1065.bundleType,
9021+
version: devToolsConfig$jscomp$inline_1065.version,
9022+
rendererPackageName: devToolsConfig$jscomp$inline_1065.rendererPackageName,
9023+
rendererConfig: devToolsConfig$jscomp$inline_1065.rendererConfig,
90249024
overrideHookState: null,
90259025
overrideHookStateDeletePath: null,
90269026
overrideHookStateRenamePath: null,
@@ -9037,26 +9037,26 @@ var internals$jscomp$inline_1245 = {
90379037
return null === fiber ? null : fiber.stateNode;
90389038
},
90399039
findFiberByHostInstance:
9040-
devToolsConfig$jscomp$inline_1063.findFiberByHostInstance ||
9040+
devToolsConfig$jscomp$inline_1065.findFiberByHostInstance ||
90419041
emptyFindFiberByHostInstance,
90429042
findHostInstancesForRefresh: null,
90439043
scheduleRefresh: null,
90449044
scheduleRoot: null,
90459045
setRefreshHandler: null,
90469046
getCurrentFiber: null,
9047-
reconcilerVersion: "18.3.0-next-7b0642bb9-20230412"
9047+
reconcilerVersion: "18.3.0-next-d121c6700-20230413"
90489048
};
90499049
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
9050-
var hook$jscomp$inline_1246 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
9050+
var hook$jscomp$inline_1248 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
90519051
if (
9052-
!hook$jscomp$inline_1246.isDisabled &&
9053-
hook$jscomp$inline_1246.supportsFiber
9052+
!hook$jscomp$inline_1248.isDisabled &&
9053+
hook$jscomp$inline_1248.supportsFiber
90549054
)
90559055
try {
9056-
(rendererID = hook$jscomp$inline_1246.inject(
9057-
internals$jscomp$inline_1245
9056+
(rendererID = hook$jscomp$inline_1248.inject(
9057+
internals$jscomp$inline_1247
90589058
)),
9059-
(injectedHook = hook$jscomp$inline_1246);
9059+
(injectedHook = hook$jscomp$inline_1248);
90609060
} catch (err) {}
90619061
}
90629062
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-next-7b0642bb9-20230412";
30+
var ReactVersion = "18.3.0-next-d121c6700-20230413";
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
@@ -639,4 +639,4 @@ exports.useSyncExternalStore = function (
639639
);
640640
};
641641
exports.useTransition = useTransition;
642-
exports.version = "18.3.0-next-7b0642bb9-20230412";
642+
exports.version = "18.3.0-next-d121c6700-20230413";

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
@@ -642,7 +642,7 @@ exports.useSyncExternalStore = function (
642642
);
643643
};
644644
exports.useTransition = useTransition;
645-
exports.version = "18.3.0-next-7b0642bb9-20230412";
645+
exports.version = "18.3.0-next-d121c6700-20230413";
646646

647647
/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
648648
if (
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
7b0642bb989ec659c6c9891ea16daa0420caab4d
1+
d121c67004a2e6b0bb5d341843663ef213f64863

0 commit comments

Comments
 (0)