@esportsplus/reactivity 0.12.3 → 0.13.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.d.ts +5 -62
- package/build/reactive/array.js +183 -169
- package/build/reactive/index.d.ts +4 -2
- package/build/reactive/object.d.ts +5 -2
- package/build/reactive/object.js +33 -32
- package/build/system.js +26 -19
- package/build/types.d.ts +2 -4
- package/package.json +2 -2
- package/src/constants.ts +3 -0
- package/src/reactive/array.ts +213 -218
- package/src/reactive/index.ts +4 -6
- package/src/reactive/object.ts +47 -38
- package/src/system.ts +33 -23
- package/src/types.ts +2 -7
package/src/reactive/object.ts
CHANGED
|
@@ -1,76 +1,87 @@
|
|
|
1
1
|
import { defineProperty, isArray, isFunction, isObject, isPromise, Prettify } from '@esportsplus/utilities';
|
|
2
|
-
import { computed, dispose, effect,
|
|
2
|
+
import { computed, dispose, effect, read, root, set, signal } from '~/system';
|
|
3
3
|
import { Computed, Infer, Signal } from '~/types';
|
|
4
4
|
import { REACTIVE_OBJECT } from '~/constants';
|
|
5
|
-
import array
|
|
5
|
+
import array from './array';
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
type API<T
|
|
8
|
+
type API<T> = Prettify<{ [K in keyof T]: Infer<T[K]> } & { dispose: VoidFunction } >;
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class ReactiveObject<T extends Record<PropertyKey, unknown>> {
|
|
12
12
|
[REACTIVE_OBJECT] = true;
|
|
13
13
|
|
|
14
14
|
|
|
15
|
+
private disposers: VoidFunction[] | null = null;
|
|
16
|
+
|
|
17
|
+
|
|
15
18
|
constructor(data: T) {
|
|
16
|
-
|
|
17
|
-
|
|
19
|
+
let keys = Object.keys(data);
|
|
20
|
+
|
|
21
|
+
for (let i = 0, n = keys.length; i < n; i++) {
|
|
22
|
+
let key = keys[i],
|
|
23
|
+
value = data[key];
|
|
18
24
|
|
|
19
25
|
if (isArray(value)) {
|
|
20
|
-
let
|
|
26
|
+
let node = array(value);
|
|
27
|
+
|
|
28
|
+
(this.disposers ??= []).push( () => node.dispose() );
|
|
21
29
|
|
|
22
30
|
defineProperty(this, key, {
|
|
23
31
|
enumerable: true,
|
|
24
|
-
|
|
25
|
-
return a;
|
|
26
|
-
}
|
|
32
|
+
value: node
|
|
27
33
|
});
|
|
28
34
|
}
|
|
29
35
|
else if (isFunction(value)) {
|
|
30
|
-
let
|
|
36
|
+
let node: Computed<T[typeof key]> | Signal<T[typeof key] | undefined> | undefined;
|
|
31
37
|
|
|
32
38
|
defineProperty(this, key, {
|
|
33
39
|
enumerable: true,
|
|
34
|
-
get() {
|
|
35
|
-
if (
|
|
40
|
+
get: () => {
|
|
41
|
+
if (node === undefined) {
|
|
36
42
|
root(() => {
|
|
37
|
-
|
|
43
|
+
node = computed(value as Computed<T[typeof key]>['fn']);
|
|
38
44
|
|
|
39
|
-
if (isPromise(
|
|
40
|
-
let factory =
|
|
45
|
+
if (isPromise(node.value)) {
|
|
46
|
+
let factory = node,
|
|
41
47
|
version = 0;
|
|
42
48
|
|
|
43
|
-
|
|
49
|
+
node = signal<T[typeof key] | undefined>(undefined);
|
|
44
50
|
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
(this.disposers ??= []).push(
|
|
52
|
+
effect(() => {
|
|
53
|
+
let id = ++version;
|
|
47
54
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
55
|
+
(read(factory) as Promise<T[typeof key]>).then((v) => {
|
|
56
|
+
if (id !== version) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
52
59
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
60
|
+
set(node as Signal<typeof v>, v);
|
|
61
|
+
});
|
|
62
|
+
})
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
(this.disposers ??= []).push(() => dispose(node as Computed<T[typeof key]>));
|
|
56
67
|
}
|
|
57
68
|
});
|
|
58
69
|
}
|
|
59
70
|
|
|
60
|
-
return read(
|
|
71
|
+
return read(node!);
|
|
61
72
|
}
|
|
62
73
|
});
|
|
63
74
|
}
|
|
64
75
|
else {
|
|
65
|
-
let
|
|
76
|
+
let node = signal(value);
|
|
66
77
|
|
|
67
78
|
defineProperty(this, key, {
|
|
68
79
|
enumerable: true,
|
|
69
80
|
get() {
|
|
70
|
-
return read(
|
|
81
|
+
return read(node);
|
|
71
82
|
},
|
|
72
83
|
set(v: typeof value) {
|
|
73
|
-
set(
|
|
84
|
+
set(node, v);
|
|
74
85
|
}
|
|
75
86
|
});
|
|
76
87
|
}
|
|
@@ -79,17 +90,15 @@ class ReactiveObject<T extends Record<PropertyKey, unknown>> {
|
|
|
79
90
|
|
|
80
91
|
|
|
81
92
|
dispose() {
|
|
82
|
-
let
|
|
93
|
+
let disposers = this.disposers,
|
|
94
|
+
disposer;
|
|
83
95
|
|
|
84
|
-
|
|
85
|
-
|
|
96
|
+
if (!disposers) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
86
99
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
else if (isComputed(value)) {
|
|
91
|
-
dispose(value);
|
|
92
|
-
}
|
|
100
|
+
while (disposer = disposers.pop()) {
|
|
101
|
+
disposer();
|
|
93
102
|
}
|
|
94
103
|
}
|
|
95
104
|
}
|
package/src/system.ts
CHANGED
|
@@ -2,15 +2,15 @@ import { isArray, isObject } from '@esportsplus/utilities';
|
|
|
2
2
|
import {
|
|
3
3
|
COMPUTED, SIGNAL,
|
|
4
4
|
STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED,
|
|
5
|
-
STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_RECOMPUTING
|
|
5
|
+
STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_NOTIFY_MASK, STATE_RECOMPUTING
|
|
6
6
|
} from './constants';
|
|
7
7
|
import { Computed, Link, Signal } from './types';
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
let depth = 0,
|
|
11
|
-
heap: (Computed<unknown> | undefined)[] = new Array(
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
heap: (Computed<unknown> | undefined)[] = new Array(64),
|
|
12
|
+
heap_i = 0,
|
|
13
|
+
heap_n = 0,
|
|
14
14
|
microtask = queueMicrotask,
|
|
15
15
|
notified = false,
|
|
16
16
|
observer: Computed<unknown> | null = null,
|
|
@@ -93,12 +93,12 @@ function insertIntoHeap<T>(computed: Computed<T>) {
|
|
|
93
93
|
heapAtHeight.prevHeap = computed;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
if (height >
|
|
97
|
-
|
|
96
|
+
if (height > heap_n) {
|
|
97
|
+
heap_n = height;
|
|
98
98
|
|
|
99
99
|
// Simple auto adjust to avoid manual management within apps.
|
|
100
100
|
if (height >= heap.length) {
|
|
101
|
-
heap.length = Math.
|
|
101
|
+
heap.length = Math.max(height + 1, Math.ceil(heap.length * 2));
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
}
|
|
@@ -163,7 +163,7 @@ function link<T>(dep: Signal<T> | Computed<T>, sub: Computed<T>) {
|
|
|
163
163
|
function notify<T>(computed: Computed<T>, newState = STATE_DIRTY) {
|
|
164
164
|
let state = computed.state;
|
|
165
165
|
|
|
166
|
-
if ((state &
|
|
166
|
+
if ((state & STATE_NOTIFY_MASK) >= newState) {
|
|
167
167
|
return;
|
|
168
168
|
}
|
|
169
169
|
|
|
@@ -183,7 +183,9 @@ function recompute<T>(computed: Computed<T>, del: boolean) {
|
|
|
183
183
|
computed.prevHeap = computed;
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
-
|
|
186
|
+
if (computed.cleanup) {
|
|
187
|
+
cleanup(computed);
|
|
188
|
+
}
|
|
187
189
|
|
|
188
190
|
let o = observer,
|
|
189
191
|
ok = true,
|
|
@@ -258,10 +260,10 @@ function stabilize() {
|
|
|
258
260
|
observer = null;
|
|
259
261
|
stabilizer = STABILIZER_RUNNING;
|
|
260
262
|
|
|
261
|
-
for (
|
|
262
|
-
let computed = heap[
|
|
263
|
+
for (heap_i = 0; heap_i <= heap_n; heap_i++) {
|
|
264
|
+
let computed = heap[heap_i];
|
|
263
265
|
|
|
264
|
-
heap[
|
|
266
|
+
heap[heap_i] = undefined;
|
|
265
267
|
|
|
266
268
|
while (computed !== undefined) {
|
|
267
269
|
let next = computed.nextHeap;
|
|
@@ -272,6 +274,10 @@ function stabilize() {
|
|
|
272
274
|
}
|
|
273
275
|
}
|
|
274
276
|
|
|
277
|
+
while (heap_n > 0 && heap[heap_n] === undefined) {
|
|
278
|
+
heap_n--;
|
|
279
|
+
}
|
|
280
|
+
|
|
275
281
|
observer = o;
|
|
276
282
|
|
|
277
283
|
if (stabilizer === STABILIZER_RESCHEDULE) {
|
|
@@ -284,7 +290,10 @@ function stabilize() {
|
|
|
284
290
|
|
|
285
291
|
// https://github.com/stackblitz/alien-signals/blob/v2.0.3/src/system.ts#L100
|
|
286
292
|
function unlink(link: Link): Link | null {
|
|
287
|
-
let
|
|
293
|
+
let dep = link.dep,
|
|
294
|
+
nextDep = link.nextDep,
|
|
295
|
+
nextSub = link.nextSub,
|
|
296
|
+
prevSub = link.prevSub;
|
|
288
297
|
|
|
289
298
|
if (nextSub !== null) {
|
|
290
299
|
nextSub.prevSub = prevSub;
|
|
@@ -377,7 +386,9 @@ const dispose = <T>(computed: Computed<T>) => {
|
|
|
377
386
|
|
|
378
387
|
computed.deps = null;
|
|
379
388
|
|
|
380
|
-
|
|
389
|
+
if (computed.cleanup) {
|
|
390
|
+
cleanup(computed);
|
|
391
|
+
}
|
|
381
392
|
};
|
|
382
393
|
|
|
383
394
|
const effect = <T>(fn: Computed<T>['fn']) => {
|
|
@@ -401,14 +412,16 @@ const onCleanup = (fn: VoidFunction): typeof fn => {
|
|
|
401
412
|
return fn;
|
|
402
413
|
}
|
|
403
414
|
|
|
404
|
-
|
|
415
|
+
let cleanup = observer.cleanup;
|
|
416
|
+
|
|
417
|
+
if (!cleanup) {
|
|
405
418
|
observer.cleanup = fn;
|
|
406
419
|
}
|
|
407
|
-
else if (isArray(
|
|
408
|
-
|
|
420
|
+
else if (isArray(cleanup)) {
|
|
421
|
+
cleanup.push(fn);
|
|
409
422
|
}
|
|
410
423
|
else {
|
|
411
|
-
observer.cleanup = [
|
|
424
|
+
observer.cleanup = [cleanup, fn];
|
|
412
425
|
}
|
|
413
426
|
|
|
414
427
|
return fn;
|
|
@@ -425,14 +438,11 @@ const read = <T>(node: Signal<T> | Computed<T>): T => {
|
|
|
425
438
|
observer.height = height + 1;
|
|
426
439
|
}
|
|
427
440
|
|
|
428
|
-
if (
|
|
429
|
-
height >= index ||
|
|
430
|
-
node.state & (STATE_DIRTY | STATE_CHECK)
|
|
431
|
-
) {
|
|
441
|
+
if (height >= heap_i || node.state & STATE_NOTIFY_MASK) {
|
|
432
442
|
if (!notified) {
|
|
433
443
|
notified = true;
|
|
434
444
|
|
|
435
|
-
for (let i = 0; i <=
|
|
445
|
+
for (let i = 0; i <= heap_n; i++) {
|
|
436
446
|
for (let computed = heap[i]; computed !== undefined; computed = computed.nextHeap) {
|
|
437
447
|
notify(computed);
|
|
438
448
|
}
|
package/src/types.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { COMPUTED, SIGNAL, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_RECOMPUTING } from './constants';
|
|
2
|
-
import { ReactiveArray } from './reactive/array';
|
|
3
2
|
import { ReactiveObject } from './reactive/object';
|
|
4
3
|
|
|
5
4
|
|
|
@@ -29,7 +28,7 @@ type Infer<T> =
|
|
|
29
28
|
: T extends (...args: any[]) => infer R
|
|
30
29
|
? R
|
|
31
30
|
: T extends (infer U)[]
|
|
32
|
-
?
|
|
31
|
+
? Infer<U>[]
|
|
33
32
|
: T extends ReactiveObject<any>
|
|
34
33
|
? T
|
|
35
34
|
: T extends Record<PropertyKey, unknown>
|
|
@@ -45,10 +44,6 @@ interface Link {
|
|
|
45
44
|
version: number;
|
|
46
45
|
}
|
|
47
46
|
|
|
48
|
-
type Reactive<T> = T extends Record<PropertyKey, unknown>
|
|
49
|
-
? ReactiveObject<T>
|
|
50
|
-
: ReactiveArray<T>;
|
|
51
|
-
|
|
52
47
|
type Signal<T> = {
|
|
53
48
|
[SIGNAL]: true;
|
|
54
49
|
subs: Link | null;
|
|
@@ -62,5 +57,5 @@ export type {
|
|
|
62
57
|
Infer,
|
|
63
58
|
Link,
|
|
64
59
|
Signal,
|
|
65
|
-
|
|
60
|
+
ReactiveObject
|
|
66
61
|
};
|