diff --git a/src/runtime/store/index.ts b/src/runtime/store/index.ts index c85163003f..6863730e4e 100644 --- a/src/runtime/store/index.ts +++ b/src/runtime/store/index.ts @@ -44,6 +44,8 @@ export interface Writable extends Readable { /** Pair of subscriber and invalidator. */ type SubscribeInvalidateTuple = [Subscriber, Invalidator]; +const subscriber_queue = []; + /** * Creates a `Readable` store that allows reading by subscription. * @param value initial value @@ -67,11 +69,20 @@ export function writable(value: T, start: StartStopNotifier = noop): Writa function set(new_value: T): void { if (safe_not_equal(value, new_value)) { value = new_value; - if (!stop) { - return; // not ready + if (stop) { // store is ready + const run_queue = !subscriber_queue.length; + for (let i = 0; i < subscribers.length; i += 1) { + const s = subscribers[i]; + s[1](); + subscriber_queue.push(s, value); + } + if (run_queue) { + for (let i = 0; i < subscriber_queue.length; i += 2) { + subscriber_queue[i][0](subscriber_queue[i + 1]); + } + subscriber_queue.length = 0; + } } - subscribers.forEach((s) => s[1]()); - subscribers.forEach((s) => s[0](value)); } } @@ -129,9 +140,7 @@ export function derived( const auto = fn.length < 2; - const invalidators: Array> = []; - - const store = readable(initial_value, (set) => { + return readable(initial_value, (set) => { let inited = false; const values: StoresValues = [] as StoresValues; @@ -160,7 +169,6 @@ export function derived( } }, () => { - run_all(invalidators); pending |= (1 << i); }), ); @@ -173,20 +181,4 @@ export function derived( cleanup(); }; }); - - return { - subscribe(run: Subscriber, invalidate: Invalidator = noop): Unsubscriber { - invalidators.push(invalidate); - - const unsubscribe = store.subscribe(run, invalidate); - - return () => { - const index = invalidators.indexOf(invalidate); - if (index !== -1) { - invalidators.splice(index, 1); - } - unsubscribe(); - }; - } - }; -} \ No newline at end of file +} diff --git a/test/js/samples/bind-open/expected.js b/test/js/samples/bind-open/expected.js index 7f739aec8b..7c73c8ddac 100644 --- a/test/js/samples/bind-open/expected.js +++ b/test/js/samples/bind-open/expected.js @@ -66,4 +66,4 @@ class Component extends SvelteComponent { } } -export default Component; \ No newline at end of file +export default Component; diff --git a/test/store/index.ts b/test/store/index.ts index 6f5ef6abdd..a39fab86e6 100644 --- a/test/store/index.ts +++ b/test/store/index.ts @@ -233,6 +233,30 @@ describe('store', () => { unsubscribe(); }); + it('derived dependency does not update and shared ancestor updates', () => { + const root = writable({ a: 0, b:0 }); + const values = []; + + const a = derived(root, $root => { + return 'a' + $root.a; + }); + + const b = derived([a, root], ([$a, $root]) => { + return 'b' + $root.b + $a; + }); + + const unsubscribe = b.subscribe(v => { + values.push(v); + }); + + assert.deepEqual(values, ['b0a0']); + + root.set({ a: 0, b: 1 }); + assert.deepEqual(values, ['b0a0', 'b1a0']); + + unsubscribe(); + }); + it('is updated with safe_not_equal logic', () => { const arr = [0];