@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/build/constants.d.ts +2 -1
- package/build/constants.js +2 -1
- package/build/reactive/array.js +24 -22
- package/build/reactive/object.js +10 -11
- package/build/system.d.ts +2 -1
- package/build/system.js +35 -23
- package/build/types.d.ts +2 -3
- package/package.json +3 -2
- package/src/constants.ts +3 -1
- package/src/reactive/array.ts +27 -26
- package/src/reactive/object.ts +17 -14
- package/src/system.ts +47 -31
- package/src/types.ts +2 -8
- package/tests/array.ts +906 -0
- package/tests/async-computed.ts +195 -0
- package/tests/bench/array.ts +227 -0
- package/tests/bench/reactive-object.ts +54 -0
- package/tests/bench/system.ts +317 -0
- package/tests/compiler.ts +326 -0
- package/tests/effects.ts +211 -0
- package/tests/nested.ts +293 -0
- package/tests/objects.ts +185 -0
- package/tests/primitives.ts +280 -0
- package/tests/reactive.ts +534 -0
- package/tests/system.ts +1014 -0
- package/tests/tsconfig.json +17 -0
- package/vitest.config.ts +18 -0
- package/test/arrays.ts +0 -146
- package/test/debug.ts +0 -7
- package/test/effects.ts +0 -168
- package/test/index.ts +0 -8
- package/test/nested.ts +0 -201
- package/test/objects.ts +0 -106
- package/test/primitives.ts +0 -87
- package/test/range.ts +0 -45
- package/test/vite.config.ts +0 -41
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,
|
|
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
|
-
|
|
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 =
|
|
139
|
+
let pooled = linkPoolHead,
|
|
142
140
|
newLink =
|
|
143
141
|
sub.depsTail =
|
|
144
142
|
dep.subsTail = pooled
|
|
145
|
-
? (
|
|
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
|
|
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 =
|
|
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.
|
|
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
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
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.
|
|
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 =
|
|
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:
|
|
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.
|
|
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.
|
|
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 {
|
|
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
|
|