Skip to content

Commit a6cc07c

Browse files
committed
simplify/DRY
1 parent 90e7e0d commit a6cc07c

File tree

9 files changed

+57
-94
lines changed

9 files changed

+57
-94
lines changed

packages/svelte/src/compiler/phases/2-analyze/visitors/ClassBody.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
/** @import { AssignmentExpression, CallExpression, ClassBody, PropertyDefinition, Expression, PrivateIdentifier, MethodDefinition } from 'estree' */
22
/** @import { StateField } from '#compiler' */
33
/** @import { Context } from '../types' */
4+
import * as b from '#compiler/builders';
45
import { get_rune } from '../../scope.js';
56
import * as e from '../../../errors.js';
67
import { is_state_creation_rune } from '../../../../utils.js';
78
import { get_name } from '../../nodes.js';
9+
import { regex_invalid_identifier_chars } from '../../patterns.js';
810

911
/**
1012
* @param {ClassBody} node
@@ -16,6 +18,18 @@ export function ClassBody(node, context) {
1618
return;
1719
}
1820

21+
/** @type {string[]} */
22+
const private_ids = [];
23+
24+
for (const prop of node.body) {
25+
if (
26+
(prop.type === 'MethodDefinition' || prop.type === 'PropertyDefinition') &&
27+
prop.key.type === 'PrivateIdentifier'
28+
) {
29+
private_ids.push(prop.key.name);
30+
}
31+
}
32+
1933
/** @type {Record<string, StateField>} */
2034
const state_fields = {};
2135

@@ -46,6 +60,8 @@ export function ClassBody(node, context) {
4660
state_fields[name] = {
4761
node,
4862
type: rune,
63+
// @ts-expect-error for public state this is filled out in a moment
64+
key: key.type === 'PrivateIdentifier' ? key : null,
4965
value: /** @type {CallExpression} */ (value)
5066
};
5167
}
@@ -84,6 +100,22 @@ export function ClassBody(node, context) {
84100
}
85101
}
86102

103+
for (const name in state_fields) {
104+
if (name[0] === '#') {
105+
continue;
106+
}
107+
108+
const field = state_fields[name];
109+
110+
let deconflicted = name.replace(regex_invalid_identifier_chars, '_');
111+
while (private_ids.includes(deconflicted)) {
112+
deconflicted = '_' + deconflicted;
113+
}
114+
115+
private_ids.push(deconflicted);
116+
field.key = b.private_id(deconflicted);
117+
}
118+
87119
context.next({
88120
...context.state,
89121
state_fields

packages/svelte/src/compiler/phases/3-transform/client/transform-client.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,6 @@ export function client_component(analysis, options) {
164164
events: new Set(),
165165
preserve_whitespace: options.preserveWhitespace,
166166
state_fields: {},
167-
backing_fields: {},
168167
transform: {},
169168
in_constructor: false,
170169
instance_level_snippets: [],
@@ -672,7 +671,6 @@ export function client_module(analysis, options) {
672671
scope: analysis.module.scope,
673672
scopes: analysis.module.scopes,
674673
state_fields: {},
675-
backing_fields: {},
676674
transform: {},
677675
in_constructor: false
678676
};

packages/svelte/src/compiler/phases/3-transform/client/visitors/AssignmentExpression.js

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,9 @@ function build_assignment(operator, left, right, context) {
6868
in_constructor: rune !== '$derived' && rune !== '$derived.by'
6969
};
7070

71-
const l = b.member(
72-
b.this,
73-
left.property.type === 'PrivateIdentifier'
74-
? left.property
75-
: context.state.backing_fields[name]
76-
);
71+
const field = context.state.state_fields[name];
72+
73+
const l = b.member(b.this, field.key);
7774

7875
const r = /** @type {Expression} */ (context.visit(right, child_state));
7976

packages/svelte/src/compiler/phases/3-transform/client/visitors/ClassBody.js

Lines changed: 5 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -17,42 +17,10 @@ export function ClassBody(node, context) {
1717
return;
1818
}
1919

20-
/** @type {string[]} */
21-
const private_ids = [];
22-
23-
for (const prop of node.body) {
24-
if (
25-
(prop.type === 'MethodDefinition' || prop.type === 'PropertyDefinition') &&
26-
prop.key.type === 'PrivateIdentifier'
27-
) {
28-
private_ids.push(prop.key.name);
29-
}
30-
}
31-
32-
/**
33-
* each `foo = $state()` needs a backing `#foo` field
34-
* @type {Record<string, PrivateIdentifier>}
35-
*/
36-
const backing_fields = {};
37-
38-
for (const name in state_fields) {
39-
if (name[0] === '#') {
40-
continue;
41-
}
42-
43-
let deconflicted = name.replace(regex_invalid_identifier_chars, '_');
44-
while (private_ids.includes(deconflicted)) {
45-
deconflicted = '_' + deconflicted;
46-
}
47-
48-
private_ids.push(deconflicted);
49-
backing_fields[name] = b.private_id(deconflicted);
50-
}
51-
5220
/** @type {Array<MethodDefinition | PropertyDefinition | StaticBlock>} */
5321
const body = [];
5422

55-
const child_state = { ...context.state, state_fields, backing_fields };
23+
const child_state = { ...context.state, state_fields };
5624

5725
for (const name in state_fields) {
5826
if (name[0] === '#') {
@@ -63,15 +31,14 @@ export function ClassBody(node, context) {
6331

6432
// insert backing fields for stuff declared in the constructor
6533
if (field.node.type === 'AssignmentExpression') {
66-
const backing = backing_fields[name];
67-
const member = b.member(b.this, backing);
34+
const member = b.member(b.this, field.key);
6835

6936
const should_proxy = field.type === '$state' && true; // TODO
7037

7138
const key = b.key(name);
7239

7340
body.push(
74-
b.prop_def(backing, null),
41+
b.prop_def(field.key, null),
7542

7643
b.method('get', key, [], [b.return(b.call('$.get', member))]),
7744

@@ -109,14 +76,13 @@ export function ClassBody(node, context) {
10976
continue;
11077
}
11178

112-
const backing = backing_fields[name];
113-
const member = b.member(b.this, backing);
79+
const member = b.member(b.this, field.key);
11480

11581
const should_proxy = field.type === '$state' && true; // TODO
11682

11783
body.push(
11884
b.prop_def(
119-
backing,
85+
field.key,
12086
/** @type {CallExpression} */ (
12187
context.visit(definition.value ?? field.value, child_state)
12288
)

packages/svelte/src/compiler/phases/3-transform/server/transform-server.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ export function server_component(analysis, options) {
9898
namespace: options.namespace,
9999
preserve_whitespace: options.preserveWhitespace,
100100
state_fields: {},
101-
backing_fields: {},
102101
skip_hydration_boundaries: false
103102
};
104103

@@ -394,8 +393,7 @@ export function server_module(analysis, options) {
394393
// to be present for `javascript_visitors_legacy` and so is included in module
395394
// transform state as well as component transform state
396395
legacy_reactive_statements: new Map(),
397-
state_fields: {},
398-
backing_fields: {}
396+
state_fields: {}
399397
};
400398

401399
const module = /** @type {Program} */ (

packages/svelte/src/compiler/phases/3-transform/server/visitors/AssignmentExpression.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,12 @@ function build_assignment(operator, left, right, context) {
3535
const rune = get_rune(right, context.state.scope);
3636

3737
if (rune) {
38+
const field = context.state.state_fields[name];
39+
3840
const key =
3941
left.property.type === 'PrivateIdentifier' || rune === '$state' || rune === '$state.raw'
4042
? left.property
41-
: context.state.backing_fields[name];
43+
: field.key;
4244

4345
const l = b.member(b.this, key, key.type === 'Literal');
4446

packages/svelte/src/compiler/phases/3-transform/server/visitors/ClassBody.js

Lines changed: 6 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
/** @import { CallExpression, ClassBody, MethodDefinition, PrivateIdentifier, PropertyDefinition, StaticBlock } from 'estree' */
1+
/** @import { CallExpression, ClassBody, MethodDefinition, PropertyDefinition, StaticBlock } from 'estree' */
22
/** @import { Context } from '../types.js' */
33
import * as b from '#compiler/builders';
4-
import { regex_invalid_identifier_chars } from '../../../patterns.js';
54
import { get_name } from '../../../nodes.js';
65

76
/**
@@ -17,42 +16,10 @@ export function ClassBody(node, context) {
1716
return;
1817
}
1918

20-
/** @type {string[]} */
21-
const private_ids = [];
22-
23-
for (const prop of node.body) {
24-
if (
25-
(prop.type === 'MethodDefinition' || prop.type === 'PropertyDefinition') &&
26-
prop.key.type === 'PrivateIdentifier'
27-
) {
28-
private_ids.push(prop.key.name);
29-
}
30-
}
31-
32-
/**
33-
* each `foo = $state()` needs a backing `#foo` field
34-
* @type {Record<string, PrivateIdentifier>}
35-
*/
36-
const backing_fields = {};
37-
38-
for (const name in state_fields) {
39-
if (name[0] === '#') {
40-
continue;
41-
}
42-
43-
let deconflicted = name.replace(regex_invalid_identifier_chars, '_');
44-
while (private_ids.includes(deconflicted)) {
45-
deconflicted = '_' + deconflicted;
46-
}
47-
48-
private_ids.push(deconflicted);
49-
backing_fields[name] = b.private_id(deconflicted);
50-
}
51-
5219
/** @type {Array<MethodDefinition | PropertyDefinition | StaticBlock>} */
5320
const body = [];
5421

55-
const child_state = { ...context.state, state_fields, backing_fields };
22+
const child_state = { ...context.state, state_fields };
5623

5724
for (const name in state_fields) {
5825
if (name[0] === '#') {
@@ -66,11 +33,10 @@ export function ClassBody(node, context) {
6633
field.node.type === 'AssignmentExpression' &&
6734
(field.type === '$derived' || field.type === '$derived.by')
6835
) {
69-
const backing = backing_fields[name];
70-
const member = b.member(b.this, backing);
36+
const member = b.member(b.this, field.key);
7137

7238
body.push(
73-
b.prop_def(backing, null),
39+
b.prop_def(field.key, null),
7440
b.method('get', b.key(name), [], [b.return(b.call(member))])
7541
);
7642
}
@@ -100,12 +66,11 @@ export function ClassBody(node, context) {
10066
continue;
10167
}
10268

103-
const backing = backing_fields[name];
104-
const member = b.member(b.this, backing);
69+
const member = b.member(b.this, field.key);
10570

10671
body.push(
10772
b.prop_def(
108-
backing,
73+
field.key,
10974
/** @type {CallExpression} */ (
11075
context.visit(definition.value ?? field.value, child_state)
11176
)

packages/svelte/src/compiler/phases/3-transform/types.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,4 @@ export interface TransformState {
1010
readonly scopes: Map<AST.SvelteNode, Scope>;
1111

1212
readonly state_fields: Record<string, StateField>;
13-
readonly backing_fields: Record<string, PrivateIdentifier>;
1413
}

packages/svelte/src/compiler/types/index.d.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@ import type { Binding } from '../phases/scope.js';
33
import type { AST, Namespace } from './template.js';
44
import type { ICompileDiagnostic } from '../utils/compile_diagnostic.js';
55
import type { StateCreationRuneName } from '../../utils.js';
6-
import type { AssignmentExpression, CallExpression, PropertyDefinition } from 'estree';
6+
import type {
7+
AssignmentExpression,
8+
CallExpression,
9+
PrivateIdentifier,
10+
PropertyDefinition
11+
} from 'estree';
712

813
/** The return value of `compile` from `svelte/compiler` */
914
export interface CompileResult {
@@ -274,6 +279,7 @@ export interface ExpressionMetadata {
274279
export interface StateField {
275280
type: StateCreationRuneName;
276281
node: PropertyDefinition | AssignmentExpression;
282+
key: PrivateIdentifier;
277283
value: CallExpression;
278284
}
279285

0 commit comments

Comments
 (0)