From 2861ad66e054d2b14f382aaada4512e3e5d56db8 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Fri, 19 Jan 2024 11:10:58 +0100 Subject: [PATCH] fix: correct increment/decrement code generation fixes #10226 --- .changeset/honest-buses-add.md | 5 ++++ .../3-transform/client/visitors/global.js | 12 +++++++-- .../3-transform/server/transform-server.js | 27 +++++++------------ packages/svelte/src/internal/server/index.js | 26 ++++++++++++++++++ .../store-increment-decrement/_config.js | 5 ++++ .../store-increment-decrement/main.svelte | 11 ++++++++ 6 files changed, 67 insertions(+), 19 deletions(-) create mode 100644 .changeset/honest-buses-add.md create mode 100644 packages/svelte/tests/runtime-runes/samples/store-increment-decrement/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/store-increment-decrement/main.svelte diff --git a/.changeset/honest-buses-add.md b/.changeset/honest-buses-add.md new file mode 100644 index 0000000000..6c28608f65 --- /dev/null +++ b/.changeset/honest-buses-add.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: correct increment/decrement code generation diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/global.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/global.js index 683bb816af..5b8910b0d6 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/global.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/global.js @@ -83,8 +83,16 @@ export const global_visitors = { argument.property.type === 'PrivateIdentifier' && context.state.private_state.has(argument.property.name) ) { - let fn = node.operator === '++' ? '$.increment' : '$.decrement'; - return b.call(fn, argument); + let fn = '$.update'; + 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 { // turn it into an IIFEE assignment expression: i++ -> (() => { const $$value = i; i+=1; return $$value; }) const assignment = b.assignment( diff --git a/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js b/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js index 49b92191ff..cc1649c370 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js @@ -511,24 +511,17 @@ const global_visitors = { const { state, next } = context; const argument = node.argument; - if (argument.type === 'Identifier') { - const binding = state.scope.get(argument.name); - 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 (is_store) { - fn += '_store'; - return b.call(fn, serialize_get_binding(b.id(name), state), b.call('$' + name)); - } else { - return b.call(fn, b.id(name)); - } - } else { - return next(); + if (argument.type === 'Identifier' && state.scope.get(argument.name)?.kind === 'store_sub') { + let fn = '$.update_store'; + if (node.prefix) fn += '_pre'; + + /** @type {import('estree').Expression[]} */ + const args = [b.id('$$store_subs'), b.literal(argument.name), b.id(argument.name.slice(1))]; + if (node.operator === '--') { + args.push(b.literal(-1)); } + + return b.call(fn, ...args); } return next(); } diff --git a/packages/svelte/src/internal/server/index.js b/packages/svelte/src/internal/server/index.js index 176da06863..cd152c9322 100644 --- a/packages/svelte/src/internal/server/index.js +++ b/packages/svelte/src/internal/server/index.js @@ -407,6 +407,32 @@ export function mutate_store(store_values, store_name, store, expression) { return expression; } +/** + * @param {Record} store_values + * @param {string} store_name + * @param {import('../client/types.js').Store} 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} store_values + * @param {string} store_name + * @param {import('../client/types.js').Store} 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} store_values */ export function unsubscribe_stores(store_values) { for (const store_name in store_values) { diff --git a/packages/svelte/tests/runtime-runes/samples/store-increment-decrement/_config.js b/packages/svelte/tests/runtime-runes/samples/store-increment-decrement/_config.js new file mode 100644 index 0000000000..17873439d0 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/store-increment-decrement/_config.js @@ -0,0 +1,5 @@ +import { test } from '../../test'; + +export default test({ + html: `0 0 2 2 0` +}); diff --git a/packages/svelte/tests/runtime-runes/samples/store-increment-decrement/main.svelte b/packages/svelte/tests/runtime-runes/samples/store-increment-decrement/main.svelte new file mode 100644 index 0000000000..079daedfa8 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/store-increment-decrement/main.svelte @@ -0,0 +1,11 @@ + + +{$x} {a} {b} {c} {d}