Skip to content

Commit

Permalink
fix: ensure $store reads are properly transformed (#12952)
Browse files Browse the repository at this point in the history
The backing store variable of a $store read could be a variable that itself needs a transformer, which is why we need to make accessing the reads lazy

fixes #12859
  • Loading branch information
Rich-Harris authored Aug 21, 2024
1 parent 732dbf7 commit af7f900
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/nervous-adults-sell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: ensure `$store` reads are properly transformed
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,17 @@ 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))));
// read lazily, so that transforms added later are still applied
/** @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,
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);
Expand All @@ -70,7 +76,7 @@ export function Program(_, context) {

return b.call(
'$.store_mutate',
store,
get_store(),
b.assignment(
mutation.operator,
/** @type {MemberExpression} */ (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { flushSync } from 'svelte';
import { test } from '../../test';

export default test({
html: `<button>false</button>`,
test({ assert, target }) {
target.querySelector('button')?.click();
flushSync();
assert.htmlEqual(target.innerHTML, `<button>true</button>`);
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script>
import { writable } from 'svelte/store';
let data = { store: writable(false) };
let { store } = $derived(data);
</script>

<button onclick={() => ($store = true)}>{$store}</button>

0 comments on commit af7f900

Please sign in to comment.