From 6f392d679bc5c4790aad8bfc1135c7f88c6ae510 Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Wed, 5 Feb 2025 20:22:36 +0100 Subject: [PATCH] fix: properly set `value` property of custom elements (#15206) Avoid going through the `element.value = element.__value = newValue` condition because `__value` is actually how Lit stores the current value on the element, and messing with that would break things: Lit would think the value hasn't changed (because `__value` is already set to the new value by us) and doesn't fire an update. fixes #15194 --- .changeset/great-planes-swim.md | 5 +++++ .../client/dom/elements/attributes.js | 7 ++++--- .../custom-element-attributes/_config.js | 13 ++++++++---- .../custom-element-attributes/main.svelte | 20 +++++++++++++++++++ 4 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 .changeset/great-planes-swim.md diff --git a/.changeset/great-planes-swim.md b/.changeset/great-planes-swim.md new file mode 100644 index 0000000000..ecf8fa17aa --- /dev/null +++ b/.changeset/great-planes-swim.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: properly set `value` property of custom elements diff --git a/packages/svelte/src/internal/client/dom/elements/attributes.js b/packages/svelte/src/internal/client/dom/elements/attributes.js index eab27e6c02..8c86fe7e02 100644 --- a/packages/svelte/src/internal/client/dom/elements/attributes.js +++ b/packages/svelte/src/internal/client/dom/elements/attributes.js @@ -363,9 +363,10 @@ export function set_attributes( element.style.cssText = value + ''; } else if (key === 'autofocus') { autofocus(/** @type {HTMLElement} */ (element), Boolean(value)); - } else if (key === '__value' || (key === 'value' && value != null)) { - // @ts-ignore - element.value = element[key] = element.__value = value; + } else if (!is_custom_element && (key === '__value' || (key === 'value' && value != null))) { + // @ts-ignore We're not running this for custom elements because __value is actually + // how Lit stores the current value on the element, and messing with that would break things. + element.value = element.__value = value; } else if (key === 'selected' && is_option_element) { set_selected(/** @type {HTMLOptionElement} */ (element), value); } else { diff --git a/packages/svelte/tests/runtime-runes/samples/custom-element-attributes/_config.js b/packages/svelte/tests/runtime-runes/samples/custom-element-attributes/_config.js index 118a51157e..7f406d8f0d 100644 --- a/packages/svelte/tests/runtime-runes/samples/custom-element-attributes/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/custom-element-attributes/_config.js @@ -1,19 +1,24 @@ import { test } from '../../test'; export default test({ - mode: ['client', 'server'], + mode: ['client'], async test({ assert, target }) { const my_element = /** @type HTMLElement & { object: { test: true }; } */ ( target.querySelector('my-element') ); - const my_link = /** @type HTMLAnchorElement & { object: { test: true }; } */ ( - target.querySelector('a') - ); assert.equal(my_element.getAttribute('string'), 'test'); assert.equal(my_element.hasAttribute('object'), false); assert.deepEqual(my_element.object, { test: true }); + + const my_link = /** @type HTMLAnchorElement & { object: { test: true }; } */ ( + target.querySelector('a') + ); assert.equal(my_link.getAttribute('string'), 'test'); assert.equal(my_link.hasAttribute('object'), false); assert.deepEqual(my_link.object, { test: true }); + + const [value1, value2] = target.querySelectorAll('value-element'); + assert.equal(value1.shadowRoot?.innerHTML, 'test'); + assert.equal(value2.shadowRoot?.innerHTML, 'test'); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/custom-element-attributes/main.svelte b/packages/svelte/tests/runtime-runes/samples/custom-element-attributes/main.svelte index ff94a9484c..4c98245e5b 100644 --- a/packages/svelte/tests/runtime-runes/samples/custom-element-attributes/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/custom-element-attributes/main.svelte @@ -1,2 +1,22 @@ + + + + +