fix: reconnect disconnect deriveds after batch processing

derived-reactivity-loss-fix-alt
Rich Harris 2 weeks ago
parent b7625fd42c
commit 1c02dc243f

@ -15,7 +15,9 @@ import {
DERIVED,
BOUNDARY_EFFECT,
EAGER_EFFECT,
HEAD_EFFECT
HEAD_EFFECT,
DISCONNECTED,
UNOWNED
} from '#client/constants';
import { async_mode_flag } from '../../flags/index.js';
import { deferred, define_property } from '../../shared/utils.js';
@ -189,7 +191,28 @@ export class Batch {
this.#deferred?.resolve();
}
batch_values = null;
if (batch_values !== null) {
for (const value of batch_values.keys()) {
// reconnect any deriveds that were disconnected from the graph
if ((value.f & UNOWNED) !== 0) {
var derived = /** @type {Derived} */ (value);
if (derived.deps !== null) {
for (var i = 0; i < derived.deps.length; i++) {
var dep = /** @type {Value} */ (derived.deps[i]);
if (!dep?.reactions?.includes(derived)) {
(dep.reactions ??= []).push(derived);
}
}
}
derived.f ^= UNOWNED;
}
}
batch_values = null;
}
}
/**

@ -0,0 +1,6 @@
<script>
let { double } = $props();
double; // forces derived into UNOWNED mode
</script>
<p>{double}</p>

@ -0,0 +1,30 @@
import { tick } from 'svelte';
import { test } from '../../test';
export default test({
async test({ assert, target }) {
const button = target.querySelector('button');
button?.click();
await tick();
assert.htmlEqual(
target.innerHTML,
`
<button>1</button>
<p>2</p>
`
);
button?.click();
await tick();
assert.htmlEqual(
target.innerHTML,
`
<button>2</button>
<p>4</p>
`
);
}
});

@ -0,0 +1,19 @@
<script>
import Component from './Component.svelte';
let count = $state(0);
const double = $derived(count * 2);
</script>
<svelte:boundary>
{await new Promise((r) => {
// long enough for the test to do all its other stuff while this is pending
setTimeout(r, 10);
})}
{#snippet pending()}{/snippet}
</svelte:boundary>
<button onclick={() => count += 1}>{count}</button>
{#if count > 0}
<Component {double} />
{/if}
Loading…
Cancel
Save