Skip to content

Commit 91b7d1d

Browse files
committed
I was stupid and forgot how this works in POJOs, disregard my last few commits
1 parent 6140fde commit 91b7d1d

File tree

1 file changed

+27
-167
lines changed

1 file changed

+27
-167
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,173 +1,51 @@
1-
/** @import { ObjectExpression, Property, CallExpression, Expression, SpreadElement, Node, Identifier, PrivateIdentifier, Statement } from 'estree' */
1+
/** @import { ObjectExpression, Property, CallExpression, Expression, SpreadElement, Statement } from 'estree' */
22
/** @import { Context } from '../types' */
33
import * as b from '../../../../utils/builders.js';
44
import { get_rune } from '../../../scope.js';
55
import { should_proxy } from '../utils.js';
6-
import { walk } from 'zimmerframe';
76

87
/**
98
* @param {ObjectExpression} node
109
* @param {Context} context
1110
*/
1211
export function ObjectExpression(node, context) {
1312
/**
14-
* @typedef {[string, NonNullable<ReturnType<typeof get_rune>>, '$.state' | '$.derived', Expression, boolean]} ReactiveProperty
13+
* @typedef {[string, NonNullable<ReturnType<typeof get_rune>>]} ReactiveProperty
1514
*/
1615
let has_runes = false;
17-
/**
18-
* @type {Array<{rune: NonNullable<ReturnType<typeof get_rune>>, property: Property & {value: CallExpression}}>}
19-
*/
20-
const reactive_properties = [];
2116
const valid_property_runes = ['$state', '$derived', '$state.raw', '$derived.by'];
17+
/** @type {Statement[]} */
18+
const body = [];
19+
/** @type {Map<Property, ReactiveProperty>} */
20+
const sources = new Map();
21+
let counter = 0;
2222
for (let property of node.properties) {
2323
if (property.type !== 'Property') continue;
2424
const rune = get_rune(property.value, context.state.scope);
2525
if (rune && valid_property_runes.includes(rune)) {
2626
has_runes = true;
27-
reactive_properties.push({
28-
rune,
29-
property: /**@type {Property & {value: CallExpression}} */ (property)
30-
});
27+
const name = context.state.scope.generate(`$$${++counter}`);
28+
const call = rune.match(/^\$state/) ? '$.state' : '$.derived';
29+
/** @type {Expression} */
30+
let value = /** @type {Expression} */ (
31+
context.visit(/** @type {CallExpression} */ (property.value).arguments[0] ?? b.void0)
32+
);
33+
value =
34+
rune === '$derived'
35+
? b.thunk(value)
36+
: rune === '$state' && should_proxy(value, context.state.scope)
37+
? b.call('$.proxy', value)
38+
: value;
39+
/** @type {ReactiveProperty} */
40+
const source = [name, rune];
41+
sources.set(property, source);
42+
body.push(b.let(name, b.call(call, value)));
3143
}
3244
}
3345
if (!has_runes) {
3446
context.next();
3547
return;
3648
}
37-
/** @type {Statement[]} */
38-
const body = [];
39-
/** @type {Map<Property, ReactiveProperty>} */
40-
const sources = new Map();
41-
let has_this_reference = false;
42-
let counter = 0;
43-
/** @type {Statement[]} */
44-
const before = [];
45-
/** @type {Statement[]} */
46-
const after = [];
47-
/** @type {string[]} */
48-
const declarations = [];
49-
/** @type {Map<string, Expression | undefined>} */
50-
const initial_declarations = new Map();
51-
// if a computed property is accessed, we treat it as if all of the object's properties have been accessed
52-
let all_are_referenced = false;
53-
/** @type {Set<any>} */
54-
const is_referenced = new Set();
55-
for (let property of node.properties) {
56-
walk(property, null, {
57-
//@ts-ignore
58-
FunctionExpression() {
59-
return;
60-
},
61-
//@ts-ignore
62-
FunctionDeclaration() {
63-
return;
64-
},
65-
ObjectExpression() {
66-
return;
67-
},
68-
/**
69-
*
70-
* @param {Node} node
71-
* @param {import('zimmerframe').Context<Node, null>} context
72-
*/
73-
ThisExpression(node, context) {
74-
const parent = context.path.at(-1);
75-
if (parent?.type === 'MemberExpression') {
76-
if (parent.computed) {
77-
all_are_referenced = true;
78-
} else {
79-
is_referenced.add(/** @type {Identifier | PrivateIdentifier} */ (parent.property).name);
80-
}
81-
}
82-
},
83-
ClassBody() {
84-
return;
85-
}
86-
});
87-
}
88-
for (let { rune, property } of reactive_properties) {
89-
const name = context.state.scope.generate(`$$${++counter}`);
90-
const call = rune.match(/^\$state/) ? '$.state' : '$.derived';
91-
let references_this = false;
92-
/** @type {Expression} */
93-
let value = /** @type {Expression} */ (context.visit(property.value.arguments[0] ?? b.void0));
94-
value = walk(value, null, {
95-
FunctionExpression() {
96-
return;
97-
},
98-
//@ts-ignore
99-
FunctionDeclaration() {
100-
return;
101-
},
102-
ObjectExpression() {
103-
return;
104-
},
105-
ThisExpression() {
106-
has_this_reference = true;
107-
references_this = true;
108-
return b.id('$$object');
109-
},
110-
ClassBody() {
111-
return;
112-
}
113-
});
114-
value =
115-
rune === '$derived'
116-
? b.thunk(value)
117-
: rune === '$state' && should_proxy(value, context.state.scope)
118-
? b.call('$.proxy', value)
119-
: value;
120-
let key = property.computed
121-
? Symbol()
122-
: property.key.type === 'Literal'
123-
? property.key.value
124-
: /** @type {Identifier} */ (property.key).name;
125-
if (rune.match(/^\$state/) && !(all_are_referenced || is_referenced.has(key))) {
126-
let should_be_declared = false;
127-
walk(value, null, {
128-
CallExpression(node, context) {
129-
should_be_declared = true;
130-
context.stop();
131-
},
132-
MemberExpression(node, context) {
133-
should_be_declared = true;
134-
context.stop();
135-
}
136-
});
137-
if (should_be_declared) {
138-
const value_name = context.state.scope.generate('$$initial');
139-
initial_declarations.set(value_name, value);
140-
value = b.id(value_name);
141-
}
142-
}
143-
/** @type {ReactiveProperty} */
144-
const source = [
145-
name,
146-
rune,
147-
call,
148-
value,
149-
(value.type === 'Identifier' && initial_declarations.has(value.name)) || references_this
150-
];
151-
sources.set(property, source);
152-
if (references_this) {
153-
declarations.push(name);
154-
} else if (source[4]) {
155-
before.push(b.let(name, value));
156-
} else {
157-
before.push(b.let(name, b.call(call, value)));
158-
}
159-
}
160-
if (declarations.length) {
161-
before.push(
162-
b.declaration(
163-
'let',
164-
declarations.map((name) => b.declarator(name))
165-
)
166-
);
167-
}
168-
for (let [name, value] of initial_declarations) {
169-
after.push(b.let(name, value));
170-
}
17149
/** @type {(Property | SpreadElement)[]} */
17250
const properties = [];
17351
for (let property of node.properties) {
@@ -176,17 +54,12 @@ export function ObjectExpression(node, context) {
17654
continue;
17755
}
17856
if (sources.has(property)) {
179-
const [name, rune, call, value, initially_declared] = /** @type {ReactiveProperty} */ (
180-
sources.get(property)
181-
);
182-
let maybe_assign = initially_declared
183-
? b.assignment('??=', b.id(name), b.call(call, value))
184-
: b.id(name);
57+
const [name, rune] = /** @type {ReactiveProperty} */ (sources.get(property));
18558
properties.push(
18659
b.prop(
18760
'get',
18861
/** @type {Expression} */ (context.visit(/**@type {Expression} */ (property.key))),
189-
b.function(null, [], b.block([b.return(b.call('$.get', maybe_assign))])),
62+
b.function(null, [], b.block([b.return(b.call('$.get', b.id(name)))])),
19063
property.computed
19164
),
19265
b.prop(
@@ -197,12 +70,7 @@ export function ObjectExpression(node, context) {
19770
[b.id('$$value')],
19871
b.block([
19972
b.stmt(
200-
b.call(
201-
'$.set',
202-
maybe_assign,
203-
b.id('$$value'),
204-
rune === '$state' ? b.true : undefined
205-
)
73+
b.call('$.set', b.id(name), b.id('$$value'), rune === '$state' ? b.true : undefined)
20674
)
20775
])
20876
),
@@ -213,14 +81,6 @@ export function ObjectExpression(node, context) {
21381
properties.push(/** @type {Property} */ (context.visit(property)));
21482
}
21583
}
216-
if (has_this_reference) {
217-
body.push(...before);
218-
body.push(b.let('$$object', b.object(properties)));
219-
body.push(...after);
220-
body.push(b.return(b.id('$$object')));
221-
} else {
222-
body.push(...before, ...after);
223-
body.push(b.return(b.object(properties)));
224-
}
84+
body.push(b.return(b.object(properties)));
22585
return b.call(b.arrow([], b.block(body)));
22686
}

0 commit comments

Comments
 (0)