diff --git a/packages/svelte/src/compiler/phases/2-analyze/index.js b/packages/svelte/src/compiler/phases/2-analyze/index.js index d442cee77d..4d047b4970 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/index.js +++ b/packages/svelte/src/compiler/phases/2-analyze/index.js @@ -546,7 +546,6 @@ export function analyze_component(root, source, options) { component_slots: new Set(), expression: null, render_tag: null, - private_derived_state: [], function_depth: scope.function_depth, instance_scope: instance.scope, reactive_statement: null, @@ -618,7 +617,6 @@ export function analyze_component(root, source, options) { component_slots: new Set(), expression: null, render_tag: null, - private_derived_state: [], function_depth: scope.function_depth }; diff --git a/packages/svelte/src/compiler/phases/2-analyze/types.d.ts b/packages/svelte/src/compiler/phases/2-analyze/types.d.ts index 2cfe76b61a..56e8a0b05b 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/types.d.ts +++ b/packages/svelte/src/compiler/phases/2-analyze/types.d.ts @@ -17,7 +17,6 @@ export interface AnalysisState { expression: ExpressionMetadata | null; /** The current {@render ...} tag, if any */ render_tag: null | RenderTag; - private_derived_state: string[]; function_depth: number; // legacy stuff diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/ClassBody.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/ClassBody.js index d445af0ebf..a3e3765934 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/visitors/ClassBody.js +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/ClassBody.js @@ -1,27 +1,10 @@ /** @import { ClassBody } from 'estree' */ /** @import { Context } from '../types' */ -import { get_rune } from '../../scope.js'; /** * @param {ClassBody} node * @param {Context} context */ export function ClassBody(node, context) { - /** @type {string[]} */ - const private_derived_state = []; - - for (const definition of node.body) { - if ( - definition.type === 'PropertyDefinition' && - definition.key.type === 'PrivateIdentifier' && - definition.value?.type === 'CallExpression' - ) { - const rune = get_rune(definition.value, context.state.scope); - if (rune === '$derived' || rune === '$derived.by') { - private_derived_state.push(definition.key.name); - } - } - } - - context.next({ ...context.state, private_derived_state }); + context.next({ ...context.state }); } diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/shared/utils.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/shared/utils.js index f6df4292bc..95916f8614 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/visitors/shared/utils.js +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/shared/utils.js @@ -51,12 +51,6 @@ export function validate_assignment(node, argument, state) { property = object.property; object = object.object; } - - if (object.type === 'ThisExpression' && property?.type === 'PrivateIdentifier') { - if (state.private_derived_state.includes(property.name)) { - e.constant_assignment(node, 'derived state'); - } - } } /** diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/AssignmentExpression.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/AssignmentExpression.js index 288f2d0cfa..2ec5127eec 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/AssignmentExpression.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/AssignmentExpression.js @@ -46,7 +46,7 @@ function build_assignment(operator, left, right, context) { if (should_proxy(value, context.state.scope)) { transformed = true; value = - private_state.kind === 'raw_state' + private_state.kind === 'raw_state' || private_state.kind === 'derived' ? value : build_proxy_reassignment(value, private_state.id); } diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/AssignmentExpression.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/AssignmentExpression.js index 2988c590fd..451ed14162 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/AssignmentExpression.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/AssignmentExpression.js @@ -24,6 +24,23 @@ export function AssignmentExpression(node, context) { function build_assignment(operator, left, right, context) { let object = left; + if ( + context.state.analysis.runes && + left.type === 'MemberExpression' && + left.object.type === 'ThisExpression' && + left.property.type === 'PrivateIdentifier' + ) { + const field = context.state.private_derived.get(left.property.name); + + if (field) { + return b.assignment( + operator, + left, + b.call('$.once', b.thunk(/** @type {Expression} */ (context.visit(right)))) + ); + } + } + while (object.type === 'MemberExpression') { // @ts-expect-error object = object.object; diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/ClassBody.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/ClassBody.js index 365084a284..4e9d35531e 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/ClassBody.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/ClassBody.js @@ -97,17 +97,6 @@ export function ClassBody(node, context) { // get foo() { return this.#foo; } body.push(b.method('get', definition.key, [], [b.return(b.call(member))])); - - if (dev && (field.kind === 'derived' || field.kind === 'derived_by')) { - body.push( - b.method( - 'set', - definition.key, - [b.id('_')], - [b.throw_error(`Cannot update a derived property ('${name}')`)] - ) - ); - } } continue; diff --git a/packages/svelte/tests/compiler-errors/samples/runes-no-derived-state-field-assignment/_config.js b/packages/svelte/tests/compiler-errors/samples/runes-no-derived-state-field-assignment/_config.js deleted file mode 100644 index 94985a9939..0000000000 --- a/packages/svelte/tests/compiler-errors/samples/runes-no-derived-state-field-assignment/_config.js +++ /dev/null @@ -1,8 +0,0 @@ -import { test } from '../../test'; - -export default test({ - error: { - code: 'constant_assignment', - message: 'Cannot assign to derived state' - } -}); diff --git a/packages/svelte/tests/compiler-errors/samples/runes-no-derived-state-field-assignment/main.svelte b/packages/svelte/tests/compiler-errors/samples/runes-no-derived-state-field-assignment/main.svelte deleted file mode 100644 index d44806757e..0000000000 --- a/packages/svelte/tests/compiler-errors/samples/runes-no-derived-state-field-assignment/main.svelte +++ /dev/null @@ -1,10 +0,0 @@ - diff --git a/packages/svelte/tests/compiler-errors/samples/runes-no-derived-state-field-update/_config.js b/packages/svelte/tests/compiler-errors/samples/runes-no-derived-state-field-update/_config.js deleted file mode 100644 index 94985a9939..0000000000 --- a/packages/svelte/tests/compiler-errors/samples/runes-no-derived-state-field-update/_config.js +++ /dev/null @@ -1,8 +0,0 @@ -import { test } from '../../test'; - -export default test({ - error: { - code: 'constant_assignment', - message: 'Cannot assign to derived state' - } -}); diff --git a/packages/svelte/tests/compiler-errors/samples/runes-no-derived-state-field-update/main.svelte b/packages/svelte/tests/compiler-errors/samples/runes-no-derived-state-field-update/main.svelte deleted file mode 100644 index e4ee2e8635..0000000000 --- a/packages/svelte/tests/compiler-errors/samples/runes-no-derived-state-field-update/main.svelte +++ /dev/null @@ -1,10 +0,0 @@ -