Skip to content

Commit

Permalink
Bugfix: useDeferredValue loop during popstate transition (#27559)
Browse files Browse the repository at this point in the history
During a popstate event, we attempt to render updates synchronously even
if they are transitions, to preserve scroll position if possible. We do
this by entangling the transition lane with the Sync lane.

However, if rendering the transition spawns additional transition
updates (e.g. a setState inside useEffect), there's no reason to render
those synchronously, too. We should use the normal transition behavior.

This fixes an issue where useDeferredValue during a popstate event would
spawn a transition update that was itself also synchronous.

DiffTrain build for [6db7f42](6db7f42)
  • Loading branch information
acdlite committed Oct 21, 2023
1 parent 5a422ba commit dc239e6
Show file tree
Hide file tree
Showing 14 changed files with 190 additions and 60 deletions.
2 changes: 1 addition & 1 deletion compiled/facebook-www/REVISION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8c85b02996b940d63f961f835348a0dd0045d3b6
6db7f4209e6f32ebde298a0b7451710dd6aa3e19
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 @@ -27,7 +27,7 @@ if (
}
"use strict";

var ReactVersion = "18.3.0-www-classic-08b720b1";
var ReactVersion = "18.3.0-www-classic-63396f54";

// ATTENTION
// When adding new symbols to this file,
Expand Down
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 @@ -579,4 +579,4 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactCurrentDispatcher.current.useTransition();
};
exports.version = "18.3.0-www-modern-f25765d2";
exports.version = "18.3.0-www-modern-ed902e38";
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 @@ -590,7 +590,7 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactCurrentDispatcher.current.useTransition();
};
exports.version = "18.3.0-www-modern-a1b21365";
exports.version = "18.3.0-www-modern-82bf9b55";

/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
if (
Expand Down
26 changes: 24 additions & 2 deletions compiled/facebook-www/ReactDOM-dev.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -34150,7 +34150,7 @@ function createFiberRoot(
return root;
}

var ReactVersion = "18.3.0-www-classic-3d4cba16";
var ReactVersion = "18.3.0-www-classic-a73ccc38";

function createPortal$1(
children,
Expand Down Expand Up @@ -42008,8 +42008,30 @@ function getCurrentEventPriority() {

return getEventPriority(currentEvent.type);
}
var currentPopstateTransitionEvent = null;
function shouldAttemptEagerTransition() {
return window.event && window.event.type === "popstate";
var event = window.event;

if (event && event.type === "popstate") {
// This is a popstate event. Attempt to render any transition during this
// event synchronously. Unless we already attempted during this event.
if (event === currentPopstateTransitionEvent) {
// We already attempted to render this popstate transition synchronously.
// Any subsequent attempts must have happened as the result of a derived
// update, like startTransition inside useEffect, or useDV. Switch back to
// the default behavior for all remaining transitions during the current
// popstate event.
return false;
} else {
// Cache the current event in case a derived transition is scheduled.
// (Refer to previous branch.)
currentPopstateTransitionEvent = event;
return true;
}
} // We're not inside a popstate event.

currentPopstateTransitionEvent = null;
return false;
}
// if a component just imports ReactDOM (e.g. for findDOMNode).
// Some environments might not have setTimeout or clearTimeout.
Expand Down
26 changes: 24 additions & 2 deletions compiled/facebook-www/ReactDOM-dev.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -33995,7 +33995,7 @@ function createFiberRoot(
return root;
}

var ReactVersion = "18.3.0-www-modern-e95a7c7a";
var ReactVersion = "18.3.0-www-modern-682a5c12";

function createPortal$1(
children,
Expand Down Expand Up @@ -42518,8 +42518,30 @@ function getCurrentEventPriority() {

return getEventPriority(currentEvent.type);
}
var currentPopstateTransitionEvent = null;
function shouldAttemptEagerTransition() {
return window.event && window.event.type === "popstate";
var event = window.event;

if (event && event.type === "popstate") {
// This is a popstate event. Attempt to render any transition during this
// event synchronously. Unless we already attempted during this event.
if (event === currentPopstateTransitionEvent) {
// We already attempted to render this popstate transition synchronously.
// Any subsequent attempts must have happened as the result of a derived
// update, like startTransition inside useEffect, or useDV. Switch back to
// the default behavior for all remaining transitions during the current
// popstate event.
return false;
} else {
// Cache the current event in case a derived transition is scheduled.
// (Refer to previous branch.)
currentPopstateTransitionEvent = event;
return true;
}
} // We're not inside a popstate event.

currentPopstateTransitionEvent = null;
return false;
}
// if a component just imports ReactDOM (e.g. for findDOMNode).
// Some environments might not have setTimeout or clearTimeout.
Expand Down
23 changes: 15 additions & 8 deletions compiled/facebook-www/ReactDOM-prod.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -3106,11 +3106,7 @@ function processRootScheduleInMicrotask() {

) {
var next = root.next;
if (
0 !== currentEventTransitionLane &&
window.event &&
"popstate" === window.event.type
) {
if (0 !== currentEventTransitionLane && shouldAttemptEagerTransition()) {
var root$jscomp$0 = root,
lane = currentEventTransitionLane;
root$jscomp$0.pendingLanes |= 2;
Expand Down Expand Up @@ -14701,6 +14697,17 @@ function shouldSetTextContent(type, props) {
null != props.dangerouslySetInnerHTML.__html)
);
}
var currentPopstateTransitionEvent = null;
function shouldAttemptEagerTransition() {
var event = window.event;
if (event && "popstate" === event.type) {
if (event === currentPopstateTransitionEvent) return !1;
currentPopstateTransitionEvent = event;
return !0;
}
currentPopstateTransitionEvent = null;
return !1;
}
var scheduleTimeout = "function" === typeof setTimeout ? setTimeout : void 0,
cancelTimeout = "function" === typeof clearTimeout ? clearTimeout : void 0,
localPromise = "function" === typeof Promise ? Promise : void 0,
Expand Down Expand Up @@ -16473,7 +16480,7 @@ Internals.Events = [
var devToolsConfig$jscomp$inline_1796 = {
findFiberByHostInstance: getClosestInstanceFromNode,
bundleType: 0,
version: "18.3.0-www-classic-5728733b",
version: "18.3.0-www-classic-3c2b8f45",
rendererPackageName: "react-dom"
};
var internals$jscomp$inline_2142 = {
Expand Down Expand Up @@ -16503,7 +16510,7 @@ var internals$jscomp$inline_2142 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-www-classic-5728733b"
reconcilerVersion: "18.3.0-www-classic-3c2b8f45"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_2143 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
Expand Down Expand Up @@ -16840,4 +16847,4 @@ exports.useFormState = function () {
exports.useFormStatus = function () {
throw Error(formatProdErrorMessage(248));
};
exports.version = "18.3.0-www-classic-5728733b";
exports.version = "18.3.0-www-classic-3c2b8f45";
23 changes: 15 additions & 8 deletions compiled/facebook-www/ReactDOM-prod.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -3003,11 +3003,7 @@ function processRootScheduleInMicrotask() {

) {
var next = root.next;
if (
0 !== currentEventTransitionLane &&
window.event &&
"popstate" === window.event.type
) {
if (0 !== currentEventTransitionLane && shouldAttemptEagerTransition()) {
var root$jscomp$0 = root,
lane = currentEventTransitionLane;
root$jscomp$0.pendingLanes |= 2;
Expand Down Expand Up @@ -14944,6 +14940,17 @@ function shouldSetTextContent(type, props) {
null != props.dangerouslySetInnerHTML.__html)
);
}
var currentPopstateTransitionEvent = null;
function shouldAttemptEagerTransition() {
var event = window.event;
if (event && "popstate" === event.type) {
if (event === currentPopstateTransitionEvent) return !1;
currentPopstateTransitionEvent = event;
return !0;
}
currentPopstateTransitionEvent = null;
return !1;
}
var scheduleTimeout = "function" === typeof setTimeout ? setTimeout : void 0,
cancelTimeout = "function" === typeof clearTimeout ? clearTimeout : void 0,
localPromise = "function" === typeof Promise ? Promise : void 0,
Expand Down Expand Up @@ -15999,7 +16006,7 @@ Internals.Events = [
var devToolsConfig$jscomp$inline_1755 = {
findFiberByHostInstance: getClosestInstanceFromNode,
bundleType: 0,
version: "18.3.0-www-modern-b72d3d1b",
version: "18.3.0-www-modern-d4fb2ac8",
rendererPackageName: "react-dom"
};
var internals$jscomp$inline_2106 = {
Expand Down Expand Up @@ -16030,7 +16037,7 @@ var internals$jscomp$inline_2106 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-www-modern-b72d3d1b"
reconcilerVersion: "18.3.0-www-modern-d4fb2ac8"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_2107 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
Expand Down Expand Up @@ -16295,4 +16302,4 @@ exports.useFormState = function () {
exports.useFormStatus = function () {
throw Error(formatProdErrorMessage(248));
};
exports.version = "18.3.0-www-modern-b72d3d1b";
exports.version = "18.3.0-www-modern-d4fb2ac8";
23 changes: 15 additions & 8 deletions compiled/facebook-www/ReactDOM-profiling.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -3253,11 +3253,7 @@ function processRootScheduleInMicrotask() {

) {
var next = root.next;
if (
0 !== currentEventTransitionLane &&
window.event &&
"popstate" === window.event.type
) {
if (0 !== currentEventTransitionLane && shouldAttemptEagerTransition()) {
var root$jscomp$0 = root,
lane = currentEventTransitionLane;
root$jscomp$0.pendingLanes |= 2;
Expand Down Expand Up @@ -15477,6 +15473,17 @@ function shouldSetTextContent(type, props) {
null != props.dangerouslySetInnerHTML.__html)
);
}
var currentPopstateTransitionEvent = null;
function shouldAttemptEagerTransition() {
var event = window.event;
if (event && "popstate" === event.type) {
if (event === currentPopstateTransitionEvent) return !1;
currentPopstateTransitionEvent = event;
return !0;
}
currentPopstateTransitionEvent = null;
return !1;
}
var scheduleTimeout = "function" === typeof setTimeout ? setTimeout : void 0,
cancelTimeout = "function" === typeof clearTimeout ? clearTimeout : void 0,
localPromise = "function" === typeof Promise ? Promise : void 0,
Expand Down Expand Up @@ -17249,7 +17256,7 @@ Internals.Events = [
var devToolsConfig$jscomp$inline_1881 = {
findFiberByHostInstance: getClosestInstanceFromNode,
bundleType: 0,
version: "18.3.0-www-classic-60bcbdf9",
version: "18.3.0-www-classic-0f5bdde1",
rendererPackageName: "react-dom"
};
(function (internals) {
Expand Down Expand Up @@ -17293,7 +17300,7 @@ var devToolsConfig$jscomp$inline_1881 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-www-classic-60bcbdf9"
reconcilerVersion: "18.3.0-www-classic-0f5bdde1"
});
assign(Internals, {
ReactBrowserEventEmitter: {
Expand Down Expand Up @@ -17617,7 +17624,7 @@ exports.useFormState = function () {
exports.useFormStatus = function () {
throw Error(formatProdErrorMessage(248));
};
exports.version = "18.3.0-www-classic-60bcbdf9";
exports.version = "18.3.0-www-classic-0f5bdde1";

/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
if (
Expand Down
23 changes: 15 additions & 8 deletions compiled/facebook-www/ReactDOM-profiling.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -3150,11 +3150,7 @@ function processRootScheduleInMicrotask() {

) {
var next = root.next;
if (
0 !== currentEventTransitionLane &&
window.event &&
"popstate" === window.event.type
) {
if (0 !== currentEventTransitionLane && shouldAttemptEagerTransition()) {
var root$jscomp$0 = root,
lane = currentEventTransitionLane;
root$jscomp$0.pendingLanes |= 2;
Expand Down Expand Up @@ -15714,6 +15710,17 @@ function shouldSetTextContent(type, props) {
null != props.dangerouslySetInnerHTML.__html)
);
}
var currentPopstateTransitionEvent = null;
function shouldAttemptEagerTransition() {
var event = window.event;
if (event && "popstate" === event.type) {
if (event === currentPopstateTransitionEvent) return !1;
currentPopstateTransitionEvent = event;
return !0;
}
currentPopstateTransitionEvent = null;
return !1;
}
var scheduleTimeout = "function" === typeof setTimeout ? setTimeout : void 0,
cancelTimeout = "function" === typeof clearTimeout ? clearTimeout : void 0,
localPromise = "function" === typeof Promise ? Promise : void 0,
Expand Down Expand Up @@ -16769,7 +16776,7 @@ Internals.Events = [
var devToolsConfig$jscomp$inline_1840 = {
findFiberByHostInstance: getClosestInstanceFromNode,
bundleType: 0,
version: "18.3.0-www-modern-3c8736cc",
version: "18.3.0-www-modern-88285787",
rendererPackageName: "react-dom"
};
(function (internals) {
Expand Down Expand Up @@ -16814,7 +16821,7 @@ var devToolsConfig$jscomp$inline_1840 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-www-modern-3c8736cc"
reconcilerVersion: "18.3.0-www-modern-88285787"
});
exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = Internals;
exports.createPortal = function (children, container) {
Expand Down Expand Up @@ -17066,7 +17073,7 @@ exports.useFormState = function () {
exports.useFormStatus = function () {
throw Error(formatProdErrorMessage(248));
};
exports.version = "18.3.0-www-modern-3c8736cc";
exports.version = "18.3.0-www-modern-88285787";

/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
if (
Expand Down
26 changes: 24 additions & 2 deletions compiled/facebook-www/ReactDOMTesting-dev.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -34767,7 +34767,7 @@ function createFiberRoot(
return root;
}

var ReactVersion = "18.3.0-www-classic-2a0db555";
var ReactVersion = "18.3.0-www-classic-0c4709ef";

function createPortal$1(
children,
Expand Down Expand Up @@ -42625,8 +42625,30 @@ function getCurrentEventPriority() {

return getEventPriority(currentEvent.type);
}
var currentPopstateTransitionEvent = null;
function shouldAttemptEagerTransition() {
return window.event && window.event.type === "popstate";
var event = window.event;

if (event && event.type === "popstate") {
// This is a popstate event. Attempt to render any transition during this
// event synchronously. Unless we already attempted during this event.
if (event === currentPopstateTransitionEvent) {
// We already attempted to render this popstate transition synchronously.
// Any subsequent attempts must have happened as the result of a derived
// update, like startTransition inside useEffect, or useDV. Switch back to
// the default behavior for all remaining transitions during the current
// popstate event.
return false;
} else {
// Cache the current event in case a derived transition is scheduled.
// (Refer to previous branch.)
currentPopstateTransitionEvent = event;
return true;
}
} // We're not inside a popstate event.

currentPopstateTransitionEvent = null;
return false;
}
// if a component just imports ReactDOM (e.g. for findDOMNode).
// Some environments might not have setTimeout or clearTimeout.
Expand Down
Loading

0 comments on commit dc239e6

Please sign in to comment.