@esportsplus/reactivity 0.19.3 → 0.20.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.
- package/build/constants.d.ts +2 -1
- package/build/constants.js +6 -5
- package/build/reactive/array.d.ts +6 -3
- package/build/reactive/array.js +31 -3
- package/build/reactive/object.d.ts +0 -2
- package/build/reactive/object.js +6 -6
- package/build/system.js +8 -8
- package/build/types.d.ts +3 -3
- package/build/types.js +1 -1
- package/package.json +1 -1
- package/src/constants.ts +9 -5
- package/src/reactive/array.ts +46 -4
- package/src/reactive/object.ts +8 -9
- package/src/system.ts +9 -8
- package/src/types.ts +3 -3
package/build/constants.d.ts
CHANGED
|
@@ -12,4 +12,5 @@ declare const STATE_DIRTY: number;
|
|
|
12
12
|
declare const STATE_RECOMPUTING: number;
|
|
13
13
|
declare const STATE_IN_HEAP: number;
|
|
14
14
|
declare const STATE_NOTIFY_MASK: number;
|
|
15
|
-
|
|
15
|
+
declare const TYPE: unique symbol;
|
|
16
|
+
export { COMPUTED, REACTIVE_ARRAY, REACTIVE_OBJECT, SIGNAL, STABILIZER_IDLE, STATE_NOTIFY_MASK, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_RECOMPUTING, TYPE };
|
package/build/constants.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
const COMPUTED = Symbol('computed');
|
|
2
|
-
const REACTIVE_ARRAY = Symbol('reactive.array');
|
|
3
|
-
const REACTIVE_OBJECT = Symbol('reactive.object');
|
|
4
|
-
const SIGNAL = Symbol('signal');
|
|
1
|
+
const COMPUTED = Symbol('reactivity.computed');
|
|
2
|
+
const REACTIVE_ARRAY = Symbol('reactivity.reactive.array');
|
|
3
|
+
const REACTIVE_OBJECT = Symbol('reactivity.reactive.object');
|
|
4
|
+
const SIGNAL = Symbol('reactivity.signal');
|
|
5
5
|
const STABILIZER_IDLE = 0;
|
|
6
6
|
const STABILIZER_RESCHEDULE = 1;
|
|
7
7
|
const STABILIZER_RUNNING = 2;
|
|
@@ -12,4 +12,5 @@ const STATE_DIRTY = 1 << 1;
|
|
|
12
12
|
const STATE_RECOMPUTING = 1 << 2;
|
|
13
13
|
const STATE_IN_HEAP = 1 << 3;
|
|
14
14
|
const STATE_NOTIFY_MASK = (STATE_CHECK | STATE_DIRTY);
|
|
15
|
-
|
|
15
|
+
const TYPE = Symbol('reactivity.type');
|
|
16
|
+
export { COMPUTED, REACTIVE_ARRAY, REACTIVE_OBJECT, SIGNAL, STABILIZER_IDLE, STATE_NOTIFY_MASK, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_RECOMPUTING, TYPE };
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { REACTIVE_ARRAY } from '../constants.js';
|
|
2
1
|
type Events<T> = {
|
|
3
2
|
clear: undefined;
|
|
3
|
+
concat: {
|
|
4
|
+
items: T[];
|
|
5
|
+
};
|
|
4
6
|
pop: {
|
|
5
7
|
item: T;
|
|
6
8
|
};
|
|
@@ -31,10 +33,11 @@ type Listener<V> = {
|
|
|
31
33
|
};
|
|
32
34
|
type Listeners = Record<string, (Listener<any> | null)[]>;
|
|
33
35
|
declare class ReactiveArray<T> extends Array<T> {
|
|
34
|
-
[REACTIVE_ARRAY]: boolean;
|
|
35
36
|
listeners: Listeners;
|
|
36
37
|
constructor(...items: T[]);
|
|
37
38
|
clear(): void;
|
|
39
|
+
concat(...items: ConcatArray<T>[]): ReactiveArray<T>;
|
|
40
|
+
concat(...items: (T | ConcatArray<T>)[]): ReactiveArray<T>;
|
|
38
41
|
dispatch<K extends keyof Events<T>, V>(event: K, value?: V): void;
|
|
39
42
|
dispose(): void;
|
|
40
43
|
on<K extends keyof Events<T>>(event: K, listener: Listener<Events<T>[K]>): void;
|
|
@@ -43,7 +46,7 @@ declare class ReactiveArray<T> extends Array<T> {
|
|
|
43
46
|
push(...items: T[]): number;
|
|
44
47
|
reverse(): this;
|
|
45
48
|
shift(): T | undefined;
|
|
46
|
-
sort(fn
|
|
49
|
+
sort(fn?: (a: T, b: T) => number): this;
|
|
47
50
|
splice(start: number, deleteCount?: number, ...items: T[]): T[];
|
|
48
51
|
unshift(...items: T[]): number;
|
|
49
52
|
}
|
package/build/reactive/array.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isArray } from '@esportsplus/utilities';
|
|
2
|
+
import { REACTIVE_ARRAY, TYPE } from '../constants.js';
|
|
2
3
|
import { isReactiveObject } from './object.js';
|
|
3
4
|
class ReactiveArray extends Array {
|
|
4
|
-
[REACTIVE_ARRAY] = true;
|
|
5
5
|
listeners = {};
|
|
6
6
|
constructor(...items) {
|
|
7
7
|
super(...items);
|
|
@@ -10,6 +10,26 @@ class ReactiveArray extends Array {
|
|
|
10
10
|
this.dispose();
|
|
11
11
|
this.dispatch('clear');
|
|
12
12
|
}
|
|
13
|
+
concat(...items) {
|
|
14
|
+
let added = [];
|
|
15
|
+
for (let i = 0, n = items.length; i < n; i++) {
|
|
16
|
+
let item = items[i];
|
|
17
|
+
if (isArray(item)) {
|
|
18
|
+
for (let j = 0, o = item.length; j < o; j++) {
|
|
19
|
+
added.push(item[j]);
|
|
20
|
+
super.push(item[j]);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
added.push(item);
|
|
25
|
+
super.push(item);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (added.length) {
|
|
29
|
+
this.dispatch('concat', { items: added });
|
|
30
|
+
}
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
13
33
|
dispatch(event, value) {
|
|
14
34
|
let listeners = this.listeners[event];
|
|
15
35
|
if (!listeners) {
|
|
@@ -30,10 +50,14 @@ class ReactiveArray extends Array {
|
|
|
30
50
|
listeners[i] = null;
|
|
31
51
|
}
|
|
32
52
|
}
|
|
53
|
+
while (listeners.length && listeners[listeners.length - 1] === null) {
|
|
54
|
+
listeners.pop();
|
|
55
|
+
}
|
|
33
56
|
}
|
|
34
57
|
dispose() {
|
|
35
58
|
let item;
|
|
36
|
-
while (
|
|
59
|
+
while (this.length) {
|
|
60
|
+
item = super.pop();
|
|
37
61
|
if (isReactiveObject(item)) {
|
|
38
62
|
item.dispose();
|
|
39
63
|
}
|
|
@@ -56,6 +80,9 @@ class ReactiveArray extends Array {
|
|
|
56
80
|
}
|
|
57
81
|
}
|
|
58
82
|
listeners[hole] = listener;
|
|
83
|
+
while (listeners.length && listeners[listeners.length - 1] === null) {
|
|
84
|
+
listeners.pop();
|
|
85
|
+
}
|
|
59
86
|
}
|
|
60
87
|
}
|
|
61
88
|
once(event, listener) {
|
|
@@ -116,4 +143,5 @@ class ReactiveArray extends Array {
|
|
|
116
143
|
return length;
|
|
117
144
|
}
|
|
118
145
|
}
|
|
146
|
+
Object.defineProperty(ReactiveArray.prototype, TYPE, { value: REACTIVE_ARRAY });
|
|
119
147
|
export { ReactiveArray };
|
package/build/reactive/object.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { defineProperty, isArray, isPromise } from '@esportsplus/utilities';
|
|
2
2
|
import { computed, dispose, effect, read, root, set, signal } from '../system.js';
|
|
3
|
-
import { REACTIVE_OBJECT } from '../constants.js';
|
|
3
|
+
import { REACTIVE_OBJECT, TYPE } from '../constants.js';
|
|
4
4
|
import { ReactiveArray } from './array.js';
|
|
5
5
|
class ReactiveObject {
|
|
6
|
-
[REACTIVE_OBJECT] = true;
|
|
7
6
|
disposers = null;
|
|
8
7
|
constructor(data) {
|
|
9
|
-
let keys = Object.keys(data)
|
|
10
|
-
|
|
11
|
-
let value = data[key], type = typeof value;
|
|
8
|
+
let keys = Object.keys(data);
|
|
9
|
+
for (let i = 0, n = keys.length; i < n; ++i) {
|
|
10
|
+
let key = keys[i], value = data[key], type = typeof value;
|
|
12
11
|
if (type === 'function') {
|
|
13
12
|
let node;
|
|
14
13
|
defineProperty(this, key, {
|
|
@@ -73,7 +72,8 @@ class ReactiveObject {
|
|
|
73
72
|
}
|
|
74
73
|
}
|
|
75
74
|
}
|
|
75
|
+
Object.defineProperty(ReactiveObject.prototype, TYPE, { value: REACTIVE_OBJECT });
|
|
76
76
|
const isReactiveObject = (value) => {
|
|
77
|
-
return typeof value === 'object' && value !== null &&
|
|
77
|
+
return typeof value === 'object' && value !== null && value[TYPE] === REACTIVE_OBJECT;
|
|
78
78
|
};
|
|
79
79
|
export { isReactiveObject, ReactiveObject };
|
package/build/system.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isObject } from '@esportsplus/utilities';
|
|
2
|
-
import { COMPUTED, SIGNAL, STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_NOTIFY_MASK, STATE_RECOMPUTING } from './constants.js';
|
|
2
|
+
import { COMPUTED, SIGNAL, STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_NOTIFY_MASK, STATE_RECOMPUTING, TYPE } from './constants.js';
|
|
3
3
|
let depth = 0, heap = new Array(64), heap_i = 0, heap_n = 0, linkPool = [], linkPoolMax = 1000, microtask = queueMicrotask, notified = false, observer = null, scope = null, stabilizer = STABILIZER_IDLE, version = 0;
|
|
4
4
|
function cleanup(computed) {
|
|
5
5
|
if (!computed.cleanup) {
|
|
@@ -219,7 +219,7 @@ function unlink(link) {
|
|
|
219
219
|
if (prevSub) {
|
|
220
220
|
prevSub.nextSub = nextSub;
|
|
221
221
|
}
|
|
222
|
-
else if ((dep.subs = nextSub) === null &&
|
|
222
|
+
else if ((dep.subs = nextSub) === null && dep[TYPE] === COMPUTED) {
|
|
223
223
|
dispose(dep);
|
|
224
224
|
}
|
|
225
225
|
if (linkPool.length < linkPoolMax) {
|
|
@@ -233,7 +233,7 @@ function update(computed) {
|
|
|
233
233
|
if (computed.state & STATE_CHECK) {
|
|
234
234
|
for (let link = computed.deps; link; link = link.nextDep) {
|
|
235
235
|
let dep = link.dep;
|
|
236
|
-
if (
|
|
236
|
+
if (dep[TYPE] === COMPUTED) {
|
|
237
237
|
update(dep);
|
|
238
238
|
if (computed.state & STATE_DIRTY) {
|
|
239
239
|
break;
|
|
@@ -248,7 +248,7 @@ function update(computed) {
|
|
|
248
248
|
}
|
|
249
249
|
const computed = (fn) => {
|
|
250
250
|
let self = {
|
|
251
|
-
[
|
|
251
|
+
[TYPE]: COMPUTED,
|
|
252
252
|
cleanup: null,
|
|
253
253
|
deps: null,
|
|
254
254
|
depsTail: null,
|
|
@@ -302,10 +302,10 @@ const effect = (fn) => {
|
|
|
302
302
|
};
|
|
303
303
|
};
|
|
304
304
|
const isComputed = (value) => {
|
|
305
|
-
return isObject(value) &&
|
|
305
|
+
return isObject(value) && value[TYPE] === COMPUTED;
|
|
306
306
|
};
|
|
307
307
|
const isSignal = (value) => {
|
|
308
|
-
return isObject(value) &&
|
|
308
|
+
return isObject(value) && value[TYPE] === SIGNAL;
|
|
309
309
|
};
|
|
310
310
|
const onCleanup = (fn) => {
|
|
311
311
|
let parent = observer || scope;
|
|
@@ -327,7 +327,7 @@ const onCleanup = (fn) => {
|
|
|
327
327
|
const read = (node) => {
|
|
328
328
|
if (observer) {
|
|
329
329
|
link(node, observer);
|
|
330
|
-
if (
|
|
330
|
+
if (node[TYPE] === COMPUTED) {
|
|
331
331
|
let height = node.height;
|
|
332
332
|
if (height >= observer.height) {
|
|
333
333
|
observer.height = height + 1;
|
|
@@ -384,7 +384,7 @@ const set = (signal, value) => {
|
|
|
384
384
|
};
|
|
385
385
|
const signal = (value) => {
|
|
386
386
|
return {
|
|
387
|
-
[
|
|
387
|
+
[TYPE]: SIGNAL,
|
|
388
388
|
subs: null,
|
|
389
389
|
subsTail: null,
|
|
390
390
|
value,
|
package/build/types.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { COMPUTED, SIGNAL, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_RECOMPUTING } from './constants.js';
|
|
1
|
+
import { COMPUTED, SIGNAL, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_RECOMPUTING, TYPE } from './constants.js';
|
|
2
2
|
import { ReactiveArray } from './reactive/array.js';
|
|
3
3
|
import { ReactiveObject } from './reactive/object.js';
|
|
4
4
|
interface Computed<T> {
|
|
5
|
-
[
|
|
5
|
+
[TYPE]: typeof COMPUTED;
|
|
6
6
|
cleanup: VoidFunction | VoidFunction[] | null;
|
|
7
7
|
deps: Link | null;
|
|
8
8
|
depsTail: Link | null;
|
|
@@ -24,7 +24,7 @@ interface Link {
|
|
|
24
24
|
version: number;
|
|
25
25
|
}
|
|
26
26
|
type Signal<T> = {
|
|
27
|
-
[
|
|
27
|
+
[TYPE]: typeof SIGNAL;
|
|
28
28
|
subs: Link | null;
|
|
29
29
|
subsTail: Link | null;
|
|
30
30
|
value: T;
|
package/build/types.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TYPE } from './constants.js';
|
package/package.json
CHANGED
package/src/constants.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
const COMPUTED = Symbol('computed');
|
|
1
|
+
const COMPUTED = Symbol('reactivity.computed');
|
|
2
2
|
|
|
3
|
-
const REACTIVE_ARRAY = Symbol('reactive.array');
|
|
3
|
+
const REACTIVE_ARRAY = Symbol('reactivity.reactive.array');
|
|
4
4
|
|
|
5
|
-
const REACTIVE_OBJECT = Symbol('reactive.object');
|
|
5
|
+
const REACTIVE_OBJECT = Symbol('reactivity.reactive.object');
|
|
6
6
|
|
|
7
|
-
const SIGNAL = Symbol('signal');
|
|
7
|
+
const SIGNAL = Symbol('reactivity.signal');
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
const STABILIZER_IDLE = 0;
|
|
@@ -29,6 +29,9 @@ const STATE_IN_HEAP = 1 << 3;
|
|
|
29
29
|
const STATE_NOTIFY_MASK = (STATE_CHECK | STATE_DIRTY);
|
|
30
30
|
|
|
31
31
|
|
|
32
|
+
const TYPE = Symbol('reactivity.type');
|
|
33
|
+
|
|
34
|
+
|
|
32
35
|
export {
|
|
33
36
|
COMPUTED,
|
|
34
37
|
REACTIVE_ARRAY,
|
|
@@ -43,5 +46,6 @@ export {
|
|
|
43
46
|
STATE_DIRTY,
|
|
44
47
|
STATE_IN_HEAP,
|
|
45
48
|
STATE_NONE,
|
|
46
|
-
STATE_RECOMPUTING
|
|
49
|
+
STATE_RECOMPUTING,
|
|
50
|
+
TYPE
|
|
47
51
|
};
|
package/src/reactive/array.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isArray } from '@esportsplus/utilities';
|
|
2
|
+
import { REACTIVE_ARRAY, TYPE } from '~/constants';
|
|
2
3
|
import { isReactiveObject } from './object';
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
type Events<T> = {
|
|
6
7
|
clear: undefined,
|
|
8
|
+
concat: {
|
|
9
|
+
items: T[];
|
|
10
|
+
};
|
|
7
11
|
pop: {
|
|
8
12
|
item: T;
|
|
9
13
|
};
|
|
@@ -38,7 +42,6 @@ type Listeners = Record<string, (Listener<any> | null)[]>;
|
|
|
38
42
|
|
|
39
43
|
|
|
40
44
|
class ReactiveArray<T> extends Array<T> {
|
|
41
|
-
[REACTIVE_ARRAY] = true;
|
|
42
45
|
listeners: Listeners = {};
|
|
43
46
|
|
|
44
47
|
|
|
@@ -52,6 +55,33 @@ class ReactiveArray<T> extends Array<T> {
|
|
|
52
55
|
this.dispatch('clear');
|
|
53
56
|
}
|
|
54
57
|
|
|
58
|
+
concat(...items: ConcatArray<T>[]): ReactiveArray<T>;
|
|
59
|
+
concat(...items: (T | ConcatArray<T>)[]): ReactiveArray<T>;
|
|
60
|
+
concat(...items: (T | ConcatArray<T>)[]) {
|
|
61
|
+
let added: T[] = [];
|
|
62
|
+
|
|
63
|
+
for (let i = 0, n = items.length; i < n; i++) {
|
|
64
|
+
let item = items[i];
|
|
65
|
+
|
|
66
|
+
if (isArray(item)) {
|
|
67
|
+
for (let j = 0, o = item.length; j < o; j++) {
|
|
68
|
+
added.push(item[j]);
|
|
69
|
+
super.push(item[j]);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
added.push(item as T);
|
|
74
|
+
super.push(item as T);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (added.length) {
|
|
79
|
+
this.dispatch('concat', { items: added });
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return this;
|
|
83
|
+
}
|
|
84
|
+
|
|
55
85
|
dispatch<K extends keyof Events<T>, V>(event: K, value?: V) {
|
|
56
86
|
let listeners = this.listeners[event];
|
|
57
87
|
|
|
@@ -77,12 +107,18 @@ class ReactiveArray<T> extends Array<T> {
|
|
|
77
107
|
listeners[i] = null;
|
|
78
108
|
}
|
|
79
109
|
}
|
|
110
|
+
|
|
111
|
+
while (listeners.length && listeners[listeners.length - 1] === null) {
|
|
112
|
+
listeners.pop();
|
|
113
|
+
}
|
|
80
114
|
}
|
|
81
115
|
|
|
82
116
|
dispose() {
|
|
83
117
|
let item;
|
|
84
118
|
|
|
85
|
-
while (
|
|
119
|
+
while (this.length) {
|
|
120
|
+
item = super.pop();
|
|
121
|
+
|
|
86
122
|
if (isReactiveObject(item)) {
|
|
87
123
|
item.dispose();
|
|
88
124
|
}
|
|
@@ -110,6 +146,10 @@ class ReactiveArray<T> extends Array<T> {
|
|
|
110
146
|
}
|
|
111
147
|
|
|
112
148
|
listeners[hole] = listener;
|
|
149
|
+
|
|
150
|
+
while (listeners.length && listeners[listeners.length - 1] === null) {
|
|
151
|
+
listeners.pop();
|
|
152
|
+
}
|
|
113
153
|
}
|
|
114
154
|
}
|
|
115
155
|
|
|
@@ -159,7 +199,7 @@ class ReactiveArray<T> extends Array<T> {
|
|
|
159
199
|
return item;
|
|
160
200
|
}
|
|
161
201
|
|
|
162
|
-
sort(fn
|
|
202
|
+
sort(fn?: (a: T, b: T) => number) {
|
|
163
203
|
super.sort(fn);
|
|
164
204
|
this.dispatch('sort');
|
|
165
205
|
|
|
@@ -193,5 +233,7 @@ class ReactiveArray<T> extends Array<T> {
|
|
|
193
233
|
}
|
|
194
234
|
}
|
|
195
235
|
|
|
236
|
+
Object.defineProperty(ReactiveArray.prototype, TYPE, { value: REACTIVE_ARRAY });
|
|
237
|
+
|
|
196
238
|
|
|
197
239
|
export { ReactiveArray };
|
package/src/reactive/object.ts
CHANGED
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
import { defineProperty, isArray, isPromise } from '@esportsplus/utilities';
|
|
2
2
|
import { computed, dispose, effect, read, root, set, signal } from '~/system';
|
|
3
3
|
import { Computed, Signal } from '~/types';
|
|
4
|
-
import { REACTIVE_OBJECT } from '~/constants';
|
|
4
|
+
import { REACTIVE_OBJECT, TYPE } from '~/constants';
|
|
5
5
|
import { ReactiveArray } from './array';
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class ReactiveObject<T extends Record<PropertyKey, unknown>> {
|
|
9
|
-
[REACTIVE_OBJECT] = true;
|
|
10
|
-
|
|
11
|
-
|
|
12
9
|
private disposers: VoidFunction[] | null = null;
|
|
13
10
|
|
|
14
11
|
|
|
15
12
|
constructor(data: T) {
|
|
16
|
-
let keys = Object.keys(data)
|
|
17
|
-
key: keyof T | undefined;
|
|
13
|
+
let keys = Object.keys(data);
|
|
18
14
|
|
|
19
|
-
|
|
20
|
-
let
|
|
15
|
+
for (let i = 0, n = keys.length; i < n; ++i) {
|
|
16
|
+
let key: keyof T | undefined = keys[i],
|
|
17
|
+
value = data[key],
|
|
21
18
|
type = typeof value;
|
|
22
19
|
|
|
23
20
|
if (type === 'function') {
|
|
@@ -108,9 +105,11 @@ class ReactiveObject<T extends Record<PropertyKey, unknown>> {
|
|
|
108
105
|
}
|
|
109
106
|
}
|
|
110
107
|
|
|
108
|
+
Object.defineProperty(ReactiveObject.prototype, TYPE, { value: REACTIVE_OBJECT });
|
|
109
|
+
|
|
111
110
|
|
|
112
111
|
const isReactiveObject = (value: any): value is ReactiveObject<any> => {
|
|
113
|
-
return typeof value === 'object' && value !== null &&
|
|
112
|
+
return typeof value === 'object' && value !== null && value[TYPE] === REACTIVE_OBJECT;
|
|
114
113
|
};
|
|
115
114
|
|
|
116
115
|
|
package/src/system.ts
CHANGED
|
@@ -2,7 +2,8 @@ import { 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_NOTIFY_MASK, STATE_RECOMPUTING
|
|
5
|
+
STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_NOTIFY_MASK, STATE_RECOMPUTING,
|
|
6
|
+
TYPE
|
|
6
7
|
} from './constants';
|
|
7
8
|
import { Computed, Link, Signal } from './types';
|
|
8
9
|
|
|
@@ -321,7 +322,7 @@ function unlink(link: Link): Link | null {
|
|
|
321
322
|
if (prevSub) {
|
|
322
323
|
prevSub.nextSub = nextSub;
|
|
323
324
|
}
|
|
324
|
-
else if ((dep.subs = nextSub) === null &&
|
|
325
|
+
else if ((dep.subs = nextSub) === null && dep[TYPE] === COMPUTED) {
|
|
325
326
|
dispose(dep);
|
|
326
327
|
}
|
|
327
328
|
|
|
@@ -340,7 +341,7 @@ function update<T>(computed: Computed<T>): void {
|
|
|
340
341
|
for (let link = computed.deps; link; link = link.nextDep) {
|
|
341
342
|
let dep = link.dep;
|
|
342
343
|
|
|
343
|
-
if (
|
|
344
|
+
if (dep[TYPE] === COMPUTED) {
|
|
344
345
|
update(dep);
|
|
345
346
|
|
|
346
347
|
if (computed.state & STATE_DIRTY) {
|
|
@@ -360,7 +361,7 @@ function update<T>(computed: Computed<T>): void {
|
|
|
360
361
|
|
|
361
362
|
const computed = <T>(fn: Computed<T>['fn']): Computed<T> => {
|
|
362
363
|
let self: Computed<T> = {
|
|
363
|
-
[
|
|
364
|
+
[TYPE]: COMPUTED,
|
|
364
365
|
cleanup: null,
|
|
365
366
|
deps: null,
|
|
366
367
|
depsTail: null,
|
|
@@ -427,11 +428,11 @@ const effect = <T>(fn: Computed<T>['fn']) => {
|
|
|
427
428
|
};
|
|
428
429
|
|
|
429
430
|
const isComputed = (value: unknown): value is Computed<unknown> => {
|
|
430
|
-
return isObject(value) &&
|
|
431
|
+
return isObject(value) && value[TYPE] === COMPUTED;
|
|
431
432
|
};
|
|
432
433
|
|
|
433
434
|
const isSignal = (value: unknown): value is Signal<unknown> => {
|
|
434
|
-
return isObject(value) &&
|
|
435
|
+
return isObject(value) && value[TYPE] === SIGNAL;
|
|
435
436
|
};
|
|
436
437
|
|
|
437
438
|
const onCleanup = (fn: VoidFunction): typeof fn => {
|
|
@@ -460,7 +461,7 @@ const read = <T>(node: Signal<T> | Computed<T>): T => {
|
|
|
460
461
|
if (observer) {
|
|
461
462
|
link(node, observer);
|
|
462
463
|
|
|
463
|
-
if (
|
|
464
|
+
if (node[TYPE] === COMPUTED) {
|
|
464
465
|
let height = node.height;
|
|
465
466
|
|
|
466
467
|
if (height >= observer.height) {
|
|
@@ -541,7 +542,7 @@ const set = <T>(signal: Signal<T>, value: T) => {
|
|
|
541
542
|
|
|
542
543
|
const signal = <T>(value: T): Signal<T> => {
|
|
543
544
|
return {
|
|
544
|
-
[
|
|
545
|
+
[TYPE]: SIGNAL,
|
|
545
546
|
subs: null,
|
|
546
547
|
subsTail: null,
|
|
547
548
|
value,
|
package/src/types.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { COMPUTED, SIGNAL, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_RECOMPUTING } from './constants';
|
|
1
|
+
import { COMPUTED, SIGNAL, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_RECOMPUTING, TYPE } from './constants';
|
|
2
2
|
import { ReactiveArray } from './reactive/array';
|
|
3
3
|
import { ReactiveObject } from './reactive/object';
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
interface Computed<T> {
|
|
7
|
-
[
|
|
7
|
+
[TYPE]: typeof COMPUTED;
|
|
8
8
|
cleanup: VoidFunction | VoidFunction[] | null;
|
|
9
9
|
deps: Link | null;
|
|
10
10
|
depsTail: Link | null;
|
|
@@ -33,7 +33,7 @@ interface Link {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
type Signal<T> = {
|
|
36
|
-
[
|
|
36
|
+
[TYPE]: typeof SIGNAL;
|
|
37
37
|
subs: Link | null;
|
|
38
38
|
subsTail: Link | null;
|
|
39
39
|
value: T;
|