@esportsplus/reactivity 0.30.2 → 0.31.0

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/src/system.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  import {
2
- COMPUTED,
3
2
  SIGNAL,
4
3
  STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED,
5
- STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_NOTIFY_MASK, STATE_RECOMPUTING
4
+ STATE_CHECK, STATE_COMPUTED, STATE_DIRTY, STATE_IN_HEAP, STATE_NOTIFY_MASK, STATE_RECOMPUTING
6
5
  } from './constants';
7
6
  import { Computed, Link, Signal } from './types';
8
7
  import { isObject } from '@esportsplus/utilities';
@@ -12,8 +11,7 @@ let depth = 0,
12
11
  heap: (Computed<unknown> | undefined)[] = new Array(64),
13
12
  heap_i = 0,
14
13
  heap_n = 0,
15
- linkPool: Link[] = [],
16
- linkPoolMax = 1000,
14
+ linkPoolHead: Link | null = null,
17
15
  microtask = queueMicrotask,
18
16
  notified = false,
19
17
  observer: Computed<unknown> | null = null,
@@ -138,11 +136,12 @@ function link<T>(dep: Signal<T> | Computed<T>, sub: Computed<T>) {
138
136
  return;
139
137
  }
140
138
 
141
- let pooled = linkPool.pop(),
139
+ let pooled = linkPoolHead,
142
140
  newLink =
143
141
  sub.depsTail =
144
142
  dep.subsTail = pooled
145
- ? (pooled.dep = dep,
143
+ ? (linkPoolHead = pooled.nextDep,
144
+ pooled.dep = dep,
146
145
  pooled.sub = sub,
147
146
  pooled.nextDep = nextDep,
148
147
  pooled.prevSub = prevSub,
@@ -173,7 +172,7 @@ function link<T>(dep: Signal<T> | Computed<T>, sub: Computed<T>) {
173
172
  }
174
173
  }
175
174
 
176
- function notify<T>(computed: Computed<T>, newState = STATE_DIRTY) {
175
+ function notify<T>(computed: Computed<T>, newState: number) {
177
176
  let state = computed.state;
178
177
 
179
178
  if ((state & STATE_NOTIFY_MASK) >= newState) {
@@ -206,7 +205,7 @@ function recompute<T>(computed: Computed<T>, del: boolean) {
206
205
 
207
206
  observer = computed;
208
207
  computed.depsTail = null;
209
- computed.state = STATE_RECOMPUTING;
208
+ computed.state = STATE_COMPUTED | STATE_RECOMPUTING;
210
209
 
211
210
  depth++;
212
211
  version++;
@@ -220,7 +219,7 @@ function recompute<T>(computed: Computed<T>, del: boolean) {
220
219
 
221
220
  depth--;
222
221
  observer = o;
223
- computed.state = STATE_NONE;
222
+ computed.state = STATE_COMPUTED;
224
223
 
225
224
  let depsTail = computed.depsTail as Link | null,
226
225
  remove = depsTail ? depsTail.nextDep : computed.deps;
@@ -298,6 +297,7 @@ function stabilize() {
298
297
  observer = o;
299
298
 
300
299
  if (stabilizer === STABILIZER_RESCHEDULE) {
300
+ stabilizer = STABILIZER_SCHEDULED;
301
301
  microtask(stabilize);
302
302
  }
303
303
  else {
@@ -322,16 +322,14 @@ function unlink(link: Link): Link | null {
322
322
  if (prevSub) {
323
323
  prevSub.nextSub = nextSub;
324
324
  }
325
- else if ((dep.subs = nextSub) === null && dep.type === COMPUTED) {
326
- dispose(dep);
325
+ else if ((dep.subs = nextSub) === null && (dep as Computed<unknown>).state & STATE_COMPUTED) {
326
+ dispose(dep as Computed<unknown>);
327
327
  }
328
328
 
329
- // Release link back to pool
330
- if (linkPool.length < linkPoolMax) {
331
- link.dep = link.sub = null as any;
332
- link.nextDep = link.nextSub = link.prevSub = null;
333
- linkPool.push(link);
334
- }
329
+ link.dep = link.sub = null as any;
330
+ link.nextSub = link.prevSub = null;
331
+ link.nextDep = linkPoolHead;
332
+ linkPoolHead = link;
335
333
 
336
334
  return nextDep;
337
335
  }
@@ -341,8 +339,8 @@ function update<T>(computed: Computed<T>): void {
341
339
  for (let link = computed.deps; link; link = link.nextDep) {
342
340
  let dep = link.dep;
343
341
 
344
- if (dep.type === COMPUTED) {
345
- update(dep);
342
+ if ((dep as Computed<unknown>).state & STATE_COMPUTED) {
343
+ update(dep as Computed<unknown>);
346
344
 
347
345
  if (computed.state & STATE_DIRTY) {
348
346
  break;
@@ -355,10 +353,28 @@ function update<T>(computed: Computed<T>): void {
355
353
  recompute(computed, true);
356
354
  }
357
355
 
358
- computed.state = STATE_NONE;
356
+ computed.state = STATE_COMPUTED;
359
357
  }
360
358
 
361
359
 
360
+ const asyncComputed = <T>(fn: Computed<Promise<T>>['fn']): Signal<T | undefined> => {
361
+ let factory = computed(fn),
362
+ node = signal<T | undefined>(undefined),
363
+ v = 0;
364
+
365
+ onCleanup(effect(() => {
366
+ let id = ++v;
367
+
368
+ (read(factory) as Promise<T>).then((value) => {
369
+ if (id === v) {
370
+ write(node, value);
371
+ }
372
+ }, () => {});
373
+ }));
374
+
375
+ return node;
376
+ };
377
+
362
378
  const computed = <T>(fn: Computed<T>['fn']): Computed<T> => {
363
379
  let self: Computed<T> = {
364
380
  cleanup: null,
@@ -368,10 +384,9 @@ const computed = <T>(fn: Computed<T>['fn']): Computed<T> => {
368
384
  height: 0,
369
385
  nextHeap: undefined,
370
386
  prevHeap: null as any,
371
- state: STATE_NONE,
387
+ state: STATE_COMPUTED,
372
388
  subs: null,
373
389
  subsTail: null,
374
- type: COMPUTED,
375
390
  value: undefined as T,
376
391
  };
377
392
 
@@ -428,7 +443,7 @@ const effect = <T>(fn: Computed<T>['fn']) => {
428
443
  };
429
444
 
430
445
  const isComputed = (value: unknown): value is Computed<unknown> => {
431
- return isObject(value) && value.type === COMPUTED;
446
+ return isObject(value) && !!((value as unknown as Computed<unknown>).state & STATE_COMPUTED);
432
447
  };
433
448
 
434
449
  const isSignal = (value: unknown): value is Signal<unknown> => {
@@ -461,25 +476,25 @@ const read = <T>(node: Signal<T> | Computed<T>): T => {
461
476
  if (observer) {
462
477
  link(node, observer);
463
478
 
464
- if (node.type === COMPUTED) {
465
- let height = node.height;
479
+ if ((node as Computed<unknown>).state & STATE_COMPUTED) {
480
+ let height = (node as Computed<T>).height;
466
481
 
467
482
  if (height >= observer.height) {
468
483
  observer.height = height + 1;
469
484
  }
470
485
 
471
- if (height >= heap_i || node.state & STATE_NOTIFY_MASK) {
486
+ if (height >= heap_i || (node as Computed<T>).state & STATE_NOTIFY_MASK) {
472
487
  if (!notified) {
473
488
  notified = true;
474
489
 
475
490
  for (let i = 0; i <= heap_n; i++) {
476
491
  for (let computed = heap[i]; computed !== undefined; computed = computed.nextHeap) {
477
- notify(computed);
492
+ notify(computed, STATE_DIRTY);
478
493
  }
479
494
  }
480
495
  }
481
496
 
482
- update(node);
497
+ update(node as Computed<T>);
483
498
  }
484
499
  }
485
500
  }
@@ -500,7 +515,7 @@ const root = <T>(fn: ((dispose: VoidFunction) => T) | (() => T)) => {
500
515
  root.disposables = 0;
501
516
 
502
517
  if (tracking) {
503
- scope = self = { cleanup: null } as Computed<unknown>;
518
+ scope = self = { cleanup: null, state: STATE_COMPUTED } as Computed<unknown>;
504
519
  value = (fn as (dispose: VoidFunction) => T)(c = () => dispose(self!));
505
520
  }
506
521
  else {
@@ -535,13 +550,14 @@ const write = <T>(signal: Signal<T>, value: T) => {
535
550
  return;
536
551
  }
537
552
 
538
- notified = false;
539
553
  signal.value = value;
540
554
 
541
555
  if (signal.subs === null) {
542
556
  return;
543
557
  }
544
558
 
559
+ notified = false;
560
+
545
561
  for (let link: Link | null = signal.subs; link; link = link.nextSub) {
546
562
  insertIntoHeap(link.sub);
547
563
  }
@@ -551,7 +567,7 @@ const write = <T>(signal: Signal<T>, value: T) => {
551
567
 
552
568
 
553
569
  export {
554
- computed,
570
+ asyncComputed, computed,
555
571
  dispose,
556
572
  effect,
557
573
  isComputed, isSignal,
package/src/types.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ts } from '@esportsplus/typescript';
2
- import { COMPUTED, SIGNAL, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_RECOMPUTING } from './constants';
2
+ import { SIGNAL } from './constants';
3
3
  import { ReactiveArray } from './reactive';
4
4
 
5
5
 
@@ -11,15 +11,9 @@ interface Computed<T> {
11
11
  height: number;
12
12
  nextHeap: Computed<unknown> | undefined;
13
13
  prevHeap: Computed<unknown>;
14
- state:
15
- typeof STATE_CHECK |
16
- typeof STATE_DIRTY |
17
- typeof STATE_IN_HEAP |
18
- typeof STATE_NONE |
19
- typeof STATE_RECOMPUTING;
14
+ state: number;
20
15
  subs: Link | null;
21
16
  subsTail: Link | null;
22
- type: typeof COMPUTED;
23
17
  value: T;
24
18
  }
25
19