-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathcore.ts
More file actions
64 lines (55 loc) · 1.93 KB
/
core.ts
File metadata and controls
64 lines (55 loc) · 1.93 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
63
64
// The core of a fine-grained reactivity library.
let currentEffect: (() => void) | undefined
/** Runs a function and tracks any dependencies within it. */
export function effect<T>(fn: () => T): T {
const parentEffect = currentEffect
currentEffect = fn
const value = fn()
currentEffect = parentEffect
return value
}
/** Prevents events from being tracked during the function call. */
export function untrack<T>(fn: () => T): T {
const parentEffect = currentEffect
currentEffect = undefined
const value = fn()
currentEffect = parentEffect
return value
}
let currentBatch: Set<Set<() => void>> | undefined
const queue = (action: Set<() => void>): void =>
void (currentBatch?.add(action) || action.forEach((fn) => fn()))
/**
* Creates a tuple of track, trigger, and cleanup functions. When `track` is
* called, the currently running effect (if any) is added to an internal
* tracking list. When `trigger` is called, all effects that have been tracked
* are re-run. When `cleanup` is called, the internal tracking list is cleared.
*/
export function event(): readonly [track: () => void, trigger: () => void] {
const tracking = new Set<() => void>()
return [
() => currentEffect && tracking.add(currentEffect),
() => queue(tracking),
]
}
/** Batches all `trigger` calls within the function and calls them all at once. */
export function batch<T>(fn: () => T): T {
const parentBatch = currentBatch
currentBatch = new Set()
const value = fn()
currentBatch.forEach((set) => set.forEach((fn) => fn()))
currentBatch.clear()
currentBatch = parentBatch
return value
}
/**
* Ignores the effect of a containing `batch` block and immediately runs
* `trigger`s inside the passed function.
*/
export function instant<T>(fn: () => T): T {
const parentBatch = currentBatch
currentBatch = undefined
const value = fn()
currentBatch = parentBatch
return value
}