Skip to content

Commit cb59d65

Browse files
committed
Render children passed to "backwards" SuspenseList in reverse mount order (#35021)
Stacked on #35018. This mounts the children of SuspenseList backwards. Meaning the first child is mounted last in the DOM (and effect list). It's like calling reverse() on the children. This is meant to set us up for allowing AsyncIterable children where the unknown number of children streams in at the end (which is the beginning in a backwards SuspenseList). For consistency we do that with other children too. `unstable_legacy-backwards` still exists for the old mode but is meant to be deprecated. <img width="100" alt="image" src="https://github.com/user-attachments/assets/5c2a95d7-34c4-4a4e-b602-3646a834d779" /> DiffTrain build for [488d88b](488d88b)
1 parent 30cd0fc commit cb59d65

37 files changed

+3398
-2751
lines changed

compiled/facebook-www/REVISION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
26cf2804802f3d32c4d8f9db73ddea12ad6c1670
1+
488d88b018ee8fd1fac56cab22dfa8796ebce30b
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
26cf2804802f3d32c4d8f9db73ddea12ad6c1670
1+
488d88b018ee8fd1fac56cab22dfa8796ebce30b

compiled/facebook-www/React-dev.classic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1499,7 +1499,7 @@ __DEV__ &&
14991499
exports.useTransition = function () {
15001500
return resolveDispatcher().useTransition();
15011501
};
1502-
exports.version = "19.3.0-www-classic-26cf2804-20251031";
1502+
exports.version = "19.3.0-www-classic-488d88b0-20251031";
15031503
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
15041504
"function" ===
15051505
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/React-dev.modern.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1499,7 +1499,7 @@ __DEV__ &&
14991499
exports.useTransition = function () {
15001500
return resolveDispatcher().useTransition();
15011501
};
1502-
exports.version = "19.3.0-www-modern-26cf2804-20251031";
1502+
exports.version = "19.3.0-www-modern-488d88b0-20251031";
15031503
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
15041504
"function" ===
15051505
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/React-prod.classic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -606,4 +606,4 @@ exports.useSyncExternalStore = function (
606606
exports.useTransition = function () {
607607
return ReactSharedInternals.H.useTransition();
608608
};
609-
exports.version = "19.3.0-www-classic-26cf2804-20251031";
609+
exports.version = "19.3.0-www-classic-488d88b0-20251031";

compiled/facebook-www/React-prod.modern.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -606,4 +606,4 @@ exports.useSyncExternalStore = function (
606606
exports.useTransition = function () {
607607
return ReactSharedInternals.H.useTransition();
608608
};
609-
exports.version = "19.3.0-www-modern-26cf2804-20251031";
609+
exports.version = "19.3.0-www-modern-488d88b0-20251031";

compiled/facebook-www/React-profiling.classic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,7 @@ exports.useSyncExternalStore = function (
610610
exports.useTransition = function () {
611611
return ReactSharedInternals.H.useTransition();
612612
};
613-
exports.version = "19.3.0-www-classic-26cf2804-20251031";
613+
exports.version = "19.3.0-www-classic-488d88b0-20251031";
614614
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
615615
"function" ===
616616
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/React-profiling.modern.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,7 @@ exports.useSyncExternalStore = function (
610610
exports.useTransition = function () {
611611
return ReactSharedInternals.H.useTransition();
612612
};
613-
exports.version = "19.3.0-www-modern-26cf2804-20251031";
613+
exports.version = "19.3.0-www-modern-488d88b0-20251031";
614614
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
615615
"function" ===
616616
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/ReactART-dev.classic.js

Lines changed: 59 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9055,6 +9055,16 @@ __DEV__ &&
90559055
propagationRoot
90569056
);
90579057
}
9058+
function findLastContentRow(firstChild) {
9059+
for (var lastContentRow = null; null !== firstChild; ) {
9060+
var currentRow = firstChild.alternate;
9061+
null !== currentRow &&
9062+
null === findFirstSuspended(currentRow) &&
9063+
(lastContentRow = firstChild);
9064+
firstChild = firstChild.sibling;
9065+
}
9066+
return lastContentRow;
9067+
}
90589068
function initSuspenseListRenderState(
90599069
workInProgress,
90609070
isBackwards,
@@ -9082,6 +9092,15 @@ __DEV__ &&
90829092
(renderState.tailMode = tailMode),
90839093
(renderState.treeForkCount = treeForkCount));
90849094
}
9095+
function reverseChildren(fiber) {
9096+
var row = fiber.child;
9097+
for (fiber.child = null; null !== row; ) {
9098+
var nextRow = row.sibling;
9099+
row.sibling = fiber.child;
9100+
fiber.child = row;
9101+
row = nextRow;
9102+
}
9103+
}
90859104
function updateSuspenseListComponent(current, workInProgress, renderLanes) {
90869105
var nextProps = workInProgress.pendingProps,
90879106
revealOrder = nextProps.revealOrder,
@@ -9100,19 +9119,16 @@ __DEV__ &&
91009119
if (
91019120
null != revealOrder &&
91029121
"forwards" !== revealOrder &&
9122+
"backwards" !== revealOrder &&
91039123
"unstable_legacy-backwards" !== revealOrder &&
91049124
"together" !== revealOrder &&
91059125
"independent" !== revealOrder &&
91069126
!didWarnAboutRevealOrder[suspenseContext]
91079127
)
91089128
if (
91099129
((didWarnAboutRevealOrder[suspenseContext] = !0),
9110-
"backwards" === revealOrder)
9130+
"string" === typeof revealOrder)
91119131
)
9112-
console.error(
9113-
'The rendering order of <SuspenseList revealOrder="backwards"> is changing. To be future compatible you must specify revealOrder="legacy_unstable-backwards" instead.'
9114-
);
9115-
else if ("string" === typeof revealOrder)
91169132
switch (revealOrder.toLowerCase()) {
91179133
case "together":
91189134
case "forwards":
@@ -9204,7 +9220,11 @@ __DEV__ &&
92049220
'A single row was passed to a <SuspenseList revealOrder="%s" />. This is not useful since it needs multiple rows. Did you mean to pass multiple children or an array?',
92059221
revealOrder
92069222
);
9207-
reconcileChildren(current, workInProgress, nextProps, renderLanes);
9223+
"backwards" === revealOrder && null !== current
9224+
? (reverseChildren(current),
9225+
reconcileChildren(current, workInProgress, nextProps, renderLanes),
9226+
reverseChildren(current))
9227+
: reconcileChildren(current, workInProgress, nextProps, renderLanes);
92089228
if (
92099229
!shouldForceFallback &&
92109230
null !== current &&
@@ -9232,6 +9252,22 @@ __DEV__ &&
92329252
}
92339253
switch (revealOrder) {
92349254
case "backwards":
9255+
renderLanes = findLastContentRow(workInProgress.child);
9256+
null === renderLanes
9257+
? ((revealOrder = workInProgress.child),
9258+
(workInProgress.child = null))
9259+
: ((revealOrder = renderLanes.sibling),
9260+
(renderLanes.sibling = null),
9261+
reverseChildren(workInProgress));
9262+
initSuspenseListRenderState(
9263+
workInProgress,
9264+
!0,
9265+
revealOrder,
9266+
null,
9267+
tailMode,
9268+
0
9269+
);
9270+
break;
92359271
case "unstable_legacy-backwards":
92369272
renderLanes = null;
92379273
revealOrder = workInProgress.child;
@@ -9269,27 +9305,20 @@ __DEV__ &&
92699305
workInProgress.memoizedState = null;
92709306
break;
92719307
default:
9272-
renderLanes = workInProgress.child;
9273-
for (revealOrder = null; null !== renderLanes; )
9274-
(current = renderLanes.alternate),
9275-
null !== current &&
9276-
null === findFirstSuspended(current) &&
9277-
(revealOrder = renderLanes),
9278-
(renderLanes = renderLanes.sibling);
9279-
renderLanes = revealOrder;
9280-
null === renderLanes
9281-
? ((revealOrder = workInProgress.child),
9282-
(workInProgress.child = null))
9283-
: ((revealOrder = renderLanes.sibling),
9284-
(renderLanes.sibling = null));
9285-
initSuspenseListRenderState(
9286-
workInProgress,
9287-
!1,
9288-
revealOrder,
9289-
renderLanes,
9290-
tailMode,
9291-
0
9292-
);
9308+
(renderLanes = findLastContentRow(workInProgress.child)),
9309+
null === renderLanes
9310+
? ((revealOrder = workInProgress.child),
9311+
(workInProgress.child = null))
9312+
: ((revealOrder = renderLanes.sibling),
9313+
(renderLanes.sibling = null)),
9314+
initSuspenseListRenderState(
9315+
workInProgress,
9316+
!1,
9317+
revealOrder,
9318+
renderLanes,
9319+
tailMode,
9320+
0
9321+
);
92939322
}
92949323
return workInProgress.child;
92959324
}
@@ -20364,10 +20393,10 @@ __DEV__ &&
2036420393
(function () {
2036520394
var internals = {
2036620395
bundleType: 1,
20367-
version: "19.3.0-www-classic-26cf2804-20251031",
20396+
version: "19.3.0-www-classic-488d88b0-20251031",
2036820397
rendererPackageName: "react-art",
2036920398
currentDispatcherRef: ReactSharedInternals,
20370-
reconcilerVersion: "19.3.0-www-classic-26cf2804-20251031"
20399+
reconcilerVersion: "19.3.0-www-classic-488d88b0-20251031"
2037120400
};
2037220401
internals.overrideHookState = overrideHookState;
2037320402
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
@@ -20402,7 +20431,7 @@ __DEV__ &&
2040220431
exports.Shape = Shape;
2040320432
exports.Surface = Surface;
2040420433
exports.Text = Text;
20405-
exports.version = "19.3.0-www-classic-26cf2804-20251031";
20434+
exports.version = "19.3.0-www-classic-488d88b0-20251031";
2040620435
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
2040720436
"function" ===
2040820437
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/ReactART-dev.modern.js

Lines changed: 59 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8886,6 +8886,16 @@ __DEV__ &&
88868886
propagationRoot
88878887
);
88888888
}
8889+
function findLastContentRow(firstChild) {
8890+
for (var lastContentRow = null; null !== firstChild; ) {
8891+
var currentRow = firstChild.alternate;
8892+
null !== currentRow &&
8893+
null === findFirstSuspended(currentRow) &&
8894+
(lastContentRow = firstChild);
8895+
firstChild = firstChild.sibling;
8896+
}
8897+
return lastContentRow;
8898+
}
88898899
function initSuspenseListRenderState(
88908900
workInProgress,
88918901
isBackwards,
@@ -8913,6 +8923,15 @@ __DEV__ &&
89138923
(renderState.tailMode = tailMode),
89148924
(renderState.treeForkCount = treeForkCount));
89158925
}
8926+
function reverseChildren(fiber) {
8927+
var row = fiber.child;
8928+
for (fiber.child = null; null !== row; ) {
8929+
var nextRow = row.sibling;
8930+
row.sibling = fiber.child;
8931+
fiber.child = row;
8932+
row = nextRow;
8933+
}
8934+
}
89168935
function updateSuspenseListComponent(current, workInProgress, renderLanes) {
89178936
var nextProps = workInProgress.pendingProps,
89188937
revealOrder = nextProps.revealOrder,
@@ -8931,19 +8950,16 @@ __DEV__ &&
89318950
if (
89328951
null != revealOrder &&
89338952
"forwards" !== revealOrder &&
8953+
"backwards" !== revealOrder &&
89348954
"unstable_legacy-backwards" !== revealOrder &&
89358955
"together" !== revealOrder &&
89368956
"independent" !== revealOrder &&
89378957
!didWarnAboutRevealOrder[suspenseContext]
89388958
)
89398959
if (
89408960
((didWarnAboutRevealOrder[suspenseContext] = !0),
8941-
"backwards" === revealOrder)
8961+
"string" === typeof revealOrder)
89428962
)
8943-
console.error(
8944-
'The rendering order of <SuspenseList revealOrder="backwards"> is changing. To be future compatible you must specify revealOrder="legacy_unstable-backwards" instead.'
8945-
);
8946-
else if ("string" === typeof revealOrder)
89478963
switch (revealOrder.toLowerCase()) {
89488964
case "together":
89498965
case "forwards":
@@ -9035,7 +9051,11 @@ __DEV__ &&
90359051
'A single row was passed to a <SuspenseList revealOrder="%s" />. This is not useful since it needs multiple rows. Did you mean to pass multiple children or an array?',
90369052
revealOrder
90379053
);
9038-
reconcileChildren(current, workInProgress, nextProps, renderLanes);
9054+
"backwards" === revealOrder && null !== current
9055+
? (reverseChildren(current),
9056+
reconcileChildren(current, workInProgress, nextProps, renderLanes),
9057+
reverseChildren(current))
9058+
: reconcileChildren(current, workInProgress, nextProps, renderLanes);
90399059
if (
90409060
!shouldForceFallback &&
90419061
null !== current &&
@@ -9063,6 +9083,22 @@ __DEV__ &&
90639083
}
90649084
switch (revealOrder) {
90659085
case "backwards":
9086+
renderLanes = findLastContentRow(workInProgress.child);
9087+
null === renderLanes
9088+
? ((revealOrder = workInProgress.child),
9089+
(workInProgress.child = null))
9090+
: ((revealOrder = renderLanes.sibling),
9091+
(renderLanes.sibling = null),
9092+
reverseChildren(workInProgress));
9093+
initSuspenseListRenderState(
9094+
workInProgress,
9095+
!0,
9096+
revealOrder,
9097+
null,
9098+
tailMode,
9099+
0
9100+
);
9101+
break;
90669102
case "unstable_legacy-backwards":
90679103
renderLanes = null;
90689104
revealOrder = workInProgress.child;
@@ -9100,27 +9136,20 @@ __DEV__ &&
91009136
workInProgress.memoizedState = null;
91019137
break;
91029138
default:
9103-
renderLanes = workInProgress.child;
9104-
for (revealOrder = null; null !== renderLanes; )
9105-
(current = renderLanes.alternate),
9106-
null !== current &&
9107-
null === findFirstSuspended(current) &&
9108-
(revealOrder = renderLanes),
9109-
(renderLanes = renderLanes.sibling);
9110-
renderLanes = revealOrder;
9111-
null === renderLanes
9112-
? ((revealOrder = workInProgress.child),
9113-
(workInProgress.child = null))
9114-
: ((revealOrder = renderLanes.sibling),
9115-
(renderLanes.sibling = null));
9116-
initSuspenseListRenderState(
9117-
workInProgress,
9118-
!1,
9119-
revealOrder,
9120-
renderLanes,
9121-
tailMode,
9122-
0
9123-
);
9139+
(renderLanes = findLastContentRow(workInProgress.child)),
9140+
null === renderLanes
9141+
? ((revealOrder = workInProgress.child),
9142+
(workInProgress.child = null))
9143+
: ((revealOrder = renderLanes.sibling),
9144+
(renderLanes.sibling = null)),
9145+
initSuspenseListRenderState(
9146+
workInProgress,
9147+
!1,
9148+
revealOrder,
9149+
renderLanes,
9150+
tailMode,
9151+
0
9152+
);
91249153
}
91259154
return workInProgress.child;
91269155
}
@@ -20135,10 +20164,10 @@ __DEV__ &&
2013520164
(function () {
2013620165
var internals = {
2013720166
bundleType: 1,
20138-
version: "19.3.0-www-modern-26cf2804-20251031",
20167+
version: "19.3.0-www-modern-488d88b0-20251031",
2013920168
rendererPackageName: "react-art",
2014020169
currentDispatcherRef: ReactSharedInternals,
20141-
reconcilerVersion: "19.3.0-www-modern-26cf2804-20251031"
20170+
reconcilerVersion: "19.3.0-www-modern-488d88b0-20251031"
2014220171
};
2014320172
internals.overrideHookState = overrideHookState;
2014420173
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
@@ -20173,7 +20202,7 @@ __DEV__ &&
2017320202
exports.Shape = Shape;
2017420203
exports.Surface = Surface;
2017520204
exports.Text = Text;
20176-
exports.version = "19.3.0-www-modern-26cf2804-20251031";
20205+
exports.version = "19.3.0-www-modern-488d88b0-20251031";
2017720206
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
2017820207
"function" ===
2017920208
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

0 commit comments

Comments
 (0)