Skip to content

Commit 1c02dc2

Browse files
committed
fix: reconnect disconnect deriveds after batch processing
1 parent b7625fd commit 1c02dc2

File tree

4 files changed

+80
-2
lines changed

4 files changed

+80
-2
lines changed

packages/svelte/src/internal/client/reactivity/batch.js

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ import {
1515
DERIVED,
1616
BOUNDARY_EFFECT,
1717
EAGER_EFFECT,
18-
HEAD_EFFECT
18+
HEAD_EFFECT,
19+
DISCONNECTED,
20+
UNOWNED
1921
} from '#client/constants';
2022
import { async_mode_flag } from '../../flags/index.js';
2123
import { deferred, define_property } from '../../shared/utils.js';
@@ -189,7 +191,28 @@ export class Batch {
189191
this.#deferred?.resolve();
190192
}
191193

192-
batch_values = null;
194+
if (batch_values !== null) {
195+
for (const value of batch_values.keys()) {
196+
// reconnect any deriveds that were disconnected from the graph
197+
if ((value.f & UNOWNED) !== 0) {
198+
var derived = /** @type {Derived} */ (value);
199+
200+
if (derived.deps !== null) {
201+
for (var i = 0; i < derived.deps.length; i++) {
202+
var dep = /** @type {Value} */ (derived.deps[i]);
203+
204+
if (!dep?.reactions?.includes(derived)) {
205+
(dep.reactions ??= []).push(derived);
206+
}
207+
}
208+
}
209+
210+
derived.f ^= UNOWNED;
211+
}
212+
}
213+
214+
batch_values = null;
215+
}
193216
}
194217

195218
/**
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<script>
2+
let { double } = $props();
3+
double; // forces derived into UNOWNED mode
4+
</script>
5+
6+
<p>{double}</p>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { tick } from 'svelte';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
async test({ assert, target }) {
6+
const button = target.querySelector('button');
7+
8+
button?.click();
9+
await tick();
10+
11+
assert.htmlEqual(
12+
target.innerHTML,
13+
`
14+
<button>1</button>
15+
<p>2</p>
16+
`
17+
);
18+
19+
button?.click();
20+
await tick();
21+
22+
assert.htmlEqual(
23+
target.innerHTML,
24+
`
25+
<button>2</button>
26+
<p>4</p>
27+
`
28+
);
29+
}
30+
});
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<script>
2+
import Component from './Component.svelte';
3+
let count = $state(0);
4+
const double = $derived(count * 2);
5+
</script>
6+
7+
<svelte:boundary>
8+
{await new Promise((r) => {
9+
// long enough for the test to do all its other stuff while this is pending
10+
setTimeout(r, 10);
11+
})}
12+
{#snippet pending()}{/snippet}
13+
</svelte:boundary>
14+
15+
<button onclick={() => count += 1}>{count}</button>
16+
17+
{#if count > 0}
18+
<Component {double} />
19+
{/if}

0 commit comments

Comments
 (0)