Skip to content

Commit 987b7bb

Browse files
committed
Match null placeholders using skewed index
If we've skewed our matching before hitting a null placeholder (e.g. we've inserted or removed an unmatched node) then let's pick up matching null placeholders from the skewedIndex. Note I don't think we need to adjust the skew when we find a null placeholder, we treat it as "matching" the current node.
1 parent 94b0563 commit 987b7bb

3 files changed

Lines changed: 13 additions & 13 deletions

File tree

src/diff/children.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -227,9 +227,11 @@ function constructNewChildrenArray(newParentVNode, renderResult, oldChildren) {
227227
childVNode = newParentVNode._children[i] = childVNode;
228228
}
229229

230+
const skewedIndex = i + skew;
231+
230232
// Handle unmounting null placeholders, i.e. VNode => null in unkeyed children
231233
if (childVNode == null) {
232-
oldVNode = oldChildren[i];
234+
oldVNode = oldChildren[skewedIndex];
233235
if (
234236
oldVNode &&
235237
oldVNode.key == null &&
@@ -238,8 +240,6 @@ function constructNewChildrenArray(newParentVNode, renderResult, oldChildren) {
238240
) {
239241
if (oldVNode._dom == newParentVNode._nextDom) {
240242
newParentVNode._nextDom = getDomSibling(oldVNode);
241-
} else {
242-
skew++;
243243
}
244244
unmount(oldVNode, oldVNode, false);
245245

@@ -252,7 +252,7 @@ function constructNewChildrenArray(newParentVNode, renderResult, oldChildren) {
252252
// to unmount this VNode again seeing `_match==true`. Further,
253253
// getDomSibling doesn't know about _match and so would incorrectly
254254
// assume DOM nodes in this subtree are mounted and usable.
255-
oldChildren[i] = null;
255+
oldChildren[skewedIndex] = null;
256256
remainingOldChildren--;
257257
}
258258
continue;
@@ -261,7 +261,6 @@ function constructNewChildrenArray(newParentVNode, renderResult, oldChildren) {
261261
childVNode._parent = newParentVNode;
262262
childVNode._depth = newParentVNode._depth + 1;
263263

264-
const skewedIndex = i + skew;
265264
const matchingIndex = findMatchingIndex(
266265
childVNode,
267266
oldChildren,

test/browser/fragments.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1304,7 +1304,7 @@ describe('Fragment', () => {
13041304
'rendering from true to false'
13051305
);
13061306
expectDomLogToBe(
1307-
['<li>1.remove()', '<li>2.remove()', '<ol>043.appendChild(<li>4)'],
1307+
['<li>1.remove()', '<li>2.remove()'],
13081308
'rendering from true to false'
13091309
);
13101310

test/browser/render.test.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,6 +1360,7 @@ describe('render()', () => {
13601360
it('should not crash or repeatedly add the same child when replacing a matched vnode with null (mixed dom-types)', () => {
13611361
const B = () => <div>B</div>;
13621362

1363+
/** @type {() => void} */
13631364
let update;
13641365
class App extends Component {
13651366
constructor(props) {
@@ -1375,38 +1376,38 @@ describe('render()', () => {
13751376
return (
13761377
<div>
13771378
<B />
1378-
<div />
1379+
<div>C</div>
13791380
</div>
13801381
);
13811382
}
13821383
return (
13831384
<div>
1384-
<span />
1385+
<span>A</span>
13851386
{null}
13861387
<B />
1387-
<div />
1388+
<div>C</div>
13881389
</div>
13891390
);
13901391
}
13911392
}
13921393

13931394
render(<App />, scratch);
1394-
expect(scratch.innerHTML).to.equal('<div><div>B</div><div></div></div>');
1395+
expect(scratch.innerHTML).to.equal('<div><div>B</div><div>C</div></div>');
13951396

13961397
update();
13971398
rerender();
13981399
expect(scratch.innerHTML).to.equal(
1399-
'<div><span></span><div>B</div><div></div></div>'
1400+
'<div><span>A</span><div>B</div><div>C</div></div>'
14001401
);
14011402

14021403
update();
14031404
rerender();
1404-
expect(scratch.innerHTML).to.equal('<div><div>B</div><div></div></div>');
1405+
expect(scratch.innerHTML).to.equal('<div><div>B</div><div>C</div></div>');
14051406

14061407
update();
14071408
rerender();
14081409
expect(scratch.innerHTML).to.equal(
1409-
'<div><span></span><div>B</div><div></div></div>'
1410+
'<div><span>A</span><div>B</div><div>C</div></div>'
14101411
);
14111412
});
14121413
});

0 commit comments

Comments
 (0)