diff --git a/src/diff/index.js b/src/diff/index.js index 57f1512ad6..3ef43bfffb 100644 --- a/src/diff/index.js +++ b/src/diff/index.js @@ -555,7 +555,11 @@ function diffElementNodes( ); // Remove children that are not part of any vnode. - if (excessDomChildren != NULL) { + if ( + excessDomChildren != NULL && + newVNode.type != 'body' && + newVNode.type != 'head' + ) { for (i = excessDomChildren.length; i--; ) { removeNode(excessDomChildren[i]); } diff --git a/test/browser/hydrate.test.js b/test/browser/hydrate.test.js index 7a6370ed68..408776a6b4 100644 --- a/test/browser/hydrate.test.js +++ b/test/browser/hydrate.test.js @@ -485,6 +485,33 @@ describe('hydrate()', () => { expect(getLog()).to.deep.equal(['Comment.remove()', 'Comment.remove()']); }); + it('should preserve existing head children when hydrating document', () => { + document.textContent = ''; + document.head.innerHTML = + 'Test'; + document.body.innerHTML = '

Test

'; + clearLog(); + + const App = () => ( + + + Test + + +

Test

+ +
+ ); + + hydrate(, document); + + expect(document.head.querySelector('meta[name="viewport"]')).to.not.equal( + null + ); + expect(document.head.querySelector('title').textContent).to.equal('Test'); + expect(document.body.innerHTML).to.equal('

Test

'); + }); + it('should work with error boundaries', () => { scratch.innerHTML = '
Hello, World!
'; class Root extends Component { diff --git a/test/browser/render.test.js b/test/browser/render.test.js index 33c264d453..29639240c1 100644 --- a/test/browser/render.test.js +++ b/test/browser/render.test.js @@ -1969,6 +1969,7 @@ describe('render()', () => { it('should work with document', () => { document.textContent = ''; + document.body.textContent = ''; const App = () => ( @@ -1980,9 +1981,8 @@ describe('render()', () => { ); render(, document); - expect(document.documentElement.innerHTML.trim()).to.equal( - 'Test

Test

' - ); + expect(document.head.querySelector('title').textContent).to.equal('Test'); + expect(document.body.innerHTML.trim()).to.equal('

Test

'); }); it('should not remount components when replacing a component with a falsy value in-between', () => {