Skip to content

Commit df5fadd

Browse files
authored
Refactor commitPlacement to recursively insert nodes (#17996)
1 parent ab7b83a commit df5fadd

File tree

2 files changed

+62
-34
lines changed

2 files changed

+62
-34
lines changed

packages/react-dom/src/client/ReactDOMHostConfig.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ export type EventTargetChildElement = {
8888
},
8989
...
9090
};
91-
export type Container = Element | Document;
91+
export type Container = DOMContainer;
9292
export type Instance = Element;
9393
export type TextInstance = Text;
9494
export type SuspenseInstance = Comment & {_reactRetry?: () => void, ...};

packages/react-reconciler/src/ReactFiberCommitWork.js

+61-33
Original file line numberDiff line numberDiff line change
@@ -1099,44 +1099,72 @@ function commitPlacement(finishedWork: Fiber): void {
10991099
const before = getHostSibling(finishedWork);
11001100
// We only have the top Fiber that was inserted but we need to recurse down its
11011101
// children to find all the terminal nodes.
1102-
let node: Fiber = finishedWork;
1103-
while (true) {
1104-
const isHost = node.tag === HostComponent || node.tag === HostText;
1105-
if (isHost || (enableFundamentalAPI && node.tag === FundamentalComponent)) {
1106-
const stateNode = isHost ? node.stateNode : node.stateNode.instance;
1107-
if (before) {
1108-
if (isContainer) {
1109-
insertInContainerBefore(parent, stateNode, before);
1110-
} else {
1111-
insertBefore(parent, stateNode, before);
1112-
}
1113-
} else {
1114-
if (isContainer) {
1115-
appendChildToContainer(parent, stateNode);
1116-
} else {
1117-
appendChild(parent, stateNode);
1118-
}
1102+
if (isContainer) {
1103+
insertOrAppendPlacementNodeIntoContainer(finishedWork, before, parent);
1104+
} else {
1105+
insertOrAppendPlacementNode(finishedWork, before, parent);
1106+
}
1107+
}
1108+
1109+
function insertOrAppendPlacementNodeIntoContainer(
1110+
node: Fiber,
1111+
before: ?Instance,
1112+
parent: Container,
1113+
): void {
1114+
const {tag} = node;
1115+
const isHost = tag === HostComponent || tag === HostText;
1116+
if (isHost || (enableFundamentalAPI && tag === FundamentalComponent)) {
1117+
const stateNode = isHost ? node.stateNode : node.stateNode.instance;
1118+
if (before) {
1119+
insertInContainerBefore(parent, stateNode, before);
1120+
} else {
1121+
appendChildToContainer(parent, stateNode);
1122+
}
1123+
} else if (tag === HostPortal) {
1124+
// If the insertion itself is a portal, then we don't want to traverse
1125+
// down its children. Instead, we'll get insertions from each child in
1126+
// the portal directly.
1127+
} else {
1128+
const child = node.child;
1129+
if (child !== null) {
1130+
insertOrAppendPlacementNodeIntoContainer(child, before, parent);
1131+
let sibling = child.sibling;
1132+
while (sibling !== null) {
1133+
insertOrAppendPlacementNodeIntoContainer(sibling, before, parent);
1134+
sibling = sibling.sibling;
11191135
}
1120-
} else if (node.tag === HostPortal) {
1121-
// If the insertion itself is a portal, then we don't want to traverse
1122-
// down its children. Instead, we'll get insertions from each child in
1123-
// the portal directly.
1124-
} else if (node.child !== null) {
1125-
node.child.return = node;
1126-
node = node.child;
1127-
continue;
11281136
}
1129-
if (node === finishedWork) {
1130-
return;
1137+
}
1138+
}
1139+
1140+
function insertOrAppendPlacementNode(
1141+
node: Fiber,
1142+
before: ?Instance,
1143+
parent: Instance,
1144+
): void {
1145+
const {tag} = node;
1146+
const isHost = tag === HostComponent || tag === HostText;
1147+
if (isHost || (enableFundamentalAPI && tag === FundamentalComponent)) {
1148+
const stateNode = isHost ? node.stateNode : node.stateNode.instance;
1149+
if (before) {
1150+
insertBefore(parent, stateNode, before);
1151+
} else {
1152+
appendChild(parent, stateNode);
11311153
}
1132-
while (node.sibling === null) {
1133-
if (node.return === null || node.return === finishedWork) {
1134-
return;
1154+
} else if (tag === HostPortal) {
1155+
// If the insertion itself is a portal, then we don't want to traverse
1156+
// down its children. Instead, we'll get insertions from each child in
1157+
// the portal directly.
1158+
} else {
1159+
const child = node.child;
1160+
if (child !== null) {
1161+
insertOrAppendPlacementNode(child, before, parent);
1162+
let sibling = child.sibling;
1163+
while (sibling !== null) {
1164+
insertOrAppendPlacementNode(sibling, before, parent);
1165+
sibling = sibling.sibling;
11351166
}
1136-
node = node.return;
11371167
}
1138-
node.sibling.return = node.return;
1139-
node = node.sibling;
11401168
}
11411169
}
11421170

0 commit comments

Comments
 (0)