diff --git a/src/diff/children.js b/src/diff/children.js index 8256e45d74..71879d3166 100644 --- a/src/diff/children.js +++ b/src/diff/children.js @@ -62,7 +62,6 @@ export function diffChildren( for (i = 0; i < newChildrenLength; i++) { childVNode = newParentVNode._children[i]; - if ( childVNode == null || typeof childVNode == 'boolean' || @@ -231,11 +230,15 @@ function constructNewChildrenArray(newParentVNode, renderResult, oldChildren) { // Handle unmounting null placeholders, i.e. VNode => null in unkeyed children if (childVNode == null) { oldVNode = oldChildren[i]; - if (oldVNode && oldVNode.key == null && oldVNode._dom) { + if ( + oldVNode && + oldVNode.key == null && + oldVNode._dom && + (oldVNode._flags & MATCHED) === 0 + ) { if (oldVNode._dom == newParentVNode._nextDom) { newParentVNode._nextDom = getDomSibling(oldVNode); } - unmount(oldVNode, oldVNode, false); // Explicitly nullify this position in oldChildren instead of just @@ -250,7 +253,6 @@ function constructNewChildrenArray(newParentVNode, renderResult, oldChildren) { oldChildren[i] = null; remainingOldChildren--; } - continue; } diff --git a/test/browser/render.test.js b/test/browser/render.test.js index 2baf381d3a..3be0393a20 100644 --- a/test/browser/render.test.js +++ b/test/browser/render.test.js @@ -1308,4 +1308,52 @@ describe('render()', () => { expect(divs[1].hasAttribute('role')).to.equal(false); expect(divs[2].hasAttribute('role')).to.equal(false); }); + + it('should not crash or repeatedly add the same child when replacing a matched vnode with null', () => { + const B = () =>