fix: update expressions on server deriveds

pull/17767/head
paoloricciuti 2 months ago
parent d258f85235
commit 25f3e69d34

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: update expressions on server deriveds

@ -9,17 +9,26 @@ import * as b from '#compiler/builders';
export function UpdateExpression(node, context) {
const argument = node.argument;
if (
argument.type === 'Identifier' &&
context.state.scope.get(argument.name)?.kind === 'store_sub'
) {
return b.call(
node.prefix ? '$.update_store_pre' : '$.update_store',
b.assignment('??=', b.id('$$store_subs'), b.object([])),
b.literal(argument.name),
b.id(argument.name.slice(1)),
node.operator === '--' && b.literal(-1)
);
if (argument.type === 'Identifier') {
const binding = context.state.scope.get(argument.name);
if (binding?.kind === 'store_sub') {
return b.call(
node.prefix ? '$.update_store_pre' : '$.update_store',
b.assignment('??=', b.id('$$store_subs'), b.object([])),
b.literal(argument.name),
b.id(argument.name.slice(1)),
node.operator === '--' && b.literal(-1)
);
}
if (binding?.kind === 'derived') {
return b.call(
node.prefix ? '$.update_derived_pre' : '$.update_derived',
binding.node,
node.operator === '--' && b.literal(-1)
);
}
}
return context.next();

@ -504,6 +504,35 @@ export function derived(fn) {
};
}
/**
* @template {number | bigint} T
* @param {(value?: T) => T} derived
* @param {1 | -1} [d]
* @returns {T}
*/
export function update_derived(derived, d = 1) {
const value = derived();
let increase = typeof value === 'bigint' ? BigInt(d) : d;
// for some reason TS is mad even if T is always number or bigint
derived(value + /** @type {*} */ (increase));
return value;
}
/**
* @template {number | bigint} T
* @param {(value?: T) => T} derived
* @param {1 | -1} [d]
* @returns {T}
*/
export function update_derived_pre(derived, d = 1) {
const old_value = derived();
let increase = typeof old_value === 'bigint' ? BigInt(d) : d;
// for some reason TS is mad even if T is always number or bigint
const value = old_value + /** @type {*} */ (increase);
derived(value);
return value;
}
/**
* @template T
* @param {()=>T} fn

@ -0,0 +1,6 @@
import { test } from '../../test';
export default test({
mode: ['async-server', 'server'],
html: '<p>postfix: 0, postfix_minus: 1, prefix: 1, prefix_minus: 0, count: 0</p><p>postfix_n: 0, postfix_minus_n: 1, prefix_n: 1, prefix_minus_n: 0, count_n: 0</p>'
});

@ -0,0 +1,17 @@
<script>
let count = $derived(0);
let postfix = count++;
let postfix_minus = count--;
let prefix = ++count;
let prefix_minus = --count;
let count_n = $derived(0n);
let postfix_n = count_n++;
let postfix_minus_n = count_n--;
let prefix_n = ++count_n;
let prefix_minus_n = --count_n;
</script>
<p>postfix: {postfix}, postfix_minus: {postfix_minus}, prefix: {prefix}, prefix_minus: {prefix_minus}, count: {count}</p>
<p>postfix_n: {postfix_n}, postfix_minus_n: {postfix_minus_n}, prefix_n: {prefix_n}, prefix_minus_n: {prefix_minus_n}, count_n: {count_n}</p>
Loading…
Cancel
Save