@but212/atom-effect 0.12.0 → 0.13.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.d.ts CHANGED
@@ -333,9 +333,27 @@ export declare interface EffectOptions {
333
333
  onError?: (error: unknown) => void;
334
334
  }
335
335
 
336
+ /** Internal atom interface for core library usage. */
337
+ export declare interface IAtom {
338
+ /** Numerical ID for the node. */
339
+ readonly id: number;
340
+ /** Current version of the node's value. */
341
+ version: number;
342
+ /** Internal method to trigger subscriber notifications. */
343
+ _internalNotifySubscribers(): void;
344
+ /** Internal method to trigger recomputation. */
345
+ recompute?(): void;
346
+ }
347
+
336
348
  /** Checks if the given object is a ReadonlyAtom. */
337
349
  export declare function isAtom(obj: unknown): obj is ReadonlyAtom;
338
350
 
351
+ /** Internal scheduler interface to break circular dependencies. */
352
+ export declare interface IScheduler<T> {
353
+ markDirty(atom: T): void;
354
+ scheduleNotify(atom: T): void;
355
+ }
356
+
339
357
  /** Checks if the given object is a ComputedAtom. */
340
358
  export declare function isComputed(obj: unknown): obj is ComputedAtom;
341
359
 
@@ -368,6 +386,24 @@ export declare interface Poolable {
368
386
  reset(): void;
369
387
  }
370
388
 
389
+ /** Statistics for pool usage and health. */
390
+ export declare interface PoolStats {
391
+ /** Number of items acquired from the pool. */
392
+ acquired: number;
393
+ /** Number of items released back to the pool. */
394
+ released: number;
395
+ /** Details for items that could not be returned to the pool. */
396
+ rejected: {
397
+ frozen: number;
398
+ tooLarge: number;
399
+ poolFull: number;
400
+ };
401
+ /** Approximate number of items that have leaked (not released or rejected). */
402
+ leaked: number;
403
+ /** Current number of items available in the pool. */
404
+ poolSize: number;
405
+ }
406
+
371
407
  /** Represents a read-only reactive atom. */
372
408
  export declare interface ReadonlyAtom<T = unknown> {
373
409
  /** The current value of the atom. Accessing this tracks it as a dependency. */
package/dist/index.mjs CHANGED
@@ -29,7 +29,7 @@ const ee = {
29
29
  }, T = {
30
30
  SYNC: 1,
31
31
  NOTIFICATION_SCHEDULED: 2
32
- }, be = {
32
+ }, ye = {
33
33
  /** Maximum number of pooled objects to prevent memory bloat */
34
34
  MAX_SIZE: 1e3,
35
35
  /** Number of objects to pre-allocate for performance-critical paths */
@@ -53,12 +53,12 @@ const ee = {
53
53
  MAX_FLUSH_ITERATIONS: 1e3,
54
54
  /** Minimum allowed value for max flush iterations */
55
55
  MIN_FLUSH_ITERATIONS: 10
56
- }, B = {
56
+ }, j = {
57
57
  /** Maximum dependencies before warning about large dependency graphs */
58
58
  MAX_DEPENDENCIES: 1e3,
59
59
  /** Enable infinite loop detection warnings */
60
60
  WARN_INFINITE_LOOP: !0
61
- }, b = 1073741823, w = 1 << 19, l = typeof process < "u" && process.env && process.env.NODE_ENV !== "production", te = Object.freeze([]);
61
+ }, b = 1073741823, te = 20, w = 1 << te - 1, l = typeof process < "u" && process.env && process.env.NODE_ENV !== "production", se = Object.freeze([]);
62
62
  class g extends Error {
63
63
  /**
64
64
  * Creates a new AtomError
@@ -152,8 +152,8 @@ const u = {
152
152
  * @remarks This prevents cascading failures from masking the original error.
153
153
  */
154
154
  CALLBACK_ERROR_IN_ERROR_HANDLER: "Error occurred during onError callback execution"
155
- }, M = /* @__PURE__ */ Symbol("debugName"), se = /* @__PURE__ */ Symbol("id"), V = /* @__PURE__ */ Symbol("type"), k = /* @__PURE__ */ Symbol("noDefaultValue");
156
- function ie(s) {
155
+ }, M = /* @__PURE__ */ Symbol("debugName"), ie = /* @__PURE__ */ Symbol("id"), V = /* @__PURE__ */ Symbol("type"), k = /* @__PURE__ */ Symbol("noDefaultValue");
156
+ function ne(s) {
157
157
  return "dependencies" in s && Array.isArray(s.dependencies);
158
158
  }
159
159
  let Q = 0;
@@ -161,7 +161,7 @@ function G(s, e, t) {
161
161
  if (s._visitedEpoch !== t) {
162
162
  if (s._visitedEpoch = t, s === e)
163
163
  throw new D("Indirect circular dependency detected");
164
- if (ie(s)) {
164
+ if (ne(s)) {
165
165
  const i = s.dependencies;
166
166
  for (let n = 0; n < i.length; n++) {
167
167
  const r = i[n];
@@ -172,8 +172,8 @@ function G(s, e, t) {
172
172
  }
173
173
  const p = {
174
174
  enabled: typeof process < "u" && process.env?.NODE_ENV === "development",
175
- maxDependencies: B.MAX_DEPENDENCIES,
176
- warnInfiniteLoop: B.WARN_INFINITE_LOOP,
175
+ maxDependencies: j.MAX_DEPENDENCIES,
176
+ warnInfiniteLoop: j.WARN_INFINITE_LOOP,
177
177
  warn(s, e) {
178
178
  this.enabled && s && console.warn(`[Atom Effect] ${e}`);
179
179
  },
@@ -191,7 +191,7 @@ const p = {
191
191
  if (!this.enabled)
192
192
  return;
193
193
  const i = s;
194
- i[M] = `${e}_${t}`, i[se] = t, i[V] = e;
194
+ i[M] = `${e}_${t}`, i[ie] = t, i[V] = e;
195
195
  },
196
196
  getDebugName(s) {
197
197
  if (s != null && M in s)
@@ -202,11 +202,11 @@ const p = {
202
202
  return s[V];
203
203
  }
204
204
  };
205
- let ne = 1;
206
- const re = () => ne++;
205
+ let re = 1;
206
+ const oe = () => re++;
207
207
  class Y {
208
208
  constructor() {
209
- this.flags = 0, this.version = 0, this._lastSeenEpoch = -1, this.id = re() & b;
209
+ this.flags = 0, this.version = 0, this._lastSeenEpoch = -1, this.id = oe() & b;
210
210
  }
211
211
  /**
212
212
  * Rotates the phase by 1, automatically incrementing cycle on overflow.
@@ -315,26 +315,141 @@ class H extends Y {
315
315
  }
316
316
  }
317
317
  }
318
+ class z {
319
+ constructor() {
320
+ this.pool = [], this.maxPoolSize = 50, this.maxReusableCapacity = 256, this.stats = l ? {
321
+ acquired: 0,
322
+ released: 0,
323
+ rejected: { frozen: 0, tooLarge: 0, poolFull: 0 }
324
+ } : null;
325
+ }
326
+ /** Acquires an array from the pool or creates a new one if the pool is empty. */
327
+ acquire() {
328
+ return l && this.stats && this.stats.acquired++, this.pool.pop() ?? [];
329
+ }
330
+ /**
331
+ * Releases an array back to the pool.
332
+ * Clears the array before storing it.
333
+ * @param arr - The array to release.
334
+ * @param emptyConst - Optional reference to a constant empty array to skip.
335
+ */
336
+ release(e, t) {
337
+ if (!(t && e === t)) {
338
+ if (Object.isFrozen(e)) {
339
+ l && this.stats && this.stats.rejected.frozen++;
340
+ return;
341
+ }
342
+ if (e.length > this.maxReusableCapacity) {
343
+ l && this.stats && this.stats.rejected.tooLarge++;
344
+ return;
345
+ }
346
+ if (this.pool.length >= this.maxPoolSize) {
347
+ l && this.stats && this.stats.rejected.poolFull++;
348
+ return;
349
+ }
350
+ e.length = 0, this.pool.push(e), l && this.stats && this.stats.released++;
351
+ }
352
+ }
353
+ /** Returns current stats for the pool (dev mode only). */
354
+ getStats() {
355
+ if (!l || !this.stats) return null;
356
+ const { acquired: e, released: t, rejected: i } = this.stats, n = i.frozen + i.tooLarge + i.poolFull;
357
+ return {
358
+ acquired: e,
359
+ released: t,
360
+ rejected: i,
361
+ leaked: e - t - n,
362
+ poolSize: this.pool.length
363
+ };
364
+ }
365
+ /** Resets the pool and its stats. */
366
+ reset() {
367
+ this.pool.length = 0, l && this.stats && (this.stats.acquired = 0, this.stats.released = 0, this.stats.rejected = { frozen: 0, tooLarge: 0, poolFull: 0 });
368
+ }
369
+ }
370
+ const _ = Object.freeze([]), f = Object.freeze([]), a = Object.freeze([]), S = new z(), C = new z(), d = new z();
371
+ function he(s) {
372
+ return s !== null && typeof s == "object" && "value" in s && "subscribe" in s && typeof s.subscribe == "function";
373
+ }
374
+ function De(s) {
375
+ if (p.enabled && (s == null || typeof s == "object")) {
376
+ const e = p.getDebugType(s);
377
+ if (e)
378
+ return e === "computed";
379
+ }
380
+ return he(s) && "invalidate" in s && typeof s.invalidate == "function";
381
+ }
382
+ function Ie(s) {
383
+ return s !== null && typeof s == "object" && "dispose" in s && "run" in s && typeof s.dispose == "function" && typeof s.run == "function";
384
+ }
385
+ function $(s) {
386
+ return s != null && typeof s.then == "function";
387
+ }
388
+ function ue(s) {
389
+ return typeof s == "object" && s !== null;
390
+ }
391
+ function ce(s) {
392
+ return (typeof s == "object" || typeof s == "function") && s !== null && typeof s.addDependency == "function";
393
+ }
394
+ function _e(s) {
395
+ return typeof s == "function" && typeof s.addDependency != "function";
396
+ }
397
+ function ae(s) {
398
+ return ue(s) && typeof s.execute == "function";
399
+ }
400
+ function J(s, e, t, i) {
401
+ if (e) {
402
+ if (ce(e)) {
403
+ e.addDependency(s);
404
+ return;
405
+ }
406
+ if (_e(e)) {
407
+ const n = e;
408
+ t.indexOf(n) === -1 && t.push(n);
409
+ return;
410
+ }
411
+ ae(e) && i.indexOf(e) === -1 && i.push(e);
412
+ }
413
+ }
414
+ function le(s, e, t, i) {
415
+ if (e !== _ && t !== f)
416
+ for (let r = 0; r < e.length; r++) {
417
+ const o = e[r];
418
+ o && (o._tempUnsub = t[r]);
419
+ }
420
+ const n = C.acquire();
421
+ n.length = s.length;
422
+ for (let r = 0; r < s.length; r++) {
423
+ const o = s[r];
424
+ o && (o._tempUnsub ? (n[r] = o._tempUnsub, o._tempUnsub = void 0) : (p.checkCircular(o, i), n[r] = o.subscribe(i)));
425
+ }
426
+ if (e !== _)
427
+ for (let r = 0; r < e.length; r++) {
428
+ const o = e[r];
429
+ o?._tempUnsub && (o._tempUnsub(), o._tempUnsub = void 0);
430
+ }
431
+ return t !== f && C.release(t), n;
432
+ }
318
433
  let x = 0;
319
- function $() {
434
+ function W() {
320
435
  return x = x + 1 & b || 1, x;
321
436
  }
322
- function oe() {
437
+ function fe() {
323
438
  return x;
324
439
  }
325
- let F = 0, z = 0, P = !1;
440
+ let F = 0, B = 0, P = !1;
326
441
  function q() {
327
442
  return P ? (l && console.warn(
328
443
  "Warning: startFlush() called during flush - ignored to prevent infinite loop detection bypass"
329
- ), !1) : (P = !0, F = F + 1 & b, z = 0, !0);
444
+ ), !1) : (P = !0, F = F + 1 & b, B = 0, !0);
330
445
  }
331
446
  function X() {
332
447
  P = !1;
333
448
  }
334
- function he() {
335
- return P ? ++z : 0;
449
+ function de() {
450
+ return P ? ++B : 0;
336
451
  }
337
- class ue {
452
+ class pe {
338
453
  constructor() {
339
454
  this.queueA = [], this.queueB = [], this.queue = this.queueA, this.queueSize = 0, this.urgentQueueA = [], this.urgentQueueB = [], this.urgentQueue = this.urgentQueueA, this.urgentQueueSize = 0, this._epoch = 0, this.isProcessing = !1, this.isBatching = !1, this.batchDepth = 0, this.batchQueue = [], this.batchQueueSize = 0, this.isFlushingSync = !1, this.maxFlushIterations = I.MAX_FLUSH_ITERATIONS;
340
455
  }
@@ -487,18 +602,8 @@ class ue {
487
602
  this.maxFlushIterations = e;
488
603
  }
489
604
  }
490
- const N = new ue();
491
- function ye(s) {
492
- if (typeof s != "function")
493
- throw new g("Batch callback must be a function");
494
- N.startBatch();
495
- try {
496
- return s();
497
- } finally {
498
- N.endBatch();
499
- }
500
- }
501
- class ce {
605
+ const N = new pe();
606
+ class Ee {
502
607
  constructor() {
503
608
  this.current = null;
504
609
  }
@@ -525,8 +630,8 @@ class ce {
525
630
  return this.current;
526
631
  }
527
632
  }
528
- const m = new ce();
529
- function _e(s) {
633
+ const m = new Ee();
634
+ function ge(s) {
530
635
  if (typeof s != "function")
531
636
  throw new g("Untracked callback must be a function");
532
637
  const e = m.current;
@@ -537,122 +642,7 @@ function _e(s) {
537
642
  m.current = e;
538
643
  }
539
644
  }
540
- class j {
541
- constructor() {
542
- this.pool = [], this.maxPoolSize = 50, this.maxReusableCapacity = 256, this.stats = l ? {
543
- acquired: 0,
544
- released: 0,
545
- rejected: { frozen: 0, tooLarge: 0, poolFull: 0 }
546
- } : null;
547
- }
548
- /** Acquires an array from the pool or creates a new one if the pool is empty. */
549
- acquire() {
550
- return l && this.stats && this.stats.acquired++, this.pool.pop() ?? [];
551
- }
552
- /**
553
- * Releases an array back to the pool.
554
- * Clears the array before storing it.
555
- * @param arr - The array to release.
556
- * @param emptyConst - Optional reference to a constant empty array to skip.
557
- */
558
- release(e, t) {
559
- if (!(t && e === t)) {
560
- if (Object.isFrozen(e)) {
561
- l && this.stats && this.stats.rejected.frozen++;
562
- return;
563
- }
564
- if (e.length > this.maxReusableCapacity) {
565
- l && this.stats && this.stats.rejected.tooLarge++;
566
- return;
567
- }
568
- if (this.pool.length >= this.maxPoolSize) {
569
- l && this.stats && this.stats.rejected.poolFull++;
570
- return;
571
- }
572
- e.length = 0, this.pool.push(e), l && this.stats && this.stats.released++;
573
- }
574
- }
575
- /** Returns current stats for the pool (dev mode only). */
576
- getStats() {
577
- if (!l || !this.stats) return null;
578
- const { acquired: e, released: t, rejected: i } = this.stats, n = i.frozen + i.tooLarge + i.poolFull;
579
- return {
580
- acquired: e,
581
- released: t,
582
- rejected: i,
583
- leaked: e - t - n,
584
- poolSize: this.pool.length
585
- };
586
- }
587
- /** Resets the pool and its stats. */
588
- reset() {
589
- this.pool.length = 0, l && this.stats && (this.stats.acquired = 0, this.stats.released = 0, this.stats.rejected = { frozen: 0, tooLarge: 0, poolFull: 0 });
590
- }
591
- }
592
- const _ = Object.freeze([]), f = Object.freeze([]), a = Object.freeze([]), S = new j(), C = new j(), d = new j();
593
- function ae(s) {
594
- return s !== null && typeof s == "object" && "value" in s && "subscribe" in s && typeof s.subscribe == "function";
595
- }
596
- function De(s) {
597
- if (p.enabled && (s == null || typeof s == "object")) {
598
- const e = p.getDebugType(s);
599
- if (e)
600
- return e === "computed";
601
- }
602
- return ae(s) && "invalidate" in s && typeof s.invalidate == "function";
603
- }
604
- function Ie(s) {
605
- return s !== null && typeof s == "object" && "dispose" in s && "run" in s && typeof s.dispose == "function" && typeof s.run == "function";
606
- }
607
- function J(s) {
608
- return s != null && typeof s.then == "function";
609
- }
610
- function le(s) {
611
- return typeof s == "object" && s !== null;
612
- }
613
- function fe(s) {
614
- return (typeof s == "object" || typeof s == "function") && s !== null && typeof s.addDependency == "function";
615
- }
616
- function de(s) {
617
- return typeof s == "function" && typeof s.addDependency != "function";
618
- }
619
- function pe(s) {
620
- return le(s) && typeof s.execute == "function";
621
- }
622
- function W(s, e, t, i) {
623
- if (e) {
624
- if (fe(e)) {
625
- e.addDependency(s);
626
- return;
627
- }
628
- if (de(e)) {
629
- const n = e;
630
- t.indexOf(n) === -1 && t.push(n);
631
- return;
632
- }
633
- pe(e) && i.indexOf(e) === -1 && i.push(e);
634
- }
635
- }
636
- function Ee(s, e, t, i) {
637
- if (e !== _ && t !== f)
638
- for (let r = 0; r < e.length; r++) {
639
- const o = e[r];
640
- o && (o._tempUnsub = t[r]);
641
- }
642
- const n = C.acquire();
643
- n.length = s.length;
644
- for (let r = 0; r < s.length; r++) {
645
- const o = s[r];
646
- o && (o._tempUnsub ? (n[r] = o._tempUnsub, o._tempUnsub = void 0) : (p.checkCircular(o, i), n[r] = o.subscribe(i)));
647
- }
648
- if (e !== _)
649
- for (let r = 0; r < e.length; r++) {
650
- const o = e[r];
651
- o?._tempUnsub && (o._tempUnsub(), o._tempUnsub = void 0);
652
- }
653
- return t !== f && C.release(t), n;
654
- }
655
- class ge extends H {
645
+ class Se extends H {
656
646
  constructor(e, t) {
657
647
  super(), this._fnSubs = null, this._objSubs = null, this._value = e, t && (this.flags |= T.SYNC), p.attachDebugInfo(this, "atom", this.id);
658
648
  }
@@ -667,7 +657,7 @@ class ge extends H {
667
657
  */
668
658
  get value() {
669
659
  const e = m.current;
670
- return e && W(this, e, this._getFnSubs(), this._getObjSubs()), this._value;
660
+ return e && J(this, e, this._getFnSubs(), this._getObjSubs()), this._value;
671
661
  }
672
662
  /**
673
663
  * Sets a new value and schedules notifications if the value has changed.
@@ -700,7 +690,7 @@ class ge extends H {
700
690
  }
701
691
  }
702
692
  function Ce(s, e = {}) {
703
- return new ge(s, e.sync ?? !1);
693
+ return new Se(s, e.sync ?? !1);
704
694
  }
705
695
  function A(s, e, t) {
706
696
  if (s instanceof TypeError)
@@ -782,8 +772,8 @@ class Z extends H {
782
772
  }
783
773
  get errors() {
784
774
  if (this._registerTracking(), !this.hasError)
785
- return te;
786
- const e = oe();
775
+ return se;
776
+ const e = fe();
787
777
  if (this._errorCacheEpoch === e && this._cachedErrors !== null)
788
778
  return this._cachedErrors;
789
779
  const t = /* @__PURE__ */ new Set();
@@ -880,7 +870,7 @@ class Z extends H {
880
870
  let t = !1;
881
871
  try {
882
872
  const i = m.run(this._trackable, this._fn);
883
- this._commitDependencies(e), t = !0, J(i) ? this._handleAsyncComputation(i) : this._handleSyncResult(i);
873
+ this._commitDependencies(e), t = !0, $(i) ? this._handleAsyncComputation(i) : this._handleSyncResult(i);
884
874
  } catch (i) {
885
875
  if (!t)
886
876
  try {
@@ -894,14 +884,14 @@ class Z extends H {
894
884
  }
895
885
  }
896
886
  _prepareComputationContext() {
897
- const e = this._dependencies, t = this._dependencyVersions, i = S.acquire(), n = d.acquire(), r = $(), o = { depCount: 0 }, c = (E) => {
887
+ const e = this._dependencies, t = this._dependencyVersions, i = S.acquire(), n = d.acquire(), r = W(), o = { depCount: 0 }, c = (E) => {
898
888
  E._lastSeenEpoch !== r && (E._lastSeenEpoch = r, o.depCount < i.length ? (i[o.depCount] = E, n[o.depCount] = E.version) : (i.push(E), n.push(E.version)), o.depCount++);
899
889
  }, R = this._trackable.addDependency;
900
890
  return this._trackable.addDependency = c, { prevDeps: e, prevVersions: t, nextDeps: i, nextVersions: n, originalAdd: R, state: o };
901
891
  }
902
892
  _commitDependencies(e) {
903
893
  const { nextDeps: t, nextVersions: i, state: n, prevDeps: r } = e;
904
- t.length = n.depCount, i.length = n.depCount, this._unsubscribes = Ee(t, r, this._unsubscribes, this), this._dependencies = t, this._dependencyVersions = i;
894
+ t.length = n.depCount, i.length = n.depCount, this._unsubscribes = le(t, r, this._unsubscribes, this), this._dependencies = t, this._dependencyVersions = i;
905
895
  }
906
896
  _cleanupContext(e, t) {
907
897
  this._trackable.addDependency = e.originalAdd, t ? (e.prevDeps !== _ && S.release(e.prevDeps), e.prevVersions !== a && d.release(e.prevVersions)) : (S.release(e.nextDeps), d.release(e.nextVersions));
@@ -1021,14 +1011,14 @@ class Z extends H {
1021
1011
  this._isRecomputing() || this._isDirty() || (this._setDirty(), this._notifyJob());
1022
1012
  }
1023
1013
  _registerTracking() {
1024
- W(this, m.getCurrent(), this._getFnSubs(), this._getObjSubs());
1014
+ J(this, m.getCurrent(), this._getFnSubs(), this._getObjSubs());
1025
1015
  }
1026
1016
  }
1027
1017
  Object.freeze(Z.prototype);
1028
1018
  function me(s, e = {}) {
1029
1019
  return new Z(s, e);
1030
1020
  }
1031
- class Se extends Y {
1021
+ class be extends Y {
1032
1022
  /**
1033
1023
  * Creates a new EffectImpl instance.
1034
1024
  * @param fn - The effect function to run.
@@ -1063,7 +1053,7 @@ class Se extends Y {
1063
1053
  let r = !1;
1064
1054
  try {
1065
1055
  const o = m.run(this, this._fn);
1066
- this._commitEffect(n), r = !0, this._checkLoopWarnings(), J(o) ? o.then((c) => {
1056
+ this._commitEffect(n), r = !0, this._checkLoopWarnings(), $(o) ? o.then((c) => {
1067
1057
  !this.isDisposed && typeof c == "function" && (this._cleanup = c);
1068
1058
  }).catch((c) => {
1069
1059
  this._handleExecutionError(c);
@@ -1082,7 +1072,7 @@ class Se extends Y {
1082
1072
  * @returns The prepared EffectExecutionContext.
1083
1073
  */
1084
1074
  _prepareEffectExecutionContext() {
1085
- const e = this._dependencies, t = this._dependencyVersions, i = this._unsubscribes, n = S.acquire(), r = d.acquire(), o = C.acquire(), c = $();
1075
+ const e = this._dependencies, t = this._dependencyVersions, i = this._unsubscribes, n = S.acquire(), r = d.acquire(), o = C.acquire(), c = W();
1086
1076
  if (e !== _ && i !== f)
1087
1077
  for (let R = 0; R < e.length; R++) {
1088
1078
  const E = e[R];
@@ -1182,7 +1172,7 @@ class Se extends Y {
1182
1172
  * @throws {EffectError} If an infinite loop is detected.
1183
1173
  */
1184
1174
  _checkInfiniteLoop() {
1185
- if (this._lastFlushEpoch !== F && (this._lastFlushEpoch = F, this._executionsInEpoch = 0), this._executionsInEpoch++, this._executionsInEpoch > this._maxExecutionsPerFlush && this._throwInfiniteLoopError("per-effect"), he() > I.MAX_EXECUTIONS_PER_FLUSH && this._throwInfiniteLoopError("global"), this._executionCount++, this._history && this._maxExecutions > 0) {
1175
+ if (this._lastFlushEpoch !== F && (this._lastFlushEpoch = F, this._executionsInEpoch = 0), this._executionsInEpoch++, this._executionsInEpoch > this._maxExecutionsPerFlush && this._throwInfiniteLoopError("per-effect"), de() > I.MAX_EXECUTIONS_PER_FLUSH && this._throwInfiniteLoopError("global"), this._executionCount++, this._history && this._maxExecutions > 0) {
1186
1176
  const e = Date.now(), t = this._historyPtr, i = this._historyCapacity;
1187
1177
  this._history[t] = e;
1188
1178
  const n = (t + 1) % i, r = this._history[n] ?? 0;
@@ -1197,7 +1187,7 @@ class Se extends Y {
1197
1187
  }
1198
1188
  _throwInfiniteLoopError(e) {
1199
1189
  const t = new y(
1200
- `Infinite loop detected (${e}): effect executed ${this._executionsInEpoch} times in current flush. Total executions in flush: ${z}`
1190
+ `Infinite loop detected (${e}): effect executed ${this._executionsInEpoch} times in current flush. Total executions in flush: ${B}`
1201
1191
  );
1202
1192
  throw this.dispose(), console.error(t), t;
1203
1193
  }
@@ -1213,7 +1203,7 @@ class Se extends Y {
1213
1203
  if (t) {
1214
1204
  if ("value" in t)
1215
1205
  try {
1216
- _e(() => t.value);
1206
+ ge(() => t.value);
1217
1207
  } catch {
1218
1208
  return !0;
1219
1209
  }
@@ -1251,27 +1241,37 @@ class Se extends Y {
1251
1241
  function Re(s, e = {}) {
1252
1242
  if (typeof s != "function")
1253
1243
  throw new y(u.EFFECT_MUST_BE_FUNCTION);
1254
- const t = new Se(s, e);
1244
+ const t = new be(s, e);
1255
1245
  return t.execute(), t;
1256
1246
  }
1247
+ function Te(s) {
1248
+ if (typeof s != "function")
1249
+ throw new g("Batch callback must be a function");
1250
+ N.startBatch();
1251
+ try {
1252
+ return s();
1253
+ } finally {
1254
+ N.endBatch();
1255
+ }
1256
+ }
1257
1257
  export {
1258
1258
  v as AsyncState,
1259
1259
  g as AtomError,
1260
1260
  D as ComputedError,
1261
- B as DEBUG_CONFIG,
1261
+ j as DEBUG_CONFIG,
1262
1262
  p as DEBUG_RUNTIME,
1263
1263
  y as EffectError,
1264
- be as POOL_CONFIG,
1264
+ ye as POOL_CONFIG,
1265
1265
  I as SCHEDULER_CONFIG,
1266
1266
  U as SchedulerError,
1267
1267
  Ce as atom,
1268
- ye as batch,
1268
+ Te as batch,
1269
1269
  me as computed,
1270
1270
  Re as effect,
1271
- ae as isAtom,
1271
+ he as isAtom,
1272
1272
  De as isComputed,
1273
1273
  Ie as isEffect,
1274
1274
  N as scheduler,
1275
- _e as untracked
1275
+ ge as untracked
1276
1276
  };
1277
1277
  //# sourceMappingURL=index.mjs.map