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 @@ + + +