Skip to content

Commit c837771

Browse files
Rich-Harristrueadm
andauthored
chore: better get_rune helper (#9594)
* chore: add $effect.active rune * chore: add $effect.active rune * WIP * allow get_rune to return a keypath * oops --------- Co-authored-by: Dominic Gannaway <[email protected]> Co-authored-by: Rich Harris <[email protected]>
1 parent 1f4ae5e commit c837771

File tree

5 files changed

+37
-36
lines changed

5 files changed

+37
-36
lines changed

packages/svelte/src/compiler/phases/2-analyze/validation.js

+8-13
Original file line numberDiff line numberDiff line change
@@ -503,24 +503,19 @@ function validate_call_expression(node, scope, path) {
503503
error(node, rune === '$derived' ? 'invalid-derived-location' : 'invalid-state-location');
504504
}
505505

506-
if (rune === '$effect') {
507-
const callee = node.callee;
508-
if (
509-
callee.type === 'MemberExpression' &&
510-
callee.property.type === 'Identifier' &&
511-
callee.property.name === 'active'
512-
) {
513-
if (node.arguments.length !== 0) {
514-
error(node, 'invalid-rune-args-length', '$effect.active', [0]);
515-
}
516-
return;
517-
}
506+
if (rune === '$effect' || rune === '$effect.pre') {
518507
if (parent.type !== 'ExpressionStatement') {
519508
error(node, 'invalid-effect-location');
520509
}
521510

522511
if (node.arguments.length !== 1) {
523-
error(node, 'invalid-rune-args-length', '$effect', [1]);
512+
error(node, 'invalid-rune-args-length', rune, [1]);
513+
}
514+
}
515+
516+
if (rune === '$effect.active') {
517+
if (node.arguments.length !== 0) {
518+
error(node, 'invalid-rune-args-length', '$effect.active', [0]);
524519
}
525520
}
526521
}

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

+4-9
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ export const javascript_visitors_runes = {
135135
for (const declarator of node.declarations) {
136136
const init = declarator.init;
137137
const rune = get_rune(init, state.scope);
138-
if (!rune || rune === '$effect') {
138+
if (!rune || rune === '$effect.active') {
139139
if (init != null && is_hoistable_function(init)) {
140140
const hoistable_function = visit(init);
141141
state.hoisted.push(
@@ -294,16 +294,11 @@ export const javascript_visitors_runes = {
294294
},
295295
CallExpression(node, { state, next }) {
296296
const rune = get_rune(node, state.scope);
297-
const callee = node.callee;
298-
299-
if (
300-
rune === '$effect' &&
301-
callee.type === 'MemberExpression' &&
302-
callee.property.type === 'Identifier' &&
303-
callee.property.name === 'active'
304-
) {
297+
298+
if (rune === '$effect.active') {
305299
return b.call('$.effect_active');
306300
}
301+
307302
next();
308303
}
309304
};

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

+3-8
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ const javascript_visitors_runes = {
550550

551551
for (const declarator of node.declarations) {
552552
const rune = get_rune(declarator.init, state.scope);
553-
if (!rune || rune === '$effect') {
553+
if (!rune || rune === '$effect.active') {
554554
declarations.push(/** @type {import('estree').VariableDeclarator} */ (visit(declarator)));
555555
continue;
556556
}
@@ -607,16 +607,11 @@ const javascript_visitors_runes = {
607607
},
608608
CallExpression(node, { state, next }) {
609609
const rune = get_rune(node, state.scope);
610-
const callee = node.callee;
611610

612-
if (
613-
rune === '$effect' &&
614-
callee.type === 'MemberExpression' &&
615-
callee.property.type === 'Identifier' &&
616-
callee.property.name === 'active'
617-
) {
611+
if (rune === '$effect.active') {
618612
return b.literal(false);
619613
}
614+
620615
next();
621616
}
622617
};

packages/svelte/src/compiler/phases/constants.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ export const ElementBindings = [
110110
'indeterminate'
111111
];
112112

113-
export const Runes = ['$state', '$props', '$derived', '$effect'];
113+
export const Runes = ['$state', '$props', '$derived', '$effect', '$effect.pre', '$effect.active'];
114114

115115
/**
116116
* Whitespace inside one of these elements will not result in

packages/svelte/src/compiler/phases/scope.js

+21-5
Original file line numberDiff line numberDiff line change
@@ -668,15 +668,31 @@ export function set_scope(scopes) {
668668

669669
/**
670670
* Returns the name of the rune if the given expression is a `CallExpression` using a rune.
671-
* @param {import('estree').Expression | null | undefined} node
671+
* @param {import('estree').Node | null | undefined} node
672672
* @param {Scope} scope
673673
*/
674674
export function get_rune(node, scope) {
675-
const callee = get_callee_name(node);
676-
if (callee === null || !Runes.includes(callee)) return null;
675+
if (!node) return null;
676+
if (node.type !== 'CallExpression') return null;
677677

678-
const binding = scope.get(callee);
678+
let n = node.callee;
679+
680+
let joined = '';
681+
682+
while (n.type === 'MemberExpression') {
683+
if (n.computed) return null;
684+
if (n.property.type !== 'Identifier') return null;
685+
joined = '.' + n.property.name + joined;
686+
n = n.object;
687+
}
688+
689+
if (n.type !== 'Identifier') return null;
690+
691+
joined = n.name + joined;
692+
if (!Runes.includes(joined)) return null;
693+
694+
const binding = scope.get(n.name);
679695
if (binding !== null) return null; // rune name, but references a variable or store
680696

681-
return callee;
697+
return joined;
682698
}

0 commit comments

Comments
 (0)