@but212/atom-effect 0.2.2 → 0.3.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/README.md +13 -8
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +27 -1
- package/dist/index.mjs +337 -268
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/dist/index.mjs
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
const
|
|
1
|
+
const T = {
|
|
2
2
|
IDLE: "idle",
|
|
3
3
|
PENDING: "pending",
|
|
4
4
|
RESOLVED: "resolved",
|
|
5
5
|
REJECTED: "rejected"
|
|
6
|
-
},
|
|
6
|
+
}, F = {
|
|
7
7
|
DISPOSED: 1,
|
|
8
8
|
// 0001 - Effect has been disposed
|
|
9
9
|
EXECUTING: 2
|
|
10
10
|
// 0010 - Effect is currently executing
|
|
11
|
-
},
|
|
11
|
+
}, h = {
|
|
12
12
|
DIRTY: 1,
|
|
13
13
|
// 0001 - Needs recomputation
|
|
14
14
|
IDLE: 2,
|
|
@@ -23,23 +23,33 @@ const C = {
|
|
|
23
23
|
// 100000 - Currently recomputing
|
|
24
24
|
HAS_ERROR: 64
|
|
25
25
|
// 1000000 - Has error state
|
|
26
|
-
},
|
|
26
|
+
}, ie = {
|
|
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
|
+
}, U = {
|
|
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
|
+
}, k = {
|
|
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
|
-
},
|
|
42
|
-
class
|
|
51
|
+
}, N = 1073741823, w = typeof process < "u" && process.env && process.env.NODE_ENV !== "production";
|
|
52
|
+
class d extends Error {
|
|
43
53
|
/**
|
|
44
54
|
* Creates a new AtomError
|
|
45
55
|
* @param message - Error message describing what went wrong
|
|
@@ -50,7 +60,7 @@ class _ extends Error {
|
|
|
50
60
|
super(e), this.name = "AtomError", this.cause = t, this.recoverable = s, this.timestamp = /* @__PURE__ */ new Date();
|
|
51
61
|
}
|
|
52
62
|
}
|
|
53
|
-
class
|
|
63
|
+
class D extends d {
|
|
54
64
|
/**
|
|
55
65
|
* Creates a new ComputedError
|
|
56
66
|
* @param message - Error message
|
|
@@ -60,7 +70,7 @@ class b extends _ {
|
|
|
60
70
|
super(e, t, !0), this.name = "ComputedError";
|
|
61
71
|
}
|
|
62
72
|
}
|
|
63
|
-
class
|
|
73
|
+
class S extends d {
|
|
64
74
|
/**
|
|
65
75
|
* Creates a new EffectError
|
|
66
76
|
* @param message - Error message
|
|
@@ -70,7 +80,7 @@ class p extends _ {
|
|
|
70
80
|
super(e, t, !1), this.name = "EffectError";
|
|
71
81
|
}
|
|
72
82
|
}
|
|
73
|
-
class
|
|
83
|
+
class C extends d {
|
|
74
84
|
/**
|
|
75
85
|
* Creates a new SchedulerError
|
|
76
86
|
* @param message - Error message
|
|
@@ -80,20 +90,20 @@ class y extends _ {
|
|
|
80
90
|
super(e, t, !1), this.name = "SchedulerError";
|
|
81
91
|
}
|
|
82
92
|
}
|
|
83
|
-
function
|
|
93
|
+
function R(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)
|
|
87
97
|
return new e(`Reference error (${t}): ${i.message}`, i);
|
|
88
|
-
if (i instanceof
|
|
98
|
+
if (i instanceof d)
|
|
89
99
|
return i;
|
|
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 X(i) {
|
|
94
104
|
return i != null && typeof i.then == "function";
|
|
95
105
|
}
|
|
96
|
-
const
|
|
106
|
+
const a = {
|
|
97
107
|
// ─────────────────────────────────────────────────────────────────
|
|
98
108
|
// Computed errors
|
|
99
109
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -102,9 +112,9 @@ const o = {
|
|
|
102
112
|
*/
|
|
103
113
|
COMPUTED_MUST_BE_FUNCTION: "Computed function must be a function",
|
|
104
114
|
/**
|
|
105
|
-
* Error thrown when subscribe() receives
|
|
115
|
+
* Error thrown when subscribe() receives an invalid listener.
|
|
106
116
|
*/
|
|
107
|
-
COMPUTED_SUBSCRIBER_MUST_BE_FUNCTION: "Subscriber listener must be a function",
|
|
117
|
+
COMPUTED_SUBSCRIBER_MUST_BE_FUNCTION: "Subscriber listener must be a function or Subscriber object",
|
|
108
118
|
/**
|
|
109
119
|
* Error thrown when accessing a pending async computed without a default value.
|
|
110
120
|
*/
|
|
@@ -125,9 +135,9 @@ const o = {
|
|
|
125
135
|
// Atom errors
|
|
126
136
|
// ─────────────────────────────────────────────────────────────────
|
|
127
137
|
/**
|
|
128
|
-
* Error thrown when atom.subscribe() receives
|
|
138
|
+
* Error thrown when atom.subscribe() receives an invalid listener.
|
|
129
139
|
*/
|
|
130
|
-
ATOM_SUBSCRIBER_MUST_BE_FUNCTION: "Subscription listener must be a function",
|
|
140
|
+
ATOM_SUBSCRIBER_MUST_BE_FUNCTION: "Subscription listener must be a function or Subscriber object",
|
|
131
141
|
/**
|
|
132
142
|
* Error thrown when the atom subscriber notification process fails.
|
|
133
143
|
*/
|
|
@@ -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 P = 0;
|
|
192
|
+
function G() {
|
|
193
|
+
return P = (P + 1 | 0) & N, P;
|
|
194
|
+
}
|
|
195
|
+
let A = 0, v = 0, O = !1;
|
|
196
|
+
function q() {
|
|
197
|
+
return O ? (w && console.warn(
|
|
198
|
+
"Warning: startFlush() called during flush - ignored to prevent infinite loop detection bypass"
|
|
199
|
+
), !1) : (O = !0, A = A + 1 & N, v = 0, !0);
|
|
200
|
+
}
|
|
201
|
+
function z() {
|
|
202
|
+
O = !1;
|
|
203
|
+
}
|
|
204
|
+
function H() {
|
|
205
|
+
return O ? ++v : 0;
|
|
206
|
+
}
|
|
207
|
+
class J {
|
|
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
|
}
|
|
@@ -208,7 +234,7 @@ class v {
|
|
|
208
234
|
*/
|
|
209
235
|
schedule(e) {
|
|
210
236
|
if (typeof e != "function")
|
|
211
|
-
throw new
|
|
237
|
+
throw new C("Scheduler callback must be a function");
|
|
212
238
|
e._nextEpoch !== this._epoch && (e._nextEpoch = this._epoch, this.isBatching || this.isFlushingSync ? this.batchQueue[this.batchQueueSize++] = e : (this.queue[this.queueSize++] = e, this.isProcessing || this.flush()));
|
|
213
239
|
}
|
|
214
240
|
/**
|
|
@@ -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 = q();
|
|
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
|
|
263
|
+
new C("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 && z(), this.queueSize > 0 && !this.isBatching && this.flush();
|
|
240
267
|
});
|
|
241
268
|
}
|
|
242
269
|
/**
|
|
@@ -254,42 +281,43 @@ class v {
|
|
|
254
281
|
*/
|
|
255
282
|
flushSync() {
|
|
256
283
|
this.isFlushingSync = !0;
|
|
284
|
+
const e = q();
|
|
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
|
-
new
|
|
297
|
+
new C(
|
|
270
298
|
`Maximum flush iterations (${this.maxFlushIterations}) exceeded. Possible infinite loop in reactive dependencies. Consider increasing the limit with scheduler.setMaxFlushIterations()`
|
|
271
299
|
)
|
|
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 (c) {
|
|
281
309
|
console.error(
|
|
282
|
-
new
|
|
310
|
+
new C("Error occurred during batch execution", c)
|
|
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 && z();
|
|
293
321
|
}
|
|
294
322
|
}
|
|
295
323
|
/**
|
|
@@ -353,24 +381,24 @@ class v {
|
|
|
353
381
|
*/
|
|
354
382
|
setMaxFlushIterations(e) {
|
|
355
383
|
if (e < 10)
|
|
356
|
-
throw new
|
|
384
|
+
throw new C("Max flush iterations must be at least 10");
|
|
357
385
|
this.maxFlushIterations = e;
|
|
358
386
|
}
|
|
359
387
|
}
|
|
360
|
-
const
|
|
361
|
-
function
|
|
388
|
+
const m = new J();
|
|
389
|
+
function ne(i) {
|
|
362
390
|
if (typeof i != "function")
|
|
363
|
-
throw new
|
|
364
|
-
|
|
391
|
+
throw new d("Batch callback must be a function");
|
|
392
|
+
m.startBatch();
|
|
365
393
|
try {
|
|
366
394
|
return i();
|
|
367
395
|
} catch (e) {
|
|
368
|
-
throw new
|
|
396
|
+
throw new d("Error occurred during batch execution", e);
|
|
369
397
|
} finally {
|
|
370
|
-
|
|
398
|
+
m.endBatch();
|
|
371
399
|
}
|
|
372
400
|
}
|
|
373
|
-
const
|
|
401
|
+
const y = {
|
|
374
402
|
/** @inheritdoc */
|
|
375
403
|
current: null,
|
|
376
404
|
/**
|
|
@@ -391,24 +419,37 @@ const S = {
|
|
|
391
419
|
return this.current;
|
|
392
420
|
}
|
|
393
421
|
};
|
|
394
|
-
function
|
|
422
|
+
function re(i) {
|
|
395
423
|
if (typeof i != "function")
|
|
396
|
-
throw new
|
|
397
|
-
const e =
|
|
398
|
-
|
|
424
|
+
throw new d("Untracked callback must be a function");
|
|
425
|
+
const e = y.current;
|
|
426
|
+
y.current = null;
|
|
399
427
|
try {
|
|
400
428
|
return i();
|
|
401
429
|
} catch (t) {
|
|
402
|
-
throw new
|
|
430
|
+
throw new d("Error occurred during untracked execution", t);
|
|
403
431
|
} finally {
|
|
404
|
-
|
|
432
|
+
y.current = e;
|
|
405
433
|
}
|
|
406
434
|
}
|
|
407
|
-
const
|
|
408
|
-
function
|
|
409
|
-
return i !== null && typeof i == "object" && "dependencies" in i && i.dependencies
|
|
435
|
+
const L = /* @__PURE__ */ Symbol("debugName"), W = /* @__PURE__ */ Symbol("id"), M = /* @__PURE__ */ Symbol("type"), j = /* @__PURE__ */ Symbol("noDefaultValue");
|
|
436
|
+
function K(i) {
|
|
437
|
+
return i !== null && typeof i == "object" && "dependencies" in i && Array.isArray(i.dependencies);
|
|
410
438
|
}
|
|
411
|
-
|
|
439
|
+
let V = 0;
|
|
440
|
+
function Y(i, e, t) {
|
|
441
|
+
const s = i;
|
|
442
|
+
if (s._visitedEpoch !== t) {
|
|
443
|
+
if (s._visitedEpoch = t, i === e)
|
|
444
|
+
throw new D("Indirect circular dependency detected");
|
|
445
|
+
if (K(i)) {
|
|
446
|
+
const n = i.dependencies;
|
|
447
|
+
for (let r = 0; r < n.length; r++)
|
|
448
|
+
Y(n[r], e, t);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
const b = {
|
|
412
453
|
/**
|
|
413
454
|
* Whether debug mode is enabled.
|
|
414
455
|
*
|
|
@@ -422,13 +463,13 @@ const a = {
|
|
|
422
463
|
*
|
|
423
464
|
* @see {@link DEBUG_CONFIG.MAX_DEPENDENCIES}
|
|
424
465
|
*/
|
|
425
|
-
maxDependencies:
|
|
466
|
+
maxDependencies: k.MAX_DEPENDENCIES,
|
|
426
467
|
/**
|
|
427
468
|
* Whether to warn about potential infinite loops.
|
|
428
469
|
*
|
|
429
470
|
* @see {@link DEBUG_CONFIG.WARN_INFINITE_LOOP}
|
|
430
471
|
*/
|
|
431
|
-
warnInfiniteLoop:
|
|
472
|
+
warnInfiniteLoop: k.WARN_INFINITE_LOOP,
|
|
432
473
|
/**
|
|
433
474
|
* Logs a warning message when condition is true and debug is enabled.
|
|
434
475
|
*
|
|
@@ -471,16 +512,10 @@ const a = {
|
|
|
471
512
|
* debug.checkCircular(computedC, computedA);
|
|
472
513
|
* ```
|
|
473
514
|
*/
|
|
474
|
-
checkCircular(i, e, t
|
|
515
|
+
checkCircular(i, e, t) {
|
|
475
516
|
if (i === e)
|
|
476
|
-
throw new
|
|
477
|
-
|
|
478
|
-
if (t.has(i))
|
|
479
|
-
throw new b("Indirect circular dependency detected");
|
|
480
|
-
if (t.add(i), q(i))
|
|
481
|
-
for (const s of i.dependencies)
|
|
482
|
-
this.checkCircular(s, e, t);
|
|
483
|
-
}
|
|
517
|
+
throw new D("Direct circular dependency detected");
|
|
518
|
+
this.enabled && (V++, Y(i, e, V));
|
|
484
519
|
},
|
|
485
520
|
/**
|
|
486
521
|
* Attaches debug metadata to a reactive object.
|
|
@@ -506,7 +541,7 @@ const a = {
|
|
|
506
541
|
if (!this.enabled)
|
|
507
542
|
return;
|
|
508
543
|
const s = i;
|
|
509
|
-
s[
|
|
544
|
+
s[L] = `${e}_${t}`, s[W] = t, s[M] = e;
|
|
510
545
|
},
|
|
511
546
|
/**
|
|
512
547
|
* Retrieves the debug display name from a reactive object.
|
|
@@ -521,8 +556,8 @@ const a = {
|
|
|
521
556
|
* ```
|
|
522
557
|
*/
|
|
523
558
|
getDebugName(i) {
|
|
524
|
-
if (i !== null && typeof i == "object" &&
|
|
525
|
-
return i[
|
|
559
|
+
if (i !== null && typeof i == "object" && L in i)
|
|
560
|
+
return i[L];
|
|
526
561
|
},
|
|
527
562
|
/**
|
|
528
563
|
* Retrieves the debug type from a reactive object.
|
|
@@ -539,13 +574,13 @@ const a = {
|
|
|
539
574
|
* ```
|
|
540
575
|
*/
|
|
541
576
|
getDebugType(i) {
|
|
542
|
-
if (i !== null && typeof i == "object" &&
|
|
543
|
-
return i[
|
|
577
|
+
if (i !== null && typeof i == "object" && M in i)
|
|
578
|
+
return i[M];
|
|
544
579
|
}
|
|
545
580
|
};
|
|
546
|
-
let
|
|
547
|
-
const
|
|
548
|
-
class
|
|
581
|
+
let Z = 1;
|
|
582
|
+
const B = () => Z++;
|
|
583
|
+
class x {
|
|
549
584
|
constructor() {
|
|
550
585
|
this.subscribers = null;
|
|
551
586
|
}
|
|
@@ -678,7 +713,7 @@ class N {
|
|
|
678
713
|
return this.subscribers ? [...this.subscribers] : [];
|
|
679
714
|
}
|
|
680
715
|
}
|
|
681
|
-
class
|
|
716
|
+
class ee {
|
|
682
717
|
/**
|
|
683
718
|
* Creates a new AtomImpl instance.
|
|
684
719
|
*
|
|
@@ -686,7 +721,7 @@ class z {
|
|
|
686
721
|
* @param sync - Whether to notify subscribers synchronously
|
|
687
722
|
*/
|
|
688
723
|
constructor(e, t) {
|
|
689
|
-
this._isNotificationScheduled = !1, this.id =
|
|
724
|
+
this._isNotificationScheduled = !1, this.id = B() & N, this.version = 0, this.flags = 0, this._lastSeenEpoch = -1, this._value = e, this._functionSubscribers = new x(), this._objectSubscribers = new x(), this._sync = t, this._notifyTask = this._flushNotifications.bind(this), b.attachDebugInfo(this, "atom", this.id);
|
|
690
725
|
}
|
|
691
726
|
/**
|
|
692
727
|
* Gets the current value and registers the atom as a dependency
|
|
@@ -699,7 +734,7 @@ class z {
|
|
|
699
734
|
* a computed or effect context.
|
|
700
735
|
*/
|
|
701
736
|
get value() {
|
|
702
|
-
const e =
|
|
737
|
+
const e = y.getCurrent();
|
|
703
738
|
return e != null && this._track(e), this._value;
|
|
704
739
|
}
|
|
705
740
|
/**
|
|
@@ -715,7 +750,7 @@ class z {
|
|
|
715
750
|
set value(e) {
|
|
716
751
|
if (Object.is(this._value, e)) return;
|
|
717
752
|
const t = this._value;
|
|
718
|
-
this.version = this.version + 1 &
|
|
753
|
+
this.version = this.version + 1 & N;
|
|
719
754
|
const s = this.version;
|
|
720
755
|
this._value = e, !(!this._functionSubscribers.hasSubscribers && !this._objectSubscribers.hasSubscribers) && this._notify(e, t, s);
|
|
721
756
|
}
|
|
@@ -755,7 +790,7 @@ class z {
|
|
|
755
790
|
* but don't schedule a new task. The pending task will see the latest value.
|
|
756
791
|
*/
|
|
757
792
|
_notify(e, t, s) {
|
|
758
|
-
this._isNotificationScheduled || (this._pendingOldValue = t, this._isNotificationScheduled = !0), this._sync && !
|
|
793
|
+
this._isNotificationScheduled || (this._pendingOldValue = t, this._isNotificationScheduled = !0), this._sync && !m.isBatching ? this._flushNotifications() : m.schedule(this._notifyTask);
|
|
759
794
|
}
|
|
760
795
|
/**
|
|
761
796
|
* Executes the pending notifications.
|
|
@@ -766,18 +801,18 @@ class z {
|
|
|
766
801
|
const e = this._pendingOldValue, t = this._value;
|
|
767
802
|
this._pendingOldValue = void 0, this._isNotificationScheduled = !1, this._functionSubscribers.forEachSafe(
|
|
768
803
|
(s) => s(t, e),
|
|
769
|
-
(s) => console.error(new
|
|
804
|
+
(s) => console.error(new d(a.ATOM_INDIVIDUAL_SUBSCRIBER_FAILED, s))
|
|
770
805
|
), this._objectSubscribers.forEachSafe(
|
|
771
806
|
(s) => s.execute(),
|
|
772
|
-
(s) => console.error(new
|
|
807
|
+
(s) => console.error(new d(a.ATOM_INDIVIDUAL_SUBSCRIBER_FAILED, s))
|
|
773
808
|
);
|
|
774
809
|
}
|
|
775
810
|
/**
|
|
776
|
-
* Subscribes a listener function to value changes.
|
|
811
|
+
* Subscribes a listener function or Subscriber object to value changes.
|
|
777
812
|
*
|
|
778
|
-
* @param listener - Function to call when the value changes
|
|
813
|
+
* @param listener - Function or Subscriber object to call when the value changes
|
|
779
814
|
* @returns An unsubscribe function
|
|
780
|
-
* @throws {AtomError} If listener is not a function
|
|
815
|
+
* @throws {AtomError} If listener is not a function or Subscriber
|
|
781
816
|
*
|
|
782
817
|
* @example
|
|
783
818
|
* ```ts
|
|
@@ -788,8 +823,10 @@ class z {
|
|
|
788
823
|
* ```
|
|
789
824
|
*/
|
|
790
825
|
subscribe(e) {
|
|
826
|
+
if (typeof e == "object" && e !== null && "execute" in e)
|
|
827
|
+
return this._objectSubscribers.add(e);
|
|
791
828
|
if (typeof e != "function")
|
|
792
|
-
throw new
|
|
829
|
+
throw new d(a.ATOM_SUBSCRIBER_MUST_BE_FUNCTION);
|
|
793
830
|
return this._functionSubscribers.add(e);
|
|
794
831
|
}
|
|
795
832
|
/**
|
|
@@ -823,44 +860,40 @@ class z {
|
|
|
823
860
|
return this._functionSubscribers.size + this._objectSubscribers.size;
|
|
824
861
|
}
|
|
825
862
|
}
|
|
826
|
-
function
|
|
827
|
-
return new
|
|
828
|
-
}
|
|
829
|
-
let O = 0;
|
|
830
|
-
function M() {
|
|
831
|
-
return O = (O + 1 | 0) & I, O;
|
|
863
|
+
function ce(i, e = {}) {
|
|
864
|
+
return new ee(i, e.sync ?? !1);
|
|
832
865
|
}
|
|
833
|
-
const
|
|
834
|
-
class
|
|
866
|
+
const p = process.env.NODE_ENV !== "production", f = Object.freeze([]), E = Object.freeze([]);
|
|
867
|
+
class $ {
|
|
835
868
|
constructor() {
|
|
836
|
-
this.pool = [], this.maxPoolSize = 50, this.maxReusableCapacity = 256, this.stats =
|
|
869
|
+
this.pool = [], this.maxPoolSize = 50, this.maxReusableCapacity = 256, this.stats = p ? {
|
|
837
870
|
acquired: 0,
|
|
838
871
|
released: 0,
|
|
839
872
|
rejected: { frozen: 0, tooLarge: 0, poolFull: 0 }
|
|
840
873
|
} : null;
|
|
841
874
|
}
|
|
842
875
|
acquire() {
|
|
843
|
-
return
|
|
876
|
+
return p && this.stats && this.stats.acquired++, this.pool.pop() ?? [];
|
|
844
877
|
}
|
|
845
878
|
release(e, t) {
|
|
846
879
|
if (!(t && e === t)) {
|
|
847
880
|
if (Object.isFrozen(e)) {
|
|
848
|
-
|
|
881
|
+
p && this.stats && this.stats.rejected.frozen++;
|
|
849
882
|
return;
|
|
850
883
|
}
|
|
851
884
|
if (e.length > this.maxReusableCapacity) {
|
|
852
|
-
|
|
885
|
+
p && this.stats && this.stats.rejected.tooLarge++;
|
|
853
886
|
return;
|
|
854
887
|
}
|
|
855
888
|
if (this.pool.length >= this.maxPoolSize) {
|
|
856
|
-
|
|
889
|
+
p && this.stats && this.stats.rejected.poolFull++;
|
|
857
890
|
return;
|
|
858
891
|
}
|
|
859
|
-
e.length = 0, this.pool.push(e),
|
|
892
|
+
e.length = 0, this.pool.push(e), p && this.stats && this.stats.released++;
|
|
860
893
|
}
|
|
861
894
|
}
|
|
862
895
|
getStats() {
|
|
863
|
-
if (!
|
|
896
|
+
if (!p || !this.stats) return null;
|
|
864
897
|
const { acquired: e, released: t, rejected: s } = this.stats, n = s.frozen + s.tooLarge + s.poolFull;
|
|
865
898
|
return {
|
|
866
899
|
acquired: e,
|
|
@@ -871,15 +904,15 @@ class V {
|
|
|
871
904
|
};
|
|
872
905
|
}
|
|
873
906
|
reset() {
|
|
874
|
-
this.pool.length = 0,
|
|
907
|
+
this.pool.length = 0, p && this.stats && (this.stats.acquired = 0, this.stats.released = 0, this.stats.rejected = { frozen: 0, tooLarge: 0, poolFull: 0 });
|
|
875
908
|
}
|
|
876
909
|
}
|
|
877
|
-
const
|
|
878
|
-
class
|
|
910
|
+
const g = new $(), I = new $();
|
|
911
|
+
class Q {
|
|
879
912
|
constructor(e, t = {}) {
|
|
880
913
|
if (typeof e != "function")
|
|
881
|
-
throw new
|
|
882
|
-
if (this.id =
|
|
914
|
+
throw new D(a.COMPUTED_MUST_BE_FUNCTION);
|
|
915
|
+
if (this.id = B() & N, this.version = 0, this.flags = 0, this._lastSeenEpoch = -1, this._value = void 0, this._stateFlags = h.DIRTY | h.IDLE, this._error = null, this._promiseId = 0, this._equal = t.equal ?? Object.is, this._fn = e, this._defaultValue = "defaultValue" in t ? t.defaultValue : j, this._hasDefaultValue = this._defaultValue !== j, this._onError = t.onError ?? null, this.MAX_PROMISE_ID = Number.MAX_SAFE_INTEGER - 1, this._functionSubscribers = new x(), this._objectSubscribers = new x(), this._dependencies = f, this._unsubscribes = E, this._recomputeJob = () => {
|
|
883
916
|
if (this._isDirty())
|
|
884
917
|
try {
|
|
885
918
|
this._recompute();
|
|
@@ -896,7 +929,7 @@ class w {
|
|
|
896
929
|
}, this._trackable = Object.assign(() => this._markDirty(), {
|
|
897
930
|
addDependency: (s) => {
|
|
898
931
|
}
|
|
899
|
-
}),
|
|
932
|
+
}), b.attachDebugInfo(this, "computed", this.id), b.enabled) {
|
|
900
933
|
const s = this;
|
|
901
934
|
s.subscriberCount = () => this._functionSubscribers.size + this._objectSubscribers.size, s.isDirty = () => this._isDirty(), s.dependencies = this._dependencies, s.stateFlags = this._getFlagsAsString();
|
|
902
935
|
}
|
|
@@ -908,14 +941,16 @@ class w {
|
|
|
908
941
|
}
|
|
909
942
|
// === PUBLIC API ===
|
|
910
943
|
get value() {
|
|
911
|
-
if ((this._stateFlags & (
|
|
944
|
+
if ((this._stateFlags & (h.RESOLVED | h.DIRTY)) === h.RESOLVED)
|
|
912
945
|
return this._registerTracking(), this._value;
|
|
913
946
|
const t = this._computeValue();
|
|
914
947
|
return this._registerTracking(), t;
|
|
915
948
|
}
|
|
916
949
|
subscribe(e) {
|
|
950
|
+
if (typeof e == "object" && e !== null && "execute" in e)
|
|
951
|
+
return this._objectSubscribers.add(e);
|
|
917
952
|
if (typeof e != "function")
|
|
918
|
-
throw new
|
|
953
|
+
throw new D(a.COMPUTED_SUBSCRIBER_MUST_BE_FUNCTION);
|
|
919
954
|
return this._functionSubscribers.add(e);
|
|
920
955
|
}
|
|
921
956
|
peek() {
|
|
@@ -940,57 +975,58 @@ class w {
|
|
|
940
975
|
this._markDirty();
|
|
941
976
|
}
|
|
942
977
|
dispose() {
|
|
943
|
-
if (this.
|
|
944
|
-
for (
|
|
945
|
-
const t = this.
|
|
946
|
-
t && t()
|
|
978
|
+
if (this._unsubscribes !== E) {
|
|
979
|
+
for (let e = 0; e < this._unsubscribes.length; e++) {
|
|
980
|
+
const t = this._unsubscribes[e];
|
|
981
|
+
t && t();
|
|
947
982
|
}
|
|
948
|
-
|
|
983
|
+
I.release(this._unsubscribes), this._unsubscribes = E;
|
|
949
984
|
}
|
|
950
|
-
this._dependencies =
|
|
985
|
+
this._dependencies !== f && (g.release(this._dependencies), this._dependencies = f), this._functionSubscribers.clear(), this._objectSubscribers.clear(), this._stateFlags = h.DIRTY | h.IDLE, this._error = null, this._value = void 0, this._promiseId = (this._promiseId + 1) % this.MAX_PROMISE_ID;
|
|
951
986
|
}
|
|
952
987
|
// === PRIVATE: State Flag Operations (inlined for performance) ===
|
|
953
988
|
_isDirty() {
|
|
954
|
-
return (this._stateFlags &
|
|
989
|
+
return (this._stateFlags & h.DIRTY) !== 0;
|
|
955
990
|
}
|
|
956
991
|
_setDirty() {
|
|
957
|
-
this._stateFlags |=
|
|
992
|
+
this._stateFlags |= h.DIRTY;
|
|
958
993
|
}
|
|
959
994
|
_clearDirty() {
|
|
960
995
|
this._stateFlags &= -2;
|
|
961
996
|
}
|
|
962
997
|
_isIdle() {
|
|
963
|
-
return (this._stateFlags &
|
|
998
|
+
return (this._stateFlags & h.IDLE) !== 0;
|
|
964
999
|
}
|
|
965
1000
|
_setIdle() {
|
|
966
|
-
this._stateFlags |=
|
|
1001
|
+
this._stateFlags |= h.IDLE, this._stateFlags &= -29;
|
|
967
1002
|
}
|
|
968
1003
|
_isPending() {
|
|
969
|
-
return (this._stateFlags &
|
|
1004
|
+
return (this._stateFlags & h.PENDING) !== 0;
|
|
970
1005
|
}
|
|
971
1006
|
_setPending() {
|
|
972
|
-
this._stateFlags |=
|
|
1007
|
+
this._stateFlags |= h.PENDING, this._stateFlags &= -27;
|
|
973
1008
|
}
|
|
974
1009
|
_isResolved() {
|
|
975
|
-
return (this._stateFlags &
|
|
1010
|
+
return (this._stateFlags & h.RESOLVED) !== 0;
|
|
976
1011
|
}
|
|
977
1012
|
_setResolved() {
|
|
978
|
-
this._stateFlags |=
|
|
1013
|
+
this._stateFlags |= h.RESOLVED, this._stateFlags &= -87;
|
|
979
1014
|
}
|
|
980
1015
|
_isRejected() {
|
|
981
|
-
return (this._stateFlags &
|
|
1016
|
+
return (this._stateFlags & h.REJECTED) !== 0;
|
|
982
1017
|
}
|
|
983
1018
|
_setRejected() {
|
|
984
|
-
this._stateFlags |=
|
|
1019
|
+
this._stateFlags |= h.REJECTED | h.HAS_ERROR, this._stateFlags &= -15;
|
|
985
1020
|
}
|
|
986
1021
|
_isRecomputing() {
|
|
987
|
-
return (this._stateFlags &
|
|
1022
|
+
return (this._stateFlags & h.RECOMPUTING) !== 0;
|
|
988
1023
|
}
|
|
989
1024
|
_setRecomputing(e) {
|
|
990
|
-
|
|
1025
|
+
const t = h.RECOMPUTING;
|
|
1026
|
+
this._stateFlags = this._stateFlags & ~t | -Number(e) & t;
|
|
991
1027
|
}
|
|
992
1028
|
_getAsyncState() {
|
|
993
|
-
return this._isPending() ?
|
|
1029
|
+
return this._isPending() ? T.PENDING : this._isResolved() ? T.RESOLVED : this._isRejected() ? T.REJECTED : T.IDLE;
|
|
994
1030
|
}
|
|
995
1031
|
_getFlagsAsString() {
|
|
996
1032
|
const e = [];
|
|
@@ -1004,47 +1040,52 @@ class w {
|
|
|
1004
1040
|
if (!this._isDirty() && this._isResolved())
|
|
1005
1041
|
return;
|
|
1006
1042
|
this._setRecomputing(!0);
|
|
1007
|
-
const e = this._dependencies, t =
|
|
1043
|
+
const e = this._dependencies, t = g.acquire(), s = G();
|
|
1008
1044
|
let n = 0;
|
|
1009
|
-
const r = (
|
|
1010
|
-
|
|
1011
|
-
},
|
|
1045
|
+
const r = (_) => {
|
|
1046
|
+
_._lastSeenEpoch !== s && (_._lastSeenEpoch = s, n < t.length ? t[n] = _ : t.push(_), n++);
|
|
1047
|
+
}, c = this._trackable.addDependency;
|
|
1012
1048
|
this._trackable.addDependency = r;
|
|
1013
|
-
let
|
|
1049
|
+
let o = !1;
|
|
1014
1050
|
try {
|
|
1015
|
-
const
|
|
1016
|
-
if (t.length = n,
|
|
1017
|
-
this._syncDependencies(e, t, s), this._dependencies = t,
|
|
1051
|
+
const _ = y.run(this._trackable, this._fn);
|
|
1052
|
+
if (t.length = n, X(_)) {
|
|
1053
|
+
this._syncDependencies(e, t, this._unsubscribes, s), this._dependencies = t, o = !0, this._handleAsyncComputation(_), this._setRecomputing(!1);
|
|
1018
1054
|
return;
|
|
1019
1055
|
}
|
|
1020
|
-
this._syncDependencies(e, t, s), this._dependencies = t,
|
|
1021
|
-
} catch (
|
|
1022
|
-
t.length = n, this._syncDependencies(e, t, s), this._dependencies = t,
|
|
1056
|
+
this._syncDependencies(e, t, this._unsubscribes, s), this._dependencies = t, o = !0, this._handleSyncResult(_);
|
|
1057
|
+
} catch (_) {
|
|
1058
|
+
t.length = n, this._syncDependencies(e, t, this._unsubscribes, s), this._dependencies = t, this._handleComputationError(_);
|
|
1023
1059
|
} finally {
|
|
1024
|
-
this._trackable.addDependency =
|
|
1060
|
+
this._trackable.addDependency = c, o ? e !== f && g.release(e) : g.release(t);
|
|
1025
1061
|
}
|
|
1026
1062
|
}
|
|
1027
1063
|
/**
|
|
1028
1064
|
* Synchronizes subscriptions based on dependency changes.
|
|
1029
1065
|
* O(N) Diff using Epoch.
|
|
1030
1066
|
*/
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
for (let n = 0; n < t.length; n++) {
|
|
1041
|
-
const r = t[n];
|
|
1042
|
-
if (r && !this._subscriptions.has(r.id)) {
|
|
1043
|
-
a.checkCircular(r, this);
|
|
1044
|
-
const u = r.subscribe(() => this._markDirty());
|
|
1045
|
-
this._subscriptions.set(r.id, u);
|
|
1067
|
+
/**
|
|
1068
|
+
* Synchronizes subscriptions based on dependency changes using O(N) strategy.
|
|
1069
|
+
* Maps unsubs 1:1 with dependencies array.
|
|
1070
|
+
*/
|
|
1071
|
+
_syncDependencies(e, t, s, n) {
|
|
1072
|
+
if (e !== f && s !== E)
|
|
1073
|
+
for (let c = 0; c < e.length; c++) {
|
|
1074
|
+
const o = e[c];
|
|
1075
|
+
o && (o._tempUnsub = s[c]);
|
|
1046
1076
|
}
|
|
1077
|
+
const r = I.acquire();
|
|
1078
|
+
r.length = t.length;
|
|
1079
|
+
for (let c = 0; c < t.length; c++) {
|
|
1080
|
+
const o = t[c];
|
|
1081
|
+
o && (o._tempUnsub ? (r[c] = o._tempUnsub, o._tempUnsub = void 0) : (b.checkCircular(o, this), r[c] = o.subscribe(this)));
|
|
1047
1082
|
}
|
|
1083
|
+
if (e !== f)
|
|
1084
|
+
for (let c = 0; c < e.length; c++) {
|
|
1085
|
+
const o = e[c];
|
|
1086
|
+
o?._tempUnsub && (o._tempUnsub(), o._tempUnsub = void 0);
|
|
1087
|
+
}
|
|
1088
|
+
s !== E && I.release(s), this._unsubscribes = r;
|
|
1048
1089
|
}
|
|
1049
1090
|
_handleSyncResult(e) {
|
|
1050
1091
|
const t = !this._isResolved() || !this._equal(this._value, e);
|
|
@@ -1064,29 +1105,29 @@ class w {
|
|
|
1064
1105
|
this._value = e, this._clearDirty(), this._setResolved(), this._error = null, this._setRecomputing(!1), t && this._notifySubscribers();
|
|
1065
1106
|
}
|
|
1066
1107
|
_handleAsyncRejection(e) {
|
|
1067
|
-
const t =
|
|
1108
|
+
const t = R(e, D, a.COMPUTED_ASYNC_COMPUTATION_FAILED);
|
|
1068
1109
|
if (this._error = t, this._setRejected(), this._clearDirty(), this._setRecomputing(!1), this._onError && typeof this._onError == "function")
|
|
1069
1110
|
try {
|
|
1070
1111
|
this._onError(t);
|
|
1071
1112
|
} catch (s) {
|
|
1072
|
-
console.error(
|
|
1113
|
+
console.error(a.CALLBACK_ERROR_IN_ERROR_HANDLER, s);
|
|
1073
1114
|
}
|
|
1074
1115
|
this._notifySubscribers();
|
|
1075
1116
|
}
|
|
1076
1117
|
_handleComputationError(e) {
|
|
1077
|
-
const t =
|
|
1118
|
+
const t = R(e, D, a.COMPUTED_COMPUTATION_FAILED);
|
|
1078
1119
|
if (this._error = t, this._setRejected(), this._clearDirty(), this._setRecomputing(!1), this._onError && typeof this._onError == "function")
|
|
1079
1120
|
try {
|
|
1080
1121
|
this._onError(t);
|
|
1081
1122
|
} catch (s) {
|
|
1082
|
-
console.error(
|
|
1123
|
+
console.error(a.CALLBACK_ERROR_IN_ERROR_HANDLER, s);
|
|
1083
1124
|
}
|
|
1084
1125
|
throw t;
|
|
1085
1126
|
}
|
|
1086
1127
|
_handlePending() {
|
|
1087
1128
|
if (this._hasDefaultValue)
|
|
1088
1129
|
return this._defaultValue;
|
|
1089
|
-
throw new
|
|
1130
|
+
throw new D(a.COMPUTED_ASYNC_PENDING_NO_DEFAULT);
|
|
1090
1131
|
}
|
|
1091
1132
|
_handleRejected() {
|
|
1092
1133
|
if (this._error?.recoverable && this._hasDefaultValue)
|
|
@@ -1096,14 +1137,21 @@ class w {
|
|
|
1096
1137
|
// === PRIVATE: Dependency Management ===
|
|
1097
1138
|
// (Replaced by _syncDependencies and inline pool logic)
|
|
1098
1139
|
// === PRIVATE: Subscriber Management ===
|
|
1140
|
+
/**
|
|
1141
|
+
* Subscriber interface implementation (Zero-Allocation pattern)
|
|
1142
|
+
* Called by dependencies when they change - delegates to _markDirty
|
|
1143
|
+
*/
|
|
1144
|
+
execute() {
|
|
1145
|
+
this._markDirty();
|
|
1146
|
+
}
|
|
1099
1147
|
_markDirty() {
|
|
1100
|
-
this._isRecomputing() || this._isDirty() || (this._setDirty(), this._setIdle(), (this._functionSubscribers.hasSubscribers || this._objectSubscribers.hasSubscribers) &&
|
|
1148
|
+
this._isRecomputing() || this._isDirty() || (this._setDirty(), this._setIdle(), (this._functionSubscribers.hasSubscribers || this._objectSubscribers.hasSubscribers) && m.schedule(this._recomputeJob));
|
|
1101
1149
|
}
|
|
1102
1150
|
_notifySubscribers() {
|
|
1103
|
-
!this._functionSubscribers.hasSubscribers && !this._objectSubscribers.hasSubscribers ||
|
|
1151
|
+
!this._functionSubscribers.hasSubscribers && !this._objectSubscribers.hasSubscribers || m.schedule(this._notifyJob);
|
|
1104
1152
|
}
|
|
1105
1153
|
_registerTracking() {
|
|
1106
|
-
const e =
|
|
1154
|
+
const e = y.getCurrent();
|
|
1107
1155
|
if (e)
|
|
1108
1156
|
if (typeof e == "object" && e !== null && e.addDependency)
|
|
1109
1157
|
e.addDependency(this);
|
|
@@ -1113,50 +1161,75 @@ class w {
|
|
|
1113
1161
|
} else e.execute && this._objectSubscribers.add(e);
|
|
1114
1162
|
}
|
|
1115
1163
|
}
|
|
1116
|
-
Object.freeze(
|
|
1117
|
-
function
|
|
1118
|
-
return new
|
|
1164
|
+
Object.freeze(Q.prototype);
|
|
1165
|
+
function ue(i, e = {}) {
|
|
1166
|
+
return new Q(i, e);
|
|
1119
1167
|
}
|
|
1120
|
-
class
|
|
1168
|
+
class te {
|
|
1121
1169
|
constructor(e, t = {}) {
|
|
1122
1170
|
this.run = () => {
|
|
1123
1171
|
if (this.isDisposed)
|
|
1124
|
-
throw new
|
|
1172
|
+
throw new S(a.EFFECT_MUST_BE_FUNCTION);
|
|
1125
1173
|
this.execute();
|
|
1126
1174
|
}, this.dispose = () => {
|
|
1127
|
-
if (!this.isDisposed
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1175
|
+
if (!this.isDisposed) {
|
|
1176
|
+
if (this._setDisposed(), this._safeCleanup(), this._unsubscribes !== E) {
|
|
1177
|
+
for (let s = 0; s < this._unsubscribes.length; s++) {
|
|
1178
|
+
const n = this._unsubscribes[s];
|
|
1179
|
+
n && n();
|
|
1180
|
+
}
|
|
1181
|
+
I.release(this._unsubscribes), this._unsubscribes = E;
|
|
1131
1182
|
}
|
|
1132
|
-
|
|
1183
|
+
this._dependencies !== f && (g.release(this._dependencies), this._dependencies = f);
|
|
1133
1184
|
}
|
|
1134
1185
|
}, this.addDependency = (s) => {
|
|
1135
|
-
if (this.isExecuting && this._nextDeps) {
|
|
1186
|
+
if (this.isExecuting && this._nextDeps && this._nextUnsubs) {
|
|
1136
1187
|
const n = s, r = this._currentEpoch;
|
|
1137
1188
|
if (n._lastSeenEpoch === r) return;
|
|
1138
|
-
n._lastSeenEpoch = r, this._nextDeps.push(n), this.
|
|
1189
|
+
n._lastSeenEpoch = r, this._nextDeps.push(n), n._tempUnsub ? (this._nextUnsubs.push(n._tempUnsub), n._tempUnsub = void 0) : this._subscribeTo(n);
|
|
1139
1190
|
}
|
|
1140
1191
|
}, this.execute = () => {
|
|
1141
1192
|
if (this.isDisposed || this.isExecuting) return;
|
|
1142
|
-
|
|
1143
|
-
this.
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1193
|
+
this._checkInfiniteLoop(), this._setExecuting(!0), this._safeCleanup();
|
|
1194
|
+
const s = this._dependencies, n = this._unsubscribes, r = g.acquire(), c = I.acquire(), o = G();
|
|
1195
|
+
if (s !== f && n !== E)
|
|
1196
|
+
for (let u = 0; u < s.length; u++) {
|
|
1197
|
+
const l = s[u];
|
|
1198
|
+
l && (l._tempUnsub = n[u]);
|
|
1199
|
+
}
|
|
1200
|
+
this._nextDeps = r, this._nextUnsubs = c, this._currentEpoch = o;
|
|
1201
|
+
let _ = !1;
|
|
1147
1202
|
try {
|
|
1148
|
-
const
|
|
1149
|
-
this.
|
|
1150
|
-
!this.isDisposed && typeof
|
|
1151
|
-
}).catch((
|
|
1152
|
-
console.error(
|
|
1153
|
-
}) : this._cleanup = typeof
|
|
1154
|
-
} catch (
|
|
1155
|
-
|
|
1203
|
+
const u = y.run(this, this._fn);
|
|
1204
|
+
this._dependencies = r, this._unsubscribes = c, _ = !0, this._checkLoopWarnings(), X(u) ? u.then((l) => {
|
|
1205
|
+
!this.isDisposed && typeof l == "function" && (this._cleanup = l);
|
|
1206
|
+
}).catch((l) => {
|
|
1207
|
+
console.error(R(l, S, a.EFFECT_EXECUTION_FAILED));
|
|
1208
|
+
}) : this._cleanup = typeof u == "function" ? u : null;
|
|
1209
|
+
} catch (u) {
|
|
1210
|
+
_ = !0, console.error(R(u, S, a.EFFECT_EXECUTION_FAILED)), this._cleanup = null;
|
|
1156
1211
|
} finally {
|
|
1157
|
-
this._setExecuting(!1), this._nextDeps = null,
|
|
1212
|
+
if (this._setExecuting(!1), this._nextDeps = null, this._nextUnsubs = null, _) {
|
|
1213
|
+
if (s !== f) {
|
|
1214
|
+
for (let u = 0; u < s.length; u++) {
|
|
1215
|
+
const l = s[u];
|
|
1216
|
+
l?._tempUnsub && (l._tempUnsub(), l._tempUnsub = void 0);
|
|
1217
|
+
}
|
|
1218
|
+
g.release(s);
|
|
1219
|
+
}
|
|
1220
|
+
n !== E && I.release(n);
|
|
1221
|
+
} else {
|
|
1222
|
+
g.release(r);
|
|
1223
|
+
for (let u = 0; u < c.length; u++)
|
|
1224
|
+
c[u]?.();
|
|
1225
|
+
if (I.release(c), s !== f)
|
|
1226
|
+
for (let u = 0; u < s.length; u++) {
|
|
1227
|
+
const l = s[u];
|
|
1228
|
+
l && (l._tempUnsub = void 0);
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1158
1231
|
}
|
|
1159
|
-
}, this._id =
|
|
1232
|
+
}, this._id = B() & N, this._flags = 0, this._currentEpoch = -1, this._fn = e, this._sync = t.sync ?? !1, this._maxExecutions = t.maxExecutionsPerSecond ?? U.MAX_EXECUTIONS_PER_SECOND, this._maxExecutionsPerFlush = t.maxExecutionsPerFlush ?? U.MAX_EXECUTIONS_PER_EFFECT, this._trackModifications = t.trackModifications ?? !1, this._cleanup = null, this._dependencies = f, this._unsubscribes = E, this._nextDeps = null, this._nextUnsubs = null, this._lastFlushEpoch = -1, this._executionsInEpoch = 0, this._history = w ? [] : null, this._executionCount = 0, b.attachDebugInfo(this, "effect", this._id);
|
|
1160
1233
|
}
|
|
1161
1234
|
/**
|
|
1162
1235
|
* Synchronizes subscriptions by unsubscribing from removed dependencies.
|
|
@@ -1165,24 +1238,16 @@ class j {
|
|
|
1165
1238
|
* @param prevDeps - Previous dependency array
|
|
1166
1239
|
* @param epoch - Current execution epoch for staleness detection
|
|
1167
1240
|
*/
|
|
1168
|
-
_syncDependencies(
|
|
1169
|
-
if (e !== l)
|
|
1170
|
-
for (let s = 0; s < e.length; s++) {
|
|
1171
|
-
const n = e[s];
|
|
1172
|
-
if (n && n._lastSeenEpoch !== t) {
|
|
1173
|
-
const r = this._subscriptions.get(n.id);
|
|
1174
|
-
r && (r(), this._subscriptions.delete(n.id));
|
|
1175
|
-
}
|
|
1176
|
-
}
|
|
1177
|
-
}
|
|
1241
|
+
// _syncDependencies removed (inline logic in execute)
|
|
1178
1242
|
_subscribeTo(e) {
|
|
1179
1243
|
try {
|
|
1180
1244
|
const t = e.subscribe(() => {
|
|
1181
|
-
this._trackModifications && this.isExecuting && this.
|
|
1245
|
+
this._trackModifications && this.isExecuting && (e._modifiedAtEpoch = this._currentEpoch), this._sync ? this.execute() : m.schedule(this.execute);
|
|
1182
1246
|
});
|
|
1183
|
-
this.
|
|
1247
|
+
this._nextUnsubs && this._nextUnsubs.push(t);
|
|
1184
1248
|
} catch (t) {
|
|
1185
|
-
console.error(
|
|
1249
|
+
console.error(R(t, S, a.EFFECT_EXECUTION_FAILED)), this._nextUnsubs && this._nextUnsubs.push(() => {
|
|
1250
|
+
});
|
|
1186
1251
|
}
|
|
1187
1252
|
}
|
|
1188
1253
|
/**
|
|
@@ -1204,7 +1269,7 @@ class j {
|
|
|
1204
1269
|
* ```
|
|
1205
1270
|
*/
|
|
1206
1271
|
get isDisposed() {
|
|
1207
|
-
return (this._flags &
|
|
1272
|
+
return (this._flags & F.DISPOSED) !== 0;
|
|
1208
1273
|
}
|
|
1209
1274
|
/**
|
|
1210
1275
|
* Returns the total number of times this effect has been executed.
|
|
@@ -1246,7 +1311,7 @@ class j {
|
|
|
1246
1311
|
* ```
|
|
1247
1312
|
*/
|
|
1248
1313
|
get isExecuting() {
|
|
1249
|
-
return (this._flags &
|
|
1314
|
+
return (this._flags & F.EXECUTING) !== 0;
|
|
1250
1315
|
}
|
|
1251
1316
|
/**
|
|
1252
1317
|
* Sets the disposed flag on this effect.
|
|
@@ -1258,7 +1323,7 @@ class j {
|
|
|
1258
1323
|
* @internal
|
|
1259
1324
|
*/
|
|
1260
1325
|
_setDisposed() {
|
|
1261
|
-
this._flags |=
|
|
1326
|
+
this._flags |= F.DISPOSED;
|
|
1262
1327
|
}
|
|
1263
1328
|
/**
|
|
1264
1329
|
* Sets or clears the executing flag on this effect.
|
|
@@ -1272,7 +1337,8 @@ class j {
|
|
|
1272
1337
|
* @internal
|
|
1273
1338
|
*/
|
|
1274
1339
|
_setExecuting(e) {
|
|
1275
|
-
|
|
1340
|
+
const t = F.EXECUTING;
|
|
1341
|
+
this._flags = this._flags & ~t | -Number(e) & t;
|
|
1276
1342
|
}
|
|
1277
1343
|
/**
|
|
1278
1344
|
* Safely executes the cleanup function if one exists.
|
|
@@ -1292,42 +1358,45 @@ class j {
|
|
|
1292
1358
|
try {
|
|
1293
1359
|
this._cleanup();
|
|
1294
1360
|
} catch (e) {
|
|
1295
|
-
console.error(
|
|
1361
|
+
console.error(R(e, S, a.EFFECT_CLEANUP_FAILED));
|
|
1296
1362
|
}
|
|
1297
1363
|
this._cleanup = null;
|
|
1298
1364
|
}
|
|
1299
1365
|
}
|
|
1300
1366
|
/**
|
|
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
|
|
1367
|
+
* Checks for infinite loop conditions using epoch-based detection.
|
|
1368
|
+
* Falls back to timestamp-based detection in development mode.
|
|
1315
1369
|
*
|
|
1370
|
+
* @throws {EffectError} When infinite loop is detected
|
|
1316
1371
|
* @internal
|
|
1317
1372
|
*/
|
|
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;
|
|
1373
|
+
_checkInfiniteLoop() {
|
|
1374
|
+
if (this._lastFlushEpoch !== A && (this._lastFlushEpoch = A, this._executionsInEpoch = 0), this._executionsInEpoch++, this._executionsInEpoch > this._maxExecutionsPerFlush && this._throwInfiniteLoopError("per-effect"), H() > U.MAX_EXECUTIONS_PER_FLUSH && this._throwInfiniteLoopError("global"), this._executionCount++, this._history) {
|
|
1375
|
+
const e = Date.now();
|
|
1376
|
+
this._history.push(e), this._history.length > U.MAX_EXECUTIONS_PER_SECOND + 10 && this._history.shift(), this._checkTimestampLoop(e);
|
|
1329
1377
|
}
|
|
1330
1378
|
}
|
|
1379
|
+
_checkTimestampLoop(e) {
|
|
1380
|
+
const t = this._history;
|
|
1381
|
+
if (!t || this._maxExecutions <= 0) return;
|
|
1382
|
+
const s = e - 1e3;
|
|
1383
|
+
let n = 0;
|
|
1384
|
+
for (let r = t.length - 1; r >= 0 && !(t[r] < s); r--)
|
|
1385
|
+
n++;
|
|
1386
|
+
if (n > this._maxExecutions) {
|
|
1387
|
+
const r = new S(
|
|
1388
|
+
`Effect executed ${n} times within 1 second. Infinite loop suspected`
|
|
1389
|
+
);
|
|
1390
|
+
if (this.dispose(), console.error(r), w)
|
|
1391
|
+
throw r;
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
_throwInfiniteLoopError(e) {
|
|
1395
|
+
const t = new S(
|
|
1396
|
+
`Infinite loop detected (${e}): effect executed ${this._executionsInEpoch} times in current flush. Total executions in flush: ${v}`
|
|
1397
|
+
);
|
|
1398
|
+
throw this.dispose(), console.error(t), t;
|
|
1399
|
+
}
|
|
1331
1400
|
/**
|
|
1332
1401
|
* Checks for and warns about potential infinite loop patterns.
|
|
1333
1402
|
*
|
|
@@ -1342,56 +1411,56 @@ class j {
|
|
|
1342
1411
|
* @internal
|
|
1343
1412
|
*/
|
|
1344
1413
|
_checkLoopWarnings() {
|
|
1345
|
-
if (this._trackModifications &&
|
|
1414
|
+
if (this._trackModifications && b.enabled) {
|
|
1346
1415
|
const e = this._dependencies;
|
|
1347
1416
|
for (let t = 0; t < e.length; t++) {
|
|
1348
1417
|
const s = e[t];
|
|
1349
|
-
s && this.
|
|
1418
|
+
s && s._modifiedAtEpoch === this._currentEpoch && b.warn(
|
|
1350
1419
|
!0,
|
|
1351
|
-
`Effect is reading a dependency (${
|
|
1420
|
+
`Effect is reading a dependency (${b.getDebugName(s) || "unknown"}) that it just modified. Infinite loop may occur`
|
|
1352
1421
|
);
|
|
1353
1422
|
}
|
|
1354
1423
|
}
|
|
1355
1424
|
}
|
|
1356
1425
|
}
|
|
1357
|
-
function
|
|
1426
|
+
function he(i, e = {}) {
|
|
1358
1427
|
if (typeof i != "function")
|
|
1359
|
-
throw new
|
|
1360
|
-
const t = new
|
|
1428
|
+
throw new S(a.EFFECT_MUST_BE_FUNCTION);
|
|
1429
|
+
const t = new te(i, e);
|
|
1361
1430
|
return t.execute(), t;
|
|
1362
1431
|
}
|
|
1363
|
-
function
|
|
1432
|
+
function se(i) {
|
|
1364
1433
|
return i !== null && typeof i == "object" && "value" in i && "subscribe" in i && typeof i.subscribe == "function";
|
|
1365
1434
|
}
|
|
1366
|
-
function
|
|
1367
|
-
if (
|
|
1368
|
-
const e =
|
|
1435
|
+
function oe(i) {
|
|
1436
|
+
if (b.enabled) {
|
|
1437
|
+
const e = b.getDebugType(i);
|
|
1369
1438
|
if (e)
|
|
1370
1439
|
return e === "computed";
|
|
1371
1440
|
}
|
|
1372
|
-
return
|
|
1441
|
+
return se(i) && "invalidate" in i && typeof i.invalidate == "function";
|
|
1373
1442
|
}
|
|
1374
|
-
function
|
|
1443
|
+
function ae(i) {
|
|
1375
1444
|
return i !== null && typeof i == "object" && "dispose" in i && "run" in i && typeof i.dispose == "function" && typeof i.run == "function";
|
|
1376
1445
|
}
|
|
1377
1446
|
export {
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1447
|
+
T as AsyncState,
|
|
1448
|
+
d as AtomError,
|
|
1449
|
+
D as ComputedError,
|
|
1450
|
+
k as DEBUG_CONFIG,
|
|
1451
|
+
b as DEBUG_RUNTIME,
|
|
1452
|
+
S as EffectError,
|
|
1453
|
+
ie as POOL_CONFIG,
|
|
1454
|
+
U as SCHEDULER_CONFIG,
|
|
1455
|
+
C as SchedulerError,
|
|
1456
|
+
ce as atom,
|
|
1457
|
+
ne as batch,
|
|
1458
|
+
ue as computed,
|
|
1459
|
+
he as effect,
|
|
1460
|
+
se as isAtom,
|
|
1461
|
+
oe as isComputed,
|
|
1462
|
+
ae as isEffect,
|
|
1463
|
+
m as scheduler,
|
|
1464
|
+
re as untracked
|
|
1396
1465
|
};
|
|
1397
1466
|
//# sourceMappingURL=index.mjs.map
|