fix: correct increment/decrement code generation

fixes #10226
pull/10233/head
Simon Holthausen 12 months ago
parent 0fd1c92822
commit 2861ad66e0

@ -0,0 +1,5 @@
---
"svelte": patch
---
fix: correct increment/decrement code generation

@ -83,8 +83,16 @@ export const global_visitors = {
argument.property.type === 'PrivateIdentifier' && argument.property.type === 'PrivateIdentifier' &&
context.state.private_state.has(argument.property.name) context.state.private_state.has(argument.property.name)
) { ) {
let fn = node.operator === '++' ? '$.increment' : '$.decrement'; let fn = '$.update';
return b.call(fn, argument); if (node.prefix) fn += '_pre';
/** @type {import('estree').Expression[]} */
const args = [argument];
if (node.operator === '--') {
args.push(b.literal(-1));
}
return b.call(fn, ...args);
} else { } else {
// turn it into an IIFEE assignment expression: i++ -> (() => { const $$value = i; i+=1; return $$value; }) // turn it into an IIFEE assignment expression: i++ -> (() => { const $$value = i; i+=1; return $$value; })
const assignment = b.assignment( const assignment = b.assignment(

@ -511,24 +511,17 @@ const global_visitors = {
const { state, next } = context; const { state, next } = context;
const argument = node.argument; const argument = node.argument;
if (argument.type === 'Identifier') { if (argument.type === 'Identifier' && state.scope.get(argument.name)?.kind === 'store_sub') {
const binding = state.scope.get(argument.name); let fn = '$.update_store';
const is_store = binding?.kind === 'store_sub';
const name = is_store ? argument.name.slice(1) : argument.name;
// use runtime functions for smaller output
if (is_store) {
let fn = node.operator === '++' ? '$.increment' : '$.decrement';
if (node.prefix) fn += '_pre'; if (node.prefix) fn += '_pre';
if (is_store) { /** @type {import('estree').Expression[]} */
fn += '_store'; const args = [b.id('$$store_subs'), b.literal(argument.name), b.id(argument.name.slice(1))];
return b.call(fn, serialize_get_binding(b.id(name), state), b.call('$' + name)); if (node.operator === '--') {
} else { args.push(b.literal(-1));
return b.call(fn, b.id(name));
}
} else {
return next();
} }
return b.call(fn, ...args);
} }
return next(); return next();
} }

@ -407,6 +407,32 @@ export function mutate_store(store_values, store_name, store, expression) {
return expression; return expression;
} }
/**
* @param {Record<string, [any, any, any]>} store_values
* @param {string} store_name
* @param {import('../client/types.js').Store<number>} store
* @param {1 | -1} [d]
* @returns {number}
*/
export function update_store(store_values, store_name, store, d = 1) {
let store_value = store_get(store_values, store_name, store);
store.set(store_value + d);
return store_value;
}
/**
* @param {Record<string, [any, any, any]>} store_values
* @param {string} store_name
* @param {import('../client/types.js').Store<number>} store
* @param {1 | -1} [d]
* @returns {number}
*/
export function update_store_pre(store_values, store_name, store, d = 1) {
const value = store_get(store_values, store_name, store) + d;
store.set(value);
return value;
}
/** @param {Record<string, [any, any, any]>} store_values */ /** @param {Record<string, [any, any, any]>} store_values */
export function unsubscribe_stores(store_values) { export function unsubscribe_stores(store_values) {
for (const store_name in store_values) { for (const store_name in store_values) {

@ -0,0 +1,5 @@
import { test } from '../../test';
export default test({
html: `0 0 2 2 0`
});

@ -0,0 +1,11 @@
<script lang="ts">
import { writable } from "svelte/store";
let x = writable(0);
const a = $x++;
const b = ++$x;
const c = $x--;
const d = --$x;
</script>
{$x} {a} {b} {c} {d}
Loading…
Cancel
Save