@but212/atom-effect 0.3.2 → 0.4.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/dist/index.mjs CHANGED
@@ -1,14 +1,17 @@
1
- const T = {
1
+ const ie = {
2
+ /** One second in milliseconds */
3
+ ONE_SECOND_MS: 1e3
4
+ }, F = {
2
5
  IDLE: "idle",
3
6
  PENDING: "pending",
4
7
  RESOLVED: "resolved",
5
8
  REJECTED: "rejected"
6
- }, F = {
9
+ }, P = {
7
10
  DISPOSED: 1,
8
11
  // 0001 - Effect has been disposed
9
12
  EXECUTING: 2
10
13
  // 0010 - Effect is currently executing
11
- }, h = {
14
+ }, o = {
12
15
  DIRTY: 1,
13
16
  // 0001 - Needs recomputation
14
17
  IDLE: 2,
@@ -23,12 +26,12 @@ const T = {
23
26
  // 100000 - Currently recomputing
24
27
  HAS_ERROR: 64
25
28
  // 1000000 - Has error state
26
- }, ie = {
29
+ }, Ee = {
27
30
  /** Maximum number of pooled objects to prevent memory bloat */
28
31
  MAX_SIZE: 1e3,
29
32
  /** Number of objects to pre-allocate for performance-critical paths */
30
33
  WARMUP_SIZE: 100
31
- }, A = {
34
+ }, y = {
32
35
  /** Maximum effect executions per second to detect infinite loops (Legacy/Fallback) */
33
36
  MAX_EXECUTIONS_PER_SECOND: 100,
34
37
  /** Threshold for cleaning up old execution timestamps */
@@ -42,25 +45,29 @@ const T = {
42
45
  * Maximum total executions across all effects in a single flush cycle
43
46
  * Increased from 1000 to 5000 based on evaluation report
44
47
  */
45
- MAX_EXECUTIONS_PER_FLUSH: 5e3
46
- }, k = {
48
+ MAX_EXECUTIONS_PER_FLUSH: 5e3,
49
+ /** Maximum iterations for synchronous flush loop to prevent infinite loops */
50
+ MAX_FLUSH_ITERATIONS: 1e3,
51
+ /** Minimum allowed value for max flush iterations */
52
+ MIN_FLUSH_ITERATIONS: 10
53
+ }, z = {
47
54
  /** Maximum dependencies before warning about large dependency graphs */
48
55
  MAX_DEPENDENCIES: 1e3,
49
56
  /** Enable infinite loop detection warnings */
50
57
  WARN_INFINITE_LOOP: !0
51
- }, D = 1073741823, M = typeof process < "u" && process.env && process.env.NODE_ENV !== "production";
52
- class d extends Error {
58
+ }, A = 1073741823, d = typeof process < "u" && process.env && process.env.NODE_ENV !== "production";
59
+ class E extends Error {
53
60
  /**
54
61
  * Creates a new AtomError
55
62
  * @param message - Error message describing what went wrong
56
63
  * @param cause - Original error that caused this error
57
64
  * @param recoverable - Whether the operation can be retried
58
65
  */
59
- constructor(e, t = null, s = !0) {
60
- super(e), this.name = "AtomError", this.cause = t, this.recoverable = s, this.timestamp = /* @__PURE__ */ new Date();
66
+ constructor(e, t = null, i = !0) {
67
+ super(e), this.name = "AtomError", this.cause = t, this.recoverable = i, this.timestamp = /* @__PURE__ */ new Date();
61
68
  }
62
69
  }
63
- class I extends d {
70
+ class T extends E {
64
71
  /**
65
72
  * Creates a new ComputedError
66
73
  * @param message - Error message
@@ -70,7 +77,7 @@ class I extends d {
70
77
  super(e, t, !0), this.name = "ComputedError";
71
78
  }
72
79
  }
73
- class g extends d {
80
+ class g extends E {
74
81
  /**
75
82
  * Creates a new EffectError
76
83
  * @param message - Error message
@@ -80,7 +87,7 @@ class g extends d {
80
87
  super(e, t, !1), this.name = "EffectError";
81
88
  }
82
89
  }
83
- class C extends d {
90
+ class x extends E {
84
91
  /**
85
92
  * Creates a new SchedulerError
86
93
  * @param message - Error message
@@ -90,20 +97,20 @@ class C extends d {
90
97
  super(e, t, !1), this.name = "SchedulerError";
91
98
  }
92
99
  }
93
- function R(i, e, t) {
94
- if (i instanceof TypeError)
95
- return new e(`Type error (${t}): ${i.message}`, i);
96
- if (i instanceof ReferenceError)
97
- return new e(`Reference error (${t}): ${i.message}`, i);
98
- if (i instanceof d)
99
- return i;
100
- const s = i instanceof Error ? i.message : String(i), n = i instanceof Error ? i : null;
101
- return new e(`Unexpected error (${t}): ${s}`, n);
100
+ function C(s, e, t) {
101
+ if (s instanceof TypeError)
102
+ return new e(`Type error (${t}): ${s.message}`, s);
103
+ if (s instanceof ReferenceError)
104
+ return new e(`Reference error (${t}): ${s.message}`, s);
105
+ if (s instanceof E)
106
+ return s;
107
+ const i = s instanceof Error ? s.message : String(s), n = s instanceof Error ? s : null;
108
+ return new e(`Unexpected error (${t}): ${i}`, n);
102
109
  }
103
- function X(i) {
104
- return i != null && typeof i.then == "function";
110
+ function Y(s) {
111
+ return s != null && typeof s.then == "function";
105
112
  }
106
- const a = {
113
+ const l = {
107
114
  // ─────────────────────────────────────────────────────────────────
108
115
  // Computed errors
109
116
  // ─────────────────────────────────────────────────────────────────
@@ -177,7 +184,7 @@ const a = {
177
184
  * // Output: "Large dependency graph detected: 150 dependencies"
178
185
  * ```
179
186
  */
180
- LARGE_DEPENDENCY_GRAPH: (i) => `Large dependency graph detected: ${i} dependencies`,
187
+ LARGE_DEPENDENCY_GRAPH: (s) => `Large dependency graph detected: ${s} dependencies`,
181
188
  /**
182
189
  * Warning logged when attempting to unsubscribe a non-existent listener.
183
190
  */
@@ -187,105 +194,155 @@ const a = {
187
194
  * @remarks This prevents cascading failures from masking the original error.
188
195
  */
189
196
  CALLBACK_ERROR_IN_ERROR_HANDLER: "Error occurred during onError callback execution"
190
- };
191
- let P = 0;
192
- function G() {
193
- return P = (P + 1 | 0) & D, P;
194
- }
195
- let U = 0, w = 0, O = !1;
196
- function q() {
197
- return O ? (M && console.warn(
198
- "Warning: startFlush() called during flush - ignored to prevent infinite loop detection bypass"
199
- ), !1) : (O = !0, U = U + 1 & D, w = 0, !0);
200
- }
201
- function z() {
202
- O = !1;
197
+ }, w = /* @__PURE__ */ Symbol("debugName"), ne = /* @__PURE__ */ Symbol("id"), V = /* @__PURE__ */ Symbol("type"), X = /* @__PURE__ */ Symbol("noDefaultValue");
198
+ function re(s) {
199
+ return "dependencies" in s && Array.isArray(s.dependencies);
203
200
  }
204
- function H() {
205
- return O ? ++w : 0;
201
+ let G = 0;
202
+ function Q(s, e, t) {
203
+ if (s._visitedEpoch !== t) {
204
+ if (s._visitedEpoch = t, s === e)
205
+ throw new T("Indirect circular dependency detected");
206
+ if (re(s)) {
207
+ const i = s.dependencies;
208
+ for (let n = 0; n < i.length; n++) {
209
+ const r = i[n];
210
+ r && Q(r, e, t);
211
+ }
212
+ }
213
+ }
206
214
  }
215
+ const S = {
216
+ enabled: typeof process < "u" && process.env?.NODE_ENV === "development",
217
+ maxDependencies: z.MAX_DEPENDENCIES,
218
+ warnInfiniteLoop: z.WARN_INFINITE_LOOP,
219
+ warn(s, e) {
220
+ this.enabled && s && console.warn(`[Atom Effect] ${e}`);
221
+ },
222
+ /**
223
+ * Checks for circular dependencies.
224
+ * Direct check runs always; indirect check only in dev mode.
225
+ * @throws {ComputedError} When circular dependency detected
226
+ */
227
+ checkCircular(s, e) {
228
+ if (s === e)
229
+ throw new T("Direct circular dependency detected");
230
+ this.enabled && (G++, Q(s, e, G));
231
+ },
232
+ attachDebugInfo(s, e, t) {
233
+ if (!this.enabled)
234
+ return;
235
+ const i = s;
236
+ i[w] = `${e}_${t}`, i[ne] = t, i[V] = e;
237
+ },
238
+ getDebugName(s) {
239
+ if (s != null && w in s)
240
+ return s[w];
241
+ },
242
+ getDebugType(s) {
243
+ if (s != null && V in s)
244
+ return s[V];
245
+ }
246
+ };
247
+ let ce = 1;
248
+ const ue = () => ce++;
207
249
  class J {
208
250
  constructor() {
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;
251
+ this.id = ue() & A, this.flags = 0;
252
+ }
253
+ }
254
+ class W extends J {
255
+ constructor() {
256
+ super(), this.version = 0, this._lastSeenEpoch = -1;
210
257
  }
211
258
  /**
212
- * Gets the current phase of the scheduler.
259
+ * Subscribes a listener function or Subscriber object to value changes.
260
+ *
261
+ * @param listener - Function or Subscriber object to call when the value changes
262
+ * @returns An unsubscribe function
263
+ * @throws {AtomError} If listener is not a function or Subscriber
213
264
  */
214
- get phase() {
215
- return this.isProcessing || this.isFlushingSync ? 2 : this.isBatching ? 1 : 0;
265
+ subscribe(e) {
266
+ if (typeof e == "object" && e !== null && "execute" in e)
267
+ return this._objectSubscribers.add(e);
268
+ if (typeof e != "function")
269
+ throw new E(l.ATOM_SUBSCRIBER_MUST_BE_FUNCTION);
270
+ return this._functionSubscribers.add(e);
216
271
  }
217
272
  /**
218
- * Schedules a callback for execution.
219
- *
220
- * If batching is active or a sync flush is in progress, the callback
221
- * is added to the batch queue. Otherwise, it's added to the main queue
222
- * and a flush is triggered via microtask.
223
- *
224
- * @param callback - The function to schedule for execution
225
- * @throws {SchedulerError} If callback is not a function
273
+ * Gets the total number of active subscribers.
274
+ */
275
+ subscriberCount() {
276
+ return this._functionSubscribers.size + this._objectSubscribers.size;
277
+ }
278
+ /**
279
+ * Notifies all subscribers of a change.
226
280
  *
227
- * @example
228
- * ```typescript
229
- * scheduler.schedule(() => {
230
- * // This runs in the next microtask (or sync if batching)
231
- * updateUI();
232
- * });
233
- * ```
281
+ * @param newValue - The new value
282
+ * @param oldValue - The old value
234
283
  */
284
+ _notifySubscribers(e, t) {
285
+ this._functionSubscribers.forEachSafe(
286
+ (i) => i(e, t),
287
+ (i) => console.error(new E(l.ATOM_INDIVIDUAL_SUBSCRIBER_FAILED, i))
288
+ ), this._objectSubscribers.forEachSafe(
289
+ (i) => i.execute(),
290
+ (i) => console.error(new E(l.ATOM_INDIVIDUAL_SUBSCRIBER_FAILED, i))
291
+ );
292
+ }
293
+ }
294
+ let B = 0;
295
+ function K() {
296
+ return B = (B + 1 | 0) & A, B;
297
+ }
298
+ let M = 0, k = 0, L = !1;
299
+ function $() {
300
+ return L ? (d && console.warn(
301
+ "Warning: startFlush() called during flush - ignored to prevent infinite loop detection bypass"
302
+ ), !1) : (L = !0, M = M + 1 & A, k = 0, !0);
303
+ }
304
+ function H() {
305
+ L = !1;
306
+ }
307
+ function oe() {
308
+ return L ? ++k : 0;
309
+ }
310
+ class he {
311
+ constructor() {
312
+ 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 = y.MAX_FLUSH_ITERATIONS;
313
+ }
314
+ get phase() {
315
+ return this.isProcessing || this.isFlushingSync ? 2 : this.isBatching ? 1 : 0;
316
+ }
235
317
  schedule(e) {
236
318
  if (typeof e != "function")
237
- throw new C("Scheduler callback must be a function");
319
+ throw new x("Scheduler callback must be a function");
238
320
  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()));
239
321
  }
240
- /**
241
- * Flushes the queue asynchronously via microtask.
242
- *
243
- * Executes all queued callbacks in a microtask, allowing the current
244
- * synchronous execution to complete first. Errors in individual
245
- * callbacks are caught and logged without interrupting others.
246
- *
247
- * @private
248
- * @remarks
249
- * This method is idempotent - calling it multiple times while
250
- * processing is active has no effect.
251
- */
252
322
  flush() {
253
323
  if (this.isProcessing || this.queueSize === 0) return;
254
324
  this.isProcessing = !0;
255
325
  const e = this.queue, t = this.queueSize;
256
326
  this.queue = this.queue === this.queueA ? this.queueB : this.queueA, this.queueSize = 0, this._epoch++, queueMicrotask(() => {
257
- const s = q();
327
+ const i = $();
258
328
  for (let n = 0; n < t; n++)
259
329
  try {
260
330
  e[n]?.();
261
331
  } catch (r) {
262
332
  console.error(
263
- new C("Error occurred during scheduler execution", r)
333
+ new x("Error occurred during scheduler execution", r)
264
334
  );
265
335
  }
266
- e.length = 0, this.isProcessing = !1, s && z(), this.queueSize > 0 && !this.isBatching && this.flush();
336
+ e.length = 0, this.isProcessing = !1, i && H(), this.queueSize > 0 && !this.isBatching && this.flush();
267
337
  });
268
338
  }
269
- /**
270
- * Flushes all queued callbacks synchronously.
271
- *
272
- * This method is called when a batch ends. It processes all callbacks
273
- * in the batch queue and main queue synchronously, allowing callbacks
274
- * to schedule additional callbacks that are processed in the same flush.
275
- *
276
- * @private
277
- * @remarks
278
- * - Includes infinite loop protection via maxFlushIterations
279
- * - Errors in callbacks are caught and logged individually
280
- * - The isFlushingSync flag prevents re-entrancy issues
281
- */
282
339
  flushSync() {
283
340
  this.isFlushingSync = !0;
284
- const e = q();
341
+ const e = $();
285
342
  try {
286
343
  if (this._epoch++, this.batchQueueSize > 0) {
287
- for (let s = 0; s < this.batchQueueSize; s++) {
288
- const n = this.batchQueue[s];
344
+ for (let i = 0; i < this.batchQueueSize; i++) {
345
+ const n = this.batchQueue[i];
289
346
  n._nextEpoch !== this._epoch && (n._nextEpoch = this._epoch, this.queue[this.queueSize++] = n);
290
347
  }
291
348
  this.batchQueueSize = 0;
@@ -294,312 +351,104 @@ class J {
294
351
  for (; this.queueSize > 0; ) {
295
352
  if (++t > this.maxFlushIterations) {
296
353
  console.error(
297
- new C(
298
- `Maximum flush iterations (${this.maxFlushIterations}) exceeded. Possible infinite loop in reactive dependencies. Consider increasing the limit with scheduler.setMaxFlushIterations()`
354
+ new x(
355
+ `Maximum flush iterations (${this.maxFlushIterations}) exceeded. Possible infinite loop.`
299
356
  )
300
357
  ), this.queueSize = 0, this.queue.length = 0, this.batchQueueSize = 0;
301
358
  break;
302
359
  }
303
- const s = this.queue, n = this.queueSize;
360
+ const i = this.queue, n = this.queueSize;
304
361
  this.queue = this.queue === this.queueA ? this.queueB : this.queueA, this.queueSize = 0, this._epoch++;
305
362
  for (let r = 0; r < n; r++)
306
363
  try {
307
- s[r]?.();
364
+ i[r]?.();
308
365
  } catch (c) {
309
366
  console.error(
310
- new C("Error occurred during batch execution", c)
367
+ new x("Error occurred during batch execution", c)
311
368
  );
312
369
  }
313
- if (s.length = 0, this.batchQueueSize > 0) {
370
+ if (i.length = 0, this.batchQueueSize > 0) {
314
371
  for (let r = 0; r < this.batchQueueSize; r++)
315
372
  this.queue[this.queueSize++] = this.batchQueue[r];
316
373
  this.batchQueueSize = 0;
317
374
  }
318
375
  }
319
376
  } finally {
320
- this.isFlushingSync = !1, e && z();
377
+ this.isFlushingSync = !1, e && H();
321
378
  }
322
379
  }
323
- /**
324
- * Starts a new batch operation.
325
- *
326
- * While batching is active, all scheduled callbacks are deferred
327
- * until endBatch() is called. Batches can be nested - only the
328
- * outermost endBatch() triggers execution.
329
- *
330
- * @example
331
- * ```typescript
332
- * scheduler.startBatch();
333
- * // All updates here are deferred
334
- * atom1.value = 'a';
335
- * atom2.value = 'b';
336
- * scheduler.endBatch(); // Both updates processed together
337
- * ```
338
- */
339
380
  startBatch() {
340
381
  this.batchDepth++, this.isBatching = !0;
341
382
  }
342
- /**
343
- * Ends a batch operation.
344
- *
345
- * Decrements the batch depth counter. When depth reaches zero,
346
- * all queued callbacks are flushed synchronously and batching
347
- * is disabled.
348
- *
349
- * @remarks
350
- * Safe to call even if startBatch() wasn't called - depth is
351
- * clamped to zero minimum.
352
- *
353
- * @example
354
- * ```typescript
355
- * scheduler.startBatch();
356
- * try {
357
- * // ... batched operations
358
- * } finally {
359
- * scheduler.endBatch(); // Always end batch, even on error
360
- * }
361
- * ```
362
- */
363
383
  endBatch() {
364
384
  this.batchDepth = Math.max(0, this.batchDepth - 1), this.batchDepth === 0 && (this.flushSync(), this.isBatching = !1);
365
385
  }
366
- /**
367
- * Sets the maximum number of flush iterations allowed.
368
- *
369
- * This limit prevents infinite loops when reactive dependencies
370
- * form cycles. If exceeded, the queue is cleared and an error
371
- * is logged.
372
- *
373
- * @param max - Maximum iterations (must be at least 10)
374
- * @throws {SchedulerError} If max is less than 10
375
- *
376
- * @example
377
- * ```typescript
378
- * // Increase limit for complex dependency graphs
379
- * scheduler.setMaxFlushIterations(5000);
380
- * ```
381
- */
382
386
  setMaxFlushIterations(e) {
383
- if (e < 10)
384
- throw new C("Max flush iterations must be at least 10");
387
+ if (e < y.MIN_FLUSH_ITERATIONS)
388
+ throw new x(
389
+ `Max flush iterations must be at least ${y.MIN_FLUSH_ITERATIONS}`
390
+ );
385
391
  this.maxFlushIterations = e;
386
392
  }
387
393
  }
388
- const N = new J();
389
- function ne(i) {
390
- if (typeof i != "function")
391
- throw new d("Batch callback must be a function");
392
- N.startBatch();
394
+ const U = new he();
395
+ function be(s) {
396
+ if (typeof s != "function")
397
+ throw new E("Batch callback must be a function");
398
+ U.startBatch();
393
399
  try {
394
- return i();
400
+ return s();
395
401
  } catch (e) {
396
- throw new d("Error occurred during batch execution", e);
402
+ throw new E("Error occurred during batch execution", e);
397
403
  } finally {
398
- N.endBatch();
404
+ U.endBatch();
399
405
  }
400
406
  }
401
- const m = {
402
- /** @inheritdoc */
407
+ const N = {
403
408
  current: null,
404
- /**
405
- * @inheritdoc
406
- * @throws Re-throws any error from the executed function after restoring context
407
- */
408
- run(i, e) {
409
+ run(s, e) {
409
410
  const t = this.current;
410
- this.current = i;
411
+ this.current = s;
411
412
  try {
412
413
  return e();
413
414
  } finally {
414
415
  this.current = t;
415
416
  }
416
417
  },
417
- /** @inheritdoc */
418
418
  getCurrent() {
419
419
  return this.current;
420
420
  }
421
421
  };
422
- function re(i) {
423
- if (typeof i != "function")
424
- throw new d("Untracked callback must be a function");
425
- const e = m.current;
426
- m.current = null;
422
+ function le(s) {
423
+ return typeof s == "object" && s !== null;
424
+ }
425
+ function Z(s) {
426
+ return (typeof s == "object" || typeof s == "function") && s !== null && typeof s.addDependency == "function";
427
+ }
428
+ function ee(s) {
429
+ return typeof s == "function" && typeof s.addDependency != "function";
430
+ }
431
+ function te(s) {
432
+ return le(s) && typeof s.execute == "function";
433
+ }
434
+ function _e(s) {
435
+ if (typeof s != "function")
436
+ throw new E("Untracked callback must be a function");
437
+ const e = N.current;
438
+ N.current = null;
427
439
  try {
428
- return i();
440
+ return s();
429
441
  } catch (t) {
430
- throw new d("Error occurred during untracked execution", t);
442
+ throw new E("Error occurred during untracked execution", t);
431
443
  } finally {
432
- m.current = e;
433
- }
434
- }
435
- const v = /* @__PURE__ */ Symbol("debugName"), W = /* @__PURE__ */ Symbol("id"), L = /* @__PURE__ */ Symbol("type"), V = /* @__PURE__ */ Symbol("noDefaultValue");
436
- function K(i) {
437
- return i !== null && typeof i == "object" && "dependencies" in i && Array.isArray(i.dependencies);
438
- }
439
- let j = 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 I("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
- }
444
+ N.current = e;
450
445
  }
451
446
  }
452
- const b = {
453
- /**
454
- * Whether debug mode is enabled.
455
- *
456
- * @remarks
457
- * Automatically set based on `NODE_ENV` environment variable.
458
- * Only `'development'` enables debug features.
459
- */
460
- enabled: typeof process < "u" && process.env?.NODE_ENV === "development",
461
- /**
462
- * Maximum number of dependencies before warning.
463
- *
464
- * @see {@link DEBUG_CONFIG.MAX_DEPENDENCIES}
465
- */
466
- maxDependencies: k.MAX_DEPENDENCIES,
467
- /**
468
- * Whether to warn about potential infinite loops.
469
- *
470
- * @see {@link DEBUG_CONFIG.WARN_INFINITE_LOOP}
471
- */
472
- warnInfiniteLoop: k.WARN_INFINITE_LOOP,
473
- /**
474
- * Logs a warning message when condition is true and debug is enabled.
475
- *
476
- * @param condition - When true, the warning is logged
477
- * @param message - The warning message to display
478
- *
479
- * @example
480
- * ```typescript
481
- * debug.warn(deps.length > 100, 'Large dependency graph detected');
482
- * ```
483
- */
484
- warn(i, e) {
485
- this.enabled && i && console.warn(`[Atom Effect] ${e}`);
486
- },
487
- /**
488
- * Checks for circular dependencies in the dependency graph.
489
- *
490
- * Detects two types of circular references:
491
- * 1. **Direct**: A depends on itself (A → A)
492
- * 2. **Indirect**: A depends on B which depends on A (A → B → A)
493
- *
494
- * @param dep - The dependency being added
495
- * @param current - The current reactive object adding the dependency
496
- * @param visited - Set of already visited nodes (for recursion)
497
- *
498
- * @throws {ComputedError} When a circular dependency is detected
499
- *
500
- * @remarks
501
- * - Direct circular detection runs in all environments
502
- * - Indirect circular detection only runs in development mode
503
- * - Uses depth-first traversal with O(n) time complexity
504
- *
505
- * @example
506
- * ```typescript
507
- * // This will throw for direct circular reference
508
- * debug.checkCircular(computedA, computedA);
509
- *
510
- * // This will throw for indirect circular reference (dev only)
511
- * // Given: A → B → C → A
512
- * debug.checkCircular(computedC, computedA);
513
- * ```
514
- */
515
- checkCircular(i, e, t) {
516
- if (i === e)
517
- throw new I("Direct circular dependency detected");
518
- this.enabled && (j++, Y(i, e, j));
519
- },
520
- /**
521
- * Attaches debug metadata to a reactive object.
522
- *
523
- * @param obj - The object to attach metadata to
524
- * @param type - The type of reactive object ('atom' | 'computed' | 'effect')
525
- * @param id - The unique identifier for this object
526
- *
527
- * @remarks
528
- * Only attaches metadata when debug mode is enabled.
529
- * Uses symbol keys to avoid property name collisions.
530
- *
531
- * @example
532
- * ```typescript
533
- * const atom = createAtomInternal(0);
534
- * debug.attachDebugInfo(atom, 'atom', 1);
535
- * // atom[DEBUG_NAME] === 'atom_1'
536
- * // atom[DEBUG_ID] === 1
537
- * // atom[DEBUG_TYPE] === 'atom'
538
- * ```
539
- */
540
- attachDebugInfo(i, e, t) {
541
- if (!this.enabled)
542
- return;
543
- const s = i;
544
- s[v] = `${e}_${t}`, s[W] = t, s[L] = e;
545
- },
546
- /**
547
- * Retrieves the debug display name from a reactive object.
548
- *
549
- * @param obj - The object to get the name from
550
- * @returns The debug name (e.g., 'atom_1') or undefined if not set
551
- *
552
- * @example
553
- * ```typescript
554
- * const name = debug.getDebugName(myAtom);
555
- * console.log(`Updating ${name ?? 'unknown'}`);
556
- * ```
557
- */
558
- getDebugName(i) {
559
- if (i !== null && typeof i == "object" && v in i)
560
- return i[v];
561
- },
562
- /**
563
- * Retrieves the debug type from a reactive object.
564
- *
565
- * @param obj - The object to get the type from
566
- * @returns The type ('atom' | 'computed' | 'effect') or undefined if not set
567
- *
568
- * @example
569
- * ```typescript
570
- * const type = debug.getDebugType(reactiveObj);
571
- * if (type === 'computed') {
572
- * // Handle computed-specific logic
573
- * }
574
- * ```
575
- */
576
- getDebugType(i) {
577
- if (i !== null && typeof i == "object" && L in i)
578
- return i[L];
579
- }
580
- };
581
- let Z = 1;
582
- const B = () => Z++;
583
- class x {
447
+ class v {
584
448
  constructor() {
585
449
  this.subscribers = null;
586
450
  }
587
- /**
588
- * Adds a subscriber and returns an unsubscribe function
589
- *
590
- * Performs lazy initialization on first subscriber.
591
- * Duplicate subscribers are ignored (idempotent).
592
- *
593
- * @param subscriber - Function to add as subscriber
594
- * @returns Unsubscribe function
595
- *
596
- * @example
597
- * ```ts
598
- * const unsub = manager.add((value) => console.log(value));
599
- * // Later...
600
- * unsub(); // Remove this subscriber
601
- * ```
602
- */
451
+ /** Adds subscriber and returns unsubscribe function (idempotent) */
603
452
  add(e) {
604
453
  if (this.subscribers || (this.subscribers = []), this.subscribers.indexOf(e) !== -1)
605
454
  return () => {
@@ -610,322 +459,180 @@ class x {
610
459
  t || (t = !0, this.remove(e));
611
460
  };
612
461
  }
613
- /**
614
- * Removes a subscriber using swap-and-pop optimization
615
- *
616
- * Linear search + O(1) swap-and-pop removal.
617
- * For small arrays, this is faster than hash-based approaches
618
- * due to cache locality.
619
- *
620
- * @param subscriber - Subscriber to remove
621
- * @returns True if removed, false if not found
622
- */
462
+ /** Removes subscriber using swap-and-pop */
623
463
  remove(e) {
624
464
  if (!this.subscribers)
625
465
  return !1;
626
466
  const t = this.subscribers.indexOf(e);
627
467
  if (t === -1)
628
468
  return !1;
629
- const s = this.subscribers.length - 1;
630
- return t !== s && (this.subscribers[t] = this.subscribers[s]), this.subscribers.pop(), !0;
469
+ const i = this.subscribers.length - 1;
470
+ return t !== i && (this.subscribers[t] = this.subscribers[i]), this.subscribers.pop(), !0;
631
471
  }
632
- /**
633
- * Checks if a subscriber is registered
634
- *
635
- * @param subscriber - Subscriber to check
636
- * @returns True if registered
637
- */
638
472
  has(e) {
639
473
  return this.subscribers ? this.subscribers.indexOf(e) !== -1 : !1;
640
474
  }
641
- /**
642
- * Iterates over all subscribers with a callback
643
- *
644
- * Optimized for cache-friendly sequential access.
645
- * Errors in callbacks are propagated to the caller.
646
- *
647
- * @param fn - Callback to execute for each subscriber
648
- *
649
- * @example
650
- * ```ts
651
- * manager.forEach((subscriber) => {
652
- * subscriber(newValue, oldValue);
653
- * });
654
- * ```
655
- */
656
475
  forEach(e) {
657
476
  if (this.subscribers)
658
477
  for (let t = 0; t < this.subscribers.length; t++)
659
478
  e(this.subscribers[t], t);
660
479
  }
661
- /**
662
- * Safely iterates over subscribers with error handling
663
- *
664
- * Catches and logs errors from individual callbacks to prevent
665
- * one failing subscriber from breaking the entire notification chain.
666
- *
667
- * @param fn - Callback to execute for each subscriber
668
- * @param onError - Optional error handler for each callback error
669
- */
480
+ /** Iterates with error handling to prevent one failure from breaking the chain */
670
481
  forEachSafe(e, t) {
671
482
  if (this.subscribers)
672
- for (let s = 0; s < this.subscribers.length; s++)
483
+ for (let i = 0; i < this.subscribers.length; i++)
673
484
  try {
674
- e(this.subscribers[s], s);
485
+ e(this.subscribers[i], i);
675
486
  } catch (n) {
676
487
  t ? t(n) : console.error("[SubscriberManager] Error in subscriber callback:", n);
677
488
  }
678
489
  }
679
- /**
680
- * Gets the current number of subscribers
681
- *
682
- * @returns Number of active subscribers
683
- */
684
490
  get size() {
685
491
  return this.subscribers?.length ?? 0;
686
492
  }
687
- /**
688
- * Checks if there are any subscribers
689
- *
690
- * @returns True if at least one subscriber exists
691
- */
692
493
  get hasSubscribers() {
693
- return this.size > 0;
494
+ return this.subscribers !== null && this.subscribers.length > 0;
694
495
  }
695
- /**
696
- * Clears all subscribers
697
- *
698
- * Removes all subscribers and releases memory.
699
- * Subsequent operations will re-initialize lazily.
700
- */
701
496
  clear() {
702
497
  this.subscribers = null;
703
498
  }
704
- /**
705
- * Gets a copy of all subscribers as an array
706
- *
707
- * Useful for debugging or manual iteration.
708
- * Returns empty array if no subscribers.
709
- *
710
- * @returns Array of all subscribers
711
- */
712
499
  toArray() {
713
500
  return this.subscribers ? [...this.subscribers] : [];
714
501
  }
715
502
  }
716
- class ee {
717
- /**
718
- * Creates a new AtomImpl instance.
719
- *
720
- * @param initialValue - The initial value of the atom
721
- * @param sync - Whether to notify subscribers synchronously
722
- */
503
+ class ae extends W {
723
504
  constructor(e, t) {
724
- this._isNotificationScheduled = !1, this.id = B() & D, 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);
505
+ super(), this._isNotificationScheduled = !1, this._value = e, this._functionSubscribersStore = new v(), this._objectSubscribersStore = new v(), this._sync = t, this._notifyTask = this._flushNotifications.bind(this), S.attachDebugInfo(this, "atom", this.id);
725
506
  }
726
- /**
727
- * Gets the current value and registers the atom as a dependency
728
- * in the current tracking context.
729
- *
730
- * @returns The current value
731
- *
732
- * @remarks
733
- * This getter automatically tracks dependencies when accessed within
734
- * a computed or effect context.
735
- */
507
+ get _functionSubscribers() {
508
+ return this._functionSubscribersStore;
509
+ }
510
+ get _objectSubscribers() {
511
+ return this._objectSubscribersStore;
512
+ }
513
+ /** Gets value and registers as dependency in current tracking context */
736
514
  get value() {
737
- const e = m.getCurrent();
738
- return e != null && this._track(e), this._value;
515
+ const e = N.getCurrent();
516
+ return e && this._track(e), this._value;
739
517
  }
740
- /**
741
- * Sets a new value and notifies all subscribers if the value changed.
742
- *
743
- * @param newValue - The new value to set
744
- *
745
- * @remarks
746
- * Uses Object.is for equality comparison. If the value is unchanged,
747
- * no notifications are sent. Notifications may be batched unless
748
- * sync mode is enabled.
749
- */
518
+ /** Sets value and notifies subscribers if changed (uses Object.is) */
750
519
  set value(e) {
751
520
  if (Object.is(this._value, e)) return;
752
521
  const t = this._value;
753
- this.version = this.version + 1 & D;
754
- const s = this.version;
755
- this._value = e, !(!this._functionSubscribers.hasSubscribers && !this._objectSubscribers.hasSubscribers) && this._notify(e, t, s);
522
+ this.version = this.version + 1 & A, this._value = e, !(!this._functionSubscribersStore.hasSubscribers && !this._objectSubscribersStore.hasSubscribers) && this._scheduleNotification(t);
756
523
  }
757
- /**
758
- * Tracks the current context as a dependency of this atom.
759
- *
760
- * @param current - The current tracking context (function or object)
761
- *
762
- * @remarks
763
- * Handles both function-based trackers (with optional addDependency method)
764
- * and object-based trackers (with execute or addDependency methods).
765
- */
766
524
  _track(e) {
767
- if (typeof e == "function") {
768
- const t = e;
769
- t.addDependency !== void 0 ? t.addDependency(this) : this._functionSubscribers.add(e);
770
- } else {
771
- const t = e;
772
- t.addDependency !== void 0 ? t.addDependency(this) : t.execute !== void 0 && this._objectSubscribers.add(t);
525
+ if (Z(e)) {
526
+ e.addDependency(this);
527
+ return;
528
+ }
529
+ if (ee(e)) {
530
+ this._functionSubscribersStore.add(e);
531
+ return;
773
532
  }
533
+ te(e) && this._objectSubscribersStore.add(e);
774
534
  }
775
- /**
776
- * Notifies all subscribers of a value change.
777
- *
778
- * @param newValue - The new value
779
- * @param oldValue - The previous value
780
- * @param currentVersion - The version at the time of change
781
- *
782
- * @remarks
783
- * Notifications are skipped if the version has changed (stale update).
784
- * Errors from individual subscribers are caught and logged without
785
- * interrupting other subscribers.
786
- */
787
- /**
788
- * Schedules a notification.
789
- * Uses coalescing: if a notification is already scheduled, we update the state
790
- * but don't schedule a new task. The pending task will see the latest value.
791
- */
792
- _notify(e, t, s) {
793
- this._isNotificationScheduled || (this._pendingOldValue = t, this._isNotificationScheduled = !0), this._sync && !N.isBatching ? this._flushNotifications() : N.schedule(this._notifyTask);
535
+ _scheduleNotification(e) {
536
+ this._isNotificationScheduled || (this._pendingOldValue = e, this._isNotificationScheduled = !0), this._sync && !U.isBatching ? this._flushNotifications() : U.schedule(this._notifyTask);
794
537
  }
795
- /**
796
- * Executes the pending notifications.
797
- * Bound to 'this' in constructor to avoid closure allocation.
798
- */
799
538
  _flushNotifications() {
800
539
  if (!this._isNotificationScheduled) return;
801
540
  const e = this._pendingOldValue, t = this._value;
802
- this._pendingOldValue = void 0, this._isNotificationScheduled = !1, this._functionSubscribers.forEachSafe(
803
- (s) => s(t, e),
804
- (s) => console.error(new d(a.ATOM_INDIVIDUAL_SUBSCRIBER_FAILED, s))
805
- ), this._objectSubscribers.forEachSafe(
806
- (s) => s.execute(),
807
- (s) => console.error(new d(a.ATOM_INDIVIDUAL_SUBSCRIBER_FAILED, s))
808
- );
541
+ this._pendingOldValue = void 0, this._isNotificationScheduled = !1, this._notifySubscribers(t, e);
809
542
  }
810
- /**
811
- * Subscribes a listener function or Subscriber object to value changes.
812
- *
813
- * @param listener - Function or Subscriber object to call when the value changes
814
- * @returns An unsubscribe function
815
- * @throws {AtomError} If listener is not a function or Subscriber
816
- *
817
- * @example
818
- * ```ts
819
- * const unsub = myAtom.subscribe((newVal, oldVal) => {
820
- * console.log(`Changed from ${oldVal} to ${newVal}`);
821
- * });
822
- * // Later: unsub();
823
- * ```
824
- */
825
- subscribe(e) {
826
- if (typeof e == "object" && e !== null && "execute" in e)
827
- return this._objectSubscribers.add(e);
828
- if (typeof e != "function")
829
- throw new d(a.ATOM_SUBSCRIBER_MUST_BE_FUNCTION);
830
- return this._functionSubscribers.add(e);
831
- }
832
- /**
833
- * Gets the current value without registering as a dependency.
834
- *
835
- * @returns The current value
836
- *
837
- * @remarks
838
- * Use this method when you need to read the value without
839
- * creating a reactive dependency (e.g., in event handlers).
840
- */
543
+ /** Gets value without registering as dependency */
841
544
  peek() {
842
545
  return this._value;
843
546
  }
844
- /**
845
- * Disposes the atom, clearing all subscribers and releasing resources.
846
- *
847
- * @remarks
848
- * After disposal, the atom should not be used. The value is set to
849
- * undefined to help with garbage collection.
850
- */
851
547
  dispose() {
852
- this._functionSubscribers.clear(), this._objectSubscribers.clear(), this._value = void 0;
853
- }
854
- /**
855
- * Gets the total number of active subscribers.
856
- *
857
- * @returns The count of function and object subscribers combined
858
- */
859
- subscriberCount() {
860
- return this._functionSubscribers.size + this._objectSubscribers.size;
548
+ this._functionSubscribersStore.clear(), this._objectSubscribersStore.clear(), this._value = void 0;
861
549
  }
862
550
  }
863
- function ce(i, e = {}) {
864
- return new ee(i, e.sync ?? !1);
551
+ function pe(s, e = {}) {
552
+ return new ae(s, e.sync ?? !1);
865
553
  }
866
- const p = process.env.NODE_ENV !== "production", f = Object.freeze([]), E = Object.freeze([]);
867
- class $ {
554
+ const a = Object.freeze([]), b = Object.freeze([]), f = Object.freeze([]);
555
+ class j {
868
556
  constructor() {
869
- this.pool = [], this.maxPoolSize = 50, this.maxReusableCapacity = 256, this.stats = p ? {
557
+ this.pool = [], this.maxPoolSize = 50, this.maxReusableCapacity = 256, this.stats = d ? {
870
558
  acquired: 0,
871
559
  released: 0,
872
560
  rejected: { frozen: 0, tooLarge: 0, poolFull: 0 }
873
561
  } : null;
874
562
  }
875
563
  acquire() {
876
- return p && this.stats && this.stats.acquired++, this.pool.pop() ?? [];
564
+ return d && this.stats && this.stats.acquired++, this.pool.pop() ?? [];
877
565
  }
878
566
  release(e, t) {
879
567
  if (!(t && e === t)) {
880
568
  if (Object.isFrozen(e)) {
881
- p && this.stats && this.stats.rejected.frozen++;
569
+ d && this.stats && this.stats.rejected.frozen++;
882
570
  return;
883
571
  }
884
572
  if (e.length > this.maxReusableCapacity) {
885
- p && this.stats && this.stats.rejected.tooLarge++;
573
+ d && this.stats && this.stats.rejected.tooLarge++;
886
574
  return;
887
575
  }
888
576
  if (this.pool.length >= this.maxPoolSize) {
889
- p && this.stats && this.stats.rejected.poolFull++;
577
+ d && this.stats && this.stats.rejected.poolFull++;
890
578
  return;
891
579
  }
892
- e.length = 0, this.pool.push(e), p && this.stats && this.stats.released++;
580
+ e.length = 0, this.pool.push(e), d && this.stats && this.stats.released++;
893
581
  }
894
582
  }
895
583
  getStats() {
896
- if (!p || !this.stats) return null;
897
- const { acquired: e, released: t, rejected: s } = this.stats, n = s.frozen + s.tooLarge + s.poolFull;
584
+ if (!d || !this.stats) return null;
585
+ const { acquired: e, released: t, rejected: i } = this.stats, n = i.frozen + i.tooLarge + i.poolFull;
898
586
  return {
899
587
  acquired: e,
900
588
  released: t,
901
- rejected: s,
589
+ rejected: i,
902
590
  leaked: e - t - n,
903
591
  poolSize: this.pool.length
904
592
  };
905
593
  }
906
594
  reset() {
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 });
595
+ this.pool.length = 0, d && this.stats && (this.stats.acquired = 0, this.stats.released = 0, this.stats.rejected = { frozen: 0, tooLarge: 0, poolFull: 0 });
908
596
  }
909
597
  }
910
- const S = new $(), y = new $();
911
- class Q {
598
+ const I = new j(), m = new j(), p = new j();
599
+ function q(s, e, t, i) {
600
+ if (e !== a && t !== b)
601
+ for (let r = 0; r < e.length; r++) {
602
+ const c = e[r];
603
+ c && (c._tempUnsub = t[r]);
604
+ }
605
+ const n = m.acquire();
606
+ n.length = s.length;
607
+ for (let r = 0; r < s.length; r++) {
608
+ const c = s[r];
609
+ c && (c._tempUnsub ? (n[r] = c._tempUnsub, c._tempUnsub = void 0) : (S.checkCircular(c, i), n[r] = c.subscribe(i)));
610
+ }
611
+ if (e !== a)
612
+ for (let r = 0; r < e.length; r++) {
613
+ const c = e[r];
614
+ c?._tempUnsub && (c._tempUnsub(), c._tempUnsub = void 0);
615
+ }
616
+ return t !== b && m.release(t), n;
617
+ }
618
+ class se extends W {
912
619
  constructor(e, t = {}) {
913
620
  if (typeof e != "function")
914
- throw new I(a.COMPUTED_MUST_BE_FUNCTION);
915
- if (this.id = B() & D, 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 : V, this._hasDefaultValue = this._defaultValue !== V, 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._notifyJob = () => {
916
- this._functionSubscribers.forEachSafe(
917
- (s) => s(),
918
- (s) => console.error(s)
919
- ), this._objectSubscribers.forEachSafe(
920
- (s) => s.execute(),
921
- (s) => console.error(s)
621
+ throw new T(l.COMPUTED_MUST_BE_FUNCTION);
622
+ if (super(), this._value = void 0, this.flags = o.DIRTY | o.IDLE, this._error = null, this._promiseId = 0, this._equal = t.equal ?? Object.is, this._fn = e, this._defaultValue = "defaultValue" in t ? t.defaultValue : X, this._hasDefaultValue = this._defaultValue !== X, this._onError = t.onError ?? null, this.MAX_PROMISE_ID = Number.MAX_SAFE_INTEGER - 1, this._functionSubscribersStore = new v(), this._objectSubscribersStore = new v(), this._dependencies = a, this._dependencyVersions = f, this._unsubscribes = b, this._notifyJob = () => {
623
+ this._functionSubscribersStore.forEachSafe(
624
+ (i) => i(),
625
+ (i) => console.error(i)
626
+ ), this._objectSubscribersStore.forEachSafe(
627
+ (i) => i.execute(),
628
+ (i) => console.error(i)
922
629
  );
923
630
  }, this._trackable = Object.assign(() => this._markDirty(), {
924
- addDependency: (s) => {
631
+ addDependency: (i) => {
925
632
  }
926
- }), b.attachDebugInfo(this, "computed", this.id), b.enabled) {
927
- const s = this;
928
- s.subscriberCount = () => this._functionSubscribers.size + this._objectSubscribers.size, s.isDirty = () => this._isDirty(), s.dependencies = this._dependencies, s.stateFlags = this._getFlagsAsString();
633
+ }), S.attachDebugInfo(this, "computed", this.id), S.enabled) {
634
+ const i = this;
635
+ i.subscriberCount = () => this._functionSubscribersStore.size + this._objectSubscribersStore.size, i.isDirty = () => this._isDirty(), i.dependencies = this._dependencies, i.stateFlags = this._getFlagsAsString();
929
636
  }
930
637
  if (t.lazy === !1)
931
638
  try {
@@ -933,19 +640,15 @@ class Q {
933
640
  } catch {
934
641
  }
935
642
  }
936
- // === PUBLIC API ===
937
- get value() {
938
- if ((this._stateFlags & (h.RESOLVED | h.DIRTY)) === h.RESOLVED)
939
- return this._registerTracking(), this._value;
940
- const t = this._computeValue();
941
- return this._registerTracking(), t;
643
+ get _functionSubscribers() {
644
+ return this._functionSubscribersStore;
942
645
  }
943
- subscribe(e) {
944
- if (typeof e == "object" && e !== null && "execute" in e)
945
- return this._objectSubscribers.add(e);
946
- if (typeof e != "function")
947
- throw new I(a.COMPUTED_SUBSCRIBER_MUST_BE_FUNCTION);
948
- return this._functionSubscribers.add(e);
646
+ get _objectSubscribers() {
647
+ return this._objectSubscribersStore;
648
+ }
649
+ get value() {
650
+ const e = this._computeValue();
651
+ return this._registerTracking(), e;
949
652
  }
950
653
  peek() {
951
654
  return this._value;
@@ -966,508 +669,362 @@ class Q {
966
669
  return this._isResolved();
967
670
  }
968
671
  invalidate() {
969
- this._markDirty();
672
+ this._markDirty(), this._dependencyVersions !== f && (p.release(this._dependencyVersions), this._dependencyVersions = f);
970
673
  }
971
674
  dispose() {
972
- if (this._unsubscribes !== E) {
675
+ if (this._unsubscribes !== b) {
973
676
  for (let e = 0; e < this._unsubscribes.length; e++) {
974
677
  const t = this._unsubscribes[e];
975
678
  t && t();
976
679
  }
977
- y.release(this._unsubscribes), this._unsubscribes = E;
680
+ m.release(this._unsubscribes), this._unsubscribes = b;
978
681
  }
979
- this._dependencies !== f && (S.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;
682
+ this._dependencies !== a && (I.release(this._dependencies), this._dependencies = a), this._dependencyVersions !== f && (p.release(this._dependencyVersions), this._dependencyVersions = f), this._functionSubscribersStore.clear(), this._objectSubscribersStore.clear(), this.flags = o.DIRTY | o.IDLE, this._error = null, this._value = void 0, this._promiseId = (this._promiseId + 1) % this.MAX_PROMISE_ID;
980
683
  }
981
- // === PRIVATE: State Flag Operations (inlined for performance) ===
684
+ // State flag operations
982
685
  _isDirty() {
983
- return (this._stateFlags & h.DIRTY) !== 0;
686
+ return (this.flags & o.DIRTY) !== 0;
984
687
  }
985
688
  _setDirty() {
986
- this._stateFlags |= h.DIRTY;
689
+ this.flags |= o.DIRTY;
987
690
  }
988
691
  _clearDirty() {
989
- this._stateFlags &= -2;
692
+ this.flags &= -2;
990
693
  }
991
694
  _isIdle() {
992
- return (this._stateFlags & h.IDLE) !== 0;
695
+ return (this.flags & o.IDLE) !== 0;
993
696
  }
994
697
  _setIdle() {
995
- this._stateFlags |= h.IDLE, this._stateFlags &= -29;
698
+ this.flags |= o.IDLE, this.flags &= -29;
996
699
  }
997
700
  _isPending() {
998
- return (this._stateFlags & h.PENDING) !== 0;
701
+ return (this.flags & o.PENDING) !== 0;
999
702
  }
1000
703
  _setPending() {
1001
- this._stateFlags |= h.PENDING, this._stateFlags &= -27;
704
+ this.flags |= o.PENDING, this.flags &= -27;
1002
705
  }
1003
706
  _isResolved() {
1004
- return (this._stateFlags & h.RESOLVED) !== 0;
707
+ return (this.flags & o.RESOLVED) !== 0;
1005
708
  }
1006
709
  _setResolved() {
1007
- this._stateFlags |= h.RESOLVED, this._stateFlags &= -87;
710
+ this.flags |= o.RESOLVED, this.flags &= -87;
1008
711
  }
1009
712
  _isRejected() {
1010
- return (this._stateFlags & h.REJECTED) !== 0;
713
+ return (this.flags & o.REJECTED) !== 0;
1011
714
  }
1012
715
  _setRejected() {
1013
- this._stateFlags |= h.REJECTED | h.HAS_ERROR, this._stateFlags &= -15;
716
+ this.flags |= o.REJECTED | o.HAS_ERROR, this.flags &= -15;
1014
717
  }
1015
718
  _isRecomputing() {
1016
- return (this._stateFlags & h.RECOMPUTING) !== 0;
719
+ return (this.flags & o.RECOMPUTING) !== 0;
1017
720
  }
1018
721
  _setRecomputing(e) {
1019
- const t = h.RECOMPUTING;
1020
- this._stateFlags = this._stateFlags & ~t | -Number(e) & t;
722
+ const t = o.RECOMPUTING;
723
+ this.flags = this.flags & ~t | -Number(e) & t;
1021
724
  }
1022
725
  _getAsyncState() {
1023
- return this._isPending() ? T.PENDING : this._isResolved() ? T.RESOLVED : this._isRejected() ? T.REJECTED : T.IDLE;
726
+ return this._isResolved() ? F.RESOLVED : this._isPending() ? F.PENDING : this._isRejected() ? F.REJECTED : F.IDLE;
1024
727
  }
1025
728
  _getFlagsAsString() {
1026
729
  const e = [];
1027
730
  return this._isDirty() && e.push("DIRTY"), this._isIdle() && e.push("IDLE"), this._isPending() && e.push("PENDING"), this._isResolved() && e.push("RESOLVED"), this._isRejected() && e.push("REJECTED"), this._isRecomputing() && e.push("RECOMPUTING"), e.join(" | ");
1028
731
  }
1029
- // === PRIVATE: Core Computation Logic ===
1030
732
  _computeValue() {
1031
- return this._isRecomputing() ? this._value : this._isPending() ? this._handlePending() : this._isRejected() ? this._handleRejected() : (this._isDirty() || this._isIdle()) && (this._recompute(), this._isPending()) ? this._handlePending() : this._value;
733
+ return this._isRecomputing() ? this._value : ((this._isDirty() || this._isIdle()) && this._recompute(), this._isPending() ? this._handlePending() : this._isRejected() ? this._handleRejected() : this._value);
1032
734
  }
1033
735
  _recompute() {
1034
- if (!this._isDirty() && this._isResolved())
1035
- return;
736
+ if (this._isRecomputing()) return;
1036
737
  this._setRecomputing(!0);
1037
- const e = this._dependencies, t = S.acquire(), s = G();
1038
- let n = 0;
1039
- const r = (_) => {
1040
- _._lastSeenEpoch !== s && (_._lastSeenEpoch = s, n < t.length ? t[n] = _ : t.push(_), n++);
1041
- }, c = this._trackable.addDependency;
1042
- this._trackable.addDependency = r;
1043
- let o = !1;
738
+ const e = this._dependencies, t = this._dependencyVersions, i = I.acquire(), n = p.acquire(), r = K();
739
+ let c = 0;
740
+ const O = (h) => {
741
+ h._lastSeenEpoch !== r && (h._lastSeenEpoch = r, c < i.length ? (i[c] = h, n[c] = h.version) : (i.push(h), n.push(h.version)), c++);
742
+ }, D = this._trackable.addDependency;
743
+ this._trackable.addDependency = O;
744
+ let R = !1;
1044
745
  try {
1045
- const _ = m.run(this._trackable, this._fn);
1046
- if (t.length = n, X(_)) {
1047
- this._syncDependencies(e, t, this._unsubscribes, s), this._dependencies = t, o = !0, this._handleAsyncComputation(_), this._setRecomputing(!1);
746
+ const h = N.run(this._trackable, this._fn);
747
+ if (i.length = c, n.length = c, Y(h)) {
748
+ this._unsubscribes = q(i, e, this._unsubscribes, this), this._dependencies = i, this._dependencyVersions = n, R = !0, this._handleAsyncComputation(h), this._setRecomputing(!1);
1048
749
  return;
1049
750
  }
1050
- this._syncDependencies(e, t, this._unsubscribes, s), this._dependencies = t, o = !0, this._handleSyncResult(_);
1051
- } catch (_) {
1052
- t.length = n, this._syncDependencies(e, t, this._unsubscribes, s), this._dependencies = t, this._handleComputationError(_);
751
+ this._unsubscribes = q(i, e, this._unsubscribes, this), this._dependencies = i, this._dependencyVersions = n, R = !0, this._handleSyncResult(h);
752
+ } catch (h) {
753
+ i.length = c, n.length = c, this._unsubscribes = q(i, e, this._unsubscribes, this), this._dependencies = i, this._dependencyVersions = n, R = !0, this._handleComputationError(h);
1053
754
  } finally {
1054
- this._trackable.addDependency = c, o ? e !== f && S.release(e) : S.release(t);
755
+ this._trackable.addDependency = D, R ? (e !== a && I.release(e), t !== f && p.release(t)) : (I.release(i), p.release(n));
1055
756
  }
1056
757
  }
1057
- /**
1058
- * Synchronizes subscriptions based on dependency changes.
1059
- * O(N) Diff using Epoch.
1060
- */
1061
- /**
1062
- * Synchronizes subscriptions based on dependency changes using O(N) strategy.
1063
- * Maps unsubs 1:1 with dependencies array.
1064
- */
1065
- _syncDependencies(e, t, s, n) {
1066
- if (e !== f && s !== E)
1067
- for (let c = 0; c < e.length; c++) {
1068
- const o = e[c];
1069
- o && (o._tempUnsub = s[c]);
1070
- }
1071
- const r = y.acquire();
1072
- r.length = t.length;
1073
- for (let c = 0; c < t.length; c++) {
1074
- const o = t[c];
1075
- o && (o._tempUnsub ? (r[c] = o._tempUnsub, o._tempUnsub = void 0) : (b.checkCircular(o, this), r[c] = o.subscribe(this)));
1076
- }
1077
- if (e !== f)
1078
- for (let c = 0; c < e.length; c++) {
1079
- const o = e[c];
1080
- o?._tempUnsub && (o._tempUnsub(), o._tempUnsub = void 0);
1081
- }
1082
- s !== E && y.release(s), this._unsubscribes = r;
1083
- }
1084
758
  _handleSyncResult(e) {
1085
- (!this._isResolved() || !this._equal(this._value, e)) && (this.version = this.version + 1 & D), this._value = e, this._clearDirty(), this._setResolved(), this._error = null, this._setRecomputing(!1);
759
+ (!this._isResolved() || !this._equal(this._value, e)) && (this.version = this.version + 1 & A), this._value = e, this._clearDirty(), this._setResolved(), this._error = null, this._setRecomputing(!1);
1086
760
  }
1087
761
  _handleAsyncComputation(e) {
1088
- this._setPending(), this._promiseId = this._promiseId >= this.MAX_PROMISE_ID ? 1 : this._promiseId + 1;
762
+ this._setPending(), this._clearDirty(), this._promiseId = this._promiseId >= this.MAX_PROMISE_ID ? 1 : this._promiseId + 1;
1089
763
  const t = this._promiseId;
1090
- e.then((s) => {
1091
- t === this._promiseId && this._handleAsyncResolution(s);
1092
- }).catch((s) => {
1093
- t === this._promiseId && this._handleAsyncRejection(s);
764
+ e.then((i) => {
765
+ t === this._promiseId && this._handleAsyncResolution(i);
766
+ }).catch((i) => {
767
+ t === this._promiseId && this._handleAsyncRejection(i);
1094
768
  });
1095
769
  }
1096
770
  _handleAsyncResolution(e) {
1097
- (!this._isResolved() || !this._equal(this._value, e)) && (this.version = this.version + 1 & D), this._value = e, this._clearDirty(), this._setResolved(), this._error = null, this._setRecomputing(!1);
771
+ (!this._isResolved() || !this._equal(this._value, e)) && (this.version = this.version + 1 & A), this._value = e, this._clearDirty(), this._setResolved(), this._error = null, this._setRecomputing(!1);
1098
772
  }
1099
773
  _handleAsyncRejection(e) {
1100
- const t = R(e, I, a.COMPUTED_ASYNC_COMPUTATION_FAILED);
1101
- if (this._error = t, this._setRejected(), this._clearDirty(), this._setRecomputing(!1), this._onError && typeof this._onError == "function")
774
+ const t = C(e, T, l.COMPUTED_ASYNC_COMPUTATION_FAILED);
775
+ if (this._error = t, this._setRejected(), this._clearDirty(), this._setRecomputing(!1), this._onError)
1102
776
  try {
1103
777
  this._onError(t);
1104
- } catch (s) {
1105
- console.error(a.CALLBACK_ERROR_IN_ERROR_HANDLER, s);
778
+ } catch (i) {
779
+ console.error(l.CALLBACK_ERROR_IN_ERROR_HANDLER, i);
1106
780
  }
1107
- this._notifySubscribers();
781
+ this._notifySubscribers(void 0, void 0);
1108
782
  }
1109
783
  _handleComputationError(e) {
1110
- const t = R(e, I, a.COMPUTED_COMPUTATION_FAILED);
1111
- if (this._error = t, this._setRejected(), this._clearDirty(), this._setRecomputing(!1), this._onError && typeof this._onError == "function")
784
+ const t = C(e, T, l.COMPUTED_COMPUTATION_FAILED);
785
+ if (this._error = t, this._setRejected(), this._clearDirty(), this._setRecomputing(!1), this._onError)
1112
786
  try {
1113
787
  this._onError(t);
1114
- } catch (s) {
1115
- console.error(a.CALLBACK_ERROR_IN_ERROR_HANDLER, s);
788
+ } catch (i) {
789
+ console.error(l.CALLBACK_ERROR_IN_ERROR_HANDLER, i);
1116
790
  }
1117
791
  throw t;
1118
792
  }
1119
793
  _handlePending() {
1120
794
  if (this._hasDefaultValue)
1121
795
  return this._defaultValue;
1122
- throw new I(a.COMPUTED_ASYNC_PENDING_NO_DEFAULT);
796
+ throw new T(l.COMPUTED_ASYNC_PENDING_NO_DEFAULT);
1123
797
  }
1124
798
  _handleRejected() {
1125
799
  if (this._error?.recoverable && this._hasDefaultValue)
1126
800
  return this._defaultValue;
1127
801
  throw this._error;
1128
802
  }
1129
- // === PRIVATE: Dependency Management ===
1130
- // (Replaced by _syncDependencies and inline pool logic)
1131
- // === PRIVATE: Subscriber Management ===
1132
- /**
1133
- * Subscriber interface implementation (Zero-Allocation pattern)
1134
- * Called by dependencies when they change - delegates to _markDirty
1135
- */
803
+ /** Subscriber interface - marks dirty on dependency change */
1136
804
  execute() {
1137
805
  this._markDirty();
1138
806
  }
1139
- /**
1140
- * Push-State, Pull-Value pattern:
1141
- * Marks this computed as dirty and propagates to all subscribers.
1142
- * - Object subscribers (Computed atoms): will mark themselves dirty
1143
- * - Function subscribers (Effects): will schedule their execution
1144
- * Actual recomputation happens lazily when .value is accessed (Pull).
1145
- */
1146
807
  _markDirty() {
1147
- this._isRecomputing() || this._isDirty() || (this._setDirty(), this._setIdle(), this._notifyJob());
1148
- }
1149
- /**
1150
- * Notifies function subscribers (Effects) of state changes.
1151
- * Currently only called from _handleAsyncRejection to notify Effects of errors.
1152
- * In normal operation, Effects are notified via _markDirty during dirty propagation.
1153
- */
1154
- _notifySubscribers() {
1155
- this._functionSubscribers.hasSubscribers && this._functionSubscribers.forEachSafe(
1156
- (e) => e(),
1157
- (e) => console.error(e)
1158
- );
808
+ this._isRecomputing() || this._isDirty() || (this._setDirty(), this._notifyJob());
1159
809
  }
1160
810
  _registerTracking() {
1161
- const e = m.getCurrent();
1162
- if (e)
1163
- if (typeof e == "object" && e !== null && e.addDependency)
811
+ const e = N.getCurrent();
812
+ if (e) {
813
+ if (Z(e)) {
1164
814
  e.addDependency(this);
1165
- else if (typeof e == "function") {
1166
- const t = e;
1167
- t.addDependency ? t.addDependency(this) : this._functionSubscribers.add(e);
1168
- } else e.execute && this._objectSubscribers.add(e);
815
+ return;
816
+ }
817
+ if (ee(e)) {
818
+ this._functionSubscribersStore.add(e);
819
+ return;
820
+ }
821
+ te(e) && this._objectSubscribersStore.add(e);
822
+ }
1169
823
  }
1170
824
  }
1171
- Object.freeze(Q.prototype);
1172
- function ue(i, e = {}) {
1173
- return new Q(i, e);
825
+ Object.freeze(se.prototype);
826
+ function Se(s, e = {}) {
827
+ return new se(s, e);
1174
828
  }
1175
- class te {
829
+ class fe extends J {
1176
830
  constructor(e, t = {}) {
1177
- this.run = () => {
831
+ super(), this.run = () => {
1178
832
  if (this.isDisposed)
1179
- throw new g(a.EFFECT_MUST_BE_FUNCTION);
1180
- this.execute();
833
+ throw new g(l.EFFECT_MUST_BE_FUNCTION);
834
+ this._dependencyVersions !== f && (p.release(this._dependencyVersions), this._dependencyVersions = f), this.execute();
1181
835
  }, this.dispose = () => {
1182
836
  if (!this.isDisposed) {
1183
- if (this._setDisposed(), this._safeCleanup(), this._unsubscribes !== E) {
1184
- for (let s = 0; s < this._unsubscribes.length; s++) {
1185
- const n = this._unsubscribes[s];
837
+ if (this._setDisposed(), this._safeCleanup(), this._unsubscribes !== b) {
838
+ for (let i = 0; i < this._unsubscribes.length; i++) {
839
+ const n = this._unsubscribes[i];
1186
840
  n && n();
1187
841
  }
1188
- y.release(this._unsubscribes), this._unsubscribes = E;
842
+ m.release(this._unsubscribes), this._unsubscribes = b;
1189
843
  }
1190
- this._dependencies !== f && (S.release(this._dependencies), this._dependencies = f);
844
+ this._dependencies !== a && (I.release(this._dependencies), this._dependencies = a), this._dependencyVersions !== f && (p.release(this._dependencyVersions), this._dependencyVersions = f);
1191
845
  }
1192
- }, this.addDependency = (s) => {
1193
- if (this.isExecuting && this._nextDeps && this._nextUnsubs) {
1194
- const n = s, r = this._currentEpoch;
1195
- if (n._lastSeenEpoch === r) return;
1196
- n._lastSeenEpoch = r, this._nextDeps.push(n), n._tempUnsub ? (this._nextUnsubs.push(n._tempUnsub), n._tempUnsub = void 0) : this._subscribeTo(n);
846
+ }, this.addDependency = (i) => {
847
+ if (this.isExecuting && this._nextDeps && this._nextUnsubs && this._nextVersions) {
848
+ const n = this._currentEpoch;
849
+ if (i._lastSeenEpoch === n) return;
850
+ i._lastSeenEpoch = n, this._nextDeps.push(i), this._nextVersions.push(i.version), i._tempUnsub ? (this._nextUnsubs.push(i._tempUnsub), i._tempUnsub = void 0) : this._subscribeTo(i);
1197
851
  }
1198
852
  }, this.execute = () => {
1199
- if (this.isDisposed || this.isExecuting) return;
853
+ if (this.isDisposed || this.isExecuting || !this._shouldExecute()) return;
1200
854
  this._checkInfiniteLoop(), this._setExecuting(!0), this._safeCleanup();
1201
- const s = this._dependencies, n = this._unsubscribes, r = S.acquire(), c = y.acquire(), o = G();
1202
- if (s !== f && n !== E)
1203
- for (let u = 0; u < s.length; u++) {
1204
- const l = s[u];
1205
- l && (l._tempUnsub = n[u]);
855
+ const i = this._dependencies, n = this._dependencyVersions, r = this._unsubscribes, c = I.acquire(), O = p.acquire(), D = m.acquire(), R = K();
856
+ if (i !== a && r !== b)
857
+ for (let u = 0; u < i.length; u++) {
858
+ const _ = i[u];
859
+ _ && (_._tempUnsub = r[u]);
1206
860
  }
1207
- this._nextDeps = r, this._nextUnsubs = c, this._currentEpoch = o;
1208
- let _ = !1;
861
+ this._nextDeps = c, this._nextVersions = O, this._nextUnsubs = D, this._currentEpoch = R;
862
+ let h = !1;
1209
863
  try {
1210
- const u = m.run(this, this._fn);
1211
- this._dependencies = r, this._unsubscribes = c, _ = !0, this._checkLoopWarnings(), X(u) ? u.then((l) => {
1212
- !this.isDisposed && typeof l == "function" && (this._cleanup = l);
1213
- }).catch((l) => {
1214
- console.error(R(l, g, a.EFFECT_EXECUTION_FAILED));
864
+ const u = N.run(this, this._fn);
865
+ this._dependencies = c, this._dependencyVersions = O, this._unsubscribes = D, h = !0, this._checkLoopWarnings(), Y(u) ? u.then((_) => {
866
+ !this.isDisposed && typeof _ == "function" && (this._cleanup = _);
867
+ }).catch((_) => {
868
+ console.error(C(_, g, l.EFFECT_EXECUTION_FAILED));
1215
869
  }) : this._cleanup = typeof u == "function" ? u : null;
1216
870
  } catch (u) {
1217
- _ = !0, console.error(R(u, g, a.EFFECT_EXECUTION_FAILED)), this._cleanup = null;
871
+ h = !0, console.error(C(u, g, l.EFFECT_EXECUTION_FAILED)), this._cleanup = null;
1218
872
  } finally {
1219
- if (this._setExecuting(!1), this._nextDeps = null, this._nextUnsubs = null, _) {
1220
- if (s !== f) {
1221
- for (let u = 0; u < s.length; u++) {
1222
- const l = s[u];
1223
- l?._tempUnsub && (l._tempUnsub(), l._tempUnsub = void 0);
873
+ if (this._setExecuting(!1), this._nextDeps = null, this._nextVersions = null, this._nextUnsubs = null, h) {
874
+ if (i !== a) {
875
+ for (let u = 0; u < i.length; u++) {
876
+ const _ = i[u];
877
+ _?._tempUnsub && (_._tempUnsub(), _._tempUnsub = void 0);
1224
878
  }
1225
- S.release(s);
879
+ I.release(i);
1226
880
  }
1227
- n !== E && y.release(n);
881
+ r !== b && m.release(r), n !== f && p.release(n);
1228
882
  } else {
1229
- S.release(r);
1230
- for (let u = 0; u < c.length; u++)
1231
- c[u]?.();
1232
- if (y.release(c), s !== f)
1233
- for (let u = 0; u < s.length; u++) {
1234
- const l = s[u];
1235
- l && (l._tempUnsub = void 0);
883
+ I.release(c), p.release(O);
884
+ for (let u = 0; u < D.length; u++)
885
+ D[u]?.();
886
+ if (m.release(D), i !== a)
887
+ for (let u = 0; u < i.length; u++) {
888
+ const _ = i[u];
889
+ _ && (_._tempUnsub = void 0);
1236
890
  }
1237
891
  }
1238
892
  }
1239
- }, this._id = B() & D, this._flags = 0, this._currentEpoch = -1, this._fn = e, this._sync = t.sync ?? !1, this._maxExecutions = t.maxExecutionsPerSecond ?? A.MAX_EXECUTIONS_PER_SECOND, this._maxExecutionsPerFlush = t.maxExecutionsPerFlush ?? A.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 = M ? [] : null, this._executionCount = 0, b.attachDebugInfo(this, "effect", this._id);
893
+ }, this._currentEpoch = -1, this._lastFlushEpoch = -1, this._executionsInEpoch = 0, this._fn = e, this._sync = t.sync ?? !1, this._maxExecutions = t.maxExecutionsPerSecond ?? y.MAX_EXECUTIONS_PER_SECOND, this._maxExecutionsPerFlush = t.maxExecutionsPerFlush ?? y.MAX_EXECUTIONS_PER_EFFECT, this._trackModifications = t.trackModifications ?? !1, this._cleanup = null, this._dependencies = a, this._dependencyVersions = f, this._unsubscribes = b, this._nextDeps = null, this._nextVersions = null, this._nextUnsubs = null, this._history = d ? [] : null, this._executionCount = 0, S.attachDebugInfo(this, "effect", this.id);
1240
894
  }
1241
- /**
1242
- * Synchronizes subscriptions by unsubscribing from removed dependencies.
1243
- * Uses epoch-based O(N) diff to identify stale dependencies.
1244
- *
1245
- * @param prevDeps - Previous dependency array
1246
- * @param epoch - Current execution epoch for staleness detection
1247
- */
1248
- // _syncDependencies removed (inline logic in execute)
1249
895
  _subscribeTo(e) {
1250
896
  try {
1251
897
  const t = e.subscribe(() => {
1252
- this._trackModifications && this.isExecuting && (e._modifiedAtEpoch = this._currentEpoch), this._sync ? this.execute() : N.schedule(this.execute);
898
+ this._trackModifications && this.isExecuting && (e._modifiedAtEpoch = this._currentEpoch), this._sync ? this.execute() : U.schedule(this.execute);
1253
899
  });
1254
900
  this._nextUnsubs && this._nextUnsubs.push(t);
1255
901
  } catch (t) {
1256
- console.error(R(t, g, a.EFFECT_EXECUTION_FAILED)), this._nextUnsubs && this._nextUnsubs.push(() => {
902
+ console.error(C(t, g, l.EFFECT_EXECUTION_FAILED)), this._nextUnsubs && this._nextUnsubs.push(() => {
1257
903
  });
1258
904
  }
1259
905
  }
1260
- /**
1261
- * Indicates whether this effect has been disposed.
1262
- *
1263
- * @returns `true` if the effect has been disposed, `false` otherwise
1264
- *
1265
- * @remarks
1266
- * A disposed effect will not execute and cannot be reactivated.
1267
- * Use this property to check if the effect is still active before
1268
- * performing operations that depend on it.
1269
- *
1270
- * @example
1271
- * ```typescript
1272
- * const fx = effect(() => console.log(counter.value));
1273
- * console.log(fx.isDisposed); // false
1274
- * fx.dispose();
1275
- * console.log(fx.isDisposed); // true
1276
- * ```
1277
- */
1278
906
  get isDisposed() {
1279
- return (this._flags & F.DISPOSED) !== 0;
907
+ return (this.flags & P.DISPOSED) !== 0;
1280
908
  }
1281
- /**
1282
- * Returns the total number of times this effect has been executed.
1283
- *
1284
- * @returns The cumulative execution count since the effect was created
1285
- *
1286
- * @remarks
1287
- * This counter is useful for debugging, testing, and monitoring
1288
- * effect behavior. It increments on every execution, regardless
1289
- * of whether the execution succeeds or fails.
1290
- *
1291
- * @example
1292
- * ```typescript
1293
- * const fx = effect(() => console.log(counter.value));
1294
- * console.log(fx.executionCount); // 1 (initial execution)
1295
- * counter.value = 10;
1296
- * console.log(fx.executionCount); // 2
1297
- * ```
1298
- */
1299
909
  get executionCount() {
1300
910
  return this._executionCount;
1301
911
  }
1302
- /**
1303
- * Indicates whether this effect is currently executing.
1304
- *
1305
- * @returns `true` if the effect is mid-execution, `false` otherwise
1306
- *
1307
- * @remarks
1308
- * This property is used internally to prevent re-entrant execution
1309
- * (an effect triggering itself during its own execution). It can
1310
- * also be useful for debugging to understand the effect's state.
1311
- *
1312
- * @example
1313
- * ```typescript
1314
- * const fx = effect(() => {
1315
- * console.log('executing:', fx.isExecuting); // true
1316
- * });
1317
- * console.log(fx.isExecuting); // false (after execution completes)
1318
- * ```
1319
- */
1320
912
  get isExecuting() {
1321
- return (this._flags & F.EXECUTING) !== 0;
913
+ return (this.flags & P.EXECUTING) !== 0;
1322
914
  }
1323
- /**
1324
- * Sets the disposed flag on this effect.
1325
- *
1326
- * @remarks
1327
- * This is a low-level method that only sets the bit flag.
1328
- * Use the public `dispose()` method for proper cleanup.
1329
- *
1330
- * @internal
1331
- */
1332
915
  _setDisposed() {
1333
- this._flags |= F.DISPOSED;
916
+ this.flags |= P.DISPOSED;
1334
917
  }
1335
- /**
1336
- * Sets or clears the executing flag on this effect.
1337
- *
1338
- * @param value - `true` to mark as executing, `false` to clear
1339
- *
1340
- * @remarks
1341
- * Uses bitwise operations for efficient flag manipulation.
1342
- * This flag prevents re-entrant execution of the effect.
1343
- *
1344
- * @internal
1345
- */
1346
918
  _setExecuting(e) {
1347
- const t = F.EXECUTING;
1348
- this._flags = this._flags & ~t | -Number(e) & t;
919
+ const t = P.EXECUTING;
920
+ this.flags = this.flags & ~t | -Number(e) & t;
1349
921
  }
1350
- /**
1351
- * Safely executes the cleanup function if one exists.
1352
- *
1353
- * @remarks
1354
- * This method:
1355
- * - Checks if a cleanup function exists and is callable
1356
- * - Wraps the cleanup call in a try-catch to prevent cleanup errors
1357
- * from breaking the effect lifecycle
1358
- * - Logs any cleanup errors to the console
1359
- * - Clears the cleanup reference after execution
1360
- *
1361
- * @internal
1362
- */
1363
922
  _safeCleanup() {
1364
- if (this._cleanup && typeof this._cleanup == "function") {
923
+ if (this._cleanup) {
1365
924
  try {
1366
925
  this._cleanup();
1367
926
  } catch (e) {
1368
- console.error(R(e, g, a.EFFECT_CLEANUP_FAILED));
927
+ console.error(C(e, g, l.EFFECT_CLEANUP_FAILED));
1369
928
  }
1370
929
  this._cleanup = null;
1371
930
  }
1372
931
  }
1373
- /**
1374
- * Checks for infinite loop conditions using epoch-based detection.
1375
- * Falls back to timestamp-based detection in development mode.
1376
- *
1377
- * @throws {EffectError} When infinite loop is detected
1378
- * @internal
1379
- */
1380
932
  _checkInfiniteLoop() {
1381
- if (this._lastFlushEpoch !== U && (this._lastFlushEpoch = U, this._executionsInEpoch = 0), this._executionsInEpoch++, this._executionsInEpoch > this._maxExecutionsPerFlush && this._throwInfiniteLoopError("per-effect"), H() > A.MAX_EXECUTIONS_PER_FLUSH && this._throwInfiniteLoopError("global"), this._executionCount++, this._history) {
933
+ if (this._lastFlushEpoch !== M && (this._lastFlushEpoch = M, this._executionsInEpoch = 0), this._executionsInEpoch++, this._executionsInEpoch > this._maxExecutionsPerFlush && this._throwInfiniteLoopError("per-effect"), oe() > y.MAX_EXECUTIONS_PER_FLUSH && this._throwInfiniteLoopError("global"), this._executionCount++, this._history) {
1382
934
  const e = Date.now();
1383
- this._history.push(e), this._history.length > A.MAX_EXECUTIONS_PER_SECOND + 10 && this._history.shift(), this._checkTimestampLoop(e);
935
+ this._history.push(e), this._history.length > y.MAX_EXECUTIONS_PER_SECOND + 10 && this._history.shift(), this._checkTimestampLoop(e);
1384
936
  }
1385
937
  }
1386
938
  _checkTimestampLoop(e) {
1387
939
  const t = this._history;
1388
940
  if (!t || this._maxExecutions <= 0) return;
1389
- const s = e - 1e3;
941
+ const i = e - ie.ONE_SECOND_MS;
1390
942
  let n = 0;
1391
- for (let r = t.length - 1; r >= 0 && !(t[r] < s); r--)
943
+ for (let r = t.length - 1; r >= 0 && !(t[r] < i); r--)
1392
944
  n++;
1393
945
  if (n > this._maxExecutions) {
1394
946
  const r = new g(
1395
947
  `Effect executed ${n} times within 1 second. Infinite loop suspected`
1396
948
  );
1397
- if (this.dispose(), console.error(r), M)
949
+ if (this.dispose(), console.error(r), d)
1398
950
  throw r;
1399
951
  }
1400
952
  }
1401
953
  _throwInfiniteLoopError(e) {
1402
954
  const t = new g(
1403
- `Infinite loop detected (${e}): effect executed ${this._executionsInEpoch} times in current flush. Total executions in flush: ${w}`
955
+ `Infinite loop detected (${e}): effect executed ${this._executionsInEpoch} times in current flush. Total executions in flush: ${k}`
1404
956
  );
1405
957
  throw this.dispose(), console.error(t), t;
1406
958
  }
1407
- /**
1408
- * Checks for and warns about potential infinite loop patterns.
1409
- *
1410
- * @remarks
1411
- * When modification tracking is enabled and debug mode is active,
1412
- * this method checks if any dependencies were both read and modified
1413
- * during the effect execution. Such patterns often lead to infinite loops.
1414
- *
1415
- * Warnings are only emitted in debug mode to avoid performance overhead
1416
- * in production.
1417
- *
1418
- * @internal
1419
- */
959
+ _shouldExecute() {
960
+ if (this._dependencies === a || this._dependencyVersions === f)
961
+ return !0;
962
+ for (let e = 0; e < this._dependencies.length; e++) {
963
+ const t = this._dependencies[e];
964
+ if (t) {
965
+ if ("value" in t)
966
+ try {
967
+ _e(() => t.value);
968
+ } catch {
969
+ return !0;
970
+ }
971
+ if (t.version !== this._dependencyVersions[e])
972
+ return !0;
973
+ }
974
+ }
975
+ return !1;
976
+ }
1420
977
  _checkLoopWarnings() {
1421
- if (this._trackModifications && b.enabled) {
978
+ if (this._trackModifications && S.enabled) {
1422
979
  const e = this._dependencies;
1423
980
  for (let t = 0; t < e.length; t++) {
1424
- const s = e[t];
1425
- s && s._modifiedAtEpoch === this._currentEpoch && b.warn(
981
+ const i = e[t];
982
+ i && i._modifiedAtEpoch === this._currentEpoch && S.warn(
1426
983
  !0,
1427
- `Effect is reading a dependency (${b.getDebugName(s) || "unknown"}) that it just modified. Infinite loop may occur`
984
+ `Effect is reading a dependency (${S.getDebugName(i) || "unknown"}) that it just modified. Infinite loop may occur`
1428
985
  );
1429
986
  }
1430
987
  }
1431
988
  }
1432
989
  }
1433
- function he(i, e = {}) {
1434
- if (typeof i != "function")
1435
- throw new g(a.EFFECT_MUST_BE_FUNCTION);
1436
- const t = new te(i, e);
990
+ function ge(s, e = {}) {
991
+ if (typeof s != "function")
992
+ throw new g(l.EFFECT_MUST_BE_FUNCTION);
993
+ const t = new fe(s, e);
1437
994
  return t.execute(), t;
1438
995
  }
1439
- function se(i) {
1440
- return i !== null && typeof i == "object" && "value" in i && "subscribe" in i && typeof i.subscribe == "function";
996
+ function de(s) {
997
+ return s !== null && typeof s == "object" && "value" in s && "subscribe" in s && typeof s.subscribe == "function";
1441
998
  }
1442
- function oe(i) {
1443
- if (b.enabled) {
1444
- const e = b.getDebugType(i);
999
+ function Ie(s) {
1000
+ if (S.enabled && (s == null || typeof s == "object")) {
1001
+ const e = S.getDebugType(s);
1445
1002
  if (e)
1446
1003
  return e === "computed";
1447
1004
  }
1448
- return se(i) && "invalidate" in i && typeof i.invalidate == "function";
1005
+ return de(s) && "invalidate" in s && typeof s.invalidate == "function";
1449
1006
  }
1450
- function ae(i) {
1451
- return i !== null && typeof i == "object" && "dispose" in i && "run" in i && typeof i.dispose == "function" && typeof i.run == "function";
1007
+ function De(s) {
1008
+ return s !== null && typeof s == "object" && "dispose" in s && "run" in s && typeof s.dispose == "function" && typeof s.run == "function";
1452
1009
  }
1453
1010
  export {
1454
- T as AsyncState,
1455
- d as AtomError,
1456
- I as ComputedError,
1457
- k as DEBUG_CONFIG,
1458
- b as DEBUG_RUNTIME,
1011
+ F as AsyncState,
1012
+ E as AtomError,
1013
+ T as ComputedError,
1014
+ z as DEBUG_CONFIG,
1015
+ S as DEBUG_RUNTIME,
1459
1016
  g as EffectError,
1460
- ie as POOL_CONFIG,
1461
- A as SCHEDULER_CONFIG,
1462
- C as SchedulerError,
1463
- ce as atom,
1464
- ne as batch,
1465
- ue as computed,
1466
- he as effect,
1467
- se as isAtom,
1468
- oe as isComputed,
1469
- ae as isEffect,
1470
- N as scheduler,
1471
- re as untracked
1017
+ Ee as POOL_CONFIG,
1018
+ y as SCHEDULER_CONFIG,
1019
+ x as SchedulerError,
1020
+ pe as atom,
1021
+ be as batch,
1022
+ Se as computed,
1023
+ ge as effect,
1024
+ de as isAtom,
1025
+ Ie as isComputed,
1026
+ De as isEffect,
1027
+ U as scheduler,
1028
+ _e as untracked
1472
1029
  };
1473
1030
  //# sourceMappingURL=index.mjs.map