diff --git a/.changeset/spicy-ladybugs-return.md b/.changeset/spicy-ladybugs-return.md new file mode 100644 index 000000000000..1b1655e90317 --- /dev/null +++ b/.changeset/spicy-ladybugs-return.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: repair invalid raw html content during hydration diff --git a/packages/svelte/.prettierignore b/packages/svelte/.prettierignore index 3f6fbefc045f..fef52b1e8f7e 100644 --- a/packages/svelte/.prettierignore +++ b/packages/svelte/.prettierignore @@ -16,6 +16,7 @@ sites/svelte.dev/.vercel /test/**/expected* /test/**/_output /test/**/shards/*.test.js +/test/hydration/samples/raw-repair/_after.html /types !rollup.config.js !vitest.config.js diff --git a/packages/svelte/src/runtime/internal/dom.js b/packages/svelte/src/runtime/internal/dom.js index 57d3b2793e80..72cb8ab75b4a 100644 --- a/packages/svelte/src/runtime/internal/dom.js +++ b/packages/svelte/src/runtime/internal/dom.js @@ -777,14 +777,14 @@ export function claim_comment(nodes, data) { ); } -function find_comment(nodes, text, start) { +function get_comment_idx(nodes, text, start) { for (let i = start; i < nodes.length; i += 1) { const node = nodes[i]; if (node.nodeType === 8 /* comment node */ && node.textContent.trim() === text) { return i; } } - return nodes.length; + return -1; } /** @@ -793,11 +793,12 @@ function find_comment(nodes, text, start) { */ export function claim_html_tag(nodes, is_svg) { // find html opening tag - const start_index = find_comment(nodes, 'HTML_TAG_START', 0); - const end_index = find_comment(nodes, 'HTML_TAG_END', start_index); - if (start_index === end_index) { + const start_index = get_comment_idx(nodes, 'HTML_TAG_START', 0); + const end_index = get_comment_idx(nodes, 'HTML_TAG_END', start_index + 1); + if (start_index === -1 || end_index === -1) { return new HtmlTagHydration(is_svg); } + init_claim_info(nodes); const html_tag_nodes = nodes.splice(start_index, end_index - start_index + 1); detach(html_tag_nodes[0]); @@ -1048,17 +1049,13 @@ export class HtmlTag { * @default false */ is_svg = false; - // parent for creating node - /** */ + /** parent for creating node */ e = undefined; - // html tag nodes - /** */ + /** html tag nodes */ n = undefined; - // target - /** */ + /** target */ t = undefined; - // anchor - /** */ + /** anchor */ a = undefined; constructor(is_svg = false) { this.is_svg = is_svg; diff --git a/packages/svelte/test/hydration/samples/raw-repair/_after.html b/packages/svelte/test/hydration/samples/raw-repair/_after.html new file mode 100644 index 000000000000..31cdc120152d --- /dev/null +++ b/packages/svelte/test/hydration/samples/raw-repair/_after.html @@ -0,0 +1,2 @@ +

invalid

+

invalid

\ No newline at end of file diff --git a/packages/svelte/test/hydration/samples/raw-repair/_before.html b/packages/svelte/test/hydration/samples/raw-repair/_before.html new file mode 100644 index 000000000000..fe958bece5e9 --- /dev/null +++ b/packages/svelte/test/hydration/samples/raw-repair/_before.html @@ -0,0 +1,8 @@ +

+

invalid

+ +

+

+

invalid

+ +

diff --git a/packages/svelte/test/hydration/samples/raw-repair/inner.svelte b/packages/svelte/test/hydration/samples/raw-repair/inner.svelte new file mode 100644 index 000000000000..a2df6c9ded2e --- /dev/null +++ b/packages/svelte/test/hydration/samples/raw-repair/inner.svelte @@ -0,0 +1,5 @@ + + +

{@html content}

diff --git a/packages/svelte/test/hydration/samples/raw-repair/main.svelte b/packages/svelte/test/hydration/samples/raw-repair/main.svelte new file mode 100644 index 000000000000..41deb9d3e631 --- /dev/null +++ b/packages/svelte/test/hydration/samples/raw-repair/main.svelte @@ -0,0 +1,7 @@ + + + + +

{@html '

invalid

'}