Skip to content
Open
5 changes: 5 additions & 0 deletions .changeset/sharp-rings-march.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

feat: allow `$state` in return statements
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,20 @@ export function CallExpression(node, context) {
}

case '$state':
if (
(!(parent.type === 'VariableDeclarator' || parent.type === 'ReturnStatement') ||
get_parent(context.path, -3).type === 'ConstTag') &&
!(parent.type === 'PropertyDefinition' && !parent.static && !parent.computed) &&
!(parent.type === 'ArrowFunctionExpression' && parent.body === node)
) {
e.state_invalid_placement(node, rune);
}

if (node.arguments.length > 1) {
e.rune_invalid_arguments_length(node, rune, 'zero or one arguments');
}

break;
case '$state.raw':
case '$derived':
case '$derived.by':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import { dev, is_ignored } from '../../../../state.js';
import * as b from '../../../../utils/builders.js';
import { get_rune } from '../../../scope.js';
import { transform_inspect_rune } from '../../utils.js';
import { should_proxy } from '../utils.js';

/**
* @param {CallExpression} node
* @param {Context} context
*/
export function CallExpression(node, context) {
const parent = context.path.at(-1);
switch (get_rune(node, context.state.scope)) {
case '$host':
return b.id('$$props.$$host');
Expand All @@ -33,6 +35,23 @@ export function CallExpression(node, context) {
case '$inspect':
case '$inspect().with':
return transform_inspect_rune(node, context);
case '$state':
if (
parent?.type === 'ReturnStatement' ||
(parent?.type === 'ArrowFunctionExpression' && parent.body === node)
) {
if (
node.arguments[0] &&
should_proxy(
/** @type {Expression} */ (context.visit(node.arguments[0])),
context.state.scope
)
) {
return b.call('$.proxy', node.arguments[0]);
} else {
return node.arguments[0] ?? b.void0;
}
}
}

if (
Expand Down