Skip to content

Commit f87b3d5

Browse files
committed
more
1 parent 72d7901 commit f87b3d5

File tree

5 files changed

+222
-190
lines changed

5 files changed

+222
-190
lines changed

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

Lines changed: 14 additions & 187 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,27 @@
1-
/** @import { Expression, ExpressionStatement, MethodDefinition, Pattern, Program, Property, PropertyDefinition, Statement, VariableDeclarator } from 'estree' */
2-
/** @import { Binding, Namespace, SvelteNode, ValidatedCompileOptions, ValidatedModuleCompileOptions } from '#compiler' */
1+
/** @import { Expression, ExpressionStatement, Program, Property, Statement, VariableDeclarator } from 'estree' */
2+
/** @import { Namespace, SvelteNode, ValidatedCompileOptions, ValidatedModuleCompileOptions } from '#compiler' */
33
/** @import { ComponentServerTransformState, ComponentVisitors, ServerTransformState, Visitors } from './types.js' */
44
/** @import { Analysis, ComponentAnalysis } from '../../types.js' */
55
/** @import { Scope } from '../../scope.js' */
66
/** @import { StateField } from '../../3-transform/client/types.js' */ // TODO move this type
77
import { walk } from 'zimmerframe';
8-
import { set_scope, get_rune } from '../../scope.js';
9-
import { extract_identifiers, extract_paths, is_expression_async } from '../../../utils/ast.js';
8+
import { set_scope } from '../../scope.js';
9+
import { extract_identifiers } from '../../../utils/ast.js';
1010
import * as b from '../../../utils/builders.js';
1111
import { filename } from '../../../state.js';
1212
import { render_stylesheet } from '../css/index.js';
1313
import { AssignmentExpression } from './visitors/javascript/AssignmentExpression.js';
1414
import { CallExpression } from './visitors/javascript/CallExpression.js';
1515
import { ClassBodyRunes } from './visitors/javascript/ClassBody.js';
16+
import { ExpressionStatementRunes } from './visitors/javascript/ExpressionStatement.js';
1617
import { Identifier } from './visitors/javascript/Identifier.js';
18+
import { MemberExpressionRunes } from './visitors/javascript/MemberExpression.js';
1719
import { UpdateExpression } from './visitors/javascript/UpdateExpression.js';
1820
import { PropertyDefinitionRunes } from './visitors/javascript/PropertyDefinition.js';
21+
import {
22+
VariableDeclarationLegacy,
23+
VariableDeclarationRunes
24+
} from './visitors/javascript/VariableDeclaration.js';
1925
import { AwaitBlock } from './visitors/template/AwaitBlock.js';
2026
import { Component } from './visitors/template/Component.js';
2127
import { ConstTag } from './visitors/template/ConstTag.js';
@@ -38,28 +44,6 @@ import { SvelteHead } from './visitors/template/SvelteHead.js';
3844
import { SvelteSelf } from './visitors/template/SvelteSelf.js';
3945
import { TitleElement } from './visitors/template/TitleElement.js';
4046

41-
/**
42-
* @param {VariableDeclarator} declarator
43-
* @param {Scope} scope
44-
* @param {Expression} value
45-
* @returns {VariableDeclarator[]}
46-
*/
47-
function create_state_declarators(declarator, scope, value) {
48-
if (declarator.id.type === 'Identifier') {
49-
return [b.declarator(declarator.id, value)];
50-
}
51-
52-
const tmp = scope.generate('tmp');
53-
const paths = extract_paths(declarator.id);
54-
return [
55-
b.declarator(b.id(tmp), value), // TODO inject declarator for opts, so we can use it below
56-
...paths.map((path) => {
57-
const value = path.expression?.(b.id(tmp));
58-
return b.declarator(path.node, value);
59-
})
60-
];
61-
}
62-
6347
/** @type {Visitors} */
6448
const global_visitors = {
6549
AssignmentExpression,
@@ -72,171 +56,14 @@ const global_visitors = {
7256
const javascript_visitors_runes = {
7357
ClassBody: ClassBodyRunes,
7458
PropertyDefinition: PropertyDefinitionRunes,
75-
VariableDeclaration(node, { state, visit }) {
76-
const declarations = [];
77-
78-
for (const declarator of node.declarations) {
79-
const init = declarator.init;
80-
const rune = get_rune(init, state.scope);
81-
if (!rune || rune === '$effect.tracking' || rune === '$inspect' || rune === '$effect.root') {
82-
declarations.push(/** @type {VariableDeclarator} */ (visit(declarator)));
83-
continue;
84-
}
85-
86-
if (rune === '$props') {
87-
// remove $bindable() from props declaration
88-
const id = walk(declarator.id, null, {
89-
AssignmentPattern(node) {
90-
if (
91-
node.right.type === 'CallExpression' &&
92-
get_rune(node.right, state.scope) === '$bindable'
93-
) {
94-
const right = node.right.arguments.length
95-
? /** @type {Expression} */ (visit(node.right.arguments[0]))
96-
: b.id('undefined');
97-
return b.assignment_pattern(node.left, right);
98-
}
99-
}
100-
});
101-
declarations.push(b.declarator(id, b.id('$$props')));
102-
continue;
103-
}
104-
105-
const args = /** @type {CallExpression} */ (init).arguments;
106-
const value =
107-
args.length === 0 ? b.id('undefined') : /** @type {Expression} */ (visit(args[0]));
108-
109-
if (rune === '$derived.by') {
110-
declarations.push(
111-
b.declarator(/** @type {Pattern} */ (visit(declarator.id)), b.call(value))
112-
);
113-
continue;
114-
}
115-
116-
if (declarator.id.type === 'Identifier') {
117-
declarations.push(b.declarator(declarator.id, value));
118-
continue;
119-
}
120-
121-
if (rune === '$derived') {
122-
declarations.push(b.declarator(/** @type {Pattern} */ (visit(declarator.id)), value));
123-
continue;
124-
}
125-
126-
declarations.push(...create_state_declarators(declarator, state.scope, value));
127-
}
128-
129-
return {
130-
...node,
131-
declarations
132-
};
133-
},
134-
ExpressionStatement(node, context) {
135-
const expression = node.expression;
136-
if (expression.type === 'CallExpression') {
137-
const callee = expression.callee;
138-
139-
if (callee.type === 'Identifier' && callee.name === '$effect') {
140-
return b.empty;
141-
}
142-
143-
if (
144-
callee.type === 'MemberExpression' &&
145-
callee.object.type === 'Identifier' &&
146-
callee.object.name === '$effect'
147-
) {
148-
return b.empty;
149-
}
150-
}
151-
context.next();
152-
},
153-
MemberExpression(node, context) {
154-
if (node.object.type === 'ThisExpression' && node.property.type === 'PrivateIdentifier') {
155-
const field = context.state.private_derived.get(node.property.name);
156-
if (field) {
157-
return b.call(node);
158-
}
159-
}
160-
161-
context.next();
162-
}
59+
VariableDeclaration: VariableDeclarationRunes,
60+
ExpressionStatement: ExpressionStatementRunes,
61+
MemberExpression: MemberExpressionRunes
16362
};
16463

16564
/** @type {Visitors} */
16665
const javascript_visitors_legacy = {
167-
VariableDeclaration(node, { state, visit }) {
168-
/** @type {VariableDeclarator[]} */
169-
const declarations = [];
170-
171-
for (const declarator of node.declarations) {
172-
const bindings = /** @type {Binding[]} */ (state.scope.get_bindings(declarator));
173-
const has_state = bindings.some((binding) => binding.kind === 'state');
174-
const has_props = bindings.some((binding) => binding.kind === 'bindable_prop');
175-
176-
if (!has_state && !has_props) {
177-
declarations.push(/** @type {VariableDeclarator} */ (visit(declarator)));
178-
continue;
179-
}
180-
181-
if (has_props) {
182-
if (declarator.id.type !== 'Identifier') {
183-
// Turn export let into props. It's really really weird because export let { x: foo, z: [bar]} = ..
184-
// means that foo and bar are the props (i.e. the leafs are the prop names), not x and z.
185-
const tmp = state.scope.generate('tmp');
186-
const paths = extract_paths(declarator.id);
187-
declarations.push(
188-
b.declarator(
189-
b.id(tmp),
190-
/** @type {Expression} */ (visit(/** @type {Expression} */ (declarator.init)))
191-
)
192-
);
193-
for (const path of paths) {
194-
const value = path.expression?.(b.id(tmp));
195-
const name = /** @type {Identifier} */ (path.node).name;
196-
const binding = /** @type {Binding} */ (state.scope.get(name));
197-
const prop = b.member(b.id('$$props'), b.literal(binding.prop_alias ?? name), true);
198-
declarations.push(
199-
b.declarator(path.node, b.call('$.value_or_fallback', prop, b.thunk(value)))
200-
);
201-
}
202-
continue;
203-
}
204-
205-
const binding = /** @type {Binding} */ (state.scope.get(declarator.id.name));
206-
const prop = b.member(
207-
b.id('$$props'),
208-
b.literal(binding.prop_alias ?? declarator.id.name),
209-
true
210-
);
211-
212-
/** @type {Expression} */
213-
let init = prop;
214-
if (declarator.init) {
215-
const default_value = /** @type {Expression} */ (visit(declarator.init));
216-
init = is_expression_async(default_value)
217-
? b.await(b.call('$.value_or_fallback_async', prop, b.thunk(default_value, true)))
218-
: b.call('$.value_or_fallback', prop, b.thunk(default_value));
219-
}
220-
221-
declarations.push(b.declarator(declarator.id, init));
222-
223-
continue;
224-
}
225-
226-
declarations.push(
227-
...create_state_declarators(
228-
declarator,
229-
state.scope,
230-
/** @type {Expression} */ (declarator.init && visit(declarator.init))
231-
)
232-
);
233-
}
234-
235-
return {
236-
...node,
237-
declarations
238-
};
239-
},
66+
VariableDeclaration: VariableDeclarationLegacy,
24067
LabeledStatement(node, context) {
24168
if (context.path.length > 1) return;
24269
if (node.label.name !== '$') return;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/** @import { ExpressionStatement } from 'estree' */
2+
/** @import { Context } from '../../types' */
3+
import * as b from '../../../../../utils/builders.js';
4+
5+
/**
6+
* @param {ExpressionStatement} node
7+
* @param {Context} context
8+
*/
9+
export function ExpressionStatementRunes(node, context) {
10+
const expression = node.expression;
11+
12+
if (expression.type === 'CallExpression') {
13+
const callee = expression.callee;
14+
15+
if (callee.type === 'Identifier' && callee.name === '$effect') {
16+
return b.empty;
17+
}
18+
19+
if (
20+
callee.type === 'MemberExpression' &&
21+
callee.object.type === 'Identifier' &&
22+
callee.object.name === '$effect'
23+
) {
24+
return b.empty;
25+
}
26+
}
27+
28+
context.next();
29+
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ import { serialize_get_binding } from './shared/utils.js';
88
* @param {Identifier} node
99
* @param {Context} context
1010
*/
11-
export function Identifier(node, { path, state }) {
12-
if (is_reference(node, /** @type {Node} */ (path.at(-1)))) {
11+
export function Identifier(node, context) {
12+
if (is_reference(node, /** @type {Node} */ (context.path.at(-1)))) {
1313
if (node.name === '$$props') {
1414
return b.id('$$sanitized_props');
1515
}
1616

17-
return serialize_get_binding(node, state);
17+
return serialize_get_binding(node, context.state);
1818
}
1919
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/** @import { MemberExpression } from 'estree' */
2+
/** @import { Context } from '../../types' */
3+
import * as b from '../../../../../utils/builders.js';
4+
5+
/**
6+
* @param {MemberExpression} node
7+
* @param {Context} context
8+
*/
9+
export function MemberExpressionRunes(node, context) {
10+
if (node.object.type === 'ThisExpression' && node.property.type === 'PrivateIdentifier') {
11+
const field = context.state.private_derived.get(node.property.name);
12+
13+
if (field) {
14+
return b.call(node);
15+
}
16+
}
17+
18+
context.next();
19+
}

0 commit comments

Comments
 (0)