diff --git a/packages/svelte/src/compiler/phases/3-transform/client/types.d.ts b/packages/svelte/src/compiler/phases/3-transform/client/types.d.ts index 0db7be1fe1..763b6773c7 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/types.d.ts +++ b/packages/svelte/src/compiler/phases/3-transform/client/types.d.ts @@ -15,9 +15,6 @@ import type { ComponentAnalysis } from '../../types.js'; import type { SourceLocation } from '#shared'; export interface ClientTransformState extends TransformState { - readonly state_fields: Record; - readonly backing_fields: Record; - /** * `true` if the current lexical scope belongs to a class constructor. this allows * us to rewrite `this.foo` as `this.#foo.value` 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 1d2cf585a6..294faa43dd 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 @@ -55,46 +55,48 @@ function build_assignment(operator, left, right, context) { if (context.state.analysis.runes && left.type === 'MemberExpression') { const name = get_name(left.property); - // special case — state declaration in class constructor - const ancestor = context.path.at(-4); - - if (ancestor?.type === 'MethodDefinition' && ancestor.kind === 'constructor') { - const rune = get_rune(right, context.state.scope); - - if (rune) { - const child_state = { - ...context.state, - in_constructor: rune !== '$derived' && rune !== '$derived.by' - }; - - const l = b.member( - b.this, - left.property.type === 'PrivateIdentifier' - ? left.property - : context.state.backing_fields[name] - ); + if (name !== null) { + // special case — state declaration in class constructor + const ancestor = context.path.at(-4); + + if (ancestor?.type === 'MethodDefinition' && ancestor.kind === 'constructor') { + const rune = get_rune(right, context.state.scope); + + if (rune) { + const child_state = { + ...context.state, + in_constructor: rune !== '$derived' && rune !== '$derived.by' + }; + + const l = b.member( + b.this, + left.property.type === 'PrivateIdentifier' + ? left.property + : context.state.backing_fields[name] + ); - const r = /** @type {Expression} */ (context.visit(right, child_state)); + const r = /** @type {Expression} */ (context.visit(right, child_state)); - return b.assignment(operator, l, r); + return b.assignment(operator, l, r); + } } - } - // special case — assignment to private state field - if (left.property.type === 'PrivateIdentifier') { - const field = context.state.state_fields[name]; + // special case — assignment to private state field + if (left.property.type === 'PrivateIdentifier') { + const field = context.state.state_fields[name]; - if (field) { - let value = /** @type {Expression} */ ( - context.visit(build_assignment_value(operator, left, right)) - ); + if (field) { + let value = /** @type {Expression} */ ( + context.visit(build_assignment_value(operator, left, right)) + ); - const needs_proxy = - field.type === '$state' && - is_non_coercive_operator(operator) && - should_proxy(value, context.state.scope); + const needs_proxy = + field.type === '$state' && + is_non_coercive_operator(operator) && + should_proxy(value, context.state.scope); - return b.call('$.set', left, value, needs_proxy && b.true); + return b.call('$.set', left, value, needs_proxy && b.true); + } } } } diff --git a/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js b/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js index e7896991d9..ef4e1577d3 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js @@ -23,7 +23,6 @@ import { Identifier } from './visitors/Identifier.js'; import { IfBlock } from './visitors/IfBlock.js'; import { KeyBlock } from './visitors/KeyBlock.js'; import { LabeledStatement } from './visitors/LabeledStatement.js'; -import { MemberExpression } from './visitors/MemberExpression.js'; import { PropertyDefinition } from './visitors/PropertyDefinition.js'; import { RegularElement } from './visitors/RegularElement.js'; import { RenderTag } from './visitors/RenderTag.js'; @@ -49,7 +48,6 @@ const global_visitors = { ExpressionStatement, Identifier, LabeledStatement, - MemberExpression, PropertyDefinition, UpdateExpression, VariableDeclaration @@ -99,7 +97,8 @@ export function server_component(analysis, options) { template: /** @type {any} */ (null), namespace: options.namespace, preserve_whitespace: options.preserveWhitespace, - private_derived: new Map(), + state_fields: {}, + backing_fields: {}, skip_hydration_boundaries: false }; @@ -395,7 +394,8 @@ export function server_module(analysis, options) { // to be present for `javascript_visitors_legacy` and so is included in module // transform state as well as component transform state legacy_reactive_statements: new Map(), - private_derived: new Map() + state_fields: {}, + backing_fields: {} }; const module = /** @type {Program} */ ( diff --git a/packages/svelte/src/compiler/phases/3-transform/server/types.d.ts b/packages/svelte/src/compiler/phases/3-transform/server/types.d.ts index 971271642c..adde7480cb 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/types.d.ts +++ b/packages/svelte/src/compiler/phases/3-transform/server/types.d.ts @@ -2,12 +2,10 @@ import type { Expression, Statement, ModuleDeclaration, LabeledStatement } from import type { AST, Namespace, ValidatedCompileOptions } from '#compiler'; import type { TransformState } from '../types.js'; import type { ComponentAnalysis } from '../../types.js'; -import type { StateField } from '../client/types.js'; export interface ServerTransformState extends TransformState { /** The $: calls, which will be ordered in the end */ readonly legacy_reactive_statements: Map; - readonly private_derived: Map; } export interface ComponentServerTransformState extends ServerTransformState { 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 defcf13672..abb073a7d2 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 @@ -25,24 +25,27 @@ export function AssignmentExpression(node, context) { */ function build_assignment(operator, left, right, context) { if (context.state.analysis.runes && left.type === 'MemberExpression') { - // special case — state declaration in class constructor - const ancestor = context.path.at(-4); + const name = get_name(left.property); - if (ancestor?.type === 'MethodDefinition' && ancestor.kind === 'constructor') { - const rune = get_rune(right, context.state.scope); + if (name !== null) { + // special case — state declaration in class constructor + const ancestor = context.path.at(-4); - if (rune) { - const name = get_name(left.property); - const key = - left.property.type === 'PrivateIdentifier' || rune === '$state' || rune === '$state.raw' - ? left.property - : context.state.backing_fields[name]; + if (ancestor?.type === 'MethodDefinition' && ancestor.kind === 'constructor') { + const rune = get_rune(right, context.state.scope); - const l = b.member(b.this, key, key.type === 'Literal'); + if (rune) { + const key = + left.property.type === 'PrivateIdentifier' || rune === '$state' || rune === '$state.raw' + ? left.property + : context.state.backing_fields[name]; - const r = /** @type {Expression} */ (context.visit(right)); + const l = b.member(b.this, key, key.type === 'Literal'); - return b.assignment(operator, l, r); + const r = /** @type {Expression} */ (context.visit(right)); + + return b.assignment(operator, l, r); + } } } } 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 09bfd2585f..03e058ea0f 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 @@ -69,14 +69,9 @@ export function ClassBody(node, context) { const backing = backing_fields[name]; const member = b.member(b.this, backing); - const should_proxy = field.type === '$state' && true; // TODO - - const key = b.key(name); - body.push( b.prop_def(backing, null), - - b.method('get', key, [], [b.return(b.call(member))]) + b.method('get', b.key(name), [], [b.return(b.call(member))]) ); } } @@ -108,8 +103,6 @@ export function ClassBody(node, context) { const backing = backing_fields[name]; const member = b.member(b.this, backing); - const should_proxy = field.type === '$state' && true; // TODO - body.push( b.prop_def( backing, diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/MemberExpression.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/MemberExpression.js deleted file mode 100644 index 73631395e6..0000000000 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/MemberExpression.js +++ /dev/null @@ -1,23 +0,0 @@ -/** @import { MemberExpression } from 'estree' */ -/** @import { Context } from '../types.js' */ -import * as b from '#compiler/builders'; - -/** - * @param {MemberExpression} node - * @param {Context} context - */ -export function MemberExpression(node, context) { - if ( - context.state.analysis.runes && - node.object.type === 'ThisExpression' && - node.property.type === 'PrivateIdentifier' - ) { - const field = context.state.private_derived.get(node.property.name); - - if (field) { - return b.call(node); - } - } - - context.next(); -} diff --git a/packages/svelte/src/compiler/phases/3-transform/types.d.ts b/packages/svelte/src/compiler/phases/3-transform/types.d.ts index 5d860207dd..cb866abef1 100644 --- a/packages/svelte/src/compiler/phases/3-transform/types.d.ts +++ b/packages/svelte/src/compiler/phases/3-transform/types.d.ts @@ -1,10 +1,14 @@ import type { Scope } from '../scope.js'; -import type { AST, ValidatedModuleCompileOptions } from '#compiler'; +import type { AST, StateField, ValidatedModuleCompileOptions } from '#compiler'; import type { Analysis } from '../types.js'; +import type { PrivateIdentifier } from 'estree'; export interface TransformState { readonly analysis: Analysis; readonly options: ValidatedModuleCompileOptions; readonly scope: Scope; readonly scopes: Map; + + readonly state_fields: Record; + readonly backing_fields: Record; }