@zeix/cause-effect 0.17.1 → 0.17.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.ai-context.md +13 -0
- package/.github/copilot-instructions.md +4 -0
- package/.zed/settings.json +3 -0
- package/CLAUDE.md +41 -7
- package/README.md +48 -25
- package/archive/benchmark.ts +0 -5
- package/archive/collection.ts +6 -65
- package/archive/composite.ts +85 -0
- package/archive/computed.ts +18 -20
- package/archive/list.ts +7 -75
- package/archive/memo.ts +15 -15
- package/archive/state.ts +2 -1
- package/archive/store.ts +8 -78
- package/archive/task.ts +20 -25
- package/index.dev.js +508 -526
- package/index.js +1 -1
- package/index.ts +9 -11
- package/package.json +6 -6
- package/src/classes/collection.ts +70 -107
- package/src/classes/computed.ts +165 -149
- package/src/classes/list.ts +145 -107
- package/src/classes/ref.ts +19 -17
- package/src/classes/state.ts +21 -17
- package/src/classes/store.ts +125 -73
- package/src/diff.ts +2 -1
- package/src/effect.ts +17 -10
- package/src/errors.ts +14 -1
- package/src/resolve.ts +1 -1
- package/src/signal.ts +3 -2
- package/src/system.ts +159 -61
- package/src/util.ts +0 -6
- package/test/batch.test.ts +4 -11
- package/test/benchmark.test.ts +4 -2
- package/test/collection.test.ts +106 -107
- package/test/computed.test.ts +351 -112
- package/test/effect.test.ts +2 -2
- package/test/list.test.ts +62 -102
- package/test/ref.test.ts +128 -2
- package/test/state.test.ts +16 -22
- package/test/store.test.ts +101 -108
- package/test/util/dependency-graph.ts +2 -2
- package/tsconfig.build.json +11 -0
- package/tsconfig.json +5 -7
- package/types/index.d.ts +3 -3
- package/types/src/classes/collection.d.ts +9 -10
- package/types/src/classes/computed.d.ts +17 -20
- package/types/src/classes/list.d.ts +8 -6
- package/types/src/classes/ref.d.ts +8 -12
- package/types/src/classes/state.d.ts +5 -8
- package/types/src/classes/store.d.ts +14 -13
- package/types/src/effect.d.ts +1 -2
- package/types/src/errors.d.ts +2 -1
- package/types/src/signal.d.ts +3 -2
- package/types/src/system.d.ts +47 -34
- package/types/src/util.d.ts +1 -2
- package/src/classes/composite.ts +0 -176
- package/types/src/classes/composite.d.ts +0 -15
package/archive/list.ts
CHANGED
|
@@ -7,16 +7,10 @@ import {
|
|
|
7
7
|
} from '../src/errors'
|
|
8
8
|
import { isMutableSignal, type MutableSignal } from '../src/signal'
|
|
9
9
|
import {
|
|
10
|
-
|
|
11
|
-
type Cleanup,
|
|
12
|
-
createWatcher,
|
|
13
|
-
emitNotification,
|
|
14
|
-
type Listener,
|
|
15
|
-
type Listeners,
|
|
16
|
-
type Notifications,
|
|
10
|
+
batch,
|
|
17
11
|
notifyWatchers,
|
|
18
12
|
subscribeActiveWatcher,
|
|
19
|
-
|
|
13
|
+
UNSET,
|
|
20
14
|
type Watcher,
|
|
21
15
|
} from '../src/system'
|
|
22
16
|
import {
|
|
@@ -26,7 +20,6 @@ import {
|
|
|
26
20
|
isRecord,
|
|
27
21
|
isString,
|
|
28
22
|
isSymbol,
|
|
29
|
-
UNSET,
|
|
30
23
|
} from '../src/util'
|
|
31
24
|
import {
|
|
32
25
|
type Collection,
|
|
@@ -63,7 +56,6 @@ type List<T extends {}> = {
|
|
|
63
56
|
update(fn: (value: T) => T): void
|
|
64
57
|
sort<U = T>(compareFn?: (a: U, b: U) => number): void
|
|
65
58
|
splice(start: number, deleteCount?: number, ...items: T[]): T[]
|
|
66
|
-
on<K extends keyof Notifications>(type: K, listener: Listener<K>): Cleanup
|
|
67
59
|
remove(index: number): void
|
|
68
60
|
}
|
|
69
61
|
|
|
@@ -90,12 +82,6 @@ const createList = <T extends {}>(
|
|
|
90
82
|
if (initialValue == null) throw new NullishSignalValueError('store')
|
|
91
83
|
|
|
92
84
|
const watchers = new Set<Watcher>()
|
|
93
|
-
const listeners: Listeners = {
|
|
94
|
-
add: new Set<Listener<'add'>>(),
|
|
95
|
-
change: new Set<Listener<'change'>>(),
|
|
96
|
-
remove: new Set<Listener<'remove'>>(),
|
|
97
|
-
sort: new Set<Listener<'sort'>>(),
|
|
98
|
-
}
|
|
99
85
|
const signals = new Map<string, MutableSignal<T>>()
|
|
100
86
|
const ownWatchers = new Map<string, Watcher>()
|
|
101
87
|
|
|
@@ -158,17 +144,6 @@ const createList = <T extends {}>(
|
|
|
158
144
|
return true
|
|
159
145
|
}
|
|
160
146
|
|
|
161
|
-
// Add own watcher for nested signal
|
|
162
|
-
const addOwnWatcher = (key: string, signal: MutableSignal<T>) => {
|
|
163
|
-
const watcher = createWatcher(() => {
|
|
164
|
-
trackSignalReads(watcher, () => {
|
|
165
|
-
signal.get() // Subscribe to the signal
|
|
166
|
-
emitNotification(listeners.change, [key])
|
|
167
|
-
})
|
|
168
|
-
})
|
|
169
|
-
ownWatchers.set(key, watcher)
|
|
170
|
-
}
|
|
171
|
-
|
|
172
147
|
// Add nested signal and own watcher
|
|
173
148
|
const addProperty = <K extends keyof T & string>(
|
|
174
149
|
key: K,
|
|
@@ -190,12 +165,9 @@ const createList = <T extends {}>(
|
|
|
190
165
|
// @ts-expect-error ignore
|
|
191
166
|
signals.set(key, signal)
|
|
192
167
|
if (!order.includes(key)) order.push(key)
|
|
193
|
-
// @ts-expect-error ignore
|
|
194
|
-
if (listeners.change.size) addOwnWatcher(key, signal)
|
|
195
168
|
|
|
196
169
|
if (single) {
|
|
197
170
|
notifyWatchers(watchers)
|
|
198
|
-
emitNotification(listeners.add, [key])
|
|
199
171
|
}
|
|
200
172
|
return true
|
|
201
173
|
}
|
|
@@ -218,29 +190,21 @@ const createList = <T extends {}>(
|
|
|
218
190
|
if (single) {
|
|
219
191
|
order = order.filter(() => true) // Compact array
|
|
220
192
|
notifyWatchers(watchers)
|
|
221
|
-
emitNotification(listeners.remove, [key])
|
|
222
193
|
}
|
|
223
194
|
}
|
|
224
195
|
|
|
225
196
|
// Commit batched changes and emit notifications
|
|
226
|
-
const batchChanges = (changes: DiffResult
|
|
197
|
+
const batchChanges = (changes: DiffResult) => {
|
|
227
198
|
// Additions
|
|
228
199
|
if (Object.keys(changes.add).length) {
|
|
229
200
|
for (const key in changes.add)
|
|
230
201
|
// @ts-expect-error ignore
|
|
231
202
|
addProperty(key, changes.add[key] as T, false)
|
|
232
|
-
|
|
233
|
-
// Queue initial additions event to allow listeners to be added first
|
|
234
|
-
if (initialRun)
|
|
235
|
-
setTimeout(() => {
|
|
236
|
-
emitNotification(listeners.add, Object.keys(changes.add))
|
|
237
|
-
}, 0)
|
|
238
|
-
else emitNotification(listeners.add, Object.keys(changes.add))
|
|
239
203
|
}
|
|
240
204
|
|
|
241
205
|
// Changes
|
|
242
206
|
if (Object.keys(changes.change).length) {
|
|
243
|
-
|
|
207
|
+
batch(() => {
|
|
244
208
|
for (const key in changes.change) {
|
|
245
209
|
const value = changes.change[key] as T
|
|
246
210
|
if (!isValidValue(key, value)) continue
|
|
@@ -249,7 +213,6 @@ const createList = <T extends {}>(
|
|
|
249
213
|
if (isMutableSignal(signal)) signal.set(value)
|
|
250
214
|
else throw new ReadonlySignalError(key, value)
|
|
251
215
|
}
|
|
252
|
-
emitNotification(listeners.change, Object.keys(changes.change))
|
|
253
216
|
})
|
|
254
217
|
}
|
|
255
218
|
|
|
@@ -257,25 +220,17 @@ const createList = <T extends {}>(
|
|
|
257
220
|
if (Object.keys(changes.remove).length) {
|
|
258
221
|
for (const key in changes.remove) removeProperty(key)
|
|
259
222
|
order = order.filter(() => true)
|
|
260
|
-
emitNotification(listeners.remove, Object.keys(changes.remove))
|
|
261
223
|
}
|
|
262
224
|
|
|
263
225
|
return changes.changed
|
|
264
226
|
}
|
|
265
227
|
|
|
266
228
|
// Reconcile data and dispatch events
|
|
267
|
-
const reconcile = (
|
|
268
|
-
oldValue
|
|
269
|
-
newValue: T[],
|
|
270
|
-
initialRun?: boolean,
|
|
271
|
-
): boolean =>
|
|
272
|
-
batchChanges(
|
|
273
|
-
diff(arrayToRecord(oldValue), arrayToRecord(newValue)),
|
|
274
|
-
initialRun,
|
|
275
|
-
)
|
|
229
|
+
const reconcile = (oldValue: T[], newValue: T[]): boolean =>
|
|
230
|
+
batchChanges(diff(arrayToRecord(oldValue), arrayToRecord(newValue)))
|
|
276
231
|
|
|
277
232
|
// Initialize data
|
|
278
|
-
reconcile([] as T[], initialValue
|
|
233
|
+
reconcile([] as T[], initialValue)
|
|
279
234
|
|
|
280
235
|
// Methods and Properties
|
|
281
236
|
const prototype: Record<PropertyKey, unknown> = {}
|
|
@@ -401,7 +356,6 @@ const createList = <T extends {}>(
|
|
|
401
356
|
if (!isEqual(newOrder, order)) {
|
|
402
357
|
order = newOrder
|
|
403
358
|
notifyWatchers(watchers)
|
|
404
|
-
emitNotification(listeners.sort, order)
|
|
405
359
|
}
|
|
406
360
|
},
|
|
407
361
|
},
|
|
@@ -472,28 +426,6 @@ const createList = <T extends {}>(
|
|
|
472
426
|
return Object.values(remove) as T[]
|
|
473
427
|
},
|
|
474
428
|
},
|
|
475
|
-
on: {
|
|
476
|
-
value: <K extends keyof Notifications>(
|
|
477
|
-
type: K,
|
|
478
|
-
listener: Listener<K>,
|
|
479
|
-
): Cleanup => {
|
|
480
|
-
listeners[type].add(listener)
|
|
481
|
-
if (type === 'change' && !ownWatchers.size) {
|
|
482
|
-
for (const [key, signal] of signals)
|
|
483
|
-
addOwnWatcher(key, signal)
|
|
484
|
-
}
|
|
485
|
-
return () => {
|
|
486
|
-
listeners[type].delete(listener)
|
|
487
|
-
if (type === 'change' && !listeners.change.size) {
|
|
488
|
-
if (ownWatchers.size) {
|
|
489
|
-
for (const watcher of ownWatchers.values())
|
|
490
|
-
watcher.stop()
|
|
491
|
-
ownWatchers.clear()
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
},
|
|
496
|
-
},
|
|
497
429
|
})
|
|
498
430
|
|
|
499
431
|
// Return proxy directly with integrated signal methods
|
package/archive/memo.ts
CHANGED
|
@@ -6,13 +6,13 @@ import {
|
|
|
6
6
|
} from '../src/errors'
|
|
7
7
|
import {
|
|
8
8
|
createWatcher,
|
|
9
|
-
|
|
9
|
+
flush,
|
|
10
10
|
notifyWatchers,
|
|
11
11
|
subscribeActiveWatcher,
|
|
12
|
-
|
|
12
|
+
UNSET,
|
|
13
13
|
type Watcher,
|
|
14
14
|
} from '../src/system'
|
|
15
|
-
import { isObjectOfType, isSyncFunction
|
|
15
|
+
import { isObjectOfType, isSyncFunction } from '../src/util'
|
|
16
16
|
|
|
17
17
|
/* === Types === */
|
|
18
18
|
|
|
@@ -53,15 +53,13 @@ const createMemo = <T extends {}>(
|
|
|
53
53
|
let computing = false
|
|
54
54
|
|
|
55
55
|
// Own watcher: called when notified from sources (push)
|
|
56
|
-
const watcher = createWatcher(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const compute = () =>
|
|
64
|
-
trackSignalReads(watcher, () => {
|
|
56
|
+
const watcher = createWatcher(
|
|
57
|
+
() => {
|
|
58
|
+
dirty = true
|
|
59
|
+
if (watchers.size) notifyWatchers(watchers)
|
|
60
|
+
else watcher.stop()
|
|
61
|
+
},
|
|
62
|
+
() => {
|
|
65
63
|
if (computing) throw new CircularDependencyError('memo')
|
|
66
64
|
let result: T
|
|
67
65
|
computing = true
|
|
@@ -86,7 +84,8 @@ const createMemo = <T extends {}>(
|
|
|
86
84
|
dirty = false
|
|
87
85
|
}
|
|
88
86
|
computing = false
|
|
89
|
-
}
|
|
87
|
+
},
|
|
88
|
+
)
|
|
90
89
|
|
|
91
90
|
const memo: Record<PropertyKey, unknown> = {}
|
|
92
91
|
Object.defineProperties(memo, {
|
|
@@ -96,8 +95,9 @@ const createMemo = <T extends {}>(
|
|
|
96
95
|
get: {
|
|
97
96
|
value: (): T => {
|
|
98
97
|
subscribeActiveWatcher(watchers)
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
flush()
|
|
99
|
+
|
|
100
|
+
if (dirty) watcher.run()
|
|
101
101
|
if (error) throw error
|
|
102
102
|
return value
|
|
103
103
|
},
|
package/archive/state.ts
CHANGED
|
@@ -3,9 +3,10 @@ import { InvalidCallbackError, NullishSignalValueError } from '../src/errors'
|
|
|
3
3
|
import {
|
|
4
4
|
notifyWatchers,
|
|
5
5
|
subscribeActiveWatcher,
|
|
6
|
+
UNSET,
|
|
6
7
|
type Watcher,
|
|
7
8
|
} from '../src/system'
|
|
8
|
-
import { isFunction, isObjectOfType
|
|
9
|
+
import { isFunction, isObjectOfType } from '../src/util'
|
|
9
10
|
|
|
10
11
|
/* === Types === */
|
|
11
12
|
|
package/archive/store.ts
CHANGED
|
@@ -7,25 +7,13 @@ import {
|
|
|
7
7
|
} from '../src/errors'
|
|
8
8
|
import { isMutableSignal, type MutableSignal } from '../src/signal'
|
|
9
9
|
import {
|
|
10
|
-
|
|
11
|
-
type Cleanup,
|
|
12
|
-
createWatcher,
|
|
13
|
-
emitNotification,
|
|
14
|
-
type Listener,
|
|
15
|
-
type Listeners,
|
|
16
|
-
type Notifications,
|
|
10
|
+
batch,
|
|
17
11
|
notifyWatchers,
|
|
18
12
|
subscribeActiveWatcher,
|
|
19
|
-
|
|
13
|
+
UNSET,
|
|
20
14
|
type Watcher,
|
|
21
15
|
} from '../src/system'
|
|
22
|
-
import {
|
|
23
|
-
isFunction,
|
|
24
|
-
isObjectOfType,
|
|
25
|
-
isRecord,
|
|
26
|
-
isSymbol,
|
|
27
|
-
UNSET,
|
|
28
|
-
} from '../src/util'
|
|
16
|
+
import { isFunction, isObjectOfType, isRecord, isSymbol } from '../src/util'
|
|
29
17
|
import { isComputed } from './computed'
|
|
30
18
|
import { createList, isList, type List } from './list'
|
|
31
19
|
import { createState, isState, type State } from './state'
|
|
@@ -62,7 +50,6 @@ type Store<T extends UnknownRecord> = {
|
|
|
62
50
|
sort<U = T[Extract<keyof T, string>]>(
|
|
63
51
|
compareFn?: (a: U, b: U) => number,
|
|
64
52
|
): void
|
|
65
|
-
on<K extends keyof Notifications>(type: K, listener: Listener<K>): Cleanup
|
|
66
53
|
remove<K extends Extract<keyof T, string>>(key: K): void
|
|
67
54
|
}
|
|
68
55
|
|
|
@@ -92,11 +79,6 @@ const createStore = <T extends UnknownRecord>(initialValue: T): Store<T> => {
|
|
|
92
79
|
if (initialValue == null) throw new NullishSignalValueError('store')
|
|
93
80
|
|
|
94
81
|
const watchers = new Set<Watcher>()
|
|
95
|
-
const listeners: Omit<Listeners, 'sort'> = {
|
|
96
|
-
add: new Set<Listener<'add'>>(),
|
|
97
|
-
change: new Set<Listener<'change'>>(),
|
|
98
|
-
remove: new Set<Listener<'remove'>>(),
|
|
99
|
-
}
|
|
100
82
|
const signals = new Map<
|
|
101
83
|
string,
|
|
102
84
|
MutableSignal<T[Extract<keyof T, string>] & {}>
|
|
@@ -123,20 +105,6 @@ const createStore = <T extends UnknownRecord>(initialValue: T): Store<T> => {
|
|
|
123
105
|
return true
|
|
124
106
|
}
|
|
125
107
|
|
|
126
|
-
// Add own watcher for nested signal
|
|
127
|
-
const addOwnWatcher = <K extends keyof T & string>(
|
|
128
|
-
key: K,
|
|
129
|
-
signal: MutableSignal<T[K] & {}>,
|
|
130
|
-
) => {
|
|
131
|
-
const watcher = createWatcher(() => {
|
|
132
|
-
trackSignalReads(watcher, () => {
|
|
133
|
-
signal.get() // Subscribe to the signal
|
|
134
|
-
emitNotification(listeners.change, [key])
|
|
135
|
-
})
|
|
136
|
-
})
|
|
137
|
-
ownWatchers.set(key, watcher)
|
|
138
|
-
}
|
|
139
|
-
|
|
140
108
|
// Add nested signal and effect
|
|
141
109
|
const addProperty = <K extends keyof T & string>(
|
|
142
110
|
key: K,
|
|
@@ -159,11 +127,9 @@ const createStore = <T extends UnknownRecord>(initialValue: T): Store<T> => {
|
|
|
159
127
|
// Set internal states
|
|
160
128
|
// @ts-expect-error non-matching signal types
|
|
161
129
|
signals.set(key, signal)
|
|
162
|
-
if (listeners.change.size) addOwnWatcher(key, signal)
|
|
163
130
|
|
|
164
131
|
if (single) {
|
|
165
132
|
notifyWatchers(watchers)
|
|
166
|
-
emitNotification(listeners.add, [key])
|
|
167
133
|
}
|
|
168
134
|
return true
|
|
169
135
|
}
|
|
@@ -183,12 +149,11 @@ const createStore = <T extends UnknownRecord>(initialValue: T): Store<T> => {
|
|
|
183
149
|
|
|
184
150
|
if (single) {
|
|
185
151
|
notifyWatchers(watchers)
|
|
186
|
-
emitNotification(listeners.remove, [key])
|
|
187
152
|
}
|
|
188
153
|
}
|
|
189
154
|
|
|
190
155
|
// Commit batched changes and emit notifications
|
|
191
|
-
const batchChanges = (changes: DiffResult
|
|
156
|
+
const batchChanges = (changes: DiffResult) => {
|
|
192
157
|
// Additions
|
|
193
158
|
if (Object.keys(changes.add).length) {
|
|
194
159
|
for (const key in changes.add)
|
|
@@ -197,18 +162,11 @@ const createStore = <T extends UnknownRecord>(initialValue: T): Store<T> => {
|
|
|
197
162
|
changes.add[key] as T[Extract<keyof T, string>] & {},
|
|
198
163
|
false,
|
|
199
164
|
)
|
|
200
|
-
|
|
201
|
-
// Queue initial additions event to allow listeners to be added first
|
|
202
|
-
if (initialRun)
|
|
203
|
-
setTimeout(() => {
|
|
204
|
-
emitNotification(listeners.add, Object.keys(changes.add))
|
|
205
|
-
}, 0)
|
|
206
|
-
else emitNotification(listeners.add, Object.keys(changes.add))
|
|
207
165
|
}
|
|
208
166
|
|
|
209
167
|
// Changes
|
|
210
168
|
if (Object.keys(changes.change).length) {
|
|
211
|
-
|
|
169
|
+
batch(() => {
|
|
212
170
|
for (const key in changes.change) {
|
|
213
171
|
const value = changes.change[key] as T[Extract<
|
|
214
172
|
keyof T,
|
|
@@ -220,28 +178,23 @@ const createStore = <T extends UnknownRecord>(initialValue: T): Store<T> => {
|
|
|
220
178
|
if (isMutableSignal(signal)) signal.set(value)
|
|
221
179
|
else throw new ReadonlySignalError(key, value)
|
|
222
180
|
}
|
|
223
|
-
emitNotification(listeners.change, Object.keys(changes.change))
|
|
224
181
|
})
|
|
225
182
|
}
|
|
226
183
|
|
|
227
184
|
// Removals
|
|
228
185
|
if (Object.keys(changes.remove).length) {
|
|
229
186
|
for (const key in changes.remove) removeProperty(key)
|
|
230
|
-
emitNotification(listeners.remove, Object.keys(changes.remove))
|
|
231
187
|
}
|
|
232
188
|
|
|
233
189
|
return changes.changed
|
|
234
190
|
}
|
|
235
191
|
|
|
236
192
|
// Reconcile data and dispatch events
|
|
237
|
-
const reconcile = (
|
|
238
|
-
oldValue
|
|
239
|
-
newValue: T,
|
|
240
|
-
initialRun?: boolean,
|
|
241
|
-
): boolean => batchChanges(diff(oldValue, newValue), initialRun)
|
|
193
|
+
const reconcile = (oldValue: T, newValue: T): boolean =>
|
|
194
|
+
batchChanges(diff(oldValue, newValue))
|
|
242
195
|
|
|
243
196
|
// Initialize data
|
|
244
|
-
reconcile({} as T, initialValue
|
|
197
|
+
reconcile({} as T, initialValue)
|
|
245
198
|
|
|
246
199
|
// Methods and Properties
|
|
247
200
|
const prototype: Record<PropertyKey, unknown> = {}
|
|
@@ -295,29 +248,6 @@ const createStore = <T extends UnknownRecord>(initialValue: T): Store<T> => {
|
|
|
295
248
|
store.set(fn(current()))
|
|
296
249
|
},
|
|
297
250
|
},
|
|
298
|
-
on: {
|
|
299
|
-
value: <K extends keyof Omit<Listeners, 'sort'>>(
|
|
300
|
-
type: K,
|
|
301
|
-
listener: Listener<K>,
|
|
302
|
-
): Cleanup => {
|
|
303
|
-
listeners[type].add(listener)
|
|
304
|
-
if (type === 'change' && !ownWatchers.size) {
|
|
305
|
-
for (const [key, signal] of signals)
|
|
306
|
-
// @ts-expect-error ignore
|
|
307
|
-
addOwnWatcher(key, signal)
|
|
308
|
-
}
|
|
309
|
-
return () => {
|
|
310
|
-
listeners[type].delete(listener)
|
|
311
|
-
if (type === 'change' && !listeners.change.size) {
|
|
312
|
-
if (ownWatchers.size) {
|
|
313
|
-
for (const watcher of ownWatchers.values())
|
|
314
|
-
watcher.stop()
|
|
315
|
-
ownWatchers.clear()
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
},
|
|
320
|
-
},
|
|
321
251
|
})
|
|
322
252
|
|
|
323
253
|
// Return proxy directly with integrated signal methods
|
package/archive/task.ts
CHANGED
|
@@ -7,18 +7,13 @@ import {
|
|
|
7
7
|
} from '../src/errors'
|
|
8
8
|
import {
|
|
9
9
|
createWatcher,
|
|
10
|
-
|
|
10
|
+
flush,
|
|
11
11
|
notifyWatchers,
|
|
12
12
|
subscribeActiveWatcher,
|
|
13
|
-
|
|
13
|
+
UNSET,
|
|
14
14
|
type Watcher,
|
|
15
15
|
} from '../src/system'
|
|
16
|
-
import {
|
|
17
|
-
isAbortError,
|
|
18
|
-
isAsyncFunction,
|
|
19
|
-
isObjectOfType,
|
|
20
|
-
UNSET,
|
|
21
|
-
} from '../src/util'
|
|
16
|
+
import { isAbortError, isAsyncFunction, isObjectOfType } from '../src/util'
|
|
22
17
|
|
|
23
18
|
/* === Types === */
|
|
24
19
|
|
|
@@ -96,19 +91,14 @@ const createTask = <T extends {}>(
|
|
|
96
91
|
}
|
|
97
92
|
|
|
98
93
|
// Own watcher: called when notified from sources (push)
|
|
99
|
-
const watcher = createWatcher(
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
// Called when requested by dependencies (pull)
|
|
110
|
-
const compute = () =>
|
|
111
|
-
trackSignalReads(watcher, () => {
|
|
94
|
+
const watcher = createWatcher(
|
|
95
|
+
() => {
|
|
96
|
+
dirty = true
|
|
97
|
+
controller?.abort()
|
|
98
|
+
if (watchers.size) notifyWatchers(watchers)
|
|
99
|
+
else watcher.stop()
|
|
100
|
+
},
|
|
101
|
+
() => {
|
|
112
102
|
if (computing) throw new CircularDependencyError('computed')
|
|
113
103
|
changed = false
|
|
114
104
|
// Return current value until promise resolves
|
|
@@ -120,7 +110,7 @@ const createTask = <T extends {}>(
|
|
|
120
110
|
() => {
|
|
121
111
|
computing = false
|
|
122
112
|
controller = undefined
|
|
123
|
-
|
|
113
|
+
watcher.run() // Retry computation with updated state
|
|
124
114
|
},
|
|
125
115
|
{
|
|
126
116
|
once: true,
|
|
@@ -141,7 +131,11 @@ const createTask = <T extends {}>(
|
|
|
141
131
|
else if (null == result || UNSET === result) nil()
|
|
142
132
|
else ok(result)
|
|
143
133
|
computing = false
|
|
144
|
-
}
|
|
134
|
+
},
|
|
135
|
+
)
|
|
136
|
+
watcher.onCleanup(() => {
|
|
137
|
+
controller?.abort()
|
|
138
|
+
})
|
|
145
139
|
|
|
146
140
|
const task: Record<PropertyKey, unknown> = {}
|
|
147
141
|
Object.defineProperties(task, {
|
|
@@ -151,8 +145,9 @@ const createTask = <T extends {}>(
|
|
|
151
145
|
get: {
|
|
152
146
|
value: (): T => {
|
|
153
147
|
subscribeActiveWatcher(watchers)
|
|
154
|
-
|
|
155
|
-
|
|
148
|
+
flush()
|
|
149
|
+
|
|
150
|
+
if (dirty) watcher.run()
|
|
156
151
|
if (error) throw error
|
|
157
152
|
return value
|
|
158
153
|
},
|