-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathsignal.ts
More file actions
62 lines (51 loc) · 1.14 KB
/
signal.ts
File metadata and controls
62 lines (51 loc) · 1.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/** --- Reactivity Types --- **/
export interface RunningEffect {
execute: () => void;
dependencies: Set<Set<RunningEffect>>;
}
export interface Signal<T> {
(): T;
set: (nextValue: T) => void;
}
const context: RunningEffect[] = [];
export function signal<T>(value: T): Signal<T> {
const subscriptions = new Set<RunningEffect>();
const read: any = () => {
const running = context[context.length - 1];
if (running) {
subscriptions.add(running);
running.dependencies.add(subscriptions);
}
return value;
};
const set = (nextValue: T) => {
value = nextValue;
for (const sub of [...subscriptions]) {
sub.execute();
}
};
read.set = set;
return read as Signal<T>;
}
function cleanup(running: RunningEffect) {
for (const dep of running.dependencies) {
dep.delete(running);
}
running.dependencies.clear();
}
export function effect(fn: () => void) {
const execute = () => {
cleanup(running);
context.push(running);
try {
fn();
} finally {
context.pop();
}
};
const running: RunningEffect = {
execute,
dependencies: new Set()
};
execute();
}