@esportsplus/reactivity 0.12.0 → 0.12.2
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 +1 -0
- package/build/reactive/array.js +26 -29
- package/build/reactive/index.js +17 -7
- package/build/reactive/object.js +2 -4
- package/build/system.d.ts +4 -1
- package/build/system.js +22 -17
- package/package.json +1 -1
- package/src/reactive/array.ts +30 -35
- package/src/reactive/index.ts +21 -8
- package/src/reactive/object.ts +3 -6
- package/src/system.ts +25 -18
|
@@ -35,6 +35,7 @@ type Listener<V> = {
|
|
|
35
35
|
type Value<T> = T extends Record<PropertyKey, unknown> ? ReactiveObject<T> : T extends Array<infer U> ? API<U> : T;
|
|
36
36
|
declare class ReactiveArray<T> {
|
|
37
37
|
[REACTIVE_ARRAY]: boolean;
|
|
38
|
+
disposables: number;
|
|
38
39
|
private data;
|
|
39
40
|
private listeners;
|
|
40
41
|
private proxy;
|
package/build/reactive/array.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { isFunction, isNumber, isObject } from '@esportsplus/utilities';
|
|
2
2
|
import { REACTIVE_ARRAY } from '../constants.js';
|
|
3
|
-
import { computed, dispose, isComputed,
|
|
3
|
+
import { computed, dispose, isComputed, read } from '../system.js';
|
|
4
4
|
import object, { isReactiveObject } from './object.js';
|
|
5
5
|
class ReactiveArray {
|
|
6
6
|
[REACTIVE_ARRAY] = true;
|
|
7
|
+
disposables = 0;
|
|
7
8
|
data;
|
|
8
9
|
listeners = null;
|
|
9
10
|
proxy;
|
|
@@ -171,36 +172,32 @@ const isReactiveArray = (value) => {
|
|
|
171
172
|
return isObject(value) && REACTIVE_ARRAY in value;
|
|
172
173
|
};
|
|
173
174
|
export default function array(input) {
|
|
174
|
-
let
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
return read(value);
|
|
181
|
-
}
|
|
182
|
-
return value;
|
|
175
|
+
let proxy = new Proxy({}, {
|
|
176
|
+
get(_, key) {
|
|
177
|
+
if (isNumber(key)) {
|
|
178
|
+
let value = wrapped[key];
|
|
179
|
+
if (isComputed(value)) {
|
|
180
|
+
return read(value);
|
|
183
181
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
return
|
|
188
|
-
},
|
|
189
|
-
set(_, key, value) {
|
|
190
|
-
if (isNumber(key)) {
|
|
191
|
-
array.splice(key, 1, value);
|
|
192
|
-
return true;
|
|
193
|
-
}
|
|
194
|
-
else if (key === 'length') {
|
|
195
|
-
return array.length = value;
|
|
196
|
-
}
|
|
197
|
-
return false;
|
|
182
|
+
return value;
|
|
183
|
+
}
|
|
184
|
+
else if (key in array) {
|
|
185
|
+
return array[key];
|
|
198
186
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
187
|
+
return wrapped[key];
|
|
188
|
+
},
|
|
189
|
+
set(_, key, value) {
|
|
190
|
+
if (isNumber(key)) {
|
|
191
|
+
array.splice(key, 1, value);
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
else if (key === 'length') {
|
|
195
|
+
return array.length = value;
|
|
196
|
+
}
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
}), wrapped = factory(input);
|
|
200
|
+
let array = new ReactiveArray(wrapped, proxy);
|
|
204
201
|
return proxy;
|
|
205
202
|
}
|
|
206
203
|
;
|
package/build/reactive/index.js
CHANGED
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
import { isArray, isObject } from '@esportsplus/utilities';
|
|
2
|
+
import { onCleanup, root } from '../system.js';
|
|
2
3
|
import array from './array.js';
|
|
3
4
|
import object from './object.js';
|
|
4
5
|
export default (input) => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
let value;
|
|
7
|
+
return root(() => {
|
|
8
|
+
if (isArray(input)) {
|
|
9
|
+
value = array(input);
|
|
10
|
+
}
|
|
11
|
+
else if (isObject(input)) {
|
|
12
|
+
value = object(input);
|
|
13
|
+
}
|
|
14
|
+
if (value) {
|
|
15
|
+
if (root.disposables) {
|
|
16
|
+
onCleanup(() => value.dispose());
|
|
17
|
+
}
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
throw new Error(`@esportsplus/reactivity: 'reactive' received invalid input - ${JSON.stringify(input)}`);
|
|
21
|
+
});
|
|
12
22
|
};
|
package/build/reactive/object.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineProperty, isArray, isFunction, isObject, isPromise } from '@esportsplus/utilities';
|
|
2
|
-
import { computed, dispose, effect, isComputed,
|
|
2
|
+
import { computed, dispose, effect, isComputed, read, root, set, signal } from '../system.js';
|
|
3
3
|
import { REACTIVE_OBJECT } from '../constants.js';
|
|
4
4
|
import array, { isReactiveArray } from './array.js';
|
|
5
5
|
class ReactiveObject {
|
|
@@ -74,9 +74,7 @@ const isReactiveObject = (value) => {
|
|
|
74
74
|
return isObject(value) && REACTIVE_OBJECT in value;
|
|
75
75
|
};
|
|
76
76
|
export default function object(input) {
|
|
77
|
-
|
|
78
|
-
onCleanup(() => object.dispose());
|
|
79
|
-
return object;
|
|
77
|
+
return new ReactiveObject(input);
|
|
80
78
|
}
|
|
81
79
|
;
|
|
82
80
|
export { isReactiveObject };
|
package/build/system.d.ts
CHANGED
|
@@ -6,7 +6,10 @@ declare const isComputed: (value: unknown) => value is Computed<unknown>;
|
|
|
6
6
|
declare const isSignal: (value: unknown) => value is Signal<unknown>;
|
|
7
7
|
declare const onCleanup: (fn: VoidFunction) => typeof fn;
|
|
8
8
|
declare const read: <T>(node: Signal<T> | Computed<T>) => T;
|
|
9
|
-
declare const root:
|
|
9
|
+
declare const root: {
|
|
10
|
+
<T>(fn: () => T): T;
|
|
11
|
+
disposables: number;
|
|
12
|
+
};
|
|
10
13
|
declare const set: <T>(signal: Signal<T>, value: T) => void;
|
|
11
14
|
declare const signal: <T>(value: T) => Signal<T>;
|
|
12
15
|
export { computed, dispose, effect, isComputed, isSignal, onCleanup, read, root, set, signal };
|
package/build/system.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import { isArray, isObject
|
|
1
|
+
import { isArray, isObject } from '@esportsplus/utilities';
|
|
2
2
|
import { COMPUTED, SIGNAL, STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_RECOMPUTING } from './constants.js';
|
|
3
3
|
let depth = 0, heap = new Array(2048), index = 0, length = 0, microtask = queueMicrotask, notified = false, observer = null, stabilizer = STABILIZER_IDLE, version = 0;
|
|
4
|
-
function cleanup(
|
|
5
|
-
if (!
|
|
4
|
+
function cleanup(computed) {
|
|
5
|
+
if (!computed.cleanup) {
|
|
6
6
|
return;
|
|
7
7
|
}
|
|
8
|
-
let
|
|
9
|
-
if (isArray(
|
|
10
|
-
for (let i = 0, n =
|
|
11
|
-
|
|
8
|
+
let value = computed.cleanup;
|
|
9
|
+
if (isArray(value)) {
|
|
10
|
+
for (let i = 0, n = value.length; i < n; i++) {
|
|
11
|
+
value[i]();
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
else {
|
|
15
|
-
|
|
15
|
+
value();
|
|
16
16
|
}
|
|
17
|
-
|
|
17
|
+
computed.cleanup = null;
|
|
18
18
|
}
|
|
19
19
|
function deleteFromHeap(computed) {
|
|
20
20
|
let state = computed.state;
|
|
@@ -138,11 +138,11 @@ function recompute(computed, del) {
|
|
|
138
138
|
depth--;
|
|
139
139
|
observer = o;
|
|
140
140
|
computed.state = STATE_NONE;
|
|
141
|
-
let depsTail = computed.depsTail,
|
|
142
|
-
if (
|
|
141
|
+
let depsTail = computed.depsTail, remove = depsTail !== null ? depsTail.nextDep : computed.deps;
|
|
142
|
+
if (remove !== null) {
|
|
143
143
|
do {
|
|
144
|
-
|
|
145
|
-
} while (
|
|
144
|
+
remove = unlink(remove);
|
|
145
|
+
} while (remove !== null);
|
|
146
146
|
if (depsTail !== null) {
|
|
147
147
|
depsTail.nextDep = null;
|
|
148
148
|
}
|
|
@@ -153,11 +153,11 @@ function recompute(computed, del) {
|
|
|
153
153
|
if (ok && value !== computed.value) {
|
|
154
154
|
computed.value = value;
|
|
155
155
|
for (let c = computed.subs; c !== null; c = c.nextSub) {
|
|
156
|
-
let
|
|
156
|
+
let s = c.sub, state = s.state;
|
|
157
157
|
if (state & STATE_CHECK) {
|
|
158
|
-
|
|
158
|
+
s.state = state | STATE_DIRTY;
|
|
159
159
|
}
|
|
160
|
-
insertIntoHeap(
|
|
160
|
+
insertIntoHeap(s);
|
|
161
161
|
}
|
|
162
162
|
schedule();
|
|
163
163
|
}
|
|
@@ -173,6 +173,7 @@ function schedule() {
|
|
|
173
173
|
}
|
|
174
174
|
function stabilize() {
|
|
175
175
|
let o = observer;
|
|
176
|
+
observer = null;
|
|
176
177
|
stabilizer = STABILIZER_RUNNING;
|
|
177
178
|
for (index = 0; index <= length; index++) {
|
|
178
179
|
let computed = heap[index];
|
|
@@ -255,6 +256,7 @@ const computed = (fn) => {
|
|
|
255
256
|
}
|
|
256
257
|
else {
|
|
257
258
|
recompute(self, false);
|
|
259
|
+
root.disposables++;
|
|
258
260
|
}
|
|
259
261
|
return self;
|
|
260
262
|
};
|
|
@@ -319,12 +321,15 @@ const read = (node) => {
|
|
|
319
321
|
return node.value;
|
|
320
322
|
};
|
|
321
323
|
const root = (fn) => {
|
|
322
|
-
let o = observer;
|
|
324
|
+
let d = root.disposables, o = observer;
|
|
323
325
|
observer = null;
|
|
326
|
+
root.disposables = 0;
|
|
324
327
|
let value = fn();
|
|
325
328
|
observer = o;
|
|
329
|
+
root.disposables = d;
|
|
326
330
|
return value;
|
|
327
331
|
};
|
|
332
|
+
root.disposables = 0;
|
|
328
333
|
const set = (signal, value) => {
|
|
329
334
|
if (signal.value === value) {
|
|
330
335
|
return;
|
package/package.json
CHANGED
package/src/reactive/array.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isFunction, isNumber, isObject } from '@esportsplus/utilities';
|
|
2
2
|
import { REACTIVE_ARRAY } from '~/constants';
|
|
3
|
-
import { computed, dispose, isComputed,
|
|
3
|
+
import { computed, dispose, isComputed, read } from '~/system';
|
|
4
4
|
import { Computed, Infer } from '~/types';
|
|
5
5
|
import object, { isReactiveObject, ReactiveObject } from './object';
|
|
6
6
|
|
|
@@ -50,6 +50,7 @@ type Value<T> =
|
|
|
50
50
|
|
|
51
51
|
class ReactiveArray<T> {
|
|
52
52
|
[REACTIVE_ARRAY] = true;
|
|
53
|
+
disposables: number = 0;
|
|
53
54
|
|
|
54
55
|
private data: Item<T>[];
|
|
55
56
|
private listeners: Record<string, (Listener<any> | null)[]> | null = null;
|
|
@@ -294,44 +295,38 @@ const isReactiveArray = (value: any): value is ReactiveArray<any> => {
|
|
|
294
295
|
|
|
295
296
|
|
|
296
297
|
export default function array<T>(input: T[]) {
|
|
297
|
-
let
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
return read(value);
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
return value;
|
|
308
|
-
}
|
|
309
|
-
else if (key in array) {
|
|
310
|
-
return array[key as keyof typeof array];
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
return wrapped[key];
|
|
314
|
-
},
|
|
315
|
-
set(_: any, key: any, value: any) {
|
|
316
|
-
if (isNumber(key)) {
|
|
317
|
-
array.splice(key, 1, value);
|
|
318
|
-
return true;
|
|
319
|
-
}
|
|
320
|
-
else if (key === 'length') {
|
|
321
|
-
return array.length = value;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
return false;
|
|
298
|
+
let proxy = new Proxy({}, {
|
|
299
|
+
get(_: any, key: any) {
|
|
300
|
+
if (isNumber(key)) {
|
|
301
|
+
let value = wrapped[key];
|
|
302
|
+
|
|
303
|
+
if (isComputed(value)) {
|
|
304
|
+
return read(value);
|
|
325
305
|
}
|
|
326
|
-
}) as API<T>,
|
|
327
|
-
wrapped = factory(input);
|
|
328
306
|
|
|
329
|
-
|
|
307
|
+
return value;
|
|
308
|
+
}
|
|
309
|
+
else if (key in array) {
|
|
310
|
+
return array[key as keyof typeof array];
|
|
311
|
+
}
|
|
330
312
|
|
|
331
|
-
|
|
332
|
-
|
|
313
|
+
return wrapped[key];
|
|
314
|
+
},
|
|
315
|
+
set(_: any, key: any, value: any) {
|
|
316
|
+
if (isNumber(key)) {
|
|
317
|
+
array.splice(key, 1, value);
|
|
318
|
+
return true;
|
|
319
|
+
}
|
|
320
|
+
else if (key === 'length') {
|
|
321
|
+
return array.length = value;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return false;
|
|
325
|
+
}
|
|
326
|
+
}) as API<T>,
|
|
327
|
+
wrapped = factory(input);
|
|
333
328
|
|
|
334
|
-
|
|
329
|
+
let array = new ReactiveArray(wrapped, proxy);
|
|
335
330
|
|
|
336
331
|
return proxy;
|
|
337
332
|
};
|
package/src/reactive/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isArray, isObject } from '@esportsplus/utilities';
|
|
2
|
+
import { onCleanup, root } from '~/system';
|
|
2
3
|
import array from './array';
|
|
3
4
|
import object from './object';
|
|
4
5
|
|
|
@@ -21,13 +22,25 @@ type Input<T> =
|
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
export default <T extends Record<PropertyKey, unknown> | unknown[]>(input: Input<T>): API<T> => {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
25
|
+
let value: API<T> | undefined;
|
|
26
|
+
|
|
27
|
+
return root(() => {
|
|
28
|
+
if (isArray(input)) {
|
|
29
|
+
value = array(input) as API<T>;
|
|
30
|
+
}
|
|
31
|
+
else if (isObject(input)) {
|
|
32
|
+
value = object(input) as API<T>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (value) {
|
|
36
|
+
if (root.disposables) {
|
|
37
|
+
onCleanup(() => value!.dispose());
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
throw new Error(`@esportsplus/reactivity: 'reactive' received invalid input - ${JSON.stringify(input)}`);
|
|
44
|
+
});
|
|
32
45
|
};
|
|
33
46
|
export type { Input };
|
package/src/reactive/object.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineProperty, isArray, isFunction, isObject, isPromise, Prettify } from '@esportsplus/utilities';
|
|
2
|
-
import { computed, dispose, effect, isComputed,
|
|
2
|
+
import { computed, dispose, effect, isComputed, read, root, set, signal } from '~/system';
|
|
3
3
|
import { Computed, Infer, Signal } from '~/types';
|
|
4
4
|
import { REACTIVE_OBJECT } from '~/constants';
|
|
5
5
|
import array, { isReactiveArray } from './array';
|
|
@@ -11,6 +11,7 @@ type API<T extends Record<PropertyKey, unknown>> = Prettify<{ [K in keyof T]: In
|
|
|
11
11
|
class ReactiveObject<T extends Record<PropertyKey, unknown>> {
|
|
12
12
|
[REACTIVE_OBJECT] = true;
|
|
13
13
|
|
|
14
|
+
|
|
14
15
|
constructor(data: T) {
|
|
15
16
|
for (let key in data) {
|
|
16
17
|
let value = data[key];
|
|
@@ -100,11 +101,7 @@ const isReactiveObject = (value: any): value is ReactiveObject<any> => {
|
|
|
100
101
|
|
|
101
102
|
|
|
102
103
|
export default function object<T extends Record<PropertyKey, unknown>>(input: T) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
onCleanup(() => object.dispose());
|
|
106
|
-
|
|
107
|
-
return object;
|
|
104
|
+
return new ReactiveObject<T>(input);
|
|
108
105
|
};
|
|
109
106
|
export { isReactiveObject };
|
|
110
107
|
export type { API as ReactiveObject };
|
package/src/system.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isArray, isObject
|
|
1
|
+
import { isArray, isObject } from '@esportsplus/utilities';
|
|
2
2
|
import {
|
|
3
3
|
COMPUTED, SIGNAL,
|
|
4
4
|
STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED,
|
|
@@ -18,23 +18,23 @@ let depth = 0,
|
|
|
18
18
|
version = 0;
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
function cleanup<T>(
|
|
22
|
-
if (!
|
|
21
|
+
function cleanup<T>(computed: Computed<T>): void {
|
|
22
|
+
if (!computed.cleanup) {
|
|
23
23
|
return;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
let
|
|
26
|
+
let value = computed.cleanup;
|
|
27
27
|
|
|
28
|
-
if (isArray(
|
|
29
|
-
for (let i = 0, n =
|
|
30
|
-
|
|
28
|
+
if (isArray(value)) {
|
|
29
|
+
for (let i = 0, n = value.length; i < n; i++) {
|
|
30
|
+
value[i]();
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
else {
|
|
34
|
-
|
|
34
|
+
value();
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
computed.cleanup = null;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
function deleteFromHeap<T>(computed: Computed<T>) {
|
|
@@ -208,13 +208,13 @@ function recompute<T>(computed: Computed<T>, del: boolean) {
|
|
|
208
208
|
computed.state = STATE_NONE;
|
|
209
209
|
|
|
210
210
|
let depsTail = computed.depsTail as Link | null,
|
|
211
|
-
|
|
211
|
+
remove = depsTail !== null ? depsTail.nextDep : computed.deps;
|
|
212
212
|
|
|
213
|
-
if (
|
|
213
|
+
if (remove !== null) {
|
|
214
214
|
do {
|
|
215
|
-
|
|
215
|
+
remove = unlink(remove);
|
|
216
216
|
}
|
|
217
|
-
while (
|
|
217
|
+
while (remove !== null);
|
|
218
218
|
|
|
219
219
|
if (depsTail !== null) {
|
|
220
220
|
depsTail.nextDep = null;
|
|
@@ -228,14 +228,14 @@ function recompute<T>(computed: Computed<T>, del: boolean) {
|
|
|
228
228
|
computed.value = value as T;
|
|
229
229
|
|
|
230
230
|
for (let c = computed.subs; c !== null; c = c.nextSub) {
|
|
231
|
-
let
|
|
232
|
-
state =
|
|
231
|
+
let s = c.sub,
|
|
232
|
+
state = s.state;
|
|
233
233
|
|
|
234
234
|
if (state & STATE_CHECK) {
|
|
235
|
-
|
|
235
|
+
s.state = state | STATE_DIRTY;
|
|
236
236
|
}
|
|
237
237
|
|
|
238
|
-
insertIntoHeap(
|
|
238
|
+
insertIntoHeap(s);
|
|
239
239
|
}
|
|
240
240
|
|
|
241
241
|
schedule();
|
|
@@ -255,6 +255,7 @@ function schedule() {
|
|
|
255
255
|
function stabilize() {
|
|
256
256
|
let o = observer;
|
|
257
257
|
|
|
258
|
+
observer = null;
|
|
258
259
|
stabilizer = STABILIZER_RUNNING;
|
|
259
260
|
|
|
260
261
|
for (index = 0; index <= length; index++) {
|
|
@@ -359,6 +360,7 @@ const computed = <T>(fn: Computed<T>['fn']): Computed<T> => {
|
|
|
359
360
|
}
|
|
360
361
|
else {
|
|
361
362
|
recompute(self, false);
|
|
363
|
+
root.disposables++;
|
|
362
364
|
}
|
|
363
365
|
|
|
364
366
|
return self;
|
|
@@ -446,17 +448,22 @@ const read = <T>(node: Signal<T> | Computed<T>): T => {
|
|
|
446
448
|
};
|
|
447
449
|
|
|
448
450
|
const root = <T>(fn: () => T) => {
|
|
449
|
-
let
|
|
451
|
+
let d = root.disposables,
|
|
452
|
+
o = observer;
|
|
450
453
|
|
|
451
454
|
observer = null;
|
|
455
|
+
root.disposables = 0;
|
|
452
456
|
|
|
453
457
|
let value = fn();
|
|
454
458
|
|
|
455
459
|
observer = o;
|
|
460
|
+
root.disposables = d;
|
|
456
461
|
|
|
457
462
|
return value;
|
|
458
463
|
};
|
|
459
464
|
|
|
465
|
+
root.disposables = 0;
|
|
466
|
+
|
|
460
467
|
const set = <T>(signal: Signal<T>, value: T) => {
|
|
461
468
|
if (signal.value === value) {
|
|
462
469
|
return;
|