Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/six-files-speak.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: remove outer hydration markers
19 changes: 9 additions & 10 deletions packages/svelte/src/internal/client/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,19 +120,9 @@ export function hydrate(component, options) {

set_hydrating(true);
set_hydrate_node(/** @type {Comment} */ (anchor));
hydrate_next();

const instance = _mount(component, { ...options, anchor });

if (
hydrate_node === null ||
hydrate_node.nodeType !== COMMENT_NODE ||
/** @type {Comment} */ (hydrate_node).data !== HYDRATION_END
) {
w.hydration_mismatch();
throw HYDRATION_ERROR;
}

set_hydrating(false);

return /** @type {Exports} */ (instance);
Expand Down Expand Up @@ -247,6 +237,15 @@ function _mount(Component, { target, anchor, props = {}, events, context, intro

if (hydrating) {
/** @type {Effect} */ (active_effect).nodes_end = hydrate_node;

if (
hydrate_node === null ||
hydrate_node.nodeType !== COMMENT_NODE ||
/** @type {Comment} */ (hydrate_node).data !== HYDRATION_END
) {
w.hydration_mismatch();
throw HYDRATION_ERROR;
}
}

if (context) {
Expand Down
3 changes: 1 addition & 2 deletions packages/svelte/src/internal/server/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -516,8 +516,7 @@ export class Renderer {
}

let head = content.head + renderer.global.get_title();

const body = BLOCK_OPEN + content.body + BLOCK_CLOSE; // this inserts a fake boundary so hydration matches
let body = content.body;

for (const { hash, code } of renderer.global.css) {
head += `<style id="${hash}">${code}</style>`;
Expand Down
22 changes: 11 additions & 11 deletions packages/svelte/src/internal/server/renderer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ test('collects synchronous body content by default', () => {

const { head, body } = Renderer.render(component as unknown as Component);
expect(head).toBe('');
expect(body).toBe('<!--[--><!--[-->abc<!--]--><!--]-->');
expect(body).toBe('<!--[-->abc<!--]-->');
});

test('child type switches content area (head vs body)', () => {
Expand All @@ -28,7 +28,7 @@ test('child type switches content area (head vs body)', () => {

const { head, body } = Renderer.render(component as unknown as Component);
expect(head).toBe('<title>T</title>');
expect(body).toBe('<!--[--><!--[-->ab<!--]--><!--]-->');
expect(body).toBe('<!--[-->ab<!--]-->');
});

test('child inherits parent type when not specified', () => {
Expand All @@ -42,7 +42,7 @@ test('child inherits parent type when not specified', () => {
};

const { head, body } = Renderer.render(component as unknown as Component);
expect(body).toBe('<!--[--><!--[--><!--]--><!--]-->');
expect(body).toBe('<!--[--><!--]-->');
expect(head).toBe('<meta name="x"/><style>/* css */</style>');
});

Expand Down Expand Up @@ -101,7 +101,7 @@ test('compact synchronously aggregates a range and can transform into head/body'

const { head, body } = Renderer.render(component as unknown as Component);
expect(head).toBe('<h>H</h>');
expect(body).toBe('<!--[--><!--[-->abdc<!--]--><!--]-->');
expect(body).toBe('<!--[-->abdc<!--]-->');
});

test('local state is shallow-copied to children', () => {
Expand Down Expand Up @@ -216,7 +216,7 @@ describe('async', () => {

const result = await Renderer.render(component as unknown as Component);
expect(result.head).toBe('');
expect(result.body).toBe('<!--[--><!--[-->123<!--]--><!--]-->');
expect(result.body).toBe('<!--[-->123<!--]-->');
expect(() => result.html).toThrow('html_deprecated');
});

Expand All @@ -239,7 +239,7 @@ describe('async', () => {

const { body, head } = await Renderer.render(component as unknown as Component);
expect(head).toBe('');
expect(body).toBe('<!--[--><!--[-->axb<!--]--><!--]-->');
expect(body).toBe('<!--[-->axb<!--]-->');
});

test('push accepts async functions in async context', async () => {
Expand All @@ -254,7 +254,7 @@ describe('async', () => {

const { head, body } = await Renderer.render(component as unknown as Component);
expect(head).toBe('');
expect(body).toBe('<!--[--><!--[-->abc<!--]--><!--]-->');
expect(body).toBe('<!--[-->abc<!--]-->');
});

test('push handles async functions with different timing', async () => {
Expand All @@ -272,7 +272,7 @@ describe('async', () => {

const { head, body } = await Renderer.render(component as unknown as Component);
expect(head).toBe('');
expect(body).toBe('<!--[--><!--[-->fastslowsync<!--]--><!--]-->');
expect(body).toBe('<!--[-->fastslowsync<!--]-->');
});

test('push async functions work with head content type', async () => {
Expand All @@ -286,7 +286,7 @@ describe('async', () => {
};

const { head, body } = await Renderer.render(component as unknown as Component);
expect(body).toBe('<!--[--><!--[--><!--]--><!--]-->');
expect(body).toBe('<!--[--><!--]-->');
expect(head).toBe('<title>Async Title</title>');
});

Expand All @@ -305,7 +305,7 @@ describe('async', () => {

const { head, body } = await Renderer.render(component as unknown as Component);
expect(head).toBe('');
expect(body).toBe('<!--[--><!--[-->start-async-child--end<!--]--><!--]-->');
expect(body).toBe('<!--[-->start-async-child--end<!--]-->');
});

test('push async functions work with compact operations', async () => {
Expand All @@ -324,7 +324,7 @@ describe('async', () => {

const { head, body } = await Renderer.render(component as unknown as Component);
expect(head).toBe('');
expect(body).toBe('<!--[--><!--[-->ABC<!--]--><!--]-->');
expect(body).toBe('<!--[-->ABC<!--]-->');
});

test('push async functions are not supported in sync context', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--[--><!--[--><input> <p>Hello world!</p><!--]--><!--]-->
<!--[--><input> <p>Hello world!</p><!--]-->
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--[--><!--[--><h1>Hello everybody!</h1><!--]--><!--]-->
<!--[--><h1>Hello everybody!</h1><!--]-->
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--[--><!--[--><ul><!--[--><li>a</li><!--]--></ul> <ul><!--[--><li>a</li><!--]--></ul> <ul><!--[--><li>a</li><!--]--></ul> <!--[--><li>a</li> <li>a</li><!--]--> <!--[--><li>a</li> <li>a</li><!--]--> <!--[--><li>a</li> <li>a</li><!--]--><!--]--><!--]-->
<!--[--><ul><!--[--><li>a</li><!--]--></ul> <ul><!--[--><li>a</li><!--]--></ul> <ul><!--[--><li>a</li><!--]--></ul> <!--[--><li>a</li> <li>a</li><!--]--> <!--[--><li>a</li> <li>a</li><!--]--> <!--[--><li>a</li> <li>a</li><!--]--><!--]-->
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--[--><!--[--><!--[!--><p>a</p><!--]--> <!--[--><p>empty</p><!--]--><!--]--><!--]-->
<!--[--><!--[!--><p>a</p><!--]--> <!--[--><p>empty</p><!--]--><!--]-->
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--[--><!--[--><ul><!--[--><li>a</li><!--]--></ul> <ul><!--[--><li>a</li><!--]--></ul> <ul><!--[--><li>a</li><!--]--></ul> <!--[--><li>a</li> <li>a</li><!--]--> <!--[--><li>a</li> <li>a</li><!--]--> <!--[--><li>a</li> <li>a</li><!--]--><!--]--><!--]-->
<!--[--><ul><!--[--><li>a</li><!--]--></ul> <ul><!--[--><li>a</li><!--]--></ul> <ul><!--[--><li>a</li><!--]--></ul> <!--[--><li>a</li> <li>a</li><!--]--> <!--[--><li>a</li> <li>a</li><!--]--> <!--[--><li>a</li> <li>a</li><!--]--><!--]-->
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--[--><!--[--><ul><!--[--><li>a</li><li>b</li><!--]--></ul> <ul><!--[--><li>a</li><li>b</li><!--]--></ul> <ul><!--[--><li>a</li><li>b</li><!--]--></ul> <!--[--><li>a</li> <li>a</li><li>b</li> <li>b</li><!--]--> <!--[--><li>a</li> <li>a</li><li>b</li> <li>b</li><!--]--> <!--[--><li>a</li> <li>a</li><li>b</li> <li>b</li><!--]--><!--]--><!--]-->
<!--[--><ul><!--[--><li>a</li><li>b</li><!--]--></ul> <ul><!--[--><li>a</li><li>b</li><!--]--></ul> <ul><!--[--><li>a</li><li>b</li><!--]--></ul> <!--[--><li>a</li> <li>a</li><li>b</li> <li>b</li><!--]--> <!--[--><li>a</li> <li>a</li><li>b</li> <li>b</li><!--]--> <!--[--><li>a</li> <li>a</li><li>b</li> <li>b</li><!--]--><!--]-->
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--[--><!--[--><div class="bar"></div><!--]--><!--]-->
<!--[--><div class="bar"></div><!--]-->
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--[--><!--[--><div class="bar"></div><!--]--><!--]-->
<!--[--><div class="bar"></div><!--]-->
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--[--><!--[--><div></div> <!--[--><div></div> <div></div><!--]--><!--]--><!--]-->
<!--[--><div></div> <!--[--><div></div> <div></div><!--]--><!--]-->
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--[--><!--[--><!--[--><!--]--> <div><!----><!----></div> hello<!--]--><!--]-->
<!--[--><!--[--><!--]--> <div><!----><!----></div> hello<!--]-->
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--[--><!--[--><!--[!--><p>foo</p><!--]--><!--]--><!--]-->
<!--[--><!--[!--><p>foo</p><!--]--><!--]-->
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--[--><!--[--><!---->.<input><!--]--><!--]-->
<!--[--><!---->.<input><!--]-->
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--[--><!--[--><input type="text"><!--]--><!--]-->
<!--[--><input type="text"><!--]-->
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--[--><!--[--><noscript>JavaScript is required for this site.</noscript> <h1>Hello!</h1><p>Count: 1</p><!--]--><!--]-->
<!--[--><noscript>JavaScript is required for this site.</noscript> <h1>Hello!</h1><p>Count: 1</p><!--]-->
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!--[--><!--[--><pre>static content no line</pre> <pre> static content ignored line
<!--[--><pre>static content no line</pre> <pre> static content ignored line
</pre> <pre>
static content relevant line
</pre> <pre><div><span></span></div>
</pre> <pre>
<div><span></span></div>
</pre><!--]--><!--]-->
</pre><!--]-->
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--[--><!--[--><div></div><!--]--><!--]-->
<!--[--><div></div><!--]-->
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--[--><!--[--><a href="/foo">foo</a> <a href="/foo">foo</a><!--]--><!--]-->
<!--[--><a href="/foo">foo</a> <a href="/foo">foo</a><!--]-->
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--[--><!--[--><h1>call <a href="tel:+636-555-3226">+636-555-3226</a> now<span>!</span></h1><!--]--><!--]-->
<!--[--><h1>call <a href="tel:+636-555-3226">+636-555-3226</a> now<span>!</span></h1><!--]-->
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--[--><!--[--><!----><script>{}<!----></script><!----><!--]--><!--]-->
<!--[--><!----><script>{}<!----></script><!----><!--]-->
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--[--><!--[--><p>hydrated</p><!--]--><!--]-->
<!--[--><p>hydrated</p><!--]-->
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--[--><!--[--><!--[--><p>child</p><!--]--> <!--[--><p>child</p><p>child</p><p>child</p><!--]--><!--]--><!--]-->
<!--[--><!--[--><p>child</p><!--]--> <!--[--><p>child</p><p>child</p><p>child</p><!--]--><!--]-->
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--[--><!--[--><!--[--><p>thing</p><!--]--> <!--[--><p>thing</p><p>thing</p><p>thing</p><!--]--><!--]--><!--]-->
<!--[--><!--[--><p>thing</p><!--]--> <!--[--><p>thing</p><p>thing</p><p>thing</p><!--]--><!--]-->
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
<!-- unrelated comment -->
<!--[--><!--[--><!--[-->hello<!--]--><!--]--><!--]-->
<!--[--><!--[-->hello<!--]--><!--]-->
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
<!-- unrelated comment -->
<!--[--><!--[--><!--[-->hello<!--]--><!--]--><!--]-->
<!--[--><!--[-->hello<!--]--><!--]-->
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--[--><!--[--><span><span></span></span><!--]--><!--]-->
<!--[--><span><span></span></span><!--]-->
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--[--><!--[--><!---->x<!--]--><!--]-->
<!--[--><!---->x<!--]-->
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
<!--[--><!--[-->
<main><p>nested</p><!----></main><!--]--><!--]-->
<!--[-->
<main><p>nested</p><!----></main><!--]-->
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export default test({
withoutNormalizeHtml: true,
// Unable to test `html` with `<textarea>` content
// as the textarea#value will not show within `innerHtml`
ssrHtml: `<!--[--><!--[--><textarea id="textarea"> A
ssrHtml: `<!--[--><textarea id="textarea"> A
B
</textarea> <div id="div-with-textarea"><textarea> A
B
Expand All @@ -14,7 +14,7 @@ newline after leading space</textarea></div> <textarea id="textarea-with-multipl

multiple leading newlines</textarea> <div id="div-with-textarea-with-multiple-leading-newlines"><textarea>

multiple leading newlines</textarea></div><!--]--><!--]-->`,
multiple leading newlines</textarea></div><!--]-->`,
test({ assert, target }) {
// Test for <textarea> tag
const elementTextarea = /** @type {HTMLTextAreaElement} */ (target.querySelector('#textarea'));
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--[--><!--[--><p>before</p><!-- a comment --><p>after</p><!--]--><!--]-->
<!--[--><p>before</p><!-- a comment --><p>after</p><!--]-->
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--[--><!--[--><div>Just a dummy page.</div><!--]--><!--]-->
<!--[--><div>Just a dummy page.</div><!--]-->
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<!--[-->
<!--[-->
<!---->
<title>lorem</title>
<!---->
Expand All @@ -16,4 +15,3 @@
</script>
<!---->
<!--]-->
<!--]-->
Loading