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 <dg@domgan.com>
Co-authored-by: Rich Harris <rich.harris@vercel.com>
pull/9598/head
Rich Harris 2 years ago committed by GitHub
parent 1f4ae5ef45
commit c837771ca6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -503,24 +503,19 @@ function validate_call_expression(node, scope, path) {
error(node, rune === '$derived' ? 'invalid-derived-location' : 'invalid-state-location'); error(node, rune === '$derived' ? 'invalid-derived-location' : 'invalid-state-location');
} }
if (rune === '$effect') { if (rune === '$effect' || rune === '$effect.pre') {
const callee = node.callee;
if (
callee.type === 'MemberExpression' &&
callee.property.type === 'Identifier' &&
callee.property.name === 'active'
) {
if (node.arguments.length !== 0) {
error(node, 'invalid-rune-args-length', '$effect.active', [0]);
}
return;
}
if (parent.type !== 'ExpressionStatement') { if (parent.type !== 'ExpressionStatement') {
error(node, 'invalid-effect-location'); error(node, 'invalid-effect-location');
} }
if (node.arguments.length !== 1) { if (node.arguments.length !== 1) {
error(node, 'invalid-rune-args-length', '$effect', [1]); error(node, 'invalid-rune-args-length', rune, [1]);
}
}
if (rune === '$effect.active') {
if (node.arguments.length !== 0) {
error(node, 'invalid-rune-args-length', '$effect.active', [0]);
} }
} }
} }

@ -135,7 +135,7 @@ export const javascript_visitors_runes = {
for (const declarator of node.declarations) { for (const declarator of node.declarations) {
const init = declarator.init; const init = declarator.init;
const rune = get_rune(init, state.scope); const rune = get_rune(init, state.scope);
if (!rune || rune === '$effect') { if (!rune || rune === '$effect.active') {
if (init != null && is_hoistable_function(init)) { if (init != null && is_hoistable_function(init)) {
const hoistable_function = visit(init); const hoistable_function = visit(init);
state.hoisted.push( state.hoisted.push(
@ -294,16 +294,11 @@ export const javascript_visitors_runes = {
}, },
CallExpression(node, { state, next }) { CallExpression(node, { state, next }) {
const rune = get_rune(node, state.scope); const rune = get_rune(node, state.scope);
const callee = node.callee;
if ( if (rune === '$effect.active') {
rune === '$effect' &&
callee.type === 'MemberExpression' &&
callee.property.type === 'Identifier' &&
callee.property.name === 'active'
) {
return b.call('$.effect_active'); return b.call('$.effect_active');
} }
next(); next();
} }
}; };

@ -550,7 +550,7 @@ const javascript_visitors_runes = {
for (const declarator of node.declarations) { for (const declarator of node.declarations) {
const rune = get_rune(declarator.init, state.scope); const rune = get_rune(declarator.init, state.scope);
if (!rune || rune === '$effect') { if (!rune || rune === '$effect.active') {
declarations.push(/** @type {import('estree').VariableDeclarator} */ (visit(declarator))); declarations.push(/** @type {import('estree').VariableDeclarator} */ (visit(declarator)));
continue; continue;
} }
@ -607,16 +607,11 @@ const javascript_visitors_runes = {
}, },
CallExpression(node, { state, next }) { CallExpression(node, { state, next }) {
const rune = get_rune(node, state.scope); const rune = get_rune(node, state.scope);
const callee = node.callee;
if ( if (rune === '$effect.active') {
rune === '$effect' &&
callee.type === 'MemberExpression' &&
callee.property.type === 'Identifier' &&
callee.property.name === 'active'
) {
return b.literal(false); return b.literal(false);
} }
next(); next();
} }
}; };

@ -110,7 +110,7 @@ export const ElementBindings = [
'indeterminate' 'indeterminate'
]; ];
export const Runes = ['$state', '$props', '$derived', '$effect']; export const Runes = ['$state', '$props', '$derived', '$effect', '$effect.pre', '$effect.active'];
/** /**
* Whitespace inside one of these elements will not result in * Whitespace inside one of these elements will not result in

@ -668,15 +668,31 @@ export function set_scope(scopes) {
/** /**
* Returns the name of the rune if the given expression is a `CallExpression` using a rune. * Returns the name of the rune if the given expression is a `CallExpression` using a rune.
* @param {import('estree').Expression | null | undefined} node * @param {import('estree').Node | null | undefined} node
* @param {Scope} scope * @param {Scope} scope
*/ */
export function get_rune(node, scope) { export function get_rune(node, scope) {
const callee = get_callee_name(node); if (!node) return null;
if (callee === null || !Runes.includes(callee)) return null; if (node.type !== 'CallExpression') return null;
const binding = scope.get(callee); let n = node.callee;
let joined = '';
while (n.type === 'MemberExpression') {
if (n.computed) return null;
if (n.property.type !== 'Identifier') return null;
joined = '.' + n.property.name + joined;
n = n.object;
}
if (n.type !== 'Identifier') return null;
joined = n.name + joined;
if (!Runes.includes(joined)) return null;
const binding = scope.get(n.name);
if (binding !== null) return null; // rune name, but references a variable or store if (binding !== null) return null; // rune name, but references a variable or store
return callee; return joined;
} }

Loading…
Cancel
Save