@but212/atom-effect 0.2.2 → 0.3.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/README.md +13 -8
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.mjs +205 -177
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const R = {
|
|
2
2
|
IDLE: "idle",
|
|
3
3
|
PENDING: "pending",
|
|
4
4
|
RESOLVED: "resolved",
|
|
@@ -23,22 +23,32 @@ const C = {
|
|
|
23
23
|
// 100000 - Currently recomputing
|
|
24
24
|
HAS_ERROR: 64
|
|
25
25
|
// 1000000 - Has error state
|
|
26
|
-
},
|
|
26
|
+
}, W = {
|
|
27
27
|
/** Maximum number of pooled objects to prevent memory bloat */
|
|
28
28
|
MAX_SIZE: 1e3,
|
|
29
29
|
/** Number of objects to pre-allocate for performance-critical paths */
|
|
30
30
|
WARMUP_SIZE: 100
|
|
31
|
-
},
|
|
32
|
-
/** Maximum effect executions per second to detect infinite loops */
|
|
31
|
+
}, N = {
|
|
32
|
+
/** Maximum effect executions per second to detect infinite loops (Legacy/Fallback) */
|
|
33
33
|
MAX_EXECUTIONS_PER_SECOND: 100,
|
|
34
34
|
/** Threshold for cleaning up old execution timestamps */
|
|
35
|
-
CLEANUP_THRESHOLD: 100
|
|
36
|
-
|
|
35
|
+
CLEANUP_THRESHOLD: 100,
|
|
36
|
+
/**
|
|
37
|
+
* Maximum executions per effect within a single flush cycle
|
|
38
|
+
* Increased from 10 to 50 based on evaluation report
|
|
39
|
+
*/
|
|
40
|
+
MAX_EXECUTIONS_PER_EFFECT: 50,
|
|
41
|
+
/**
|
|
42
|
+
* Maximum total executions across all effects in a single flush cycle
|
|
43
|
+
* Increased from 1000 to 5000 based on evaluation report
|
|
44
|
+
*/
|
|
45
|
+
MAX_EXECUTIONS_PER_FLUSH: 5e3
|
|
46
|
+
}, M = {
|
|
37
47
|
/** Maximum dependencies before warning about large dependency graphs */
|
|
38
48
|
MAX_DEPENDENCIES: 1e3,
|
|
39
49
|
/** Enable infinite loop detection warnings */
|
|
40
50
|
WARN_INFINITE_LOOP: !0
|
|
41
|
-
}, I = 1073741823;
|
|
51
|
+
}, I = 1073741823, U = typeof process < "u" && process.env && process.env.NODE_ENV !== "production";
|
|
42
52
|
class _ extends Error {
|
|
43
53
|
/**
|
|
44
54
|
* Creates a new AtomError
|
|
@@ -60,7 +70,7 @@ class b extends _ {
|
|
|
60
70
|
super(e, t, !0), this.name = "ComputedError";
|
|
61
71
|
}
|
|
62
72
|
}
|
|
63
|
-
class
|
|
73
|
+
class E extends _ {
|
|
64
74
|
/**
|
|
65
75
|
* Creates a new EffectError
|
|
66
76
|
* @param message - Error message
|
|
@@ -80,7 +90,7 @@ class y extends _ {
|
|
|
80
90
|
super(e, t, !1), this.name = "SchedulerError";
|
|
81
91
|
}
|
|
82
92
|
}
|
|
83
|
-
function
|
|
93
|
+
function D(i, e, t) {
|
|
84
94
|
if (i instanceof TypeError)
|
|
85
95
|
return new e(`Type error (${t}): ${i.message}`, i);
|
|
86
96
|
if (i instanceof ReferenceError)
|
|
@@ -90,10 +100,10 @@ function g(i, e, t) {
|
|
|
90
100
|
const s = i instanceof Error ? i.message : String(i), n = i instanceof Error ? i : null;
|
|
91
101
|
return new e(`Unexpected error (${t}): ${s}`, n);
|
|
92
102
|
}
|
|
93
|
-
function
|
|
103
|
+
function k(i) {
|
|
94
104
|
return i != null && typeof i.then == "function";
|
|
95
105
|
}
|
|
96
|
-
const
|
|
106
|
+
const h = {
|
|
97
107
|
// ─────────────────────────────────────────────────────────────────
|
|
98
108
|
// Computed errors
|
|
99
109
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -178,7 +188,23 @@ const o = {
|
|
|
178
188
|
*/
|
|
179
189
|
CALLBACK_ERROR_IN_ERROR_HANDLER: "Error occurred during onError callback execution"
|
|
180
190
|
};
|
|
181
|
-
|
|
191
|
+
let A = 0;
|
|
192
|
+
function q() {
|
|
193
|
+
return A = (A + 1 | 0) & I, A;
|
|
194
|
+
}
|
|
195
|
+
let C = 0, P = 0, T = !1;
|
|
196
|
+
function w() {
|
|
197
|
+
return T ? (U && console.warn(
|
|
198
|
+
"Warning: startFlush() called during flush - ignored to prevent infinite loop detection bypass"
|
|
199
|
+
), !1) : (T = !0, C = C + 1 & I, P = 0, !0);
|
|
200
|
+
}
|
|
201
|
+
function v() {
|
|
202
|
+
T = !1;
|
|
203
|
+
}
|
|
204
|
+
function V() {
|
|
205
|
+
return T ? ++P : 0;
|
|
206
|
+
}
|
|
207
|
+
class X {
|
|
182
208
|
constructor() {
|
|
183
209
|
this.queueA = [], this.queueB = [], this.queue = this.queueA, this.queueSize = 0, this._epoch = 0, this.isProcessing = !1, this.isBatching = !1, this.batchDepth = 0, this.batchQueue = [], this.batchQueueSize = 0, this.isFlushingSync = !1, this.maxFlushIterations = 1e3;
|
|
184
210
|
}
|
|
@@ -228,15 +254,16 @@ class v {
|
|
|
228
254
|
this.isProcessing = !0;
|
|
229
255
|
const e = this.queue, t = this.queueSize;
|
|
230
256
|
this.queue = this.queue === this.queueA ? this.queueB : this.queueA, this.queueSize = 0, this._epoch++, queueMicrotask(() => {
|
|
231
|
-
|
|
257
|
+
const s = w();
|
|
258
|
+
for (let n = 0; n < t; n++)
|
|
232
259
|
try {
|
|
233
|
-
e[
|
|
234
|
-
} catch (
|
|
260
|
+
e[n]?.();
|
|
261
|
+
} catch (r) {
|
|
235
262
|
console.error(
|
|
236
|
-
new y("Error occurred during scheduler execution",
|
|
263
|
+
new y("Error occurred during scheduler execution", r)
|
|
237
264
|
);
|
|
238
265
|
}
|
|
239
|
-
e.length = 0, this.isProcessing = !1, this.queueSize > 0 && !this.isBatching && this.flush();
|
|
266
|
+
e.length = 0, this.isProcessing = !1, s && v(), this.queueSize > 0 && !this.isBatching && this.flush();
|
|
240
267
|
});
|
|
241
268
|
}
|
|
242
269
|
/**
|
|
@@ -254,17 +281,18 @@ class v {
|
|
|
254
281
|
*/
|
|
255
282
|
flushSync() {
|
|
256
283
|
this.isFlushingSync = !0;
|
|
284
|
+
const e = w();
|
|
257
285
|
try {
|
|
258
286
|
if (this._epoch++, this.batchQueueSize > 0) {
|
|
259
|
-
for (let
|
|
260
|
-
const
|
|
261
|
-
|
|
287
|
+
for (let s = 0; s < this.batchQueueSize; s++) {
|
|
288
|
+
const n = this.batchQueue[s];
|
|
289
|
+
n._nextEpoch !== this._epoch && (n._nextEpoch = this._epoch, this.queue[this.queueSize++] = n);
|
|
262
290
|
}
|
|
263
291
|
this.batchQueueSize = 0;
|
|
264
292
|
}
|
|
265
|
-
let
|
|
293
|
+
let t = 0;
|
|
266
294
|
for (; this.queueSize > 0; ) {
|
|
267
|
-
if (++
|
|
295
|
+
if (++t > this.maxFlushIterations) {
|
|
268
296
|
console.error(
|
|
269
297
|
new y(
|
|
270
298
|
`Maximum flush iterations (${this.maxFlushIterations}) exceeded. Possible infinite loop in reactive dependencies. Consider increasing the limit with scheduler.setMaxFlushIterations()`
|
|
@@ -272,24 +300,24 @@ class v {
|
|
|
272
300
|
), this.queueSize = 0, this.queue.length = 0, this.batchQueueSize = 0;
|
|
273
301
|
break;
|
|
274
302
|
}
|
|
275
|
-
const
|
|
303
|
+
const s = this.queue, n = this.queueSize;
|
|
276
304
|
this.queue = this.queue === this.queueA ? this.queueB : this.queueA, this.queueSize = 0, this._epoch++;
|
|
277
|
-
for (let
|
|
305
|
+
for (let r = 0; r < n; r++)
|
|
278
306
|
try {
|
|
279
|
-
|
|
280
|
-
} catch (
|
|
307
|
+
s[r]?.();
|
|
308
|
+
} catch (u) {
|
|
281
309
|
console.error(
|
|
282
|
-
new y("Error occurred during batch execution",
|
|
310
|
+
new y("Error occurred during batch execution", u)
|
|
283
311
|
);
|
|
284
312
|
}
|
|
285
|
-
if (
|
|
286
|
-
for (let
|
|
287
|
-
this.queue[this.queueSize++] = this.batchQueue[
|
|
313
|
+
if (s.length = 0, this.batchQueueSize > 0) {
|
|
314
|
+
for (let r = 0; r < this.batchQueueSize; r++)
|
|
315
|
+
this.queue[this.queueSize++] = this.batchQueue[r];
|
|
288
316
|
this.batchQueueSize = 0;
|
|
289
317
|
}
|
|
290
318
|
}
|
|
291
319
|
} finally {
|
|
292
|
-
this.isFlushingSync = !1;
|
|
320
|
+
this.isFlushingSync = !1, e && v();
|
|
293
321
|
}
|
|
294
322
|
}
|
|
295
323
|
/**
|
|
@@ -357,17 +385,17 @@ class v {
|
|
|
357
385
|
this.maxFlushIterations = e;
|
|
358
386
|
}
|
|
359
387
|
}
|
|
360
|
-
const
|
|
361
|
-
function
|
|
388
|
+
const g = new X();
|
|
389
|
+
function K(i) {
|
|
362
390
|
if (typeof i != "function")
|
|
363
391
|
throw new _("Batch callback must be a function");
|
|
364
|
-
|
|
392
|
+
g.startBatch();
|
|
365
393
|
try {
|
|
366
394
|
return i();
|
|
367
395
|
} catch (e) {
|
|
368
396
|
throw new _("Error occurred during batch execution", e);
|
|
369
397
|
} finally {
|
|
370
|
-
|
|
398
|
+
g.endBatch();
|
|
371
399
|
}
|
|
372
400
|
}
|
|
373
401
|
const S = {
|
|
@@ -391,7 +419,7 @@ const S = {
|
|
|
391
419
|
return this.current;
|
|
392
420
|
}
|
|
393
421
|
};
|
|
394
|
-
function
|
|
422
|
+
function Z(i) {
|
|
395
423
|
if (typeof i != "function")
|
|
396
424
|
throw new _("Untracked callback must be a function");
|
|
397
425
|
const e = S.current;
|
|
@@ -404,11 +432,11 @@ function Q(i) {
|
|
|
404
432
|
S.current = e;
|
|
405
433
|
}
|
|
406
434
|
}
|
|
407
|
-
const
|
|
408
|
-
function
|
|
435
|
+
const O = /* @__PURE__ */ Symbol("debugName"), j = /* @__PURE__ */ Symbol("id"), x = /* @__PURE__ */ Symbol("type"), B = /* @__PURE__ */ Symbol("noDefaultValue");
|
|
436
|
+
function G(i) {
|
|
409
437
|
return i !== null && typeof i == "object" && "dependencies" in i && i.dependencies instanceof Set;
|
|
410
438
|
}
|
|
411
|
-
const
|
|
439
|
+
const f = {
|
|
412
440
|
/**
|
|
413
441
|
* Whether debug mode is enabled.
|
|
414
442
|
*
|
|
@@ -422,13 +450,13 @@ const a = {
|
|
|
422
450
|
*
|
|
423
451
|
* @see {@link DEBUG_CONFIG.MAX_DEPENDENCIES}
|
|
424
452
|
*/
|
|
425
|
-
maxDependencies:
|
|
453
|
+
maxDependencies: M.MAX_DEPENDENCIES,
|
|
426
454
|
/**
|
|
427
455
|
* Whether to warn about potential infinite loops.
|
|
428
456
|
*
|
|
429
457
|
* @see {@link DEBUG_CONFIG.WARN_INFINITE_LOOP}
|
|
430
458
|
*/
|
|
431
|
-
warnInfiniteLoop:
|
|
459
|
+
warnInfiniteLoop: M.WARN_INFINITE_LOOP,
|
|
432
460
|
/**
|
|
433
461
|
* Logs a warning message when condition is true and debug is enabled.
|
|
434
462
|
*
|
|
@@ -477,7 +505,7 @@ const a = {
|
|
|
477
505
|
if (this.enabled) {
|
|
478
506
|
if (t.has(i))
|
|
479
507
|
throw new b("Indirect circular dependency detected");
|
|
480
|
-
if (t.add(i),
|
|
508
|
+
if (t.add(i), G(i))
|
|
481
509
|
for (const s of i.dependencies)
|
|
482
510
|
this.checkCircular(s, e, t);
|
|
483
511
|
}
|
|
@@ -506,7 +534,7 @@ const a = {
|
|
|
506
534
|
if (!this.enabled)
|
|
507
535
|
return;
|
|
508
536
|
const s = i;
|
|
509
|
-
s[
|
|
537
|
+
s[O] = `${e}_${t}`, s[j] = t, s[x] = e;
|
|
510
538
|
},
|
|
511
539
|
/**
|
|
512
540
|
* Retrieves the debug display name from a reactive object.
|
|
@@ -521,8 +549,8 @@ const a = {
|
|
|
521
549
|
* ```
|
|
522
550
|
*/
|
|
523
551
|
getDebugName(i) {
|
|
524
|
-
if (i !== null && typeof i == "object" &&
|
|
525
|
-
return i[
|
|
552
|
+
if (i !== null && typeof i == "object" && O in i)
|
|
553
|
+
return i[O];
|
|
526
554
|
},
|
|
527
555
|
/**
|
|
528
556
|
* Retrieves the debug type from a reactive object.
|
|
@@ -539,13 +567,13 @@ const a = {
|
|
|
539
567
|
* ```
|
|
540
568
|
*/
|
|
541
569
|
getDebugType(i) {
|
|
542
|
-
if (i !== null && typeof i == "object" &&
|
|
543
|
-
return i[
|
|
570
|
+
if (i !== null && typeof i == "object" && x in i)
|
|
571
|
+
return i[x];
|
|
544
572
|
}
|
|
545
573
|
};
|
|
546
|
-
let
|
|
547
|
-
const
|
|
548
|
-
class
|
|
574
|
+
let $ = 1;
|
|
575
|
+
const L = () => $++;
|
|
576
|
+
class F {
|
|
549
577
|
constructor() {
|
|
550
578
|
this.subscribers = null;
|
|
551
579
|
}
|
|
@@ -678,7 +706,7 @@ class N {
|
|
|
678
706
|
return this.subscribers ? [...this.subscribers] : [];
|
|
679
707
|
}
|
|
680
708
|
}
|
|
681
|
-
class
|
|
709
|
+
class Y {
|
|
682
710
|
/**
|
|
683
711
|
* Creates a new AtomImpl instance.
|
|
684
712
|
*
|
|
@@ -686,7 +714,7 @@ class z {
|
|
|
686
714
|
* @param sync - Whether to notify subscribers synchronously
|
|
687
715
|
*/
|
|
688
716
|
constructor(e, t) {
|
|
689
|
-
this._isNotificationScheduled = !1, this.id =
|
|
717
|
+
this._isNotificationScheduled = !1, this.id = L() & I, this.version = 0, this.flags = 0, this._lastSeenEpoch = -1, this._value = e, this._functionSubscribers = new F(), this._objectSubscribers = new F(), this._sync = t, this._notifyTask = this._flushNotifications.bind(this), f.attachDebugInfo(this, "atom", this.id);
|
|
690
718
|
}
|
|
691
719
|
/**
|
|
692
720
|
* Gets the current value and registers the atom as a dependency
|
|
@@ -755,7 +783,7 @@ class z {
|
|
|
755
783
|
* but don't schedule a new task. The pending task will see the latest value.
|
|
756
784
|
*/
|
|
757
785
|
_notify(e, t, s) {
|
|
758
|
-
this._isNotificationScheduled || (this._pendingOldValue = t, this._isNotificationScheduled = !0), this._sync && !
|
|
786
|
+
this._isNotificationScheduled || (this._pendingOldValue = t, this._isNotificationScheduled = !0), this._sync && !g.isBatching ? this._flushNotifications() : g.schedule(this._notifyTask);
|
|
759
787
|
}
|
|
760
788
|
/**
|
|
761
789
|
* Executes the pending notifications.
|
|
@@ -766,10 +794,10 @@ class z {
|
|
|
766
794
|
const e = this._pendingOldValue, t = this._value;
|
|
767
795
|
this._pendingOldValue = void 0, this._isNotificationScheduled = !1, this._functionSubscribers.forEachSafe(
|
|
768
796
|
(s) => s(t, e),
|
|
769
|
-
(s) => console.error(new _(
|
|
797
|
+
(s) => console.error(new _(h.ATOM_INDIVIDUAL_SUBSCRIBER_FAILED, s))
|
|
770
798
|
), this._objectSubscribers.forEachSafe(
|
|
771
799
|
(s) => s.execute(),
|
|
772
|
-
(s) => console.error(new _(
|
|
800
|
+
(s) => console.error(new _(h.ATOM_INDIVIDUAL_SUBSCRIBER_FAILED, s))
|
|
773
801
|
);
|
|
774
802
|
}
|
|
775
803
|
/**
|
|
@@ -789,7 +817,7 @@ class z {
|
|
|
789
817
|
*/
|
|
790
818
|
subscribe(e) {
|
|
791
819
|
if (typeof e != "function")
|
|
792
|
-
throw new _(
|
|
820
|
+
throw new _(h.ATOM_SUBSCRIBER_MUST_BE_FUNCTION);
|
|
793
821
|
return this._functionSubscribers.add(e);
|
|
794
822
|
}
|
|
795
823
|
/**
|
|
@@ -823,44 +851,40 @@ class z {
|
|
|
823
851
|
return this._functionSubscribers.size + this._objectSubscribers.size;
|
|
824
852
|
}
|
|
825
853
|
}
|
|
826
|
-
function
|
|
827
|
-
return new
|
|
828
|
-
}
|
|
829
|
-
let O = 0;
|
|
830
|
-
function M() {
|
|
831
|
-
return O = (O + 1 | 0) & I, O;
|
|
854
|
+
function ee(i, e = {}) {
|
|
855
|
+
return new Y(i, e.sync ?? !1);
|
|
832
856
|
}
|
|
833
|
-
const
|
|
834
|
-
class
|
|
857
|
+
const d = process.env.NODE_ENV !== "production", l = Object.freeze([]);
|
|
858
|
+
class Q {
|
|
835
859
|
constructor() {
|
|
836
|
-
this.pool = [], this.maxPoolSize = 50, this.maxReusableCapacity = 256, this.stats =
|
|
860
|
+
this.pool = [], this.maxPoolSize = 50, this.maxReusableCapacity = 256, this.stats = d ? {
|
|
837
861
|
acquired: 0,
|
|
838
862
|
released: 0,
|
|
839
863
|
rejected: { frozen: 0, tooLarge: 0, poolFull: 0 }
|
|
840
864
|
} : null;
|
|
841
865
|
}
|
|
842
866
|
acquire() {
|
|
843
|
-
return
|
|
867
|
+
return d && this.stats && this.stats.acquired++, this.pool.pop() ?? [];
|
|
844
868
|
}
|
|
845
869
|
release(e, t) {
|
|
846
870
|
if (!(t && e === t)) {
|
|
847
871
|
if (Object.isFrozen(e)) {
|
|
848
|
-
|
|
872
|
+
d && this.stats && this.stats.rejected.frozen++;
|
|
849
873
|
return;
|
|
850
874
|
}
|
|
851
875
|
if (e.length > this.maxReusableCapacity) {
|
|
852
|
-
|
|
876
|
+
d && this.stats && this.stats.rejected.tooLarge++;
|
|
853
877
|
return;
|
|
854
878
|
}
|
|
855
879
|
if (this.pool.length >= this.maxPoolSize) {
|
|
856
|
-
|
|
880
|
+
d && this.stats && this.stats.rejected.poolFull++;
|
|
857
881
|
return;
|
|
858
882
|
}
|
|
859
|
-
e.length = 0, this.pool.push(e),
|
|
883
|
+
e.length = 0, this.pool.push(e), d && this.stats && this.stats.released++;
|
|
860
884
|
}
|
|
861
885
|
}
|
|
862
886
|
getStats() {
|
|
863
|
-
if (!
|
|
887
|
+
if (!d || !this.stats) return null;
|
|
864
888
|
const { acquired: e, released: t, rejected: s } = this.stats, n = s.frozen + s.tooLarge + s.poolFull;
|
|
865
889
|
return {
|
|
866
890
|
acquired: e,
|
|
@@ -871,15 +895,15 @@ class V {
|
|
|
871
895
|
};
|
|
872
896
|
}
|
|
873
897
|
reset() {
|
|
874
|
-
this.pool.length = 0,
|
|
898
|
+
this.pool.length = 0, d && this.stats && (this.stats.acquired = 0, this.stats.released = 0, this.stats.rejected = { frozen: 0, tooLarge: 0, poolFull: 0 });
|
|
875
899
|
}
|
|
876
900
|
}
|
|
877
|
-
const
|
|
878
|
-
class
|
|
901
|
+
const p = new Q();
|
|
902
|
+
class z {
|
|
879
903
|
constructor(e, t = {}) {
|
|
880
904
|
if (typeof e != "function")
|
|
881
|
-
throw new b(
|
|
882
|
-
if (this.id =
|
|
905
|
+
throw new b(h.COMPUTED_MUST_BE_FUNCTION);
|
|
906
|
+
if (this.id = L() & I, this.version = 0, this.flags = 0, this._lastSeenEpoch = -1, this._value = void 0, this._stateFlags = c.DIRTY | c.IDLE, this._error = null, this._promiseId = 0, this._equal = t.equal ?? Object.is, this._fn = e, this._defaultValue = "defaultValue" in t ? t.defaultValue : B, this._hasDefaultValue = this._defaultValue !== B, this._onError = t.onError ?? null, this.MAX_PROMISE_ID = Number.MAX_SAFE_INTEGER - 1, this._functionSubscribers = new F(), this._objectSubscribers = new F(), this._dependencies = l, this._subscriptions = /* @__PURE__ */ new Map(), this._recomputeJob = () => {
|
|
883
907
|
if (this._isDirty())
|
|
884
908
|
try {
|
|
885
909
|
this._recompute();
|
|
@@ -896,7 +920,7 @@ class w {
|
|
|
896
920
|
}, this._trackable = Object.assign(() => this._markDirty(), {
|
|
897
921
|
addDependency: (s) => {
|
|
898
922
|
}
|
|
899
|
-
}),
|
|
923
|
+
}), f.attachDebugInfo(this, "computed", this.id), f.enabled) {
|
|
900
924
|
const s = this;
|
|
901
925
|
s.subscriberCount = () => this._functionSubscribers.size + this._objectSubscribers.size, s.isDirty = () => this._isDirty(), s.dependencies = this._dependencies, s.stateFlags = this._getFlagsAsString();
|
|
902
926
|
}
|
|
@@ -915,7 +939,7 @@ class w {
|
|
|
915
939
|
}
|
|
916
940
|
subscribe(e) {
|
|
917
941
|
if (typeof e != "function")
|
|
918
|
-
throw new b(
|
|
942
|
+
throw new b(h.COMPUTED_SUBSCRIBER_MUST_BE_FUNCTION);
|
|
919
943
|
return this._functionSubscribers.add(e);
|
|
920
944
|
}
|
|
921
945
|
peek() {
|
|
@@ -945,7 +969,7 @@ class w {
|
|
|
945
969
|
const t = this._subscriptions.get(e.id);
|
|
946
970
|
t && t(), this._subscriptions.delete(e.id);
|
|
947
971
|
}
|
|
948
|
-
|
|
972
|
+
p.release(this._dependencies);
|
|
949
973
|
}
|
|
950
974
|
this._dependencies = l, this._functionSubscribers.clear(), this._objectSubscribers.clear(), this._stateFlags = c.DIRTY | c.IDLE, this._error = null, this._value = void 0, this._promiseId = (this._promiseId + 1) % this.MAX_PROMISE_ID;
|
|
951
975
|
}
|
|
@@ -987,10 +1011,11 @@ class w {
|
|
|
987
1011
|
return (this._stateFlags & c.RECOMPUTING) !== 0;
|
|
988
1012
|
}
|
|
989
1013
|
_setRecomputing(e) {
|
|
990
|
-
|
|
1014
|
+
const t = c.RECOMPUTING;
|
|
1015
|
+
this._stateFlags = this._stateFlags & ~t | -Number(e) & t;
|
|
991
1016
|
}
|
|
992
1017
|
_getAsyncState() {
|
|
993
|
-
return this._isPending() ?
|
|
1018
|
+
return this._isPending() ? R.PENDING : this._isResolved() ? R.RESOLVED : this._isRejected() ? R.REJECTED : R.IDLE;
|
|
994
1019
|
}
|
|
995
1020
|
_getFlagsAsString() {
|
|
996
1021
|
const e = [];
|
|
@@ -1004,24 +1029,24 @@ class w {
|
|
|
1004
1029
|
if (!this._isDirty() && this._isResolved())
|
|
1005
1030
|
return;
|
|
1006
1031
|
this._setRecomputing(!0);
|
|
1007
|
-
const e = this._dependencies, t =
|
|
1032
|
+
const e = this._dependencies, t = p.acquire(), s = q();
|
|
1008
1033
|
let n = 0;
|
|
1009
|
-
const r = (
|
|
1010
|
-
|
|
1034
|
+
const r = (o) => {
|
|
1035
|
+
o._lastSeenEpoch !== s && (o._lastSeenEpoch = s, n < t.length ? t[n] = o : t.push(o), n++);
|
|
1011
1036
|
}, u = this._trackable.addDependency;
|
|
1012
1037
|
this._trackable.addDependency = r;
|
|
1013
|
-
let
|
|
1038
|
+
let a = !1;
|
|
1014
1039
|
try {
|
|
1015
|
-
const
|
|
1016
|
-
if (t.length = n,
|
|
1017
|
-
this._syncDependencies(e, t, s), this._dependencies = t,
|
|
1040
|
+
const o = S.run(this._trackable, this._fn);
|
|
1041
|
+
if (t.length = n, k(o)) {
|
|
1042
|
+
this._syncDependencies(e, t, s), this._dependencies = t, a = !0, this._handleAsyncComputation(o), this._setRecomputing(!1);
|
|
1018
1043
|
return;
|
|
1019
1044
|
}
|
|
1020
|
-
this._syncDependencies(e, t, s), this._dependencies = t,
|
|
1021
|
-
} catch (
|
|
1022
|
-
t.length = n, this._syncDependencies(e, t, s), this._dependencies = t,
|
|
1045
|
+
this._syncDependencies(e, t, s), this._dependencies = t, a = !0, this._handleSyncResult(o);
|
|
1046
|
+
} catch (o) {
|
|
1047
|
+
t.length = n, this._syncDependencies(e, t, s), this._dependencies = t, a = !0, this._handleComputationError(o);
|
|
1023
1048
|
} finally {
|
|
1024
|
-
this._trackable.addDependency = u,
|
|
1049
|
+
this._trackable.addDependency = u, a ? e !== l && p.release(e) : p.release(t);
|
|
1025
1050
|
}
|
|
1026
1051
|
}
|
|
1027
1052
|
/**
|
|
@@ -1040,7 +1065,7 @@ class w {
|
|
|
1040
1065
|
for (let n = 0; n < t.length; n++) {
|
|
1041
1066
|
const r = t[n];
|
|
1042
1067
|
if (r && !this._subscriptions.has(r.id)) {
|
|
1043
|
-
|
|
1068
|
+
f.checkCircular(r, this);
|
|
1044
1069
|
const u = r.subscribe(() => this._markDirty());
|
|
1045
1070
|
this._subscriptions.set(r.id, u);
|
|
1046
1071
|
}
|
|
@@ -1064,29 +1089,29 @@ class w {
|
|
|
1064
1089
|
this._value = e, this._clearDirty(), this._setResolved(), this._error = null, this._setRecomputing(!1), t && this._notifySubscribers();
|
|
1065
1090
|
}
|
|
1066
1091
|
_handleAsyncRejection(e) {
|
|
1067
|
-
const t =
|
|
1092
|
+
const t = D(e, b, h.COMPUTED_ASYNC_COMPUTATION_FAILED);
|
|
1068
1093
|
if (this._error = t, this._setRejected(), this._clearDirty(), this._setRecomputing(!1), this._onError && typeof this._onError == "function")
|
|
1069
1094
|
try {
|
|
1070
1095
|
this._onError(t);
|
|
1071
1096
|
} catch (s) {
|
|
1072
|
-
console.error(
|
|
1097
|
+
console.error(h.CALLBACK_ERROR_IN_ERROR_HANDLER, s);
|
|
1073
1098
|
}
|
|
1074
1099
|
this._notifySubscribers();
|
|
1075
1100
|
}
|
|
1076
1101
|
_handleComputationError(e) {
|
|
1077
|
-
const t =
|
|
1102
|
+
const t = D(e, b, h.COMPUTED_COMPUTATION_FAILED);
|
|
1078
1103
|
if (this._error = t, this._setRejected(), this._clearDirty(), this._setRecomputing(!1), this._onError && typeof this._onError == "function")
|
|
1079
1104
|
try {
|
|
1080
1105
|
this._onError(t);
|
|
1081
1106
|
} catch (s) {
|
|
1082
|
-
console.error(
|
|
1107
|
+
console.error(h.CALLBACK_ERROR_IN_ERROR_HANDLER, s);
|
|
1083
1108
|
}
|
|
1084
1109
|
throw t;
|
|
1085
1110
|
}
|
|
1086
1111
|
_handlePending() {
|
|
1087
1112
|
if (this._hasDefaultValue)
|
|
1088
1113
|
return this._defaultValue;
|
|
1089
|
-
throw new b(
|
|
1114
|
+
throw new b(h.COMPUTED_ASYNC_PENDING_NO_DEFAULT);
|
|
1090
1115
|
}
|
|
1091
1116
|
_handleRejected() {
|
|
1092
1117
|
if (this._error?.recoverable && this._hasDefaultValue)
|
|
@@ -1097,10 +1122,10 @@ class w {
|
|
|
1097
1122
|
// (Replaced by _syncDependencies and inline pool logic)
|
|
1098
1123
|
// === PRIVATE: Subscriber Management ===
|
|
1099
1124
|
_markDirty() {
|
|
1100
|
-
this._isRecomputing() || this._isDirty() || (this._setDirty(), this._setIdle(), (this._functionSubscribers.hasSubscribers || this._objectSubscribers.hasSubscribers) &&
|
|
1125
|
+
this._isRecomputing() || this._isDirty() || (this._setDirty(), this._setIdle(), (this._functionSubscribers.hasSubscribers || this._objectSubscribers.hasSubscribers) && g.schedule(this._recomputeJob));
|
|
1101
1126
|
}
|
|
1102
1127
|
_notifySubscribers() {
|
|
1103
|
-
!this._functionSubscribers.hasSubscribers && !this._objectSubscribers.hasSubscribers ||
|
|
1128
|
+
!this._functionSubscribers.hasSubscribers && !this._objectSubscribers.hasSubscribers || g.schedule(this._notifyJob);
|
|
1104
1129
|
}
|
|
1105
1130
|
_registerTracking() {
|
|
1106
1131
|
const e = S.getCurrent();
|
|
@@ -1113,15 +1138,15 @@ class w {
|
|
|
1113
1138
|
} else e.execute && this._objectSubscribers.add(e);
|
|
1114
1139
|
}
|
|
1115
1140
|
}
|
|
1116
|
-
Object.freeze(
|
|
1117
|
-
function
|
|
1118
|
-
return new
|
|
1141
|
+
Object.freeze(z.prototype);
|
|
1142
|
+
function te(i, e = {}) {
|
|
1143
|
+
return new z(i, e);
|
|
1119
1144
|
}
|
|
1120
|
-
class
|
|
1145
|
+
class H {
|
|
1121
1146
|
constructor(e, t = {}) {
|
|
1122
1147
|
this.run = () => {
|
|
1123
1148
|
if (this.isDisposed)
|
|
1124
|
-
throw new
|
|
1149
|
+
throw new E(h.EFFECT_MUST_BE_FUNCTION);
|
|
1125
1150
|
this.execute();
|
|
1126
1151
|
}, this.dispose = () => {
|
|
1127
1152
|
if (!this.isDisposed && (this._setDisposed(), this._safeCleanup(), this._dependencies !== l)) {
|
|
@@ -1129,7 +1154,7 @@ class j {
|
|
|
1129
1154
|
const n = this._subscriptions.get(s.id);
|
|
1130
1155
|
n && n(), this._subscriptions.delete(s.id);
|
|
1131
1156
|
}
|
|
1132
|
-
|
|
1157
|
+
p.release(this._dependencies), this._dependencies = l;
|
|
1133
1158
|
}
|
|
1134
1159
|
}, this.addDependency = (s) => {
|
|
1135
1160
|
if (this.isExecuting && this._nextDeps) {
|
|
@@ -1139,24 +1164,23 @@ class j {
|
|
|
1139
1164
|
}
|
|
1140
1165
|
}, this.execute = () => {
|
|
1141
1166
|
if (this.isDisposed || this.isExecuting) return;
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
let d = !1;
|
|
1167
|
+
this._checkInfiniteLoop(), this._setExecuting(!0), this._safeCleanup(), this._modifiedDeps.clear();
|
|
1168
|
+
const s = this._dependencies, n = p.acquire(), r = q();
|
|
1169
|
+
this._nextDeps = n, this._currentEpoch = r;
|
|
1170
|
+
let u = !1;
|
|
1147
1171
|
try {
|
|
1148
|
-
const
|
|
1149
|
-
this._syncDependencies(
|
|
1150
|
-
!this.isDisposed && typeof
|
|
1151
|
-
}).catch((
|
|
1152
|
-
console.error(
|
|
1153
|
-
}) : this._cleanup = typeof
|
|
1154
|
-
} catch (
|
|
1155
|
-
this._syncDependencies(
|
|
1172
|
+
const a = S.run(this, this._fn);
|
|
1173
|
+
this._syncDependencies(s, r), this._dependencies = n, u = !0, this._checkLoopWarnings(), k(a) ? a.then((o) => {
|
|
1174
|
+
!this.isDisposed && typeof o == "function" && (this._cleanup = o);
|
|
1175
|
+
}).catch((o) => {
|
|
1176
|
+
console.error(D(o, E, h.EFFECT_EXECUTION_FAILED));
|
|
1177
|
+
}) : this._cleanup = typeof a == "function" ? a : null;
|
|
1178
|
+
} catch (a) {
|
|
1179
|
+
this._syncDependencies(s, r), this._dependencies = n, u = !0, console.error(D(a, E, h.EFFECT_EXECUTION_FAILED)), this._cleanup = null;
|
|
1156
1180
|
} finally {
|
|
1157
|
-
this._setExecuting(!1), this._nextDeps = null,
|
|
1181
|
+
this._setExecuting(!1), this._nextDeps = null, u ? s !== l && p.release(s) : p.release(n);
|
|
1158
1182
|
}
|
|
1159
|
-
}, this._id =
|
|
1183
|
+
}, this._id = L() & I, this._flags = 0, this._currentEpoch = -1, this._fn = e, this._sync = t.sync ?? !1, this._maxExecutions = t.maxExecutionsPerSecond ?? N.MAX_EXECUTIONS_PER_SECOND, this._maxExecutionsPerFlush = t.maxExecutionsPerFlush ?? N.MAX_EXECUTIONS_PER_EFFECT, this._trackModifications = t.trackModifications ?? !1, this._cleanup = null, this._dependencies = l, this._subscriptions = /* @__PURE__ */ new Map(), this._nextDeps = null, this._modifiedDeps = /* @__PURE__ */ new Set(), this._lastFlushEpoch = -1, this._executionsInEpoch = 0, this._history = U ? [] : null, this._executionCount = 0, f.attachDebugInfo(this, "effect", this._id);
|
|
1160
1184
|
}
|
|
1161
1185
|
/**
|
|
1162
1186
|
* Synchronizes subscriptions by unsubscribing from removed dependencies.
|
|
@@ -1178,11 +1202,11 @@ class j {
|
|
|
1178
1202
|
_subscribeTo(e) {
|
|
1179
1203
|
try {
|
|
1180
1204
|
const t = e.subscribe(() => {
|
|
1181
|
-
this._trackModifications && this.isExecuting && this._modifiedDeps.add(e), this._sync ? this.execute() :
|
|
1205
|
+
this._trackModifications && this.isExecuting && this._modifiedDeps.add(e), this._sync ? this.execute() : g.schedule(this.execute);
|
|
1182
1206
|
});
|
|
1183
1207
|
this._subscriptions.set(e.id, t);
|
|
1184
1208
|
} catch (t) {
|
|
1185
|
-
console.error(
|
|
1209
|
+
console.error(D(t, E, h.EFFECT_EXECUTION_FAILED));
|
|
1186
1210
|
}
|
|
1187
1211
|
}
|
|
1188
1212
|
/**
|
|
@@ -1272,7 +1296,8 @@ class j {
|
|
|
1272
1296
|
* @internal
|
|
1273
1297
|
*/
|
|
1274
1298
|
_setExecuting(e) {
|
|
1275
|
-
|
|
1299
|
+
const t = m.EXECUTING;
|
|
1300
|
+
this._flags = this._flags & ~t | -Number(e) & t;
|
|
1276
1301
|
}
|
|
1277
1302
|
/**
|
|
1278
1303
|
* Safely executes the cleanup function if one exists.
|
|
@@ -1292,42 +1317,45 @@ class j {
|
|
|
1292
1317
|
try {
|
|
1293
1318
|
this._cleanup();
|
|
1294
1319
|
} catch (e) {
|
|
1295
|
-
console.error(
|
|
1320
|
+
console.error(D(e, E, h.EFFECT_CLEANUP_FAILED));
|
|
1296
1321
|
}
|
|
1297
1322
|
this._cleanup = null;
|
|
1298
1323
|
}
|
|
1299
1324
|
}
|
|
1300
1325
|
/**
|
|
1301
|
-
*
|
|
1302
|
-
*
|
|
1303
|
-
* @param now - The current timestamp in milliseconds (from `Date.now()`)
|
|
1304
|
-
*
|
|
1305
|
-
* @remarks
|
|
1306
|
-
* This method implements a circular buffer to track recent execution
|
|
1307
|
-
* timestamps. If the number of executions within the last second exceeds
|
|
1308
|
-
* `_maxExecutions`, the effect is disposed and an error is thrown (in debug mode)
|
|
1309
|
-
* or logged (in production mode).
|
|
1310
|
-
*
|
|
1311
|
-
* The circular buffer approach provides O(1) insertion and efficient
|
|
1312
|
-
* memory usage for tracking execution history.
|
|
1313
|
-
*
|
|
1314
|
-
* @throws {EffectError} In debug mode, throws when infinite loop is detected
|
|
1326
|
+
* Checks for infinite loop conditions using epoch-based detection.
|
|
1327
|
+
* Falls back to timestamp-based detection in development mode.
|
|
1315
1328
|
*
|
|
1329
|
+
* @throws {EffectError} When infinite loop is detected
|
|
1316
1330
|
* @internal
|
|
1317
1331
|
*/
|
|
1318
|
-
|
|
1319
|
-
if (this.
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
let s = 0, n = (this._historyIdx - 1 + this._historyCapacity) % this._historyCapacity;
|
|
1323
|
-
for (let r = 0; r < this._historyCount && !(this._history[n] < t); r++)
|
|
1324
|
-
s++, n = (n - 1 + this._historyCapacity) % this._historyCapacity;
|
|
1325
|
-
if (s > this._maxExecutions) {
|
|
1326
|
-
const r = `Effect executed ${s} times within 1 second. Infinite loop suspected`, u = new p(r);
|
|
1327
|
-
if (this.dispose(), console.error(u), a.enabled)
|
|
1328
|
-
throw u;
|
|
1332
|
+
_checkInfiniteLoop() {
|
|
1333
|
+
if (this._lastFlushEpoch !== C && (this._lastFlushEpoch = C, this._executionsInEpoch = 0), this._executionsInEpoch++, this._executionsInEpoch > this._maxExecutionsPerFlush && this._throwInfiniteLoopError("per-effect"), V() > N.MAX_EXECUTIONS_PER_FLUSH && this._throwInfiniteLoopError("global"), this._executionCount++, this._history) {
|
|
1334
|
+
const e = Date.now();
|
|
1335
|
+
this._history.push(e), this._history.length > N.MAX_EXECUTIONS_PER_SECOND + 10 && this._history.shift(), this._checkTimestampLoop(e);
|
|
1329
1336
|
}
|
|
1330
1337
|
}
|
|
1338
|
+
_checkTimestampLoop(e) {
|
|
1339
|
+
const t = this._history;
|
|
1340
|
+
if (!t || this._maxExecutions <= 0) return;
|
|
1341
|
+
const s = e - 1e3;
|
|
1342
|
+
let n = 0;
|
|
1343
|
+
for (let r = t.length - 1; r >= 0 && !(t[r] < s); r--)
|
|
1344
|
+
n++;
|
|
1345
|
+
if (n > this._maxExecutions) {
|
|
1346
|
+
const r = new E(
|
|
1347
|
+
`Effect executed ${n} times within 1 second. Infinite loop suspected`
|
|
1348
|
+
);
|
|
1349
|
+
if (this.dispose(), console.error(r), U)
|
|
1350
|
+
throw r;
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
_throwInfiniteLoopError(e) {
|
|
1354
|
+
const t = new E(
|
|
1355
|
+
`Infinite loop detected (${e}): effect executed ${this._executionsInEpoch} times in current flush. Total executions in flush: ${P}`
|
|
1356
|
+
);
|
|
1357
|
+
throw this.dispose(), console.error(t), t;
|
|
1358
|
+
}
|
|
1331
1359
|
/**
|
|
1332
1360
|
* Checks for and warns about potential infinite loop patterns.
|
|
1333
1361
|
*
|
|
@@ -1342,56 +1370,56 @@ class j {
|
|
|
1342
1370
|
* @internal
|
|
1343
1371
|
*/
|
|
1344
1372
|
_checkLoopWarnings() {
|
|
1345
|
-
if (this._trackModifications &&
|
|
1373
|
+
if (this._trackModifications && f.enabled) {
|
|
1346
1374
|
const e = this._dependencies;
|
|
1347
1375
|
for (let t = 0; t < e.length; t++) {
|
|
1348
1376
|
const s = e[t];
|
|
1349
|
-
s && this._modifiedDeps.has(s) &&
|
|
1377
|
+
s && this._modifiedDeps.has(s) && f.warn(
|
|
1350
1378
|
!0,
|
|
1351
|
-
`Effect is reading a dependency (${
|
|
1379
|
+
`Effect is reading a dependency (${f.getDebugName(s) || "unknown"}) that it just modified. Infinite loop may occur`
|
|
1352
1380
|
);
|
|
1353
1381
|
}
|
|
1354
1382
|
}
|
|
1355
1383
|
}
|
|
1356
1384
|
}
|
|
1357
|
-
function
|
|
1385
|
+
function se(i, e = {}) {
|
|
1358
1386
|
if (typeof i != "function")
|
|
1359
|
-
throw new
|
|
1360
|
-
const t = new
|
|
1387
|
+
throw new E(h.EFFECT_MUST_BE_FUNCTION);
|
|
1388
|
+
const t = new H(i, e);
|
|
1361
1389
|
return t.execute(), t;
|
|
1362
1390
|
}
|
|
1363
|
-
function
|
|
1391
|
+
function J(i) {
|
|
1364
1392
|
return i !== null && typeof i == "object" && "value" in i && "subscribe" in i && typeof i.subscribe == "function";
|
|
1365
1393
|
}
|
|
1366
|
-
function
|
|
1367
|
-
if (
|
|
1368
|
-
const e =
|
|
1394
|
+
function ie(i) {
|
|
1395
|
+
if (f.enabled) {
|
|
1396
|
+
const e = f.getDebugType(i);
|
|
1369
1397
|
if (e)
|
|
1370
1398
|
return e === "computed";
|
|
1371
1399
|
}
|
|
1372
|
-
return
|
|
1400
|
+
return J(i) && "invalidate" in i && typeof i.invalidate == "function";
|
|
1373
1401
|
}
|
|
1374
|
-
function
|
|
1402
|
+
function ne(i) {
|
|
1375
1403
|
return i !== null && typeof i == "object" && "dispose" in i && "run" in i && typeof i.dispose == "function" && typeof i.run == "function";
|
|
1376
1404
|
}
|
|
1377
1405
|
export {
|
|
1378
|
-
|
|
1406
|
+
R as AsyncState,
|
|
1379
1407
|
_ as AtomError,
|
|
1380
1408
|
b as ComputedError,
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1409
|
+
M as DEBUG_CONFIG,
|
|
1410
|
+
f as DEBUG_RUNTIME,
|
|
1411
|
+
E as EffectError,
|
|
1412
|
+
W as POOL_CONFIG,
|
|
1413
|
+
N as SCHEDULER_CONFIG,
|
|
1386
1414
|
y as SchedulerError,
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1415
|
+
ee as atom,
|
|
1416
|
+
K as batch,
|
|
1417
|
+
te as computed,
|
|
1418
|
+
se as effect,
|
|
1419
|
+
J as isAtom,
|
|
1420
|
+
ie as isComputed,
|
|
1421
|
+
ne as isEffect,
|
|
1422
|
+
g as scheduler,
|
|
1423
|
+
Z as untracked
|
|
1396
1424
|
};
|
|
1397
1425
|
//# sourceMappingURL=index.mjs.map
|