Skip to content

Commit

Permalink
Fix: Infinite act loop caused by wrong shouldYield (#26317)
Browse files Browse the repository at this point in the history
Based on a bug report from @bvaughn.

`act` should not consult `shouldYield` when it's performing work,
because in a unit testing environment, I/O (such as `setTimeout`) is
likely mocked. So the result of `shouldYield` can't be trusted.

In the regression test, I simulate the bug by mocking `shouldYield` to
always return `true`. This causes an infinite loop in `act`, because it
will keep trying to render and React will keep yielding.

DiffTrain build for [49f7410](49f7410)
  • Loading branch information
acdlite committed Mar 6, 2023
1 parent 07b0722 commit 0fa8f92
Show file tree
Hide file tree
Showing 28 changed files with 130 additions and 50 deletions.
2 changes: 1 addition & 1 deletion compiled/facebook-www/REVISION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
106ea1c584d811eda5d328a5f7f856a738c2ca24
49f7410467950de57bd1d9509e67de91185f7bad
2 changes: 1 addition & 1 deletion compiled/facebook-www/REVISION_TRANSFORMS
Original file line number Diff line number Diff line change
@@ -1 +1 @@
106ea1c584d811eda5d328a5f7f856a738c2ca24
49f7410467950de57bd1d9509e67de91185f7bad
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-106ea1c58-20230305";
var ReactVersion = "18.3.0-www-classic-49f741046-20230305";

// ATTENTION
// When adding new symbols to this file,
Expand Down
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-dev.modern.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-modern-106ea1c58-20230305";
var ReactVersion = "18.3.0-www-modern-49f741046-20230305";

// ATTENTION
// When adding new symbols to this file,
Expand Down
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-prod.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -646,4 +646,4 @@ exports.useSyncExternalStore = function (
);
};
exports.useTransition = useTransition;
exports.version = "18.3.0-www-classic-106ea1c58-20230305";
exports.version = "18.3.0-www-classic-49f741046-20230305";
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 @@ -638,4 +638,4 @@ exports.useSyncExternalStore = function (
);
};
exports.useTransition = useTransition;
exports.version = "18.3.0-www-modern-106ea1c58-20230305";
exports.version = "18.3.0-www-modern-49f741046-20230305";
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-profiling.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -657,7 +657,7 @@ exports.useSyncExternalStore = function (
);
};
exports.useTransition = useTransition;
exports.version = "18.3.0-www-classic-106ea1c58-20230305";
exports.version = "18.3.0-www-classic-49f741046-20230305";

/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
if (
Expand Down
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 @@ -649,7 +649,7 @@ exports.useSyncExternalStore = function (
);
};
exports.useTransition = useTransition;
exports.version = "18.3.0-www-modern-106ea1c58-20230305";
exports.version = "18.3.0-www-modern-49f741046-20230305";

/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
if (
Expand Down
14 changes: 12 additions & 2 deletions compiled/facebook-www/ReactART-dev.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ function _assertThisInitialized(self) {
return self;
}

var ReactVersion = "18.3.0-www-classic-106ea1c58-20230305";
var ReactVersion = "18.3.0-www-classic-49f741046-20230305";

var LegacyRoot = 0;
var ConcurrentRoot = 1;
Expand Down Expand Up @@ -24600,7 +24600,17 @@ function renderRootConcurrent(root, lanes) {
}
}

workLoopConcurrent();
if (true && ReactCurrentActQueue.current !== null) {
// `act` special case: If we're inside an `act` scope, don't consult
// `shouldYield`. Always keep working until the render is complete.
// This is not just an optimization: in a unit test environment, we
// can't trust the result of `shouldYield`, because the host I/O is
// likely mocked.
workLoopSync();
} else {
workLoopConcurrent();
}

break;
} catch (thrownValue) {
handleThrow(root, thrownValue);
Expand Down
14 changes: 12 additions & 2 deletions compiled/facebook-www/ReactART-dev.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ function _assertThisInitialized(self) {
return self;
}

var ReactVersion = "18.3.0-www-modern-106ea1c58-20230305";
var ReactVersion = "18.3.0-www-modern-49f741046-20230305";

var LegacyRoot = 0;
var ConcurrentRoot = 1;
Expand Down Expand Up @@ -24260,7 +24260,17 @@ function renderRootConcurrent(root, lanes) {
}
}

workLoopConcurrent();
if (true && ReactCurrentActQueue.current !== null) {
// `act` special case: If we're inside an `act` scope, don't consult
// `shouldYield`. Always keep working until the render is complete.
// This is not just an optimization: in a unit test environment, we
// can't trust the result of `shouldYield`, because the host I/O is
// likely mocked.
workLoopSync();
} else {
workLoopConcurrent();
}

break;
} catch (thrownValue) {
handleThrow(root, thrownValue);
Expand Down
4 changes: 2 additions & 2 deletions compiled/facebook-www/ReactART-prod.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -9780,7 +9780,7 @@ var slice = Array.prototype.slice,
return null;
},
bundleType: 0,
version: "18.3.0-www-classic-106ea1c58-20230305",
version: "18.3.0-www-classic-49f741046-20230305",
rendererPackageName: "react-art"
};
var internals$jscomp$inline_1300 = {
Expand Down Expand Up @@ -9811,7 +9811,7 @@ var internals$jscomp$inline_1300 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-next-106ea1c58-20230305"
reconcilerVersion: "18.3.0-next-49f741046-20230305"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1301 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
Expand Down
4 changes: 2 additions & 2 deletions compiled/facebook-www/ReactART-prod.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -9445,7 +9445,7 @@ var slice = Array.prototype.slice,
return null;
},
bundleType: 0,
version: "18.3.0-www-modern-106ea1c58-20230305",
version: "18.3.0-www-modern-49f741046-20230305",
rendererPackageName: "react-art"
};
var internals$jscomp$inline_1280 = {
Expand Down Expand Up @@ -9476,7 +9476,7 @@ var internals$jscomp$inline_1280 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-next-106ea1c58-20230305"
reconcilerVersion: "18.3.0-next-49f741046-20230305"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1281 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
Expand Down
14 changes: 12 additions & 2 deletions compiled/facebook-www/ReactDOM-dev.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -39167,7 +39167,17 @@ function renderRootConcurrent(root, lanes) {
}
}

workLoopConcurrent();
if (true && ReactCurrentActQueue.current !== null) {
// `act` special case: If we're inside an `act` scope, don't consult
// `shouldYield`. Always keep working until the render is complete.
// This is not just an optimization: in a unit test environment, we
// can't trust the result of `shouldYield`, because the host I/O is
// likely mocked.
workLoopSync();
} else {
workLoopConcurrent();
}

break;
} catch (thrownValue) {
handleThrow(root, thrownValue);
Expand Down Expand Up @@ -42108,7 +42118,7 @@ function createFiberRoot(
return root;
}

var ReactVersion = "18.3.0-www-classic-106ea1c58-20230305";
var ReactVersion = "18.3.0-www-classic-49f741046-20230305";

function createPortal$1(
children,
Expand Down
14 changes: 12 additions & 2 deletions compiled/facebook-www/ReactDOM-dev.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -38771,7 +38771,17 @@ function renderRootConcurrent(root, lanes) {
}
}

workLoopConcurrent();
if (true && ReactCurrentActQueue.current !== null) {
// `act` special case: If we're inside an `act` scope, don't consult
// `shouldYield`. Always keep working until the render is complete.
// This is not just an optimization: in a unit test environment, we
// can't trust the result of `shouldYield`, because the host I/O is
// likely mocked.
workLoopSync();
} else {
workLoopConcurrent();
}

break;
} catch (thrownValue) {
handleThrow(root, thrownValue);
Expand Down Expand Up @@ -41712,7 +41722,7 @@ function createFiberRoot(
return root;
}

var ReactVersion = "18.3.0-www-modern-106ea1c58-20230305";
var ReactVersion = "18.3.0-www-modern-49f741046-20230305";

function createPortal$1(
children,
Expand Down
6 changes: 3 additions & 3 deletions compiled/facebook-www/ReactDOM-prod.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -15490,7 +15490,7 @@ Internals.Events = [
var devToolsConfig$jscomp$inline_1741 = {
findFiberByHostInstance: getClosestInstanceFromNode,
bundleType: 0,
version: "18.3.0-www-classic-106ea1c58-20230305",
version: "18.3.0-www-classic-49f741046-20230305",
rendererPackageName: "react-dom"
};
var internals$jscomp$inline_2108 = {
Expand Down Expand Up @@ -15520,7 +15520,7 @@ var internals$jscomp$inline_2108 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-next-106ea1c58-20230305"
reconcilerVersion: "18.3.0-next-49f741046-20230305"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_2109 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
Expand Down Expand Up @@ -15776,4 +15776,4 @@ exports.unstable_renderSubtreeIntoContainer = function (
);
};
exports.unstable_runWithPriority = runWithPriority;
exports.version = "18.3.0-next-106ea1c58-20230305";
exports.version = "18.3.0-next-49f741046-20230305";
6 changes: 3 additions & 3 deletions compiled/facebook-www/ReactDOM-prod.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -15019,7 +15019,7 @@ Internals.Events = [
var devToolsConfig$jscomp$inline_1700 = {
findFiberByHostInstance: getClosestInstanceFromNode,
bundleType: 0,
version: "18.3.0-www-modern-106ea1c58-20230305",
version: "18.3.0-www-modern-49f741046-20230305",
rendererPackageName: "react-dom"
};
var internals$jscomp$inline_2072 = {
Expand Down Expand Up @@ -15050,7 +15050,7 @@ var internals$jscomp$inline_2072 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-next-106ea1c58-20230305"
reconcilerVersion: "18.3.0-next-49f741046-20230305"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_2073 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
Expand Down Expand Up @@ -15235,4 +15235,4 @@ exports.unstable_flushControlled = function (fn) {
}
};
exports.unstable_runWithPriority = runWithPriority;
exports.version = "18.3.0-next-106ea1c58-20230305";
exports.version = "18.3.0-next-49f741046-20230305";
6 changes: 3 additions & 3 deletions compiled/facebook-www/ReactDOM-profiling.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -16267,7 +16267,7 @@ Internals.Events = [
var devToolsConfig$jscomp$inline_1821 = {
findFiberByHostInstance: getClosestInstanceFromNode,
bundleType: 0,
version: "18.3.0-www-classic-106ea1c58-20230305",
version: "18.3.0-www-classic-49f741046-20230305",
rendererPackageName: "react-dom"
};
(function (internals) {
Expand Down Expand Up @@ -16311,7 +16311,7 @@ var devToolsConfig$jscomp$inline_1821 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-next-106ea1c58-20230305"
reconcilerVersion: "18.3.0-next-49f741046-20230305"
});
assign(Internals, {
ReactBrowserEventEmitter: {
Expand Down Expand Up @@ -16554,7 +16554,7 @@ exports.unstable_renderSubtreeIntoContainer = function (
);
};
exports.unstable_runWithPriority = runWithPriority;
exports.version = "18.3.0-next-106ea1c58-20230305";
exports.version = "18.3.0-next-49f741046-20230305";

/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
if (
Expand Down
6 changes: 3 additions & 3 deletions compiled/facebook-www/ReactDOM-profiling.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -15786,7 +15786,7 @@ Internals.Events = [
var devToolsConfig$jscomp$inline_1780 = {
findFiberByHostInstance: getClosestInstanceFromNode,
bundleType: 0,
version: "18.3.0-www-modern-106ea1c58-20230305",
version: "18.3.0-www-modern-49f741046-20230305",
rendererPackageName: "react-dom"
};
(function (internals) {
Expand Down Expand Up @@ -15831,7 +15831,7 @@ var devToolsConfig$jscomp$inline_1780 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-next-106ea1c58-20230305"
reconcilerVersion: "18.3.0-next-49f741046-20230305"
});
exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = Internals;
exports.createPortal = function (children, container) {
Expand Down Expand Up @@ -16003,7 +16003,7 @@ exports.unstable_flushControlled = function (fn) {
}
};
exports.unstable_runWithPriority = runWithPriority;
exports.version = "18.3.0-next-106ea1c58-20230305";
exports.version = "18.3.0-next-49f741046-20230305";

/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
if (
Expand Down
2 changes: 1 addition & 1 deletion compiled/facebook-www/ReactDOMServer-dev.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ if (__DEV__) {
var React = require("react");
var ReactDOM = require("react-dom");

var ReactVersion = "18.3.0-www-classic-106ea1c58-20230305";
var ReactVersion = "18.3.0-www-classic-49f741046-20230305";

// This refers to a WWW module.
var warningWWW = require("warning");
Expand Down
2 changes: 1 addition & 1 deletion compiled/facebook-www/ReactDOMServer-dev.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ if (__DEV__) {
var React = require("react");
var ReactDOM = require("react-dom");

var ReactVersion = "18.3.0-www-modern-106ea1c58-20230305";
var ReactVersion = "18.3.0-www-modern-49f741046-20230305";

// This refers to a WWW module.
var warningWWW = require("warning");
Expand Down
2 changes: 1 addition & 1 deletion compiled/facebook-www/ReactDOMServer-prod.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -3771,4 +3771,4 @@ exports.renderToString = function (children, options) {
'The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToReadableStream" which supports Suspense on the server'
);
};
exports.version = "18.3.0-www-classic-106ea1c58-20230305";
exports.version = "18.3.0-www-classic-49f741046-20230305";
2 changes: 1 addition & 1 deletion compiled/facebook-www/ReactDOMServer-prod.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -3669,4 +3669,4 @@ exports.renderToString = function (children, options) {
'The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToReadableStream" which supports Suspense on the server'
);
};
exports.version = "18.3.0-www-modern-106ea1c58-20230305";
exports.version = "18.3.0-www-modern-49f741046-20230305";
14 changes: 12 additions & 2 deletions compiled/facebook-www/ReactDOMTesting-dev.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -28814,7 +28814,17 @@ function renderRootConcurrent(root, lanes) {
}
}

workLoopConcurrent();
if (true && ReactCurrentActQueue.current !== null) {
// `act` special case: If we're inside an `act` scope, don't consult
// `shouldYield`. Always keep working until the render is complete.
// This is not just an optimization: in a unit test environment, we
// can't trust the result of `shouldYield`, because the host I/O is
// likely mocked.
workLoopSync();
} else {
workLoopConcurrent();
}

break;
} catch (thrownValue) {
handleThrow(root, thrownValue);
Expand Down Expand Up @@ -31237,7 +31247,7 @@ function createFiberRoot(
return root;
}

var ReactVersion = "18.3.0-www-classic-106ea1c58-20230305";
var ReactVersion = "18.3.0-www-classic-49f741046-20230305";

function createPortal$1(
children,
Expand Down
14 changes: 12 additions & 2 deletions compiled/facebook-www/ReactDOMTesting-dev.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -35305,7 +35305,17 @@ function renderRootConcurrent(root, lanes) {
}
}

workLoopConcurrent();
if (true && ReactCurrentActQueue.current !== null) {
// `act` special case: If we're inside an `act` scope, don't consult
// `shouldYield`. Always keep working until the render is complete.
// This is not just an optimization: in a unit test environment, we
// can't trust the result of `shouldYield`, because the host I/O is
// likely mocked.
workLoopSync();
} else {
workLoopConcurrent();
}

break;
} catch (thrownValue) {
handleThrow(root, thrownValue);
Expand Down Expand Up @@ -37728,7 +37738,7 @@ function createFiberRoot(
return root;
}

var ReactVersion = "18.3.0-www-modern-106ea1c58-20230305";
var ReactVersion = "18.3.0-www-modern-49f741046-20230305";

function createPortal$1(
children,
Expand Down
Loading

0 comments on commit 0fa8f92

Please sign in to comment.