From aa8cc5d26ff569d4d2b7ea552f87ef89a9d29b51 Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Fri, 16 Jun 2023 22:12:35 +0200 Subject: [PATCH] fix: never use html optimization for mustache tags in hydration mode (#8744) --------- Co-authored-by: gtmnayan --- .changeset/fair-geese-repeat.md | 5 +++++ packages/svelte/src/compiler/compile/Component.js | 8 +++----- packages/svelte/src/compiler/compile/nodes/Element.js | 9 +++++++++ .../compile/render_dom/wrappers/Element/index.js | 10 +++++----- .../compiler/compile/render_ssr/handlers/Element.js | 2 +- .../repairs-apparent-static-content/_after.html | 1 + .../repairs-apparent-static-content/_before.html | 1 + .../samples/repairs-apparent-static-content/_config.js | 7 +++++++ .../repairs-apparent-static-content/main.svelte | 1 + 9 files changed, 33 insertions(+), 11 deletions(-) create mode 100644 .changeset/fair-geese-repeat.md create mode 100644 packages/svelte/test/hydration/samples/repairs-apparent-static-content/_after.html create mode 100644 packages/svelte/test/hydration/samples/repairs-apparent-static-content/_before.html create mode 100644 packages/svelte/test/hydration/samples/repairs-apparent-static-content/_config.js create mode 100644 packages/svelte/test/hydration/samples/repairs-apparent-static-content/main.svelte diff --git a/.changeset/fair-geese-repeat.md b/.changeset/fair-geese-repeat.md new file mode 100644 index 0000000000..f99f912e0d --- /dev/null +++ b/.changeset/fair-geese-repeat.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: never use html optimization for mustache tags in hydration mode diff --git a/packages/svelte/src/compiler/compile/Component.js b/packages/svelte/src/compiler/compile/Component.js index 894cb9b787..7a7a1ba17e 100644 --- a/packages/svelte/src/compiler/compile/Component.js +++ b/packages/svelte/src/compiler/compile/Component.js @@ -1632,11 +1632,9 @@ export default class Component { unsorted_reactive_declarations.forEach(add_declaration); } check_if_tags_content_dynamic() { - this.tags.forEach( - /** @param {any} tag */ (tag) => { - tag.check_if_content_dynamic(); - } - ); + this.tags.forEach((tag) => { + tag.check_if_content_dynamic(); + }); } /** diff --git a/packages/svelte/src/compiler/compile/nodes/Element.js b/packages/svelte/src/compiler/compile/nodes/Element.js index 3f67615e06..3b18ce0e94 100644 --- a/packages/svelte/src/compiler/compile/nodes/Element.js +++ b/packages/svelte/src/compiler/compile/nodes/Element.js @@ -1464,6 +1464,15 @@ export default class Element extends Node { this.children.length > 0 ); } + get can_optimise_hydration() { + // In contrast to normal html string optimization, we also bail in case of mustache tags even + // if they seem to contain static content. This is because we cannot know whether that static + // value is different between client and server builds, e.g. {browser ? 'hi' : 'bye'} which + // becomes {'hi'} and {'bye'} respectively. + const is_static_text_content = + this.is_static_content && this.children.every((node) => node.type === 'Text'); + return this.can_optimise_to_html_string && (this.can_use_innerhtml || is_static_text_content); + } hash() { return `svelte-${hash(this.component.source.slice(this.start, this.end))}`; } diff --git a/packages/svelte/src/compiler/compile/render_dom/wrappers/Element/index.js b/packages/svelte/src/compiler/compile/render_dom/wrappers/Element/index.js index 687741d21a..eca5f09fc5 100644 --- a/packages/svelte/src/compiler/compile/render_dom/wrappers/Element/index.js +++ b/packages/svelte/src/compiler/compile/render_dom/wrappers/Element/index.js @@ -458,13 +458,13 @@ export default class ElementWrapper extends Wrapper { block.add_variable(node); const render_statement = this.get_render_statement(block); block.chunks.create.push(b`${node} = ${render_statement};`); - const { can_use_textcontent, can_optimise_to_html_string } = this.node; + const { can_use_textcontent, can_optimise_to_html_string, can_optimise_hydration } = this.node; if (hydratable) { if (parent_nodes) { block.chunks.claim.push(b` - ${node} = ${this.get_claim_statement(block, parent_nodes, can_optimise_to_html_string)}; + ${node} = ${this.get_claim_statement(block, parent_nodes, can_optimise_hydration)}; `); - if (!can_optimise_to_html_string && !this.void && this.node.children.length > 0) { + if (!can_optimise_hydration && !this.void && this.node.children.length > 0) { block.chunks.claim.push(b` var ${nodes} = ${children}; `); @@ -500,7 +500,7 @@ export default class ElementWrapper extends Wrapper { } // insert static children with textContent or innerHTML // skip textcontent for