From d36f460a5407cb5994f6a7669c010422cb01eee6 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Sat, 30 Dec 2023 21:03:35 -0800 Subject: [PATCH] test case and fix --- .../3-transform/client/visitors/template.js | 20 ++++++++++++------- .../svelte/src/compiler/types/template.d.ts | 5 +++++ .../_expected/client/index.svelte.js | 16 +++++++++++---- .../_expected/server/index.svelte.js | 9 ++++++--- .../samples/hoist-unmodified-var/index.svelte | 7 +++++-- 5 files changed, 41 insertions(+), 16 deletions(-) diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js index a987f2182d..b43f6580e8 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js @@ -564,14 +564,20 @@ function serialize_element_attribute_update_assignment(element, node_id, attribu } }; - let can_inline = false; + let has_expression_tag = false; + let can_inline = true; if (Array.isArray(attribute.value)) { for (let value of attribute.value) { - if (value.type === 'ExpressionTag' && value.expression.type === 'Identifier') { - const binding = context.state.scope - .owner(value.expression.name) - ?.declarations.get(value.expression.name); - can_inline ||= can_inline_variable(binding, value.expression.name); + if (value.type === 'ExpressionTag') { + if (value.expression.type === 'Identifier') { + const binding = context.state.scope + .owner(value.expression.name) + ?.declarations.get(value.expression.name); + can_inline &&= can_inline_variable(binding, value.expression.name); + } else { + can_inline = false; + } + has_expression_tag = true; } } } @@ -588,7 +594,7 @@ function serialize_element_attribute_update_assignment(element, node_id, attribu ); return true; } else { - if (can_inline) { + if (has_expression_tag && can_inline) { push_template_quasi(context.state, ` ${name}="`); push_template_expression(context.state, grouped_value); push_template_quasi(context.state, `"`); diff --git a/packages/svelte/src/compiler/types/template.d.ts b/packages/svelte/src/compiler/types/template.d.ts index 4646dc6d32..843d6d211f 100644 --- a/packages/svelte/src/compiler/types/template.d.ts +++ b/packages/svelte/src/compiler/types/template.d.ts @@ -422,6 +422,11 @@ export type Block = EachBlock | IfBlock | AwaitBlock | KeyBlock | SnippetBlock; export interface Attribute extends BaseNode { type: 'Attribute'; name: string; + /** + * The attribute may be omitted when false. + * String values are represented by an array since it may be a combination of text and expression + * values such as `style="color: {color} !import"`. + */ value: true | Array; metadata: { dynamic: boolean; diff --git a/packages/svelte/tests/snapshot/samples/hoist-unmodified-var/_expected/client/index.svelte.js b/packages/svelte/tests/snapshot/samples/hoist-unmodified-var/_expected/client/index.svelte.js index 03c98b0f8d..7d640226f1 100644 --- a/packages/svelte/tests/snapshot/samples/hoist-unmodified-var/_expected/client/index.svelte.js +++ b/packages/svelte/tests/snapshot/samples/hoist-unmodified-var/_expected/client/index.svelte.js @@ -2,21 +2,29 @@ // Note: compiler output will change before 5.0 is released! import "svelte/internal/disclose-version"; -const autocapitalize = 'words'; +const o = 'o'; +const d = 'd'; import * as $ from "svelte/internal"; const boolean = false; -var frag = $.template(`

`); +var frag = $.template(`

`); export default function Hoist_unmodified_var($$anchor, $$props) { $.push($$props, true); + let value = 'd'; + + value += 'd'; + /* Init */ var p = $.open($$anchor, true, frag); + + $.attr(p, "itemid", `w${$.stringify(o)}r${$.stringify(value)}s`); + var text = $.child(p); - text.nodeValue = `boolean is ${$.stringify(boolean)} and autocapitalize is ${$.stringify(autocapitalize)}`; + text.nodeValue = `boolean is ${$.stringify(boolean)} and autocapitalize is w${$.stringify(o)}r${$.stringify(d)}s`; $.close($$anchor, p); $.pop(); -} +} \ No newline at end of file diff --git a/packages/svelte/tests/snapshot/samples/hoist-unmodified-var/_expected/server/index.svelte.js b/packages/svelte/tests/snapshot/samples/hoist-unmodified-var/_expected/server/index.svelte.js index a85632b097..20d3af1f0c 100644 --- a/packages/svelte/tests/snapshot/samples/hoist-unmodified-var/_expected/server/index.svelte.js +++ b/packages/svelte/tests/snapshot/samples/hoist-unmodified-var/_expected/server/index.svelte.js @@ -2,13 +2,16 @@ // Note: compiler output will change before 5.0 is released! import * as $ from "svelte/internal/server"; -const autocapitalize = 'words'; +const o = 'o'; +const d = 'd'; export default function Hoist_unmodified_var($$payload, $$props) { $.push(true); let boolean = false; + let value = 'd'; - $$payload.out += `boolean is ${$.escape(boolean)} and autocapitalize is ${$.escape(autocapitalize)}

`; + value += 'd'; + $$payload.out += `boolean is ${$.escape(boolean)} and autocapitalize is w${$.escape(o)}r${$.escape(d)}s

`; $.pop(); -} +} \ No newline at end of file diff --git a/packages/svelte/tests/snapshot/samples/hoist-unmodified-var/index.svelte b/packages/svelte/tests/snapshot/samples/hoist-unmodified-var/index.svelte index a33528e340..261937285c 100644 --- a/packages/svelte/tests/snapshot/samples/hoist-unmodified-var/index.svelte +++ b/packages/svelte/tests/snapshot/samples/hoist-unmodified-var/index.svelte @@ -1,11 +1,14 @@ -

boolean is {boolean} and autocapitalize is {autocapitalize}

+

boolean is {boolean} and autocapitalize is w{o}r{d}s