Skip to content

Commit 99d3a06

Browse files
committed
simplify
1 parent c7475d6 commit 99d3a06

File tree

1 file changed

+125
-145
lines changed

1 file changed

+125
-145
lines changed

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

Lines changed: 125 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -18,60 +18,49 @@ export const javascript_visitors_runes = {
1818
/** @type {string[]} */
1919
const private_ids = [];
2020

21-
/**
22-
*
23-
* @param {import("estree").PropertyDefinition} definition
24-
* @param {boolean} is_private
25-
* @param {string} name
26-
*/
27-
function create_state_field(definition, is_private, name) {
28-
if (definition.value?.type === 'CallExpression') {
29-
const rune = get_rune(definition.value, state.scope);
30-
if (
31-
rune === '$state' ||
32-
rune === '$state.frozen' ||
33-
rune === '$derived' ||
34-
rune === '$derived.by'
35-
) {
36-
/** @type {import('../types.js').StateField} */
37-
const field = {
38-
kind:
39-
rune === '$state'
40-
? 'state'
41-
: rune === '$state.frozen'
42-
? 'frozen_state'
43-
: rune === '$derived.by'
44-
? 'derived_call'
45-
: 'derived',
46-
// @ts-expect-error this is set in the next pass
47-
id: is_private ? definition.key : null
48-
};
49-
50-
if (is_private) {
51-
private_state.set(name, field);
52-
} else {
53-
public_state.set(name, field);
54-
}
55-
}
56-
}
57-
}
58-
5921
for (const definition of node.body) {
6022
if (
6123
definition.type === 'PropertyDefinition' &&
62-
(definition.key.type === 'Identifier' || definition.key.type === 'PrivateIdentifier')
24+
(definition.key.type === 'Identifier' ||
25+
definition.key.type === 'PrivateIdentifier' ||
26+
definition.key.type === 'Literal')
6327
) {
64-
const { type, name } = definition.key;
28+
const type = definition.key.type;
29+
const name = get_name(definition.key);
30+
if (!name) continue;
6531

6632
const is_private = type === 'PrivateIdentifier';
6733
if (is_private) private_ids.push(name);
6834

69-
create_state_field(definition, is_private, name);
70-
} else if (definition.type === 'PropertyDefinition' && definition.key.type === 'Literal') {
71-
const name = definition.key.value
72-
?.toString()
73-
.replaceAll(regex_invalid_identifier_chars, '_');
74-
if (name) create_state_field(definition, false, name);
35+
if (definition.value?.type === 'CallExpression') {
36+
const rune = get_rune(definition.value, state.scope);
37+
if (
38+
rune === '$state' ||
39+
rune === '$state.frozen' ||
40+
rune === '$derived' ||
41+
rune === '$derived.by'
42+
) {
43+
/** @type {import('../types.js').StateField} */
44+
const field = {
45+
kind:
46+
rune === '$state'
47+
? 'state'
48+
: rune === '$state.frozen'
49+
? 'frozen_state'
50+
: rune === '$derived.by'
51+
? 'derived_call'
52+
: 'derived',
53+
// @ts-expect-error this is set in the next pass
54+
id: is_private ? definition.key : null
55+
};
56+
57+
if (is_private) {
58+
private_state.set(name, field);
59+
} else {
60+
public_state.set(name, field);
61+
}
62+
}
63+
}
7564
}
7665
}
7766

@@ -91,114 +80,94 @@ export const javascript_visitors_runes = {
9180

9281
const child_state = { ...state, public_state, private_state };
9382

94-
/**
95-
*
96-
* @param {import("estree").PropertyDefinition} definition
97-
* @param {boolean} is_private
98-
* @param {string} name
99-
*/
100-
function replace_class_body(definition, is_private, name) {
101-
const field = (is_private ? private_state : public_state).get(name);
102-
103-
if (definition.value?.type === 'CallExpression' && field !== undefined) {
104-
let value = null;
105-
106-
if (definition.value.arguments.length > 0) {
107-
const init = /** @type {import('estree').Expression} **/ (
108-
visit(definition.value.arguments[0], child_state)
109-
);
110-
111-
value =
112-
field.kind === 'state'
113-
? b.call(
114-
'$.source',
115-
should_proxy_or_freeze(init, state.scope) ? b.call('$.proxy', init) : init
116-
)
117-
: field.kind === 'frozen_state'
118-
? b.call(
119-
'$.source',
120-
should_proxy_or_freeze(init, state.scope) ? b.call('$.freeze', init) : init
121-
)
122-
: field.kind === 'derived_call'
123-
? b.call('$.derived', init)
124-
: b.call('$.derived', b.thunk(init));
125-
} else {
126-
// if no arguments, we know it's state as `$derived()` is a compile error
127-
value = b.call('$.source');
128-
}
129-
130-
if (is_private) {
131-
body.push(b.prop_def(field.id, value));
132-
} else {
133-
// #foo;
134-
const member = b.member(b.this, field.id);
135-
body.push(b.prop_def(field.id, value));
136-
137-
// get foo() { return this.#foo; }
138-
body.push(b.method('get', definition.key, [], [b.return(b.call('$.get', member))]));
139-
140-
if (field.kind === 'state') {
141-
// set foo(value) { this.#foo = value; }
142-
const value = b.id('value');
143-
body.push(
144-
b.method(
145-
'set',
146-
definition.key,
147-
[value],
148-
[b.stmt(b.call('$.set', member, b.call('$.proxy', value)))]
149-
)
150-
);
151-
}
152-
153-
if (field.kind === 'frozen_state') {
154-
// set foo(value) { this.#foo = value; }
155-
const value = b.id('value');
156-
body.push(
157-
b.method(
158-
'set',
159-
definition.key,
160-
[value],
161-
[b.stmt(b.call('$.set', member, b.call('$.freeze', value)))]
162-
)
163-
);
164-
}
165-
166-
if ((field.kind === 'derived' || field.kind === 'derived_call') && state.options.dev) {
167-
body.push(
168-
b.method(
169-
'set',
170-
definition.key,
171-
[b.id('_')],
172-
[b.throw_error(`Cannot update a derived property ('${name}')`)]
173-
)
174-
);
175-
}
176-
}
177-
178-
return true;
179-
}
180-
return false;
181-
}
182-
18383
// Replace parts of the class body
18484
for (const definition of node.body) {
18585
if (
18686
definition.type === 'PropertyDefinition' &&
187-
(definition.key.type === 'Identifier' || definition.key.type === 'PrivateIdentifier')
87+
(definition.key.type === 'Identifier' ||
88+
definition.key.type === 'PrivateIdentifier' ||
89+
definition.key.type === 'Literal')
18890
) {
189-
const name = definition.key.name;
91+
const name = get_name(definition.key);
92+
if (!name) continue;
19093

19194
const is_private = definition.key.type === 'PrivateIdentifier';
95+
const field = (is_private ? private_state : public_state).get(name);
19296

193-
if (replace_class_body(definition, is_private, name)) {
194-
continue;
195-
}
196-
} else if (definition.type === 'PropertyDefinition' && definition.key.type === 'Literal') {
197-
const name = definition.key.value
198-
?.toString()
199-
.replaceAll(regex_invalid_identifier_chars, '_');
97+
if (definition.value?.type === 'CallExpression' && field !== undefined) {
98+
let value = null;
99+
100+
if (definition.value.arguments.length > 0) {
101+
const init = /** @type {import('estree').Expression} **/ (
102+
visit(definition.value.arguments[0], child_state)
103+
);
104+
105+
value =
106+
field.kind === 'state'
107+
? b.call(
108+
'$.source',
109+
should_proxy_or_freeze(init, state.scope) ? b.call('$.proxy', init) : init
110+
)
111+
: field.kind === 'frozen_state'
112+
? b.call(
113+
'$.source',
114+
should_proxy_or_freeze(init, state.scope) ? b.call('$.freeze', init) : init
115+
)
116+
: field.kind === 'derived_call'
117+
? b.call('$.derived', init)
118+
: b.call('$.derived', b.thunk(init));
119+
} else {
120+
// if no arguments, we know it's state as `$derived()` is a compile error
121+
value = b.call('$.source');
122+
}
200123

201-
if (name && replace_class_body(definition, false, name)) {
124+
if (is_private) {
125+
body.push(b.prop_def(field.id, value));
126+
} else {
127+
// #foo;
128+
const member = b.member(b.this, field.id);
129+
body.push(b.prop_def(field.id, value));
130+
131+
// get foo() { return this.#foo; }
132+
body.push(b.method('get', definition.key, [], [b.return(b.call('$.get', member))]));
133+
134+
if (field.kind === 'state') {
135+
// set foo(value) { this.#foo = value; }
136+
const value = b.id('value');
137+
body.push(
138+
b.method(
139+
'set',
140+
definition.key,
141+
[value],
142+
[b.stmt(b.call('$.set', member, b.call('$.proxy', value)))]
143+
)
144+
);
145+
}
146+
147+
if (field.kind === 'frozen_state') {
148+
// set foo(value) { this.#foo = value; }
149+
const value = b.id('value');
150+
body.push(
151+
b.method(
152+
'set',
153+
definition.key,
154+
[value],
155+
[b.stmt(b.call('$.set', member, b.call('$.freeze', value)))]
156+
)
157+
);
158+
}
159+
160+
if ((field.kind === 'derived' || field.kind === 'derived_call') && state.options.dev) {
161+
body.push(
162+
b.method(
163+
'set',
164+
definition.key,
165+
[b.id('_')],
166+
[b.throw_error(`Cannot update a derived property ('${name}')`)]
167+
)
168+
);
169+
}
170+
}
202171
continue;
203172
}
204173
}
@@ -475,3 +444,14 @@ export const javascript_visitors_runes = {
475444
context.next();
476445
}
477446
};
447+
448+
/**
449+
* @param {import('estree').Identifier | import('estree').PrivateIdentifier | import('estree').Literal} node
450+
*/
451+
function get_name(node) {
452+
if (node.type === 'Literal') {
453+
return node.value?.toString().replace(regex_invalid_identifier_chars, '_');
454+
} else {
455+
return node.name;
456+
}
457+
}

0 commit comments

Comments
 (0)