Skip to content

Commit

Permalink
Merge pull request #3219 from btakita/gh-3191
Browse files Browse the repository at this point in the history
Breadth First Subscriber Resolution
  • Loading branch information
Rich-Harris authored Jul 26, 2019
2 parents 729fc4e + 95b2a72 commit 7dee7fa
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 26 deletions.
42 changes: 17 additions & 25 deletions src/runtime/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ export interface Writable<T> extends Readable<T> {
/** Pair of subscriber and invalidator. */
type SubscribeInvalidateTuple<T> = [Subscriber<T>, Invalidator<T>];

const subscriber_queue = [];

/**
* Creates a `Readable` store that allows reading by subscription.
* @param value initial value
Expand All @@ -67,11 +69,20 @@ export function writable<T>(value: T, start: StartStopNotifier<T> = 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));
}
}

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

const auto = fn.length < 2;

const invalidators: Array<Invalidator<T>> = [];

const store = readable(initial_value, (set) => {
return readable(initial_value, (set) => {
let inited = false;
const values: StoresValues<S> = [] as StoresValues<S>;

Expand Down Expand Up @@ -160,7 +169,6 @@ export function derived<T, S extends Stores>(
}
},
() => {
run_all(invalidators);
pending |= (1 << i);
}),
);
Expand All @@ -173,20 +181,4 @@ export function derived<T, S extends Stores>(
cleanup();
};
});

return {
subscribe(run: Subscriber<T>, invalidate: Invalidator<T> = 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();
};
}
};
}
}
2 changes: 1 addition & 1 deletion test/js/samples/bind-open/expected.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,4 @@ class Component extends SvelteComponent {
}
}

export default Component;
export default Component;
24 changes: 24 additions & 0 deletions test/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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];

Expand Down

0 comments on commit 7dee7fa

Please sign in to comment.