diff --git a/compat/test/browser/suspense-hydration.test.js b/compat/test/browser/suspense-hydration.test.js index fd61a2bb02..027cca24a8 100644 --- a/compat/test/browser/suspense-hydration.test.js +++ b/compat/test/browser/suspense-hydration.test.js @@ -132,7 +132,7 @@ describe('suspense hydration', () => { }); it('Should hydrate a fragment with no children correctly', () => { - scratch.innerHTML = '
Hello
World!
'; + scratch.innerHTML = ''; clearLog(); const [Lazy, resolve] = createLazy(); @@ -143,22 +143,13 @@ describe('suspense hydration', () => { scratch ); rerender(); // Flush rerender queue to mimic what preact will really do - expect(scratch.innerHTML).to.equal( - '
Hello
World!
' - ); + expect(scratch.innerHTML).to.equal(''); expect(getLog()).to.deep.equal([]); clearLog(); - return resolve(() => ( - <> -
Hello
-
World!
- - )).then(() => { + return resolve(() => null).then(() => { rerender(); - expect(scratch.innerHTML).to.equal( - '
Hello
World!
' - ); + expect(scratch.innerHTML).to.equal(''); expect(getLog()).to.deep.equal([]); clearLog(); @@ -167,7 +158,7 @@ describe('suspense hydration', () => { // This is in theory correct but still it shows that our oldDom becomes stale very quickly // and moves DOM into weird places - it.skip('Should hydrate a fragment with no children and an adjacent node correctly', () => { + it('Should hydrate a fragment with no children and an adjacent node correctly', () => { scratch.innerHTML = '
Baz
'; clearLog(); diff --git a/src/component.js b/src/component.js index 287f3233f4..3df40d08df 100644 --- a/src/component.js +++ b/src/component.js @@ -100,7 +100,11 @@ export function getDomSibling(vnode, childIndex) { for (; childIndex < vnode._children.length; childIndex++) { sibling = vnode._children[childIndex]; - if (sibling != null && sibling._dom != null) { + if ( + sibling != null && + sibling._dom != null && + sibling._dom.nodeType !== 8 + ) { // Since updateParentDomPointers keeps _dom pointer correct, // we can rely on _dom to tell us if this subtree contains a // rendered DOM node, and what the first rendered DOM node is diff --git a/src/diff/children.js b/src/diff/children.js index 1e44c5cade..b18963895a 100644 --- a/src/diff/children.js +++ b/src/diff/children.js @@ -135,6 +135,9 @@ export function diffChildren( oldDom = childVNode._nextDom; } else if (newDom) { oldDom = newDom.nextSibling; + while (oldDom && oldDom.nodeType == 8) { + oldDom = oldDom.nextSibling; + } } // Eagerly cleanup _nextDom. We don't need to persist the value because it diff --git a/src/diff/index.js b/src/diff/index.js index 25e02fe702..f8ee1ea300 100644 --- a/src/diff/index.js +++ b/src/diff/index.js @@ -54,7 +54,7 @@ export function diff( isHydrating = !!(oldVNode._flags & MODE_HYDRATE); if (oldVNode._excess) { excessDomChildren = oldVNode._excess; - oldDom = newVNode._dom = oldVNode._dom = excessDomChildren[1]; + oldDom = newVNode._dom = oldVNode._dom = excessDomChildren[0]; } else { oldDom = newVNode._dom = oldVNode._dom; excessDomChildren = [oldDom]; @@ -283,26 +283,32 @@ export function diff( : MODE_HYDRATE; let found = excessDomChildren.find( - child => child && child.nodeType == 8 && child.data == '$s' - ), - index = excessDomChildren.indexOf(found) + 1; + child => child && child.nodeType == 8 && child.data == '$s' + ); newVNode._dom = oldDom; if (found) { - let commentMarkersToFind = 1; - newVNode._excess = [found]; + let commentMarkersToFind = 1, + index = excessDomChildren.indexOf(found) + 1; + newVNode._excess = []; + // Clear the comment marker so we don't reuse them for sibling + // Suspenders. excessDomChildren[index - 1] = null; + while (commentMarkersToFind && index <= excessDomChildren.length) { const node = excessDomChildren[index]; excessDomChildren[index] = null; index++; - newVNode._excess.push(node); + // node being undefined here would be a problem as it would + // imply that we have a mismatch. if (node.nodeType == 8) { if (node.data == '$s') { commentMarkersToFind++; } else if (node.data == '/$s') { commentMarkersToFind--; } + } else { + newVNode._excess.push(node); } } } else {