diff --git a/.changeset/hungry-tips-unite.md b/.changeset/hungry-tips-unite.md
new file mode 100644
index 0000000000..b138fd409d
--- /dev/null
+++ b/.changeset/hungry-tips-unite.md
@@ -0,0 +1,5 @@
+---
+'svelte': patch
+---
+
+fix: port over props that were set prior to initialization
diff --git a/packages/svelte/src/internal/client/custom-element.js b/packages/svelte/src/internal/client/custom-element.js
index ded94b616d..bafdbc00f3 100644
--- a/packages/svelte/src/internal/client/custom-element.js
+++ b/packages/svelte/src/internal/client/custom-element.js
@@ -127,6 +127,16 @@ 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) {
+ // @ts-expect-error
+ if (!(key in this.$$d) && this[key] !== undefined) {
+ // @ts-expect-error
+ this.$$d[key] = this[key]; // don't transform, these were set through JavaScript
+ // @ts-expect-error
+ delete this[key]; // remove the property that shadows the getter/setter
+ }
+ }
this.$$c = createClassComponent({
component: this.$$ctor,
target: this.shadowRoot || this,
diff --git a/packages/svelte/tests/runtime-browser/custom-elements-samples/set-property-before-mounted/_config.js b/packages/svelte/tests/runtime-browser/custom-elements-samples/set-property-before-mounted/_config.js
new file mode 100644
index 0000000000..843e164522
--- /dev/null
+++ b/packages/svelte/tests/runtime-browser/custom-elements-samples/set-property-before-mounted/_config.js
@@ -0,0 +1,25 @@
+import { test } from '../../assert';
+
+const tick = () => Promise.resolve();
+
+export default test({
+ async test({ assert, target, componentCtor }) {
+ target.innerHTML = '
{prop}