From f27e1882fc07e6f44bbfbb04f92bc2583429f38f Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Wed, 21 Aug 2024 09:01:06 -0400 Subject: [PATCH 1/4] failing test --- .../samples/store-from-derived/_config.js | 11 +++++++++++ .../samples/store-from-derived/main.svelte | 7 +++++++ 2 files changed, 18 insertions(+) create mode 100644 packages/svelte/tests/runtime-runes/samples/store-from-derived/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/store-from-derived/main.svelte diff --git a/packages/svelte/tests/runtime-runes/samples/store-from-derived/_config.js b/packages/svelte/tests/runtime-runes/samples/store-from-derived/_config.js new file mode 100644 index 000000000000..8cb3fd9cae10 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/store-from-derived/_config.js @@ -0,0 +1,11 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + html: ``, + test({ assert, target }) { + target.querySelector('button')?.click(); + flushSync(); + assert.htmlEqual(target.innerHTML, ``); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/store-from-derived/main.svelte b/packages/svelte/tests/runtime-runes/samples/store-from-derived/main.svelte new file mode 100644 index 000000000000..728544e664fa --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/store-from-derived/main.svelte @@ -0,0 +1,7 @@ + + + From c24cecf0510e06f452be7427cd45361bed1aa6d3 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Wed, 21 Aug 2024 09:07:32 -0400 Subject: [PATCH 2/4] alternative fix for #12951 --- .changeset/nervous-adults-sell.md | 5 +++++ .../compiler/phases/3-transform/client/visitors/Program.js | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 .changeset/nervous-adults-sell.md diff --git a/.changeset/nervous-adults-sell.md b/.changeset/nervous-adults-sell.md new file mode 100644 index 000000000000..a7bad9bda8a3 --- /dev/null +++ b/.changeset/nervous-adults-sell.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: ensure `$store` reads are properly transformed diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/Program.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/Program.js index dc30255a1a4d..f6fae339aa14 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/Program.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/Program.js @@ -42,11 +42,11 @@ export function Program(_, context) { for (const [name, binding] of context.state.scope.declarations) { if (binding.kind === 'store_sub') { - const store = /** @type {Expression} */ (context.visit(b.id(name.slice(1)))); + const get_store = () => /** @type {Expression} */ (context.visit(b.id(name.slice(1)))); context.state.transform[name] = { read: b.call, - assign: (_, value) => b.call('$.store_set', store, value), + assign: (_, value) => b.call('$.store_set', get_store(), value), mutate: (node, mutation) => { // We need to untrack the store read, for consistency with Svelte 4 const untracked = b.call('$.untrack', node); @@ -70,7 +70,7 @@ export function Program(_, context) { return b.call( '$.store_mutate', - store, + get_store(), b.assignment( mutation.operator, /** @type {MemberExpression} */ ( From 1c230536e8ab75e811228c6474adfc180d2abed7 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Wed, 21 Aug 2024 12:28:55 -0400 Subject: [PATCH 3/4] comment --- .../src/compiler/phases/3-transform/client/visitors/Program.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/Program.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/Program.js index f6fae339aa14..f3d88f25a897 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/Program.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/Program.js @@ -42,6 +42,7 @@ export function Program(_, context) { for (const [name, binding] of context.state.scope.declarations) { if (binding.kind === 'store_sub') { + // read lazily, so that transforms added later are still applied const get_store = () => /** @type {Expression} */ (context.visit(b.id(name.slice(1)))); context.state.transform[name] = { From 5fe578982dd0c4583dcf7c91a58c4d4f58a6e951 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Wed, 21 Aug 2024 15:16:59 -0400 Subject: [PATCH 4/4] cache --- .../compiler/phases/3-transform/client/visitors/Program.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/Program.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/Program.js index f3d88f25a897..f3f3808594df 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/Program.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/Program.js @@ -43,7 +43,12 @@ export function Program(_, context) { for (const [name, binding] of context.state.scope.declarations) { if (binding.kind === 'store_sub') { // read lazily, so that transforms added later are still applied - const get_store = () => /** @type {Expression} */ (context.visit(b.id(name.slice(1)))); + /** @type {Expression} */ + let cached; + + const get_store = () => { + return (cached ??= /** @type {Expression} */ (context.visit(b.id(name.slice(1))))); + }; context.state.transform[name] = { read: b.call,