Skip to content

Commit 7dee7fa

Browse files
authored
Merge pull request #3219 from btakita/gh-3191
Breadth First Subscriber Resolution
2 parents 729fc4e + 95b2a72 commit 7dee7fa

File tree

3 files changed

+42
-26
lines changed

3 files changed

+42
-26
lines changed

src/runtime/store/index.ts

+17-25
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ export interface Writable<T> extends Readable<T> {
4444
/** Pair of subscriber and invalidator. */
4545
type SubscribeInvalidateTuple<T> = [Subscriber<T>, Invalidator<T>];
4646

47+
const subscriber_queue = [];
48+
4749
/**
4850
* Creates a `Readable` store that allows reading by subscription.
4951
* @param value initial value
@@ -67,11 +69,20 @@ export function writable<T>(value: T, start: StartStopNotifier<T> = noop): Writa
6769
function set(new_value: T): void {
6870
if (safe_not_equal(value, new_value)) {
6971
value = new_value;
70-
if (!stop) {
71-
return; // not ready
72+
if (stop) { // store is ready
73+
const run_queue = !subscriber_queue.length;
74+
for (let i = 0; i < subscribers.length; i += 1) {
75+
const s = subscribers[i];
76+
s[1]();
77+
subscriber_queue.push(s, value);
78+
}
79+
if (run_queue) {
80+
for (let i = 0; i < subscriber_queue.length; i += 2) {
81+
subscriber_queue[i][0](subscriber_queue[i + 1]);
82+
}
83+
subscriber_queue.length = 0;
84+
}
7285
}
73-
subscribers.forEach((s) => s[1]());
74-
subscribers.forEach((s) => s[0](value));
7586
}
7687
}
7788

@@ -129,9 +140,7 @@ export function derived<T, S extends Stores>(
129140

130141
const auto = fn.length < 2;
131142

132-
const invalidators: Array<Invalidator<T>> = [];
133-
134-
const store = readable(initial_value, (set) => {
143+
return readable(initial_value, (set) => {
135144
let inited = false;
136145
const values: StoresValues<S> = [] as StoresValues<S>;
137146

@@ -160,7 +169,6 @@ export function derived<T, S extends Stores>(
160169
}
161170
},
162171
() => {
163-
run_all(invalidators);
164172
pending |= (1 << i);
165173
}),
166174
);
@@ -173,20 +181,4 @@ export function derived<T, S extends Stores>(
173181
cleanup();
174182
};
175183
});
176-
177-
return {
178-
subscribe(run: Subscriber<T>, invalidate: Invalidator<T> = noop): Unsubscriber {
179-
invalidators.push(invalidate);
180-
181-
const unsubscribe = store.subscribe(run, invalidate);
182-
183-
return () => {
184-
const index = invalidators.indexOf(invalidate);
185-
if (index !== -1) {
186-
invalidators.splice(index, 1);
187-
}
188-
unsubscribe();
189-
};
190-
}
191-
};
192-
}
184+
}

test/js/samples/bind-open/expected.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,4 @@ class Component extends SvelteComponent {
6666
}
6767
}
6868

69-
export default Component;
69+
export default Component;

test/store/index.ts

+24
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,30 @@ describe('store', () => {
233233
unsubscribe();
234234
});
235235

236+
it('derived dependency does not update and shared ancestor updates', () => {
237+
const root = writable({ a: 0, b:0 });
238+
const values = [];
239+
240+
const a = derived(root, $root => {
241+
return 'a' + $root.a;
242+
});
243+
244+
const b = derived([a, root], ([$a, $root]) => {
245+
return 'b' + $root.b + $a;
246+
});
247+
248+
const unsubscribe = b.subscribe(v => {
249+
values.push(v);
250+
});
251+
252+
assert.deepEqual(values, ['b0a0']);
253+
254+
root.set({ a: 0, b: 1 });
255+
assert.deepEqual(values, ['b0a0', 'b1a0']);
256+
257+
unsubscribe();
258+
});
259+
236260
it('is updated with safe_not_equal logic', () => {
237261
const arr = [0];
238262

0 commit comments

Comments
 (0)