@esportsplus/reactivity 0.16.7 → 0.17.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/reactive/array.d.ts +20 -156
- package/build/reactive/array.js +98 -173
- package/build/reactive/index.d.ts +13 -4
- package/build/reactive/index.js +6 -6
- package/build/reactive/object.d.ts +1 -14
- package/build/reactive/object.js +23 -23
- package/build/system.js +27 -24
- package/package.json +1 -1
- package/src/reactive/array.ts +106 -200
- package/src/reactive/index.ts +24 -11
- package/src/reactive/object.ts +30 -41
- package/src/system.ts +28 -24
package/src/reactive/object.ts
CHANGED
|
@@ -1,24 +1,8 @@
|
|
|
1
|
-
import { defineProperty, isArray,
|
|
1
|
+
import { defineProperty, isArray, isObject, isPromise } from '@esportsplus/utilities';
|
|
2
2
|
import { computed, dispose, effect, read, root, set, signal } from '~/system';
|
|
3
3
|
import { Computed, Signal } from '~/types';
|
|
4
4
|
import { REACTIVE_OBJECT } from '~/constants';
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
type API<T> = Prettify<{ [K in keyof T]: Infer<T[K]> } & { dispose: VoidFunction } >;
|
|
9
|
-
|
|
10
|
-
type Infer<T> =
|
|
11
|
-
T extends (...args: unknown[]) => Promise<infer R>
|
|
12
|
-
? R | undefined
|
|
13
|
-
: T extends (...args: any[]) => infer R
|
|
14
|
-
? R
|
|
15
|
-
: T extends (infer U)[]
|
|
16
|
-
? ReactiveArray<U>
|
|
17
|
-
: T extends ReactiveObject<any>
|
|
18
|
-
? T
|
|
19
|
-
: T extends Record<PropertyKey, unknown>
|
|
20
|
-
? { [K in keyof T]: T[K] }
|
|
21
|
-
: T;
|
|
5
|
+
import { ReactiveArray } from './array';
|
|
22
6
|
|
|
23
7
|
|
|
24
8
|
class ReactiveObject<T extends Record<PropertyKey, unknown>> {
|
|
@@ -35,17 +19,9 @@ class ReactiveObject<T extends Record<PropertyKey, unknown>> {
|
|
|
35
19
|
let key = keys[i],
|
|
36
20
|
value = data[key];
|
|
37
21
|
|
|
38
|
-
|
|
39
|
-
let node = array(value);
|
|
40
|
-
|
|
41
|
-
(this.disposers ??= []).push( () => node.dispose() );
|
|
22
|
+
let type = typeof value;
|
|
42
23
|
|
|
43
|
-
|
|
44
|
-
enumerable: true,
|
|
45
|
-
value: node
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
else if (isFunction(value)) {
|
|
24
|
+
if (type === 'function') {
|
|
49
25
|
let node: Computed<T[typeof key]> | Signal<T[typeof key] | undefined> | undefined;
|
|
50
26
|
|
|
51
27
|
defineProperty(this, key, {
|
|
@@ -84,20 +60,37 @@ class ReactiveObject<T extends Record<PropertyKey, unknown>> {
|
|
|
84
60
|
return read(node!);
|
|
85
61
|
}
|
|
86
62
|
});
|
|
63
|
+
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (value == null || type !== 'object') {
|
|
68
|
+
// Avoid isArray when possible
|
|
87
69
|
}
|
|
88
|
-
else {
|
|
89
|
-
let node =
|
|
70
|
+
else if (isArray(value)) {
|
|
71
|
+
let node = new ReactiveArray(value);
|
|
72
|
+
|
|
73
|
+
(this.disposers ??= []).push( () => node.dispose() );
|
|
90
74
|
|
|
91
75
|
defineProperty(this, key, {
|
|
92
76
|
enumerable: true,
|
|
93
|
-
|
|
94
|
-
return read(node);
|
|
95
|
-
},
|
|
96
|
-
set(v: typeof value) {
|
|
97
|
-
set(node, v);
|
|
98
|
-
}
|
|
77
|
+
value: node
|
|
99
78
|
});
|
|
79
|
+
|
|
80
|
+
continue;
|
|
100
81
|
}
|
|
82
|
+
|
|
83
|
+
let node = signal(value);
|
|
84
|
+
|
|
85
|
+
defineProperty(this, key, {
|
|
86
|
+
enumerable: true,
|
|
87
|
+
get() {
|
|
88
|
+
return read(node);
|
|
89
|
+
},
|
|
90
|
+
set(v: typeof value) {
|
|
91
|
+
set(node, v);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
101
94
|
}
|
|
102
95
|
}
|
|
103
96
|
|
|
@@ -122,8 +115,4 @@ const isReactiveObject = (value: any): value is ReactiveObject<any> => {
|
|
|
122
115
|
};
|
|
123
116
|
|
|
124
117
|
|
|
125
|
-
export
|
|
126
|
-
return new ReactiveObject<T>(input) as API<T>;
|
|
127
|
-
};
|
|
128
|
-
export { isReactiveObject };
|
|
129
|
-
export type { API as ReactiveObject };
|
|
118
|
+
export { isReactiveObject, ReactiveObject };
|
package/src/system.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isObject } from '@esportsplus/utilities';
|
|
2
2
|
import {
|
|
3
3
|
COMPUTED, SIGNAL,
|
|
4
4
|
STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED,
|
|
@@ -26,14 +26,14 @@ function cleanup<T>(computed: Computed<T>): void {
|
|
|
26
26
|
|
|
27
27
|
let value = computed.cleanup;
|
|
28
28
|
|
|
29
|
-
if (
|
|
29
|
+
if (typeof value === 'function') {
|
|
30
|
+
value();
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
30
33
|
for (let i = 0, n = value.length; i < n; i++) {
|
|
31
34
|
value[i]();
|
|
32
35
|
}
|
|
33
36
|
}
|
|
34
|
-
else {
|
|
35
|
-
value();
|
|
36
|
-
}
|
|
37
37
|
|
|
38
38
|
computed.cleanup = null;
|
|
39
39
|
}
|
|
@@ -108,16 +108,16 @@ function insertIntoHeap<T>(computed: Computed<T>) {
|
|
|
108
108
|
function link<T>(dep: Signal<T> | Computed<T>, sub: Computed<T>) {
|
|
109
109
|
let prevDep = sub.depsTail;
|
|
110
110
|
|
|
111
|
-
if (prevDep
|
|
111
|
+
if (prevDep && prevDep.dep === dep) {
|
|
112
112
|
return;
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
let nextDep: Link | null = null;
|
|
116
116
|
|
|
117
117
|
if (sub.state & STATE_RECOMPUTING) {
|
|
118
|
-
nextDep = prevDep
|
|
118
|
+
nextDep = prevDep ? prevDep.nextDep : sub.deps;
|
|
119
119
|
|
|
120
|
-
if (nextDep
|
|
120
|
+
if (nextDep && nextDep.dep === dep) {
|
|
121
121
|
nextDep.version = version;
|
|
122
122
|
sub.depsTail = nextDep;
|
|
123
123
|
return;
|
|
@@ -128,7 +128,7 @@ function link<T>(dep: Signal<T> | Computed<T>, sub: Computed<T>) {
|
|
|
128
128
|
|
|
129
129
|
// https://github.com/stackblitz/alien-signals/commit/54fe1b3947fac5c0aecb73b0b0eaff000806c454
|
|
130
130
|
if (
|
|
131
|
-
prevSub
|
|
131
|
+
prevSub &&
|
|
132
132
|
prevSub.version === version &&
|
|
133
133
|
prevSub.sub === sub
|
|
134
134
|
) {
|
|
@@ -146,14 +146,14 @@ function link<T>(dep: Signal<T> | Computed<T>, sub: Computed<T>) {
|
|
|
146
146
|
version
|
|
147
147
|
};
|
|
148
148
|
|
|
149
|
-
if (prevDep
|
|
149
|
+
if (prevDep) {
|
|
150
150
|
prevDep.nextDep = newLink;
|
|
151
151
|
}
|
|
152
152
|
else {
|
|
153
153
|
sub.deps = newLink;
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
if (prevSub
|
|
156
|
+
if (prevSub) {
|
|
157
157
|
prevSub.nextSub = newLink;
|
|
158
158
|
}
|
|
159
159
|
else {
|
|
@@ -170,7 +170,7 @@ function notify<T>(computed: Computed<T>, newState = STATE_DIRTY) {
|
|
|
170
170
|
|
|
171
171
|
computed.state = state | newState;
|
|
172
172
|
|
|
173
|
-
for (let link = computed.subs; link
|
|
173
|
+
for (let link = computed.subs; link; link = link.nextSub) {
|
|
174
174
|
notify(link.sub, STATE_CHECK);
|
|
175
175
|
}
|
|
176
176
|
}
|
|
@@ -211,15 +211,15 @@ function recompute<T>(computed: Computed<T>, del: boolean) {
|
|
|
211
211
|
computed.state = STATE_NONE;
|
|
212
212
|
|
|
213
213
|
let depsTail = computed.depsTail as Link | null,
|
|
214
|
-
remove = depsTail
|
|
214
|
+
remove = depsTail ? depsTail.nextDep : computed.deps;
|
|
215
215
|
|
|
216
|
-
if (remove
|
|
216
|
+
if (remove) {
|
|
217
217
|
do {
|
|
218
218
|
remove = unlink(remove);
|
|
219
219
|
}
|
|
220
|
-
while (remove
|
|
220
|
+
while (remove);
|
|
221
221
|
|
|
222
|
-
if (depsTail
|
|
222
|
+
if (depsTail) {
|
|
223
223
|
depsTail.nextDep = null;
|
|
224
224
|
}
|
|
225
225
|
else {
|
|
@@ -230,7 +230,7 @@ function recompute<T>(computed: Computed<T>, del: boolean) {
|
|
|
230
230
|
if (ok && value !== computed.value) {
|
|
231
231
|
computed.value = value as T;
|
|
232
232
|
|
|
233
|
-
for (let c = computed.subs; c
|
|
233
|
+
for (let c = computed.subs; c; c = c.nextSub) {
|
|
234
234
|
let s = c.sub,
|
|
235
235
|
state = s.state;
|
|
236
236
|
|
|
@@ -246,6 +246,10 @@ function recompute<T>(computed: Computed<T>, del: boolean) {
|
|
|
246
246
|
}
|
|
247
247
|
|
|
248
248
|
function schedule() {
|
|
249
|
+
if (stabilizer === STABILIZER_SCHEDULED) {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
|
|
249
253
|
if (stabilizer === STABILIZER_IDLE && !depth) {
|
|
250
254
|
stabilizer = STABILIZER_SCHEDULED;
|
|
251
255
|
microtask(stabilize);
|
|
@@ -296,14 +300,14 @@ function unlink(link: Link): Link | null {
|
|
|
296
300
|
nextSub = link.nextSub,
|
|
297
301
|
prevSub = link.prevSub;
|
|
298
302
|
|
|
299
|
-
if (nextSub
|
|
303
|
+
if (nextSub) {
|
|
300
304
|
nextSub.prevSub = prevSub;
|
|
301
305
|
}
|
|
302
306
|
else {
|
|
303
307
|
dep.subsTail = prevSub;
|
|
304
308
|
}
|
|
305
309
|
|
|
306
|
-
if (prevSub
|
|
310
|
+
if (prevSub) {
|
|
307
311
|
prevSub.nextSub = nextSub;
|
|
308
312
|
}
|
|
309
313
|
else if ((dep.subs = nextSub) === null && 'fn' in dep) {
|
|
@@ -385,7 +389,7 @@ const dispose = <T>(computed: Computed<T>) => {
|
|
|
385
389
|
|
|
386
390
|
let dep = computed.deps;
|
|
387
391
|
|
|
388
|
-
while (dep
|
|
392
|
+
while (dep) {
|
|
389
393
|
dep = unlink(dep);
|
|
390
394
|
}
|
|
391
395
|
|
|
@@ -424,11 +428,11 @@ const onCleanup = (fn: VoidFunction): typeof fn => {
|
|
|
424
428
|
if (!cleanup) {
|
|
425
429
|
parent.cleanup = fn;
|
|
426
430
|
}
|
|
427
|
-
else if (
|
|
428
|
-
cleanup
|
|
431
|
+
else if (typeof cleanup === 'function') {
|
|
432
|
+
parent.cleanup = [cleanup, fn];
|
|
429
433
|
}
|
|
430
434
|
else {
|
|
431
|
-
|
|
435
|
+
cleanup.push(fn);
|
|
432
436
|
}
|
|
433
437
|
|
|
434
438
|
return fn;
|
|
@@ -510,7 +514,7 @@ const set = <T>(signal: Signal<T>, value: T) => {
|
|
|
510
514
|
return;
|
|
511
515
|
}
|
|
512
516
|
|
|
513
|
-
for (let link: Link | null = signal.subs; link
|
|
517
|
+
for (let link: Link | null = signal.subs; link; link = link.nextSub) {
|
|
514
518
|
insertIntoHeap(link.sub);
|
|
515
519
|
}
|
|
516
520
|
|