signalium 0.2.2 → 0.2.3
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/CHANGELOG.md +6 -0
- package/dist/signals.d.ts +8 -12
- package/dist/signals.js +98 -261
- package/package.json +1 -1
- package/src/__tests__/async.test.ts +141 -11
- package/src/__tests__/subscription.test.ts +3 -3
- package/src/__tests__/utils/instrumented.ts +3 -3
- package/src/signals.ts +108 -322
package/src/signals.ts
CHANGED
@@ -1,13 +1,10 @@
|
|
1
1
|
import { scheduleDisconnect, scheduleWatcher } from './scheduling.js';
|
2
2
|
|
3
|
+
let CURRENT_ORD = 0;
|
3
4
|
let CURRENT_CONSUMER: ComputedSignal<any> | undefined;
|
4
|
-
let CURRENT_DEP_TAIL: Link | undefined;
|
5
|
-
let CURRENT_ORD: number = 0;
|
6
|
-
let CURRENT_IS_WATCHED: boolean = false;
|
7
5
|
let CURRENT_IS_WAITING: boolean = false;
|
8
|
-
let CURRENT_SEEN: WeakSet<ComputedSignal<any>> | undefined;
|
9
6
|
|
10
|
-
let
|
7
|
+
let ID = 0;
|
11
8
|
|
12
9
|
const enum SignalType {
|
13
10
|
Computed,
|
@@ -61,188 +58,30 @@ const enum SignalState {
|
|
61
58
|
const WAITING = Symbol();
|
62
59
|
|
63
60
|
interface Link {
|
64
|
-
id: number;
|
65
|
-
sub: WeakRef<ComputedSignal<any>>;
|
66
61
|
dep: ComputedSignal<any>;
|
62
|
+
sub: WeakRef<ComputedSignal<any>>;
|
67
63
|
ord: number;
|
68
64
|
version: number;
|
69
|
-
|
70
|
-
nextDep: Link | undefined;
|
71
|
-
nextSub: Link | undefined;
|
72
|
-
prevSub: Link | undefined;
|
65
|
+
consumedAt: number;
|
73
66
|
|
74
67
|
nextDirty: Link | undefined;
|
75
68
|
}
|
76
69
|
|
77
|
-
let linkPool: Link | undefined;
|
78
|
-
|
79
|
-
const checkForCircularLinks = (link: Link | undefined) => {
|
80
|
-
if (!link) return;
|
81
|
-
|
82
|
-
for (const key of ['nextDep', 'nextSub', 'prevSub', 'nextDirty'] as const) {
|
83
|
-
let currentLink: Link | undefined = link?.[key];
|
84
|
-
|
85
|
-
while (currentLink !== undefined) {
|
86
|
-
if (currentLink === link) {
|
87
|
-
throw new Error(
|
88
|
-
`Circular link detected via ${key}. This is a bug, please report it to the Signalium maintainers.`,
|
89
|
-
);
|
90
|
-
}
|
91
|
-
|
92
|
-
currentLink = currentLink[key];
|
93
|
-
}
|
94
|
-
}
|
95
|
-
};
|
96
|
-
|
97
|
-
const typeToString = (type: SignalType) => {
|
98
|
-
switch (type) {
|
99
|
-
case SignalType.Computed:
|
100
|
-
return 'Computed';
|
101
|
-
case SignalType.Subscription:
|
102
|
-
return 'Subscription';
|
103
|
-
case SignalType.Async:
|
104
|
-
return 'Async';
|
105
|
-
case SignalType.Watcher:
|
106
|
-
return 'Watcher';
|
107
|
-
}
|
108
|
-
};
|
109
|
-
|
110
|
-
const printComputed = (computed: ComputedSignal<any>) => {
|
111
|
-
const type = typeToString(computed._type);
|
112
|
-
|
113
|
-
return `ComputedSignal<${type}:${computed.id}>`;
|
114
|
-
};
|
115
|
-
|
116
|
-
const printLink = (link: Link) => {
|
117
|
-
const sub = link.sub.deref();
|
118
|
-
const subStr = sub === undefined ? 'undefined' : printComputed(sub);
|
119
|
-
const depStr = printComputed(link.dep);
|
120
|
-
|
121
|
-
return `Link<${link.id}> sub(${subStr}) -> dep(${depStr})`;
|
122
|
-
};
|
123
|
-
|
124
|
-
function linkNewDep(
|
125
|
-
dep: ComputedSignal<any>,
|
126
|
-
sub: ComputedSignal<any>,
|
127
|
-
nextDep: Link | undefined,
|
128
|
-
depsTail: Link | undefined,
|
129
|
-
ord: number,
|
130
|
-
): Link {
|
131
|
-
let newLink: Link;
|
132
|
-
|
133
|
-
if (linkPool !== undefined) {
|
134
|
-
newLink = linkPool;
|
135
|
-
linkPool = newLink.nextDep;
|
136
|
-
newLink.nextDep = nextDep;
|
137
|
-
newLink.dep = dep;
|
138
|
-
newLink.sub = sub._ref;
|
139
|
-
newLink.ord = ord;
|
140
|
-
} else {
|
141
|
-
newLink = {
|
142
|
-
id: id++,
|
143
|
-
dep,
|
144
|
-
sub: sub._ref,
|
145
|
-
ord,
|
146
|
-
version: 0,
|
147
|
-
nextDep,
|
148
|
-
nextDirty: undefined,
|
149
|
-
prevSub: undefined,
|
150
|
-
nextSub: undefined,
|
151
|
-
};
|
152
|
-
}
|
153
|
-
|
154
|
-
if (depsTail === undefined) {
|
155
|
-
sub._deps = newLink;
|
156
|
-
} else {
|
157
|
-
depsTail.nextDep = newLink;
|
158
|
-
}
|
159
|
-
|
160
|
-
if (dep._subs === undefined) {
|
161
|
-
dep._subs = newLink;
|
162
|
-
} else {
|
163
|
-
const oldTail = dep._subsTail!;
|
164
|
-
newLink.prevSub = oldTail;
|
165
|
-
oldTail.nextSub = newLink;
|
166
|
-
}
|
167
|
-
|
168
|
-
dep._subsTail = newLink;
|
169
|
-
|
170
|
-
return newLink;
|
171
|
-
}
|
172
|
-
|
173
|
-
function poolLink(link: Link) {
|
174
|
-
const dep = link.dep;
|
175
|
-
const nextSub = link.nextSub;
|
176
|
-
const prevSub = link.prevSub;
|
177
|
-
|
178
|
-
if (nextSub !== undefined) {
|
179
|
-
nextSub.prevSub = prevSub;
|
180
|
-
link.nextSub = undefined;
|
181
|
-
} else {
|
182
|
-
dep._subsTail = prevSub;
|
183
|
-
}
|
184
|
-
|
185
|
-
if (prevSub !== undefined) {
|
186
|
-
prevSub.nextSub = nextSub;
|
187
|
-
link.prevSub = undefined;
|
188
|
-
} else {
|
189
|
-
dep._subs = nextSub;
|
190
|
-
}
|
191
|
-
|
192
|
-
// @ts-expect-error - override to pool the value
|
193
|
-
link.dep = undefined;
|
194
|
-
// @ts-expect-error - override to pool the value
|
195
|
-
link.sub = undefined;
|
196
|
-
link.nextDep = linkPool;
|
197
|
-
linkPool = link;
|
198
|
-
|
199
|
-
link.prevSub = undefined;
|
200
|
-
}
|
201
|
-
|
202
|
-
export function endTrack(sub: ComputedSignal<any>, shouldDisconnect: boolean): void {
|
203
|
-
if (CURRENT_DEP_TAIL !== undefined) {
|
204
|
-
if (CURRENT_DEP_TAIL.nextDep !== undefined) {
|
205
|
-
clearTrack(CURRENT_DEP_TAIL.nextDep, shouldDisconnect);
|
206
|
-
CURRENT_DEP_TAIL.nextDep = undefined;
|
207
|
-
}
|
208
|
-
} else if (sub._deps !== undefined) {
|
209
|
-
clearTrack(sub._deps, shouldDisconnect);
|
210
|
-
sub._deps = undefined;
|
211
|
-
}
|
212
|
-
}
|
213
|
-
|
214
|
-
function clearTrack(link: Link, shouldDisconnect: boolean): void {
|
215
|
-
do {
|
216
|
-
const nextDep = link.nextDep;
|
217
|
-
|
218
|
-
if (shouldDisconnect) {
|
219
|
-
scheduleDisconnect(link.dep);
|
220
|
-
}
|
221
|
-
|
222
|
-
poolLink(link);
|
223
|
-
|
224
|
-
link = nextDep!;
|
225
|
-
} while (link !== undefined);
|
226
|
-
}
|
227
|
-
|
228
70
|
export class ComputedSignal<T> {
|
229
|
-
|
71
|
+
_id = ID++;
|
230
72
|
_type: SignalType;
|
231
73
|
|
232
|
-
|
233
|
-
_subsTail: Link | undefined;
|
234
|
-
|
235
|
-
_deps: Link | undefined;
|
236
|
-
_dirtyDep: Link | undefined;
|
74
|
+
_deps = new Map<ComputedSignal<any>, Link>();
|
237
75
|
|
76
|
+
_dirtyDep: Link | undefined = undefined;
|
77
|
+
_subs = new Set<Link>();
|
238
78
|
_state: SignalState = SignalState.Dirty;
|
239
|
-
|
240
79
|
_version: number = 0;
|
241
|
-
|
242
|
-
_connectedCount: number;
|
243
|
-
|
80
|
+
_computedCount: number = 0;
|
81
|
+
_connectedCount: number = 0;
|
244
82
|
_currentValue: T | AsyncResult<T> | undefined;
|
245
83
|
_compute: SignalCompute<T> | SignalAsyncCompute<T> | SignalSubscribe<T> | undefined;
|
84
|
+
|
246
85
|
_equals: SignalEquals<T>;
|
247
86
|
_ref: WeakRef<ComputedSignal<T>> = new WeakRef(this);
|
248
87
|
|
@@ -300,45 +139,33 @@ export class ComputedSignal<T> {
|
|
300
139
|
}
|
301
140
|
|
302
141
|
get(): T | AsyncResult<T> {
|
303
|
-
|
142
|
+
if (CURRENT_CONSUMER !== undefined) {
|
143
|
+
const { _deps: deps, _computedCount: computedCount, _connectedCount: connectedCount } = CURRENT_CONSUMER;
|
144
|
+
const prevLink = deps.get(this);
|
304
145
|
|
305
|
-
if (CURRENT_CONSUMER !== undefined && this._type !== SignalType.Watcher && !CURRENT_SEEN!.has(this)) {
|
306
146
|
const ord = CURRENT_ORD++;
|
307
147
|
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
break;
|
329
|
-
}
|
330
|
-
|
331
|
-
newLink = newLink.nextDep;
|
148
|
+
this._check(!prevLink && connectedCount > 0);
|
149
|
+
|
150
|
+
if (prevLink === undefined) {
|
151
|
+
const newLink = {
|
152
|
+
dep: this,
|
153
|
+
sub: CURRENT_CONSUMER._ref,
|
154
|
+
ord,
|
155
|
+
version: this._version,
|
156
|
+
consumedAt: CURRENT_CONSUMER._computedCount,
|
157
|
+
nextDirty: undefined,
|
158
|
+
};
|
159
|
+
|
160
|
+
deps.set(this, newLink);
|
161
|
+
this._subs.add(newLink);
|
162
|
+
} else if (prevLink.consumedAt !== computedCount) {
|
163
|
+
prevLink.ord = ord;
|
164
|
+
prevLink.version = this._version;
|
165
|
+
prevLink.consumedAt = computedCount;
|
166
|
+
// prevLink.nextDirty = undefined;
|
167
|
+
this._subs.add(prevLink);
|
332
168
|
}
|
333
|
-
|
334
|
-
this._check(CURRENT_IS_WATCHED && !prevTracked);
|
335
|
-
|
336
|
-
CURRENT_DEP_TAIL = newLink ?? linkNewDep(this, CURRENT_CONSUMER, nextDep, CURRENT_DEP_TAIL, ord);
|
337
|
-
|
338
|
-
if (process.env.NODE_ENV !== 'production') checkForCircularLinks(CURRENT_DEP_TAIL);
|
339
|
-
|
340
|
-
CURRENT_DEP_TAIL.version = this._version;
|
341
|
-
CURRENT_SEEN!.add(this);
|
342
169
|
} else {
|
343
170
|
this._check();
|
344
171
|
}
|
@@ -347,6 +174,7 @@ export class ComputedSignal<T> {
|
|
347
174
|
}
|
348
175
|
|
349
176
|
_check(shouldWatch = false): number {
|
177
|
+
// COUNTS.checks++;
|
350
178
|
let state = this._state;
|
351
179
|
let connectedCount = this._connectedCount;
|
352
180
|
|
@@ -361,19 +189,11 @@ export class ComputedSignal<T> {
|
|
361
189
|
if (this._type === SignalType.Subscription) {
|
362
190
|
state = SignalState.Dirty;
|
363
191
|
} else {
|
364
|
-
|
365
|
-
|
366
|
-
if (process.env.NODE_ENV !== 'production') checkForCircularLinks(link);
|
367
|
-
|
368
|
-
while (link !== undefined) {
|
369
|
-
const dep = link.dep;
|
370
|
-
|
192
|
+
for (const [dep, link] of this._deps) {
|
371
193
|
if (link.version !== dep._check(true)) {
|
372
194
|
state = SignalState.Dirty;
|
373
195
|
break;
|
374
196
|
}
|
375
|
-
|
376
|
-
link = link.nextDep;
|
377
197
|
}
|
378
198
|
}
|
379
199
|
}
|
@@ -398,7 +218,7 @@ export class ComputedSignal<T> {
|
|
398
218
|
}
|
399
219
|
|
400
220
|
if (state === SignalState.Dirty) {
|
401
|
-
this._run(wasConnected,
|
221
|
+
this._run(wasConnected, shouldConnect);
|
402
222
|
} else {
|
403
223
|
this._resetDirty();
|
404
224
|
}
|
@@ -409,22 +229,16 @@ export class ComputedSignal<T> {
|
|
409
229
|
return this._version;
|
410
230
|
}
|
411
231
|
|
412
|
-
_run(wasConnected: boolean,
|
232
|
+
_run(wasConnected: boolean, shouldConnect: boolean) {
|
413
233
|
const { _type: type } = this;
|
414
234
|
|
415
235
|
const prevConsumer = CURRENT_CONSUMER;
|
416
|
-
const prevOrd = CURRENT_ORD;
|
417
|
-
const prevSeen = CURRENT_SEEN;
|
418
|
-
const prevDepTail = CURRENT_DEP_TAIL;
|
419
|
-
const prevIsWatched = CURRENT_IS_WATCHED;
|
420
236
|
|
421
237
|
try {
|
422
238
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
423
239
|
CURRENT_CONSUMER = this;
|
424
|
-
|
425
|
-
|
426
|
-
CURRENT_DEP_TAIL = undefined;
|
427
|
-
CURRENT_IS_WATCHED = isConnected;
|
240
|
+
|
241
|
+
this._computedCount++;
|
428
242
|
|
429
243
|
switch (type) {
|
430
244
|
case SignalType.Computed: {
|
@@ -552,44 +366,37 @@ export class ComputedSignal<T> {
|
|
552
366
|
}
|
553
367
|
}
|
554
368
|
} finally {
|
555
|
-
|
369
|
+
const deps = this._deps;
|
370
|
+
|
371
|
+
for (const link of deps.values()) {
|
372
|
+
if (link.consumedAt === this._computedCount) continue;
|
373
|
+
|
374
|
+
const dep = link.dep;
|
375
|
+
|
376
|
+
if (wasConnected) {
|
377
|
+
scheduleDisconnect(dep);
|
378
|
+
}
|
379
|
+
|
380
|
+
deps.delete(dep);
|
381
|
+
dep._subs.delete(link);
|
382
|
+
}
|
556
383
|
|
557
384
|
CURRENT_CONSUMER = prevConsumer;
|
558
|
-
CURRENT_SEEN = prevSeen;
|
559
|
-
CURRENT_DEP_TAIL = prevDepTail;
|
560
|
-
CURRENT_ORD = prevOrd;
|
561
|
-
CURRENT_IS_WATCHED = prevIsWatched;
|
562
385
|
}
|
563
386
|
}
|
564
387
|
|
565
388
|
_resetDirty() {
|
566
389
|
let dirty = this._dirtyDep;
|
390
|
+
// COUNTS.dirtyResetIterations++;
|
567
391
|
|
568
392
|
while (dirty !== undefined) {
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
if (oldHead === undefined) {
|
573
|
-
dep._subs = dirty;
|
574
|
-
dirty.nextSub = undefined;
|
575
|
-
dirty.prevSub = undefined;
|
576
|
-
} else {
|
577
|
-
dirty.nextSub = oldHead;
|
578
|
-
dirty.prevSub = undefined;
|
579
|
-
oldHead.prevSub = dirty;
|
580
|
-
dep._subs = dirty;
|
581
|
-
}
|
582
|
-
|
583
|
-
if (process.env.NODE_ENV !== 'production') {
|
584
|
-
checkForCircularLinks(this._dirtyDep);
|
585
|
-
}
|
393
|
+
// COUNTS.dirtyResetIterations++;
|
394
|
+
dirty.dep._subs.add(dirty);
|
586
395
|
|
587
396
|
let nextDirty = dirty.nextDirty;
|
588
397
|
dirty.nextDirty = undefined;
|
589
398
|
dirty = nextDirty;
|
590
399
|
}
|
591
|
-
|
592
|
-
if (process.env.NODE_ENV !== 'production') checkForCircularLinks(this._dirtyDep);
|
593
400
|
}
|
594
401
|
|
595
402
|
_dirty() {
|
@@ -604,61 +411,43 @@ export class ComputedSignal<T> {
|
|
604
411
|
} else {
|
605
412
|
this._dirtyConsumers();
|
606
413
|
}
|
607
|
-
|
608
|
-
this._subs = undefined;
|
609
414
|
}
|
610
415
|
|
611
416
|
_dirtyConsumers() {
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
if (state === SignalState.MaybeDirty) {
|
635
|
-
let dirty = consumer._dirtyDep;
|
636
|
-
const ord = link.ord;
|
637
|
-
|
638
|
-
if (dirty!.ord > ord) {
|
639
|
-
consumer._dirtyDep = link;
|
640
|
-
link.nextDirty = dirty;
|
641
|
-
} else {
|
642
|
-
let nextDirty = dirty!.nextDirty;
|
643
|
-
|
644
|
-
while (nextDirty !== undefined && nextDirty!.ord < ord) {
|
645
|
-
dirty = nextDirty;
|
646
|
-
nextDirty = dirty.nextDirty;
|
417
|
+
for (const link of this._subs.values()) {
|
418
|
+
const sub = link.sub.deref();
|
419
|
+
|
420
|
+
if (sub === undefined) continue;
|
421
|
+
|
422
|
+
switch (sub._state) {
|
423
|
+
case SignalState.MaybeDirty: {
|
424
|
+
let dirty = sub._dirtyDep;
|
425
|
+
const ord = link.ord;
|
426
|
+
if (dirty!.ord > ord) {
|
427
|
+
sub._dirtyDep = link;
|
428
|
+
link.nextDirty = dirty;
|
429
|
+
} else {
|
430
|
+
let nextDirty = dirty!.nextDirty;
|
431
|
+
while (nextDirty !== undefined && nextDirty!.ord < ord) {
|
432
|
+
// COUNTS.dirtyInsertIterations++;
|
433
|
+
dirty = nextDirty;
|
434
|
+
nextDirty = dirty.nextDirty;
|
435
|
+
}
|
436
|
+
link.nextDirty = nextDirty;
|
437
|
+
dirty!.nextDirty = link;
|
647
438
|
}
|
648
|
-
|
649
|
-
|
650
|
-
|
439
|
+
break;
|
440
|
+
}
|
441
|
+
case SignalState.Clean: {
|
442
|
+
sub._state = SignalState.MaybeDirty;
|
443
|
+
sub._dirtyDep = link;
|
444
|
+
link.nextDirty = undefined;
|
445
|
+
sub._dirty();
|
651
446
|
}
|
652
|
-
} else {
|
653
|
-
// consumer._dirtyQueueLength = dirtyQueueLength + 2;
|
654
|
-
consumer._state = SignalState.MaybeDirty;
|
655
|
-
consumer._dirtyDep = link;
|
656
|
-
link.nextDirty = undefined;
|
657
|
-
consumer._dirty();
|
658
447
|
}
|
659
|
-
|
660
|
-
link = link.nextSub;
|
661
448
|
}
|
449
|
+
|
450
|
+
this._subs = new Set();
|
662
451
|
}
|
663
452
|
|
664
453
|
_disconnect(count = 1) {
|
@@ -679,14 +468,10 @@ export class ComputedSignal<T> {
|
|
679
468
|
}
|
680
469
|
}
|
681
470
|
|
682
|
-
|
683
|
-
|
684
|
-
while (link !== undefined) {
|
471
|
+
for (const link of this._deps.values()) {
|
685
472
|
const dep = link.dep;
|
686
473
|
|
687
474
|
dep._disconnect();
|
688
|
-
|
689
|
-
link = link.nextDep;
|
690
475
|
}
|
691
476
|
}
|
692
477
|
}
|
@@ -719,7 +504,7 @@ export interface AsyncReady<T> extends AsyncBaseResult<T> {
|
|
719
504
|
export type AsyncResult<T> = AsyncPending<T> | AsyncReady<T>;
|
720
505
|
|
721
506
|
class StateSignal<T> implements StateSignal<T> {
|
722
|
-
private
|
507
|
+
private _subs: WeakRef<ComputedSignal<unknown>>[] = [];
|
723
508
|
|
724
509
|
constructor(
|
725
510
|
private _value: T,
|
@@ -728,7 +513,7 @@ class StateSignal<T> implements StateSignal<T> {
|
|
728
513
|
|
729
514
|
get(): T {
|
730
515
|
if (CURRENT_CONSUMER !== undefined) {
|
731
|
-
this.
|
516
|
+
this._subs.push(CURRENT_CONSUMER._ref);
|
732
517
|
}
|
733
518
|
|
734
519
|
return this._value!;
|
@@ -740,21 +525,28 @@ class StateSignal<T> implements StateSignal<T> {
|
|
740
525
|
}
|
741
526
|
|
742
527
|
this._value = value;
|
528
|
+
const subs = this._subs;
|
529
|
+
const subsLength = subs.length;
|
743
530
|
|
744
|
-
|
745
|
-
|
746
|
-
for (const consumerRef of consumers) {
|
747
|
-
const consumer = consumerRef.deref();
|
531
|
+
for (let i = 0; i < subsLength; i++) {
|
532
|
+
const sub = subs[i].deref();
|
748
533
|
|
749
|
-
if (
|
534
|
+
if (sub === undefined) {
|
750
535
|
continue;
|
751
536
|
}
|
752
537
|
|
753
|
-
|
754
|
-
|
538
|
+
switch (sub._state) {
|
539
|
+
case SignalState.Clean:
|
540
|
+
sub._state = SignalState.Dirty;
|
541
|
+
sub._dirty();
|
542
|
+
break;
|
543
|
+
case SignalState.MaybeDirty:
|
544
|
+
sub._state = SignalState.Dirty;
|
545
|
+
break;
|
546
|
+
}
|
755
547
|
}
|
756
548
|
|
757
|
-
|
549
|
+
this._subs = [];
|
758
550
|
}
|
759
551
|
}
|
760
552
|
|
@@ -790,7 +582,7 @@ export interface Watcher {
|
|
790
582
|
}
|
791
583
|
|
792
584
|
export function watcher(fn: () => void): Watcher {
|
793
|
-
const subscribers
|
585
|
+
const subscribers: (() => void)[] = [];
|
794
586
|
const watcher = new ComputedSignal(SignalType.Watcher, () => {
|
795
587
|
fn();
|
796
588
|
|
@@ -809,10 +601,10 @@ export function watcher(fn: () => void): Watcher {
|
|
809
601
|
},
|
810
602
|
|
811
603
|
subscribe(subscriber: () => void) {
|
812
|
-
subscribers.
|
604
|
+
subscribers.push(subscriber);
|
813
605
|
|
814
606
|
return () => {
|
815
|
-
subscribers.
|
607
|
+
subscribers.splice(subscribers.indexOf(subscriber), 1);
|
816
608
|
};
|
817
609
|
},
|
818
610
|
};
|
@@ -824,19 +616,13 @@ export function isTracking(): boolean {
|
|
824
616
|
|
825
617
|
export function untrack<T = void>(fn: () => T): T {
|
826
618
|
const prevConsumer = CURRENT_CONSUMER;
|
827
|
-
const prevOrd = CURRENT_ORD;
|
828
|
-
const prevIsWatched = CURRENT_IS_WATCHED;
|
829
619
|
|
830
620
|
try {
|
831
621
|
CURRENT_CONSUMER = undefined;
|
832
622
|
// LAST_CONSUMED = undefined;
|
833
|
-
CURRENT_ORD = 0;
|
834
|
-
CURRENT_IS_WATCHED = false;
|
835
623
|
|
836
624
|
return fn();
|
837
625
|
} finally {
|
838
626
|
CURRENT_CONSUMER = prevConsumer;
|
839
|
-
CURRENT_ORD = prevOrd;
|
840
|
-
CURRENT_IS_WATCHED = prevIsWatched;
|
841
627
|
}
|
842
628
|
}
|