@zeix/cause-effect 0.17.3 → 0.18.1

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.
Files changed (94) hide show
  1. package/.ai-context.md +169 -227
  2. package/.cursorrules +41 -35
  3. package/.github/copilot-instructions.md +176 -116
  4. package/ARCHITECTURE.md +276 -0
  5. package/CHANGELOG.md +29 -0
  6. package/CLAUDE.md +201 -143
  7. package/GUIDE.md +298 -0
  8. package/README.md +246 -193
  9. package/REQUIREMENTS.md +100 -0
  10. package/bench/reactivity.bench.ts +577 -0
  11. package/context7.json +4 -0
  12. package/examples/events-sensor.ts +187 -0
  13. package/examples/selector-sensor.ts +173 -0
  14. package/index.dev.js +1390 -1008
  15. package/index.js +1 -1
  16. package/index.ts +60 -74
  17. package/package.json +5 -2
  18. package/skills/changelog-keeper/SKILL.md +59 -0
  19. package/skills/changelog-keeper/agents/openai.yaml +4 -0
  20. package/src/errors.ts +118 -74
  21. package/src/graph.ts +612 -0
  22. package/src/nodes/collection.ts +512 -0
  23. package/src/nodes/effect.ts +149 -0
  24. package/src/nodes/list.ts +589 -0
  25. package/src/nodes/memo.ts +148 -0
  26. package/src/nodes/sensor.ts +149 -0
  27. package/src/nodes/state.ts +135 -0
  28. package/src/nodes/store.ts +378 -0
  29. package/src/nodes/task.ts +174 -0
  30. package/src/signal.ts +112 -66
  31. package/src/util.ts +26 -57
  32. package/test/batch.test.ts +96 -62
  33. package/test/benchmark.test.ts +473 -487
  34. package/test/collection.test.ts +456 -707
  35. package/test/effect.test.ts +293 -696
  36. package/test/list.test.ts +335 -592
  37. package/test/memo.test.ts +574 -0
  38. package/test/regression.test.ts +156 -0
  39. package/test/scope.test.ts +191 -0
  40. package/test/sensor.test.ts +454 -0
  41. package/test/signal.test.ts +220 -213
  42. package/test/state.test.ts +217 -265
  43. package/test/store.test.ts +346 -446
  44. package/test/task.test.ts +529 -0
  45. package/test/untrack.test.ts +167 -0
  46. package/types/index.d.ts +13 -15
  47. package/types/src/errors.d.ts +73 -17
  48. package/types/src/graph.d.ts +218 -0
  49. package/types/src/nodes/collection.d.ts +69 -0
  50. package/types/src/nodes/effect.d.ts +48 -0
  51. package/types/src/nodes/list.d.ts +66 -0
  52. package/types/src/nodes/memo.d.ts +63 -0
  53. package/types/src/nodes/sensor.d.ts +81 -0
  54. package/types/src/nodes/state.d.ts +78 -0
  55. package/types/src/nodes/store.d.ts +51 -0
  56. package/types/src/nodes/task.d.ts +79 -0
  57. package/types/src/signal.d.ts +43 -29
  58. package/types/src/util.d.ts +9 -16
  59. package/archive/benchmark.ts +0 -683
  60. package/archive/collection.ts +0 -253
  61. package/archive/composite.ts +0 -85
  62. package/archive/computed.ts +0 -195
  63. package/archive/list.ts +0 -483
  64. package/archive/memo.ts +0 -139
  65. package/archive/state.ts +0 -90
  66. package/archive/store.ts +0 -298
  67. package/archive/task.ts +0 -189
  68. package/src/classes/collection.ts +0 -245
  69. package/src/classes/computed.ts +0 -349
  70. package/src/classes/list.ts +0 -343
  71. package/src/classes/ref.ts +0 -70
  72. package/src/classes/state.ts +0 -102
  73. package/src/classes/store.ts +0 -262
  74. package/src/diff.ts +0 -138
  75. package/src/effect.ts +0 -93
  76. package/src/match.ts +0 -45
  77. package/src/resolve.ts +0 -49
  78. package/src/system.ts +0 -257
  79. package/test/computed.test.ts +0 -1108
  80. package/test/diff.test.ts +0 -955
  81. package/test/match.test.ts +0 -388
  82. package/test/ref.test.ts +0 -353
  83. package/test/resolve.test.ts +0 -154
  84. package/types/src/classes/collection.d.ts +0 -45
  85. package/types/src/classes/computed.d.ts +0 -94
  86. package/types/src/classes/list.d.ts +0 -43
  87. package/types/src/classes/ref.d.ts +0 -35
  88. package/types/src/classes/state.d.ts +0 -49
  89. package/types/src/classes/store.d.ts +0 -52
  90. package/types/src/diff.d.ts +0 -28
  91. package/types/src/effect.d.ts +0 -15
  92. package/types/src/match.d.ts +0 -21
  93. package/types/src/resolve.d.ts +0 -29
  94. package/types/src/system.d.ts +0 -78
package/src/graph.ts ADDED
@@ -0,0 +1,612 @@
1
+ import { CircularDependencyError, type Guard } from './errors'
2
+
3
+ /* === Internal Types === */
4
+
5
+ type SourceFields<T extends {}> = {
6
+ value: T
7
+ sinks: Edge | null
8
+ sinksTail: Edge | null
9
+ stop?: Cleanup
10
+ }
11
+
12
+ type OptionsFields<T extends {}> = {
13
+ equals: (a: T, b: T) => boolean
14
+ guard?: Guard<T>
15
+ }
16
+
17
+ type SinkFields = {
18
+ fn: unknown
19
+ flags: number
20
+ sources: Edge | null
21
+ sourcesTail: Edge | null
22
+ }
23
+
24
+ type OwnerFields = {
25
+ cleanup: Cleanup | Cleanup[] | null
26
+ }
27
+
28
+ type AsyncFields = {
29
+ controller: AbortController | undefined
30
+ error: Error | undefined
31
+ }
32
+
33
+ type StateNode<T extends {}> = SourceFields<T> & OptionsFields<T>
34
+
35
+ type MemoNode<T extends {}> = SourceFields<T> &
36
+ OptionsFields<T> &
37
+ SinkFields & {
38
+ fn: MemoCallback<T>
39
+ error: Error | undefined
40
+ }
41
+
42
+ type TaskNode<T extends {}> = SourceFields<T> &
43
+ OptionsFields<T> &
44
+ SinkFields &
45
+ AsyncFields & {
46
+ fn: (prev: T, abort: AbortSignal) => Promise<T>
47
+ }
48
+
49
+ type EffectNode = SinkFields &
50
+ OwnerFields & {
51
+ fn: EffectCallback
52
+ }
53
+
54
+ type Scope = OwnerFields
55
+
56
+ type SourceNode = SourceFields<unknown & {}>
57
+ type SinkNode = MemoNode<unknown & {}> | TaskNode<unknown & {}> | EffectNode
58
+ type OwnerNode = EffectNode | Scope
59
+
60
+ type Edge = {
61
+ source: SourceNode
62
+ sink: SinkNode
63
+ nextSource: Edge | null
64
+ prevSink: Edge | null
65
+ nextSink: Edge | null
66
+ }
67
+
68
+ /* === Public API Types === */
69
+
70
+ type Signal<T extends {}> = {
71
+ get(): T
72
+ }
73
+
74
+ /**
75
+ * A cleanup function that can be called to dispose of resources.
76
+ */
77
+ type Cleanup = () => void
78
+
79
+ // biome-ignore lint/suspicious/noConfusingVoidType: optional Cleanup return type
80
+ type MaybeCleanup = Cleanup | undefined | void
81
+
82
+ /**
83
+ * Options for configuring signal behavior.
84
+ *
85
+ * @template T - The type of value in the signal
86
+ */
87
+ type SignalOptions<T extends {}> = {
88
+ /**
89
+ * Optional type guard to validate values.
90
+ * If provided, will throw an error if an invalid value is set.
91
+ */
92
+ guard?: Guard<T>
93
+
94
+ /**
95
+ * Optional custom equality function.
96
+ * Used to determine if a new value is different from the old value.
97
+ * Defaults to reference equality (===).
98
+ */
99
+ equals?: (a: T, b: T) => boolean
100
+ }
101
+
102
+ type ComputedOptions<T extends {}> = SignalOptions<T> & {
103
+ /**
104
+ * Optional initial value.
105
+ * Useful for reducer patterns so that calculations start with a value of correct type.
106
+ */
107
+ value?: T
108
+
109
+ /**
110
+ * Optional callback invoked when the signal is first watched by an effect.
111
+ * Receives an `invalidate` function that marks the signal dirty and triggers re-evaluation.
112
+ * Must return a cleanup function that is called when the signal is no longer watched.
113
+ *
114
+ * This enables lazy resource activation for computed signals that need to
115
+ * react to external events (e.g. DOM mutations, timers) in addition to
116
+ * tracked signal dependencies.
117
+ */
118
+ watched?: (invalidate: () => void) => Cleanup
119
+ }
120
+
121
+ /**
122
+ * A callback function for memos that computes a value based on the previous value.
123
+ *
124
+ * @template T - The type of value computed
125
+ * @param prev - The previous computed value
126
+ * @returns The new computed value
127
+ */
128
+ type MemoCallback<T extends {}> = (prev: T | undefined) => T
129
+
130
+ /**
131
+ * A callback function for tasks that asynchronously computes a value.
132
+ *
133
+ * @template T - The type of value computed
134
+ * @param prev - The previous computed value
135
+ * @param signal - An AbortSignal that will be triggered if the task is aborted
136
+ * @returns A promise that resolves to the new computed value
137
+ */
138
+ type TaskCallback<T extends {}> = (
139
+ prev: T | undefined,
140
+ signal: AbortSignal,
141
+ ) => Promise<T>
142
+
143
+ /**
144
+ * A callback function for effects that can perform side effects.
145
+ *
146
+ * @returns An optional cleanup function that will be called before the effect re-runs or is disposed
147
+ */
148
+ type EffectCallback = () => MaybeCleanup
149
+
150
+ /* === Constants === */
151
+
152
+ const TYPE_STATE = 'State'
153
+ const TYPE_MEMO = 'Memo'
154
+ const TYPE_TASK = 'Task'
155
+ const TYPE_SENSOR = 'Sensor'
156
+ const TYPE_LIST = 'List'
157
+ const TYPE_COLLECTION = 'Collection'
158
+ const TYPE_STORE = 'Store'
159
+
160
+ const FLAG_CLEAN = 0
161
+ const FLAG_CHECK = 1 << 0
162
+ const FLAG_DIRTY = 1 << 1
163
+ const FLAG_RUNNING = 1 << 2
164
+
165
+ /* === Module State === */
166
+
167
+ let activeSink: SinkNode | null = null
168
+ let activeOwner: OwnerNode | null = null
169
+ const queuedEffects: EffectNode[] = []
170
+ let batchDepth = 0
171
+ let flushing = false
172
+
173
+ /* === Utility Functions === */
174
+
175
+ const DEFAULT_EQUALITY = <T extends {}>(a: T, b: T): boolean => a === b
176
+
177
+ /**
178
+ * Equality function that always returns false, causing propagation on every update.
179
+ * Use with `createSensor` for observing mutable objects where the reference stays the same
180
+ * but internal state changes (e.g., DOM elements observed via MutationObserver).
181
+ *
182
+ * @example
183
+ * ```ts
184
+ * const el = createSensor<HTMLElement>((set) => {
185
+ * const node = document.getElementById('box')!;
186
+ * set(node);
187
+ * const obs = new MutationObserver(() => set(node));
188
+ * obs.observe(node, { attributes: true });
189
+ * return () => obs.disconnect();
190
+ * }, { value: node, equals: SKIP_EQUALITY });
191
+ * ```
192
+ */
193
+ const SKIP_EQUALITY = (_a?: unknown, _b?: unknown): boolean => false
194
+
195
+ /* === Link Management === */
196
+
197
+ function isValidEdge(checkEdge: Edge, node: SinkNode): boolean {
198
+ const sourcesTail = node.sourcesTail
199
+ if (sourcesTail) {
200
+ let edge = node.sources
201
+ while (edge) {
202
+ if (edge === checkEdge) return true
203
+ if (edge === sourcesTail) break
204
+ edge = edge.nextSource
205
+ }
206
+ }
207
+ return false
208
+ }
209
+
210
+ function link(source: SourceNode, sink: SinkNode): void {
211
+ const prevSource = sink.sourcesTail
212
+ if (prevSource?.source === source) return
213
+
214
+ let nextSource: Edge | null = null
215
+ const isRecomputing = sink.flags & FLAG_RUNNING
216
+ if (isRecomputing) {
217
+ nextSource = prevSource ? prevSource.nextSource : sink.sources
218
+ if (nextSource?.source === source) {
219
+ sink.sourcesTail = nextSource
220
+ return
221
+ }
222
+ }
223
+
224
+ const prevSink = source.sinksTail
225
+ if (
226
+ prevSink?.sink === sink &&
227
+ (!isRecomputing || isValidEdge(prevSink, sink))
228
+ )
229
+ return
230
+
231
+ const newEdge = { source, sink, nextSource, prevSink, nextSink: null }
232
+ sink.sourcesTail = source.sinksTail = newEdge
233
+ if (prevSource) prevSource.nextSource = newEdge
234
+ else sink.sources = newEdge
235
+ if (prevSink) prevSink.nextSink = newEdge
236
+ else source.sinks = newEdge
237
+ }
238
+
239
+ function unlink(edge: Edge): Edge | null {
240
+ const { source, nextSource, nextSink, prevSink } = edge
241
+
242
+ if (nextSink) nextSink.prevSink = prevSink
243
+ else source.sinksTail = prevSink
244
+ if (prevSink) prevSink.nextSink = nextSink
245
+ else source.sinks = nextSink
246
+
247
+ if (!source.sinks && source.stop) {
248
+ source.stop()
249
+ source.stop = undefined
250
+ }
251
+
252
+ return nextSource
253
+ }
254
+
255
+ function trimSources(node: SinkNode): void {
256
+ const tail = node.sourcesTail
257
+ let source = tail ? tail.nextSource : node.sources
258
+ while (source) source = unlink(source)
259
+ if (tail) tail.nextSource = null
260
+ else node.sources = null
261
+ }
262
+
263
+ /* === Propagation === */
264
+
265
+ function propagate(node: SinkNode, newFlag = FLAG_DIRTY): void {
266
+ const flags = node.flags
267
+
268
+ if ('sinks' in node) {
269
+ if ((flags & (FLAG_DIRTY | FLAG_CHECK)) >= newFlag) return
270
+
271
+ node.flags = flags | newFlag
272
+
273
+ // Abort in-flight work when sources change
274
+ if ('controller' in node && node.controller) {
275
+ node.controller.abort()
276
+ node.controller = undefined
277
+ }
278
+
279
+ // Propagate Check to sinks
280
+ for (let e = node.sinks; e; e = e.nextSink)
281
+ propagate(e.sink, FLAG_CHECK)
282
+ } else {
283
+ if (flags & FLAG_DIRTY) return
284
+
285
+ // Enqueue effect for later execution
286
+ node.flags = FLAG_DIRTY
287
+ queuedEffects.push(node as EffectNode)
288
+ }
289
+ }
290
+
291
+ /* === State Management === */
292
+
293
+ function setState<T extends {}>(node: StateNode<T>, next: T): void {
294
+ if (node.equals(node.value, next)) return
295
+
296
+ node.value = next
297
+ for (let e = node.sinks; e; e = e.nextSink) propagate(e.sink)
298
+ if (batchDepth === 0) flush()
299
+ }
300
+
301
+ /* === Cleanup Management === */
302
+
303
+ function registerCleanup(owner: OwnerNode, fn: Cleanup): void {
304
+ if (!owner.cleanup) owner.cleanup = fn
305
+ else if (Array.isArray(owner.cleanup)) owner.cleanup.push(fn)
306
+ else owner.cleanup = [owner.cleanup, fn]
307
+ }
308
+
309
+ function runCleanup(owner: OwnerNode): void {
310
+ if (!owner.cleanup) return
311
+
312
+ if (Array.isArray(owner.cleanup))
313
+ for (let i = 0; i < owner.cleanup.length; i++) owner.cleanup[i]()
314
+ else owner.cleanup()
315
+ owner.cleanup = null
316
+ }
317
+
318
+ /* === Recomputation === */
319
+
320
+ function recomputeMemo(node: MemoNode<unknown & {}>): void {
321
+ const prevWatcher = activeSink
322
+ activeSink = node
323
+ node.sourcesTail = null
324
+ node.flags = FLAG_RUNNING
325
+
326
+ let changed = false
327
+ try {
328
+ const next = node.fn(node.value)
329
+ if (node.error || !node.equals(next, node.value)) {
330
+ node.value = next
331
+ node.error = undefined
332
+ changed = true
333
+ }
334
+ } catch (err: unknown) {
335
+ changed = true
336
+ node.error = err instanceof Error ? err : new Error(String(err))
337
+ } finally {
338
+ activeSink = prevWatcher
339
+ trimSources(node)
340
+ }
341
+
342
+ if (changed) {
343
+ for (let e = node.sinks; e; e = e.nextSink)
344
+ if (e.sink.flags & FLAG_CHECK) e.sink.flags |= FLAG_DIRTY
345
+ }
346
+
347
+ node.flags = FLAG_CLEAN
348
+ }
349
+
350
+ function recomputeTask(node: TaskNode<unknown & {}>): void {
351
+ node.controller?.abort()
352
+
353
+ const controller = new AbortController()
354
+ node.controller = controller
355
+ node.error = undefined
356
+
357
+ const prevWatcher = activeSink
358
+ activeSink = node
359
+ node.sourcesTail = null
360
+ node.flags = FLAG_RUNNING
361
+
362
+ let promise: Promise<unknown & {}>
363
+ try {
364
+ promise = node.fn(node.value, controller.signal)
365
+ } catch (err) {
366
+ node.controller = undefined
367
+ node.error = err instanceof Error ? err : new Error(String(err))
368
+ return
369
+ } finally {
370
+ activeSink = prevWatcher
371
+ trimSources(node)
372
+ }
373
+
374
+ promise.then(
375
+ next => {
376
+ if (controller.signal.aborted) return
377
+
378
+ node.controller = undefined
379
+ if (node.error || !node.equals(next, node.value)) {
380
+ node.value = next
381
+ node.error = undefined
382
+ for (let e = node.sinks; e; e = e.nextSink) propagate(e.sink)
383
+ if (batchDepth === 0) flush()
384
+ }
385
+ },
386
+ (err: unknown) => {
387
+ if (controller.signal.aborted) return
388
+
389
+ node.controller = undefined
390
+ const error = err instanceof Error ? err : new Error(String(err))
391
+ if (
392
+ !node.error ||
393
+ error.name !== node.error.name ||
394
+ error.message !== node.error.message
395
+ ) {
396
+ // We don't clear old value on errors
397
+ node.error = error
398
+ for (let e = node.sinks; e; e = e.nextSink) propagate(e.sink)
399
+ if (batchDepth === 0) flush()
400
+ }
401
+ },
402
+ )
403
+
404
+ node.flags = FLAG_CLEAN
405
+ }
406
+
407
+ function runEffect(node: EffectNode): void {
408
+ runCleanup(node)
409
+ const prevContext = activeSink
410
+ const prevOwner = activeOwner
411
+ activeSink = activeOwner = node
412
+ node.sourcesTail = null
413
+ node.flags = FLAG_RUNNING
414
+
415
+ try {
416
+ const out = node.fn()
417
+ if (typeof out === 'function') registerCleanup(node, out)
418
+ } finally {
419
+ activeSink = prevContext
420
+ activeOwner = prevOwner
421
+ trimSources(node)
422
+ }
423
+
424
+ node.flags = FLAG_CLEAN
425
+ }
426
+
427
+ function refresh(node: SinkNode): void {
428
+ if (node.flags & FLAG_CHECK) {
429
+ for (let e = node.sources; e; e = e.nextSource) {
430
+ if ('fn' in e.source) refresh(e.source as SinkNode)
431
+ if (node.flags & FLAG_DIRTY) break
432
+ }
433
+ }
434
+
435
+ if (node.flags & FLAG_RUNNING) {
436
+ throw new CircularDependencyError(
437
+ 'controller' in node
438
+ ? TYPE_TASK
439
+ : 'value' in node
440
+ ? TYPE_MEMO
441
+ : 'Effect',
442
+ )
443
+ }
444
+
445
+ if (node.flags & FLAG_DIRTY) {
446
+ if ('controller' in node) recomputeTask(node)
447
+ else if ('value' in node) recomputeMemo(node)
448
+ else runEffect(node)
449
+ } else {
450
+ node.flags = FLAG_CLEAN
451
+ }
452
+ }
453
+
454
+ /* === Batching === */
455
+
456
+ function flush(): void {
457
+ if (flushing) return
458
+ flushing = true
459
+ try {
460
+ for (let i = 0; i < queuedEffects.length; i++) {
461
+ const effect = queuedEffects[i]
462
+ if (effect.flags & FLAG_DIRTY) refresh(effect)
463
+ }
464
+ queuedEffects.length = 0
465
+ } finally {
466
+ flushing = false
467
+ }
468
+ }
469
+
470
+ /**
471
+ * Batches multiple signal updates together.
472
+ * Effects will not run until the batch completes.
473
+ * Batches can be nested; effects run when the outermost batch completes.
474
+ *
475
+ * @param fn - The function to execute within the batch
476
+ *
477
+ * @example
478
+ * ```ts
479
+ * const count = createState(0);
480
+ * const double = createMemo(() => count.get() * 2);
481
+ *
482
+ * batch(() => {
483
+ * count.set(1);
484
+ * count.set(2);
485
+ * count.set(3);
486
+ * // Effects run only once at the end with count = 3
487
+ * });
488
+ * ```
489
+ */
490
+ function batch(fn: () => void): void {
491
+ batchDepth++
492
+ try {
493
+ fn()
494
+ } finally {
495
+ batchDepth--
496
+ if (batchDepth === 0) flush()
497
+ }
498
+ }
499
+
500
+ /**
501
+ * Runs a callback without tracking dependencies.
502
+ * Any signal reads inside the callback will not create edges to the current active sink.
503
+ *
504
+ * @param fn - The function to execute without tracking
505
+ * @returns The return value of the function
506
+ *
507
+ * @example
508
+ * ```ts
509
+ * const count = createState(0);
510
+ * const label = createState('Count');
511
+ *
512
+ * createEffect(() => {
513
+ * // Only re-runs when count changes, not when label changes
514
+ * const name = untrack(() => label.get());
515
+ * console.log(`${name}: ${count.get()}`);
516
+ * });
517
+ * ```
518
+ */
519
+ function untrack<T>(fn: () => T): T {
520
+ const prev = activeSink
521
+ activeSink = null
522
+ try {
523
+ return fn()
524
+ } finally {
525
+ activeSink = prev
526
+ }
527
+ }
528
+
529
+ /* === Scope Management === */
530
+
531
+ /**
532
+ * Creates a new ownership scope for managing cleanup of nested effects and resources.
533
+ * All effects created within the scope will be automatically disposed when the scope is disposed.
534
+ * Scopes can be nested - disposing a parent scope disposes all child scopes.
535
+ *
536
+ * @param fn - The function to execute within the scope, may return a cleanup function
537
+ * @returns A dispose function that cleans up the scope
538
+ *
539
+ * @example
540
+ * ```ts
541
+ * const dispose = createScope(() => {
542
+ * const count = createState(0);
543
+ *
544
+ * createEffect(() => {
545
+ * console.log(count.get());
546
+ * });
547
+ *
548
+ * return () => console.log('Scope disposed');
549
+ * });
550
+ *
551
+ * dispose(); // Cleans up the effect and runs cleanup callbacks
552
+ * ```
553
+ */
554
+ function createScope(fn: () => MaybeCleanup): Cleanup {
555
+ const prevOwner = activeOwner
556
+ const scope: Scope = { cleanup: null }
557
+ activeOwner = scope
558
+
559
+ try {
560
+ const out = fn()
561
+ if (typeof out === 'function') registerCleanup(scope, out)
562
+ const dispose = () => runCleanup(scope)
563
+ if (prevOwner) registerCleanup(prevOwner, dispose)
564
+ return dispose
565
+ } finally {
566
+ activeOwner = prevOwner
567
+ }
568
+ }
569
+
570
+ export {
571
+ type Cleanup,
572
+ type ComputedOptions,
573
+ type EffectCallback,
574
+ type EffectNode,
575
+ type MaybeCleanup,
576
+ type MemoCallback,
577
+ type MemoNode,
578
+ type Scope,
579
+ type Signal,
580
+ type SignalOptions,
581
+ type SinkNode,
582
+ type StateNode,
583
+ type TaskCallback,
584
+ type TaskNode,
585
+ activeOwner,
586
+ activeSink,
587
+ batch,
588
+ batchDepth,
589
+ createScope,
590
+ DEFAULT_EQUALITY,
591
+ SKIP_EQUALITY,
592
+ FLAG_CLEAN,
593
+ FLAG_DIRTY,
594
+ flush,
595
+ link,
596
+ propagate,
597
+ refresh,
598
+ registerCleanup,
599
+ runCleanup,
600
+ runEffect,
601
+ setState,
602
+ trimSources,
603
+ TYPE_COLLECTION,
604
+ TYPE_LIST,
605
+ TYPE_MEMO,
606
+ TYPE_SENSOR,
607
+ TYPE_STATE,
608
+ TYPE_STORE,
609
+ TYPE_TASK,
610
+ unlink,
611
+ untrack,
612
+ }