fix: derived store restarting when unsubscribed from another store with a shared ancestor (#8368)

Fixes #8364

---------

Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
pull/8382/head
Jon Rouleau 1 year ago committed by GitHub
parent c99dd2e045
commit 127b61a465
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -164,7 +164,7 @@ export function derived<T>(stores: Stores, fn: Function, initial_value?: T): Rea
const auto = fn.length < 2; const auto = fn.length < 2;
return readable(initial_value, (set) => { return readable(initial_value, (set) => {
let inited = false; let started = false;
const values = []; const values = [];
let pending = 0; let pending = 0;
@ -188,7 +188,7 @@ export function derived<T>(stores: Stores, fn: Function, initial_value?: T): Rea
(value) => { (value) => {
values[i] = value; values[i] = value;
pending &= ~(1 << i); pending &= ~(1 << i);
if (inited) { if (started) {
sync(); sync();
} }
}, },
@ -197,12 +197,16 @@ export function derived<T>(stores: Stores, fn: Function, initial_value?: T): Rea
}) })
); );
inited = true; started = true;
sync(); sync();
return function stop() { return function stop() {
run_all(unsubscribers); run_all(unsubscribers);
cleanup(); cleanup();
// We need to set this to false because callbacks can still happen despite having unsubscribed:
// Callbacks might already be placed in the queue which doesn't know it should no longer
// invoke this derived store.
started = false;
}; };
}); });
} }

@ -407,6 +407,25 @@ describe('store', () => {
const d = derived(fake_observable, _ => _); const d = derived(fake_observable, _ => _);
assert.equal(get(d), 42); assert.equal(get(d), 42);
}); });
it('doesn\'t restart when unsubscribed from another store with a shared ancestor', () => {
const a = writable(true);
let b_started = false;
const b = derived(a, (_, __) => {
b_started = true;
return () => {
assert.equal(b_started, true);
b_started = false;
};
});
const c = derived(a, ($a, set) => {
if ($a) return b.subscribe(set);
});
c.subscribe(() => { });
a.set(false);
assert.equal(b_started, false);
});
}); });
describe('get', () => { describe('get', () => {

Loading…
Cancel
Save