From 31d939fefab1c0da9b660d6097aaca679dd264eb Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Thu, 30 Nov 2023 11:11:51 +0100 Subject: [PATCH] fix: port over props that were set prior to initialization (#9701) ...and then delete the property descriptor that shadows the prototype descriptor fixes #9487 --- .changeset/wicked-chefs-bow.md | 5 ++++ .../svelte/src/runtime/internal/Component.js | 7 ++++++ .../set-property-before-mounted/main.svelte | 9 ++++++++ .../set-property-before-mounted/test.js | 23 +++++++++++++++++++ 4 files changed, 44 insertions(+) create mode 100644 .changeset/wicked-chefs-bow.md create mode 100644 packages/svelte/test/runtime-browser/custom-elements-samples/set-property-before-mounted/main.svelte create mode 100644 packages/svelte/test/runtime-browser/custom-elements-samples/set-property-before-mounted/test.js diff --git a/.changeset/wicked-chefs-bow.md b/.changeset/wicked-chefs-bow.md new file mode 100644 index 0000000000..b138fd409d --- /dev/null +++ b/.changeset/wicked-chefs-bow.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: port over props that were set prior to initialization diff --git a/packages/svelte/src/runtime/internal/Component.js b/packages/svelte/src/runtime/internal/Component.js index 88f048c6ee..3b9848772f 100644 --- a/packages/svelte/src/runtime/internal/Component.js +++ b/packages/svelte/src/runtime/internal/Component.js @@ -270,6 +270,13 @@ if (typeof HTMLElement === 'function') { this.$$d[name] = get_custom_element_value(name, attribute.value, this.$$p_d, 'toProp'); } } + // Port over props that were set programmatically before ce was initialized + for (const key in this.$$p_d) { + if (!(key in this.$$d) && this[key] !== undefined) { + this.$$d[key] = this[key]; // don't transform, these were set through JavaScript + delete this[key]; // remove the property that shadows the getter/setter + } + } this.$$c = new this.$$ctor({ target: this.shadowRoot || this, props: { diff --git a/packages/svelte/test/runtime-browser/custom-elements-samples/set-property-before-mounted/main.svelte b/packages/svelte/test/runtime-browser/custom-elements-samples/set-property-before-mounted/main.svelte new file mode 100644 index 0000000000..f8c6ea9984 --- /dev/null +++ b/packages/svelte/test/runtime-browser/custom-elements-samples/set-property-before-mounted/main.svelte @@ -0,0 +1,9 @@ + + + + +

{prop}

diff --git a/packages/svelte/test/runtime-browser/custom-elements-samples/set-property-before-mounted/test.js b/packages/svelte/test/runtime-browser/custom-elements-samples/set-property-before-mounted/test.js new file mode 100644 index 0000000000..b170b6b164 --- /dev/null +++ b/packages/svelte/test/runtime-browser/custom-elements-samples/set-property-before-mounted/test.js @@ -0,0 +1,23 @@ +import * as assert from 'assert.js'; +import { tick } from 'svelte'; +import Main from './main.svelte'; + +export default async function (target) { + target.innerHTML = ''; + const ce = target.querySelector('custom-element'); + ce.prop = 1; + customElements.define('custom-element', Main.element); + await tick(); + await tick(); + + const ce_root = target.querySelector('custom-element').shadowRoot; + const p = ce_root.querySelector('p'); + + assert.equal(p.textContent, '1'); + + ce.prop = 2; + await tick(); + await tick(); + + assert.equal(p.textContent, '2'); +}