[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
pull/7693/head
Maximiliano Ruani 2 years ago committed by GitHub
parent 7ac3854613
commit 8ffc8fd77b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -36,7 +36,7 @@ export default class HeadWrapper extends Wrapper {
let nodes;
if (this.renderer.options.hydratable && this.fragment.nodes.length) {
nodes = block.get_unique_name('head_nodes');
block.chunks.claim.push(b`const ${nodes} = @query_selector_all('[data-svelte="${this.node.id}"]', @_document.head);`);
block.chunks.claim.push(b`const ${nodes} = @head_selector('${this.node.id}', @_document.head);`);
}
this.fragment.render(block, x`@_document.head` as unknown as Identifier, nodes);

@ -157,10 +157,6 @@ export default function (node: Element, renderer: Renderer, options: RenderOptio
}
});
if (options.hydratable && options.head_id) {
renderer.add_string(` data-svelte="${options.head_id}"`);
}
renderer.add_string('>');
if (node_contents !== undefined) {

@ -12,5 +12,5 @@ export default function(node: Head, renderer: Renderer, options: RenderOptions)
renderer.render(node.children, head_options);
const result = renderer.pop();
renderer.add_expression(x`$$result.head += ${result}, ""`);
renderer.add_expression(x`$$result.head += '<!-- HEAD_${node.id}_START -->' + ${result} + '<!-- HEAD_${node.id}_END -->', ""`);
}

@ -646,6 +646,27 @@ export function query_selector_all(selector: string, parent: HTMLElement = docum
return Array.from(parent.querySelectorAll(selector)) as ChildNodeArray;
}
export function head_selector(nodeId: string, head: HTMLElement) {
const result = [];
let started = 0;
for (const node of head.childNodes) {
if (node.nodeType === 8 /* comment node */) {
const comment = node.textContent.trim();
if (comment === `HEAD_${nodeId}_END`) {
started -= 1;
result.push(node);
} else if (comment === `HEAD_${nodeId}_START`) {
started += 1;
result.push(node);
}
} else if (started > 0) {
result.push(node);
}
}
return result;
}
export class HtmlTag {
private is_svg = false;
// parent for creating node

@ -0,0 +1,2 @@
{@html '<meta name="head_nested_html" content="head_nested_html">'}
<meta name="head_nested" content="head_nested">

@ -0,0 +1,5 @@
<svelte:head>
{@html '<meta name="nested_html" content="nested_html">'}
<meta name="nested" content="nested">
</svelte:head>

@ -0,0 +1,12 @@
<!-- HEAD_svelte-17ibcve_START -->
<!-- HTML_TAG_START --><meta name="main_html" content="main_html"><!-- HTML_TAG_END -->
<meta name="main" content="main">
<!-- HTML_TAG_START --><meta name="head_nested_html" content="head_nested_html"><!-- HTML_TAG_END -->
<meta name="head_nested" content="head_nested">
<!-- HEAD_svelte-17ibcve_END -->
<!-- HEAD_svelte-1gqzvnn_START -->
<!-- HTML_TAG_START --><meta name="nested_html" content="nested_html"><!-- HTML_TAG_END -->
<meta name="nested" content="nested">
<!-- HEAD_svelte-1gqzvnn_END -->

@ -0,0 +1,11 @@
<!-- HEAD_svelte-17ibcve_START -->
<!-- HTML_TAG_START --><meta name="main_html" content="main_html"><!-- HTML_TAG_END -->
<meta name="main" content="main">
<!-- HTML_TAG_START --><meta name="head_nested_html" content="head_nested_html"><!-- HTML_TAG_END -->
<meta name="head_nested" content="head_nested">
<!-- HEAD_svelte-17ibcve_END -->
<!-- HEAD_svelte-1gqzvnn_START -->
<!-- HTML_TAG_START --><meta name="nested_html" content="nested_html"><!-- HTML_TAG_END -->
<meta name="nested" content="nested">
<!-- HEAD_svelte-1gqzvnn_END -->

@ -0,0 +1,12 @@
<script>
import HeadNested from './HeadNested.svelte';
import Nested from './Nested.svelte';
</script>
<svelte:head>
{@html '<meta name="main_html" content="main_html">'}
<meta name="main" content="main">
<HeadNested />
</svelte:head>
<Nested/>

@ -1,4 +1,6 @@
<title>Some Title</title>
<link href="/" rel="canonical">
<meta content="some description" name="description">
<meta content="some keywords" name="keywords">
<!-- HEAD_svelte-1s8aodm_START -->
<link rel="canonical" href="/">
<meta name="description" content="some description">
<meta name="keywords" content="some keywords">
<!-- HEAD_svelte-1s8aodm_END -->

@ -1,4 +1,6 @@
<title>Some Title</title>
<link rel="canonical" href="/" data-svelte="svelte-1s8aodm">
<meta name="description" content="some description" data-svelte="svelte-1s8aodm">
<meta name="keywords" content="some keywords" data-svelte="svelte-1s8aodm">
<!-- HEAD_svelte-1s8aodm_START -->
<link rel="canonical" href="/">
<meta name="description" content="some description">
<meta name="keywords" content="some keywords">
<!-- HEAD_svelte-1s8aodm_END -->

@ -0,0 +1,2 @@
{@html '<meta name="head_nested_html" content="head_nested_html">'}
<meta name="head_nested" content="head_nested">

@ -0,0 +1,5 @@
<svelte:head>
{@html '<meta name="nested_html" content="nested_html">'}
<meta name="nested" content="nested">
</svelte:head>

@ -0,0 +1,11 @@
<!-- HEAD_svelte-17ibcve_START -->
<!-- HTML_TAG_START --><meta name="main_html" content="main_html"><!-- HTML_TAG_END -->
<meta name="main" content="main">
<!-- HTML_TAG_START --><meta name="head_nested_html" content="head_nested_html"><!-- HTML_TAG_END -->
<meta name="head_nested" content="head_nested">
<!-- HEAD_svelte-17ibcve_END -->
<!-- HEAD_svelte-1gqzvnn_START -->
<!-- HTML_TAG_START --><meta name="nested_html" content="nested_html"><!-- HTML_TAG_END -->
<meta name="nested" content="nested">
<!-- HEAD_svelte-1gqzvnn_END -->

@ -0,0 +1,12 @@
<script>
import HeadNested from './HeadNested.svelte';
import Nested from './Nested.svelte';
</script>
<svelte:head>
{@html '<meta name="main_html" content="main_html">'}
<meta name="main" content="main">
<HeadNested />
</svelte:head>
<Nested/>

@ -1,4 +1,6 @@
<title>Some Title</title>
<link rel="canonical" href="/" data-svelte="svelte-1s8aodm">
<meta name="description" content="some description" data-svelte="svelte-1s8aodm">
<meta name="keywords" content="some keywords" data-svelte="svelte-1s8aodm">
<!-- HEAD_svelte-1s8aodm_START -->
<link rel="canonical" href="/">
<meta name="description" content="some description">
<meta name="keywords" content="some keywords">
<!-- HEAD_svelte-1s8aodm_END -->

Loading…
Cancel
Save