Skip to content

Commit 38330c9

Browse files
authored
Merge pull request #2955 from sveltejs/gh-2660
solve diamond dependencies
2 parents 77bb111 + 0d31e5c commit 38330c9

File tree

2 files changed

+53
-6
lines changed

2 files changed

+53
-6
lines changed

src/runtime/store/index.ts

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ type Unsubscriber = () => void;
1010
type Updater<T> = (value: T) => T;
1111

1212
/** Cleanup logic callback. */
13-
type Invalidater<T> = (value?: T) => void;
13+
type Invalidator<T> = (value?: T) => void;
1414

1515
/** Start and stop notification callbacks. */
1616
type StartStopNotifier<T> = (set: Subscriber<T>) => Unsubscriber | void;
@@ -22,7 +22,7 @@ export interface Readable<T> {
2222
* @param run subscription callback
2323
* @param invalidate cleanup callback
2424
*/
25-
subscribe(run: Subscriber<T>, invalidate?: Invalidater<T>): Unsubscriber;
25+
subscribe(run: Subscriber<T>, invalidate?: Invalidator<T>): Unsubscriber;
2626
}
2727

2828
/** Writable interface for both updating and subscribing. */
@@ -41,7 +41,7 @@ export interface Writable<T> extends Readable<T> {
4141
}
4242

4343
/** Pair of subscriber and invalidator. */
44-
type SubscribeInvalidateTuple<T> = [Subscriber<T>, Invalidater<T>];
44+
type SubscribeInvalidateTuple<T> = [Subscriber<T>, Invalidator<T>];
4545

4646
/**
4747
* Creates a `Readable` store that allows reading by subscription.
@@ -78,7 +78,7 @@ export function writable<T>(value: T, start: StartStopNotifier<T> = noop): Writa
7878
set(fn(value));
7979
}
8080

81-
function subscribe(run: Subscriber<T>, invalidate: Invalidater<T> = noop): Unsubscriber {
81+
function subscribe(run: Subscriber<T>, invalidate: Invalidator<T> = noop): Unsubscriber {
8282
const subscriber: SubscribeInvalidateTuple<T> = [run, invalidate];
8383
subscribers.push(subscriber);
8484
if (subscribers.length === 1) {
@@ -127,7 +127,9 @@ export function derived<T, S extends Stores>(
127127

128128
const auto = fn.length < 2;
129129

130-
return readable(initial_value, (set) => {
130+
const invalidators: Array<Invalidator<T>> = [];
131+
132+
const store = readable(initial_value, (set) => {
131133
let inited = false;
132134
const values: StoresValues<S> = [] as StoresValues<S>;
133135

@@ -156,6 +158,7 @@ export function derived<T, S extends Stores>(
156158
}
157159
},
158160
() => {
161+
run_all(invalidators);
159162
pending |= (1 << i);
160163
}),
161164
);
@@ -168,6 +171,22 @@ export function derived<T, S extends Stores>(
168171
cleanup();
169172
};
170173
});
174+
175+
return {
176+
subscribe(run: Subscriber<T>, invalidate: Invalidator<T> = noop): Unsubscriber {
177+
invalidators.push(invalidate);
178+
179+
const unsubscribe = store.subscribe(run, invalidate);
180+
181+
return () => {
182+
const index = invalidators.indexOf(invalidate);
183+
if (index !== -1) {
184+
invalidators.splice(index, 1);
185+
}
186+
unsubscribe();
187+
};
188+
}
189+
}
171190
}
172191

173192
/**
@@ -178,4 +197,4 @@ export function get<T>(store: Readable<T>): T {
178197
let value: T | undefined;
179198
store.subscribe((_: T) => value = _)();
180199
return value as T;
181-
}
200+
}

test/store/index.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,34 @@ describe('store', () => {
189189
unsubscribe();
190190
});
191191

192+
it('prevents diamond dependency problem', () => {
193+
const count = writable(0);
194+
const values = [];
195+
196+
const a = derived(count, $count => {
197+
return 'a' + $count;
198+
});
199+
200+
const b = derived(count, $count => {
201+
return 'b' + $count;
202+
});
203+
204+
const combined = derived([a, b], ([a, b]) => {
205+
return a + b;
206+
});
207+
208+
const unsubscribe = combined.subscribe(v => {
209+
values.push(v);
210+
});
211+
212+
assert.deepEqual(values, ['a0b0']);
213+
214+
count.set(1);
215+
assert.deepEqual(values, ['a0b0', 'a1b1']);
216+
217+
unsubscribe();
218+
});
219+
192220
it('is updated with safe_not_equal logic', () => {
193221
const arr = [0];
194222

0 commit comments

Comments
 (0)