Fix hydration duplicate head tag issue sveltejs#7444

pull/7738/head
Maximiliano Ruani 4 years ago
parent 75897afd72
commit bb02faec16

@ -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);

@ -3,7 +3,13 @@ import RawMustacheTag from '../../nodes/RawMustacheTag';
import { Expression } from 'estree';
export default function(node: RawMustacheTag, renderer: Renderer, options: RenderOptions) {
if (options.hydratable) renderer.add_string('<!-- HTML_TAG_START -->');
if (options.hydratable) {
renderer.add_string(`<!-- HTML_TAG_START ${options.head_id ? `data-svelte="${options.head_id}" ` : ''}-->`);
}
renderer.add_expression(node.expression.node as Expression);
if (options.hydratable) renderer.add_string('<!-- HTML_TAG_END -->');
if (options.hydratable) {
renderer.add_string(`<!-- HTML_TAG_END ${options.head_id ? `data-svelte="${options.head_id}" ` : ''}-->`);
}
}

@ -477,21 +477,24 @@ export function claim_space(nodes) {
return claim_text(nodes, ' ');
}
function find_comment(nodes, text, start) {
function find_html_tag_comment(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) {
if (node.nodeType === 8 /* comment node */) {
const value = node.textContent.trim();
if (value === text || value.startsWith(text + ' data-svelte="') === true) {
return i;
}
}
}
return nodes.length;
}
export function claim_html_tag(nodes, is_svg: boolean) {
// 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);
const start_index = find_html_tag_comment(nodes, 'HTML_TAG_START', 0);
const end_index = find_html_tag_comment(nodes, 'HTML_TAG_END', start_index);
if (start_index === end_index) {
return new HtmlTagHydration(undefined, is_svg);
}
@ -640,6 +643,25 @@ 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 */ && node.textContent.trim() === `HTML_TAG_END data-svelte="${nodeId}"`) {
started -= 1;
result.push(node);
} else if (node.nodeType === 8 /* comment node */ && node.textContent.trim() === `HTML_TAG_START data-svelte="${nodeId}"`) {
started += 1;
result.push(node);
} else if (started > 0) {
result.push(node);
} else if (node.nodeType === 1 /* element node */ && (<Element>node).getAttribute('data-svelte') === nodeId) {
result.push(node);
}
}
return result;
}
export class HtmlTag {
private is_svg = false;
// parent for creating node

@ -0,0 +1,4 @@
<svelte:head>
{@html '<meta name="nested_meta" content="nested_value">'}
</svelte:head>

@ -0,0 +1,7 @@
<!-- HTML_TAG_START data-svelte="svelte-p6n9ep" -->
<meta name="main_meta" content="main_value">
<!-- HTML_TAG_END data-svelte="svelte-p6n9ep" -->
<!-- HTML_TAG_START data-svelte="svelte-1ygcsvx" -->
<meta name="nested_meta" content="nested_value">
<!-- HTML_TAG_END data-svelte="svelte-1ygcsvx" -->

@ -0,0 +1,7 @@
<!-- HTML_TAG_START data-svelte="svelte-p6n9ep" -->
<meta name="main_meta" content="main_value">
<!-- HTML_TAG_END data-svelte="svelte-p6n9ep" -->
<!-- HTML_TAG_START data-svelte="svelte-1ygcsvx" -->
<meta name="nested_meta" content="nested_value">
<!-- HTML_TAG_END data-svelte="svelte-1ygcsvx" -->

@ -0,0 +1,9 @@
<script>
import Nested from './Nested.svelte';
</script>
<svelte:head>
{@html '<meta name="main_meta" content="main_value">'}
</svelte:head>
<Nested/>
Loading…
Cancel
Save