Skip to content

Commit 8ffc8fd

Browse files
author
Maximiliano Ruani
authored
[fix] Fix hydration duplicate svelte:head tag issue with @html expressions and nested components (#7745)
* Fix hydration duplicate `svelte:head` tag issue with `@html` and nested components #7444 #6463 * - Changed comment style to HEAD_${head_id}_START and HEAD_${head_id}_END - Improved claim logic - Changed tests accordingly
1 parent 7ac3854 commit 8ffc8fd

File tree

19 files changed

+110
-15
lines changed

19 files changed

+110
-15
lines changed

src/compiler/compile/render_dom/wrappers/Head.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export default class HeadWrapper extends Wrapper {
3636
let nodes;
3737
if (this.renderer.options.hydratable && this.fragment.nodes.length) {
3838
nodes = block.get_unique_name('head_nodes');
39-
block.chunks.claim.push(b`const ${nodes} = @query_selector_all('[data-svelte="${this.node.id}"]', @_document.head);`);
39+
block.chunks.claim.push(b`const ${nodes} = @head_selector('${this.node.id}', @_document.head);`);
4040
}
4141

4242
this.fragment.render(block, x`@_document.head` as unknown as Identifier, nodes);

src/compiler/compile/render_ssr/handlers/Element.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,6 @@ export default function (node: Element, renderer: Renderer, options: RenderOptio
157157
}
158158
});
159159

160-
if (options.hydratable && options.head_id) {
161-
renderer.add_string(` data-svelte="${options.head_id}"`);
162-
}
163-
164160
renderer.add_string('>');
165161

166162
if (node_contents !== undefined) {

src/compiler/compile/render_ssr/handlers/Head.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ export default function(node: Head, renderer: Renderer, options: RenderOptions)
1212
renderer.render(node.children, head_options);
1313
const result = renderer.pop();
1414

15-
renderer.add_expression(x`$$result.head += ${result}, ""`);
15+
renderer.add_expression(x`$$result.head += '<!-- HEAD_${node.id}_START -->' + ${result} + '<!-- HEAD_${node.id}_END -->', ""`);
1616
}

src/runtime/internal/dom.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,27 @@ export function query_selector_all(selector: string, parent: HTMLElement = docum
646646
return Array.from(parent.querySelectorAll(selector)) as ChildNodeArray;
647647
}
648648

649+
export function head_selector(nodeId: string, head: HTMLElement) {
650+
const result = [];
651+
let started = 0;
652+
653+
for (const node of head.childNodes) {
654+
if (node.nodeType === 8 /* comment node */) {
655+
const comment = node.textContent.trim();
656+
if (comment === `HEAD_${nodeId}_END`) {
657+
started -= 1;
658+
result.push(node);
659+
} else if (comment === `HEAD_${nodeId}_START`) {
660+
started += 1;
661+
result.push(node);
662+
}
663+
} else if (started > 0) {
664+
result.push(node);
665+
}
666+
}
667+
return result;
668+
}
669+
649670
export class HtmlTag {
650671
private is_svg = false;
651672
// parent for creating node
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{@html '<meta name="head_nested_html" content="head_nested_html">'}
2+
<meta name="head_nested" content="head_nested">
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
<svelte:head>
3+
{@html '<meta name="nested_html" content="nested_html">'}
4+
<meta name="nested" content="nested">
5+
</svelte:head>

test/hydration/samples/head-html-and-component/_after.html

Whitespace-only changes.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!-- HEAD_svelte-17ibcve_START -->
2+
<!-- HTML_TAG_START --><meta name="main_html" content="main_html"><!-- HTML_TAG_END -->
3+
<meta name="main" content="main">
4+
<!-- HTML_TAG_START --><meta name="head_nested_html" content="head_nested_html"><!-- HTML_TAG_END -->
5+
<meta name="head_nested" content="head_nested">
6+
<!-- HEAD_svelte-17ibcve_END -->
7+
8+
<!-- HEAD_svelte-1gqzvnn_START -->
9+
<!-- HTML_TAG_START --><meta name="nested_html" content="nested_html"><!-- HTML_TAG_END -->
10+
<meta name="nested" content="nested">
11+
<!-- HEAD_svelte-1gqzvnn_END -->
12+

test/hydration/samples/head-html-and-component/_before.html

Whitespace-only changes.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!-- HEAD_svelte-17ibcve_START -->
2+
<!-- HTML_TAG_START --><meta name="main_html" content="main_html"><!-- HTML_TAG_END -->
3+
<meta name="main" content="main">
4+
<!-- HTML_TAG_START --><meta name="head_nested_html" content="head_nested_html"><!-- HTML_TAG_END -->
5+
<meta name="head_nested" content="head_nested">
6+
<!-- HEAD_svelte-17ibcve_END -->
7+
8+
<!-- HEAD_svelte-1gqzvnn_START -->
9+
<!-- HTML_TAG_START --><meta name="nested_html" content="nested_html"><!-- HTML_TAG_END -->
10+
<meta name="nested" content="nested">
11+
<!-- HEAD_svelte-1gqzvnn_END -->

0 commit comments

Comments
 (0)