|
|
@ -1,7 +1,6 @@
|
|
|
|
/** @import { CallExpression, ClassBody, MethodDefinition, PrivateIdentifier, PropertyDefinition, StaticBlock } from 'estree' */
|
|
|
|
/** @import { CallExpression, ClassBody, MethodDefinition, PropertyDefinition, StaticBlock } from 'estree' */
|
|
|
|
/** @import { Context } from '../types.js' */
|
|
|
|
/** @import { Context } from '../types.js' */
|
|
|
|
import * as b from '#compiler/builders';
|
|
|
|
import * as b from '#compiler/builders';
|
|
|
|
import { regex_invalid_identifier_chars } from '../../../patterns.js';
|
|
|
|
|
|
|
|
import { get_name } from '../../../nodes.js';
|
|
|
|
import { get_name } from '../../../nodes.js';
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
@ -17,42 +16,10 @@ export function ClassBody(node, context) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** @type {string[]} */
|
|
|
|
|
|
|
|
const private_ids = [];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (const prop of node.body) {
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
|
|
|
(prop.type === 'MethodDefinition' || prop.type === 'PropertyDefinition') &&
|
|
|
|
|
|
|
|
prop.key.type === 'PrivateIdentifier'
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
private_ids.push(prop.key.name);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* each `foo = $state()` needs a backing `#foo` field
|
|
|
|
|
|
|
|
* @type {Record<string, PrivateIdentifier>}
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
const backing_fields = {};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (const name in state_fields) {
|
|
|
|
|
|
|
|
if (name[0] === '#') {
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let deconflicted = name.replace(regex_invalid_identifier_chars, '_');
|
|
|
|
|
|
|
|
while (private_ids.includes(deconflicted)) {
|
|
|
|
|
|
|
|
deconflicted = '_' + deconflicted;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private_ids.push(deconflicted);
|
|
|
|
|
|
|
|
backing_fields[name] = b.private_id(deconflicted);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** @type {Array<MethodDefinition | PropertyDefinition | StaticBlock>} */
|
|
|
|
/** @type {Array<MethodDefinition | PropertyDefinition | StaticBlock>} */
|
|
|
|
const body = [];
|
|
|
|
const body = [];
|
|
|
|
|
|
|
|
|
|
|
|
const child_state = { ...context.state, state_fields, backing_fields };
|
|
|
|
const child_state = { ...context.state, state_fields };
|
|
|
|
|
|
|
|
|
|
|
|
for (const name in state_fields) {
|
|
|
|
for (const name in state_fields) {
|
|
|
|
if (name[0] === '#') {
|
|
|
|
if (name[0] === '#') {
|
|
|
@ -66,11 +33,10 @@ export function ClassBody(node, context) {
|
|
|
|
field.node.type === 'AssignmentExpression' &&
|
|
|
|
field.node.type === 'AssignmentExpression' &&
|
|
|
|
(field.type === '$derived' || field.type === '$derived.by')
|
|
|
|
(field.type === '$derived' || field.type === '$derived.by')
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
const backing = backing_fields[name];
|
|
|
|
const member = b.member(b.this, field.key);
|
|
|
|
const member = b.member(b.this, backing);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
body.push(
|
|
|
|
body.push(
|
|
|
|
b.prop_def(backing, null),
|
|
|
|
b.prop_def(field.key, null),
|
|
|
|
b.method('get', b.key(name), [], [b.return(b.call(member))])
|
|
|
|
b.method('get', b.key(name), [], [b.return(b.call(member))])
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -100,12 +66,11 @@ export function ClassBody(node, context) {
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const backing = backing_fields[name];
|
|
|
|
const member = b.member(b.this, field.key);
|
|
|
|
const member = b.member(b.this, backing);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
body.push(
|
|
|
|
body.push(
|
|
|
|
b.prop_def(
|
|
|
|
b.prop_def(
|
|
|
|
backing,
|
|
|
|
field.key,
|
|
|
|
/** @type {CallExpression} */ (
|
|
|
|
/** @type {CallExpression} */ (
|
|
|
|
context.visit(definition.value ?? field.value, child_state)
|
|
|
|
context.visit(definition.value ?? field.value, child_state)
|
|
|
|
)
|
|
|
|
)
|
|
|
|