Skip to content

Commit 70c731f

Browse files
committed
fix: ensure SvelteMap reactivity persists through deriveds
1 parent 04c38b0 commit 70c731f

File tree

4 files changed

+60
-1
lines changed

4 files changed

+60
-1
lines changed

.changeset/hungry-dogs-happen.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: ensure SvelteMap reactivity persists through deriveds

packages/svelte/src/reactivity/map.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,20 @@ export class SvelteMap extends Map {
9494
var s = sources.get(key);
9595
var prev_res = super.get(key);
9696
var res = super.set(key, value);
97+
var version = this.#version;
9798

9899
if (s === undefined) {
99100
sources.set(key, source(0));
100101
set(this.#size, super.size);
101-
increment(this.#version);
102+
increment(version);
102103
} else if (prev_res !== value) {
103104
increment(s);
105+
// If no one listening to this property yet, but version is
106+
// being listened to, then also increment version to keep
107+
// those cases in sync
108+
if (s.reactions === null || version.reactions === null) {
109+
increment(this.#version);
110+
}
104111
}
105112

106113
return res;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { flushSync } from 'svelte';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
html: `Loading`,
6+
7+
async test({ assert, target }) {
8+
await Promise.resolve();
9+
flushSync();
10+
11+
assert.htmlEqual(target.innerHTML, `1`);
12+
}
13+
});
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<script>
2+
import { untrack } from 'svelte';
3+
import { SvelteMap } from 'svelte/reactivity';
4+
5+
const cache = new SvelteMap();
6+
7+
function get_async(id) {
8+
const model = cache.get(id);
9+
10+
if (!model) {
11+
const promise = new Promise(async () => {
12+
await Promise.resolve();
13+
cache.set(id, id.toString());
14+
}).then(() => cache.get(id));
15+
16+
untrack(() => {
17+
cache.set(id, promise);
18+
});
19+
20+
return promise;
21+
}
22+
23+
return model;
24+
}
25+
26+
const value = $derived(get_async(1));
27+
</script>
28+
29+
{#if value instanceof Promise}
30+
Loading
31+
{:else}
32+
{value}
33+
{/if}
34+

0 commit comments

Comments
 (0)