diff --git a/.changeset/tall-books-grin.md b/.changeset/tall-books-grin.md
new file mode 100644
index 0000000000..5587b6103c
--- /dev/null
+++ b/.changeset/tall-books-grin.md
@@ -0,0 +1,5 @@
+---
+'svelte': patch
+---
+
+fix: ensure class constructor values are proxied
diff --git a/packages/svelte/src/compiler/phases/3-transform/client/utils.js b/packages/svelte/src/compiler/phases/3-transform/client/utils.js
index f22bf8065b..a2956f5afc 100644
--- a/packages/svelte/src/compiler/phases/3-transform/client/utils.js
+++ b/packages/svelte/src/compiler/phases/3-transform/client/utils.js
@@ -157,16 +157,45 @@ export function serialize_set_binding(node, context, fallback) {
let left = node.left;
+ // Handle class private/public state assignment cases
while (left.type === 'MemberExpression') {
- if (left.object.type === 'ThisExpression' && left.property.type === 'PrivateIdentifier') {
- if (context.state.private_state.has(left.property.name) && !state.in_constructor) {
- const value = get_assignment_value(node, context);
+ if (
+ left.object.type === 'ThisExpression' &&
+ left.property.type === 'PrivateIdentifier' &&
+ context.state.private_state.has(left.property.name)
+ ) {
+ const value = get_assignment_value(node, context);
+ if (state.in_constructor) {
+ // See if we should wrap value in $.proxy
+ if (context.state.analysis.runes && should_proxy(value)) {
+ const assignment = fallback();
+ if (assignment.type === 'AssignmentExpression') {
+ assignment.right = b.call('$.proxy', value);
+ return assignment;
+ }
+ }
+ } else {
return b.call(
'$.set',
left,
context.state.analysis.runes && should_proxy(value) ? b.call('$.proxy', value) : value
);
}
+ } else if (
+ left.object.type === 'ThisExpression' &&
+ left.property.type === 'Identifier' &&
+ context.state.public_state.has(left.property.name) &&
+ state.in_constructor
+ ) {
+ const value = get_assignment_value(node, context);
+ // See if we should wrap value in $.proxy
+ if (context.state.analysis.runes && should_proxy(value)) {
+ const assignment = fallback();
+ if (assignment.type === 'AssignmentExpression') {
+ assignment.right = b.call('$.proxy', value);
+ return assignment;
+ }
+ }
}
// @ts-expect-error
left = left.object;
diff --git a/packages/svelte/tests/runtime-runes/samples/class-private-state-proxy/_config.js b/packages/svelte/tests/runtime-runes/samples/class-private-state-proxy/_config.js
new file mode 100644
index 0000000000..436ce99798
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/class-private-state-proxy/_config.js
@@ -0,0 +1,15 @@
+import { test } from '../../test';
+
+export default test({
+ html: ``,
+
+ async test({ assert, target }) {
+ const btn = target.querySelector('button');
+
+ await btn?.click();
+ assert.htmlEqual(target.innerHTML, ``);
+
+ await btn?.click();
+ assert.htmlEqual(target.innerHTML, ``);
+ }
+});
diff --git a/packages/svelte/tests/runtime-runes/samples/class-private-state-proxy/main.svelte b/packages/svelte/tests/runtime-runes/samples/class-private-state-proxy/main.svelte
new file mode 100644
index 0000000000..7359f15304
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/class-private-state-proxy/main.svelte
@@ -0,0 +1,16 @@
+
+
+
diff --git a/packages/svelte/tests/runtime-runes/samples/class-state-proxy/_config.js b/packages/svelte/tests/runtime-runes/samples/class-state-proxy/_config.js
new file mode 100644
index 0000000000..436ce99798
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/class-state-proxy/_config.js
@@ -0,0 +1,15 @@
+import { test } from '../../test';
+
+export default test({
+ html: ``,
+
+ async test({ assert, target }) {
+ const btn = target.querySelector('button');
+
+ await btn?.click();
+ assert.htmlEqual(target.innerHTML, ``);
+
+ await btn?.click();
+ assert.htmlEqual(target.innerHTML, ``);
+ }
+});
diff --git a/packages/svelte/tests/runtime-runes/samples/class-state-proxy/main.svelte b/packages/svelte/tests/runtime-runes/samples/class-state-proxy/main.svelte
new file mode 100644
index 0000000000..bf24921321
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/class-state-proxy/main.svelte
@@ -0,0 +1,12 @@
+
+
+