Skip to content

Commit

Permalink
handle derivation from multiple signals
Browse files Browse the repository at this point in the history
  • Loading branch information
AlessioCoser committed Apr 3, 2024
1 parent 4d25fd7 commit 78d48c3
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 9 deletions.
18 changes: 10 additions & 8 deletions src/reactivity/utils/Subscriptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Subscriber, _Signal } from "../types";

export class Subscriptions {
private currentSubscriber: Subscriber | null = null;
private ancestors = new Map<_Signal<any>, _Signal<any>>();
private ancestors = new MapSet<_Signal<any>, _Signal<any>>();
private subscriptions = new MapSet<_Signal<any>, Subscriber>();

run(subscriber: Subscriber, fn: () => void): void {
Expand All @@ -22,10 +22,12 @@ export class Subscriptions {
}

if (subscriber.derived) {
this.ancestors.set(subscriber.derived, signal);
this.ancestors.addTo(subscriber.derived, signal);
}

this.subscriptions.addTo(this._getAncestor(signal), subscriber);
this._getAncestors(signal).forEach((ancestor) => {
this.subscriptions.addTo(ancestor, subscriber);
});
}

executeAllSubscriptionsTo(signal: _Signal<any>) {
Expand All @@ -35,12 +37,12 @@ export class Subscriptions {
.forEach((subscriber) => subscriber.execute());
}

private _getAncestor(signal: _Signal<any>): _Signal<any> {
const ancestor = this.ancestors.get(signal);
if (!ancestor) {
return signal;
private _getAncestors(signal: _Signal<any>): _Signal<any>[] {
const ancestors = this.ancestors.get(signal);
if (!ancestors || ancestors.length === 0) {
return [signal];
}

return this._getAncestor(ancestor);
return ancestors.flatMap((ancestor) => this._getAncestors(ancestor));
}
}
46 changes: 46 additions & 0 deletions test/reactivity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,4 +188,50 @@ describe("reactivity", () => {
"14px 14pt",
]);
});

it("derive from multiple signals", () => {
const calls: string[] = [];
const [count, setCount] = signal(1);
const [name, setName] = signal("First");
const nameAndCount = d`${name} -> ${count}`

effect(() => calls.push(nameAndCount()));

setCount(5);
setName("Second");
setName("Third");
setCount(7);

expect(calls).toEqual([
"First -> 1",
"First -> 5",
"Second -> 5",
"Third -> 5",
"Third -> 7",
]);
});

it("derive from multiple signals and other derivations", () => {
const calls: string[] = [];
const [count, setCount] = signal(1);
const [name, setName] = signal("First");
const nameAndCount = d`${name} -> ${count}`
const sum = derive(0, () => count() + count())
const sumText = d`${nameAndCount} + ${count} = ${sum}`

effect(() => calls.push(sumText()));

setCount(5);
setName("Second");
setName("Third");
setCount(7);

expect(calls).toEqual([
"First -> 1 + 1 = 2",
"First -> 5 + 5 = 10",
"Second -> 5 + 5 = 10",
"Third -> 5 + 5 = 10",
"Third -> 7 + 7 = 14",
]);
});
});
2 changes: 1 addition & 1 deletion vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default defineConfig({
environment: "jsdom",
coverage: {
reporter: ["text", "html"],
exclude: [ "index.ts", "examples/**" ],
exclude: [ "index.ts", "examples/**", "cdn/**" ],
},
}
});

0 comments on commit 78d48c3

Please sign in to comment.