diff --git a/packages/react-reconciler/src/ReactFiberLane.js b/packages/react-reconciler/src/ReactFiberLane.js
index 905eda36a93e8..c110b29c250ef 100644
--- a/packages/react-reconciler/src/ReactFiberLane.js
+++ b/packages/react-reconciler/src/ReactFiberLane.js
@@ -423,7 +423,9 @@ export function markStarvedLanesAsExpired(
// We exclude retry lanes because those must always be time sliced, in order
// to unwrap uncached promises.
// TODO: Write a test for this
- let lanes = pendingLanes & ~RetryLanes;
+ let lanes = enableRetryLaneExpiration
+ ? pendingLanes
+ : pendingLanes & ~RetryLanes;
while (lanes > 0) {
const index = pickArbitraryLaneIndex(lanes);
const lane = 1 << index;
diff --git a/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js b/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js
index d93c8bcf606ab..77aae6ee53d9b 100644
--- a/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js
+++ b/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js
@@ -5,6 +5,7 @@ let Scheduler;
let act;
let waitFor;
let waitForAll;
+let waitForMicrotasks;
let assertLog;
let waitForPaint;
let Suspense;
@@ -29,6 +30,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
waitFor = InternalTestUtils.waitFor;
waitForAll = InternalTestUtils.waitForAll;
waitForPaint = InternalTestUtils.waitForPaint;
+ waitForMicrotasks = InternalTestUtils.waitForMicrotasks;
assertLog = InternalTestUtils.assertLog;
getCacheForType = React.unstable_getCacheForType;
@@ -4008,4 +4010,74 @@ describe('ReactSuspenseWithNoopRenderer', () => {
);
},
);
+
+ // @gate enableLegacyCache && enableRetryLaneExpiration
+ it('recurring updates in siblings should not block expensive content in suspense boundary from committing', async () => {
+ const {useState} = React;
+
+ let setText;
+ function UpdatingText() {
+ const [text, _setText] = useState('1');
+ setText = _setText;
+ return ;
+ }
+
+ function ExpensiveText({text, ms}) {
+ Scheduler.log(text);
+ Scheduler.unstable_advanceTime(ms);
+ return ;
+ }
+
+ function App() {
+ return (
+ <>
+
+ }>
+
+
+
+
+
+ >
+ );
+ }
+
+ const root = ReactNoop.createRoot();
+ root.render();
+ await waitForAll(['1', 'Suspend! [Async]', 'Loading...']);
+ expect(root).toMatchRenderedOutput(
+ <>
+
+
+ >,
+ );
+
+ await resolveText('Async');
+ expect(root).toMatchRenderedOutput(
+ <>
+
+
+ >,
+ );
+
+ await waitFor(['Async', 'A', 'B']);
+ ReactNoop.expire(100000);
+ await advanceTimers(100000);
+ setText('2');
+ await waitForPaint(['2']);
+
+ await waitForMicrotasks();
+ Scheduler.unstable_flushNumberOfYields(1);
+ assertLog(['Async', 'A', 'B', 'C']);
+
+ expect(root).toMatchRenderedOutput(
+ <>
+
+
+
+
+
+ >,
+ );
+ });
});