signalium 3.0.2 → 4.0.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.
Files changed (149) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/dist/cjs/development/{component-shared-Cug2Y5YZ.js → component-shared-BjwFh5Jq.js} +2 -2
  3. package/dist/cjs/development/{component-shared-Cug2Y5YZ.js.map → component-shared-BjwFh5Jq.js.map} +1 -1
  4. package/dist/cjs/development/config-D6wyrhrW.js +58 -0
  5. package/dist/cjs/development/config-D6wyrhrW.js.map +1 -0
  6. package/dist/cjs/development/config.js +1 -1
  7. package/dist/cjs/development/{debug-C46WDxhL.js → debug-CbAX7VeM.js} +260 -43
  8. package/dist/cjs/development/debug-CbAX7VeM.js.map +1 -0
  9. package/dist/cjs/development/debug.js +3 -1
  10. package/dist/cjs/development/debug.js.map +1 -1
  11. package/dist/cjs/development/index.js +3 -2
  12. package/dist/cjs/development/index.js.map +1 -1
  13. package/dist/cjs/development/react/index.js +399 -52
  14. package/dist/cjs/development/react/index.js.map +1 -1
  15. package/dist/cjs/development/react/index.server.js +2 -2
  16. package/dist/cjs/development/react/index.server.js.map +1 -1
  17. package/dist/cjs/development/react/server.js +1 -1
  18. package/dist/cjs/development/{snapshot-CbZ6IH3B.js → snapshot-BTMVSd8Y.js} +4 -2
  19. package/dist/cjs/development/snapshot-BTMVSd8Y.js.map +1 -0
  20. package/dist/cjs/development/transform/index.js +5 -2
  21. package/dist/cjs/development/transform/index.js.map +1 -1
  22. package/dist/cjs/development/utils.js +34 -2
  23. package/dist/cjs/development/utils.js.map +1 -1
  24. package/dist/cjs/production/{component-shared-D0J85PUi.js → component-shared-CcxyLg4p.js} +2 -2
  25. package/dist/cjs/production/{component-shared-D0J85PUi.js.map → component-shared-CcxyLg4p.js.map} +1 -1
  26. package/dist/cjs/production/config-BHvmcsLQ.js +52 -0
  27. package/dist/cjs/production/config-BHvmcsLQ.js.map +1 -0
  28. package/dist/cjs/production/config.js +1 -1
  29. package/dist/cjs/production/{contexts-CM3QLfV8.js → contexts-waczQzHZ.js} +260 -43
  30. package/dist/cjs/production/contexts-waczQzHZ.js.map +1 -0
  31. package/dist/cjs/production/debug.js +3 -1
  32. package/dist/cjs/production/debug.js.map +1 -1
  33. package/dist/cjs/production/index.js +3 -2
  34. package/dist/cjs/production/index.js.map +1 -1
  35. package/dist/cjs/production/react/index.js +399 -52
  36. package/dist/cjs/production/react/index.js.map +1 -1
  37. package/dist/cjs/production/react/index.server.js +2 -2
  38. package/dist/cjs/production/react/index.server.js.map +1 -1
  39. package/dist/cjs/production/react/server.js +1 -1
  40. package/dist/cjs/production/{snapshot-DWwH7_9y.js → snapshot-7264bWj1.js} +4 -2
  41. package/dist/cjs/production/snapshot-7264bWj1.js.map +1 -0
  42. package/dist/cjs/production/transform/index.js +5 -2
  43. package/dist/cjs/production/transform/index.js.map +1 -1
  44. package/dist/cjs/production/utils.js +34 -2
  45. package/dist/cjs/production/utils.js.map +1 -1
  46. package/dist/esm/config.d.ts +1 -1
  47. package/dist/esm/config.d.ts.map +1 -1
  48. package/dist/esm/debug.d.ts +1 -0
  49. package/dist/esm/debug.d.ts.map +1 -1
  50. package/dist/esm/development/{component-shared-CLSmdnGU.js → component-shared-B3Q6mIzY.js} +2 -2
  51. package/dist/esm/development/{component-shared-CLSmdnGU.js.map → component-shared-B3Q6mIzY.js.map} +1 -1
  52. package/dist/esm/development/config-CQLKpPRj.js +59 -0
  53. package/dist/esm/development/config-CQLKpPRj.js.map +1 -0
  54. package/dist/esm/development/config.js +2 -2
  55. package/dist/esm/development/{debug-BTLbgTPK.js → debug-C3HD8WcT.js} +288 -71
  56. package/dist/esm/development/debug-C3HD8WcT.js.map +1 -0
  57. package/dist/esm/development/debug.js +12 -10
  58. package/dist/esm/development/index.js +18 -17
  59. package/dist/esm/development/react/index.js +400 -53
  60. package/dist/esm/development/react/index.js.map +1 -1
  61. package/dist/esm/development/react/index.server.js +2 -2
  62. package/dist/esm/development/react/index.server.js.map +1 -1
  63. package/dist/esm/development/react/server.js +1 -1
  64. package/dist/esm/development/{snapshot-CkndI4Hh.js → snapshot-CCKlBy-y.js} +7 -5
  65. package/dist/esm/development/snapshot-CCKlBy-y.js.map +1 -0
  66. package/dist/esm/development/transform/index.js +5 -2
  67. package/dist/esm/development/transform/index.js.map +1 -1
  68. package/dist/esm/development/utils.js +38 -6
  69. package/dist/esm/development/utils.js.map +1 -1
  70. package/dist/esm/index.d.ts +2 -2
  71. package/dist/esm/index.d.ts.map +1 -1
  72. package/dist/esm/internals/async.d.ts.map +1 -1
  73. package/dist/esm/internals/config.d.ts +40 -0
  74. package/dist/esm/internals/config.d.ts.map +1 -1
  75. package/dist/esm/internals/lease.d.ts +30 -0
  76. package/dist/esm/internals/lease.d.ts.map +1 -0
  77. package/dist/esm/internals/reactive.d.ts +18 -1
  78. package/dist/esm/internals/reactive.d.ts.map +1 -1
  79. package/dist/esm/internals/scheduling.d.ts +2 -1
  80. package/dist/esm/internals/scheduling.d.ts.map +1 -1
  81. package/dist/esm/internals/utils/hash.d.ts +7 -0
  82. package/dist/esm/internals/utils/hash.d.ts.map +1 -1
  83. package/dist/esm/internals/utils/snapshot.d.ts +2 -0
  84. package/dist/esm/internals/utils/snapshot.d.ts.map +1 -1
  85. package/dist/esm/internals/watch.d.ts +3 -2
  86. package/dist/esm/internals/watch.d.ts.map +1 -1
  87. package/dist/esm/production/{component-shared-Dva0S5e3.js → component-shared-CycOXiis.js} +2 -2
  88. package/dist/esm/production/{component-shared-Dva0S5e3.js.map → component-shared-CycOXiis.js.map} +1 -1
  89. package/dist/esm/production/config-BhtwQYAN.js +53 -0
  90. package/dist/esm/production/config-BhtwQYAN.js.map +1 -0
  91. package/dist/esm/production/config.js +2 -2
  92. package/dist/esm/production/{contexts-FxCndlvf.js → contexts-ry5lvNSx.js} +291 -74
  93. package/dist/esm/production/contexts-ry5lvNSx.js.map +1 -0
  94. package/dist/esm/production/debug.js +3 -1
  95. package/dist/esm/production/index.js +19 -18
  96. package/dist/esm/production/react/index.js +400 -53
  97. package/dist/esm/production/react/index.js.map +1 -1
  98. package/dist/esm/production/react/index.server.js +2 -2
  99. package/dist/esm/production/react/index.server.js.map +1 -1
  100. package/dist/esm/production/react/server.js +1 -1
  101. package/dist/esm/production/{snapshot-CdCaJJ0L.js → snapshot-1d_HVP3L.js} +7 -5
  102. package/dist/esm/production/snapshot-1d_HVP3L.js.map +1 -0
  103. package/dist/esm/production/transform/index.js +5 -2
  104. package/dist/esm/production/transform/index.js.map +1 -1
  105. package/dist/esm/production/utils.js +39 -7
  106. package/dist/esm/production/utils.js.map +1 -1
  107. package/dist/esm/react/async-component.d.ts +10 -2
  108. package/dist/esm/react/async-component.d.ts.map +1 -1
  109. package/dist/esm/react/component-server.d.ts +6 -2
  110. package/dist/esm/react/component-server.d.ts.map +1 -1
  111. package/dist/esm/react/component.d.ts +5 -2
  112. package/dist/esm/react/component.d.ts.map +1 -1
  113. package/dist/esm/react/delivery.d.ts +107 -0
  114. package/dist/esm/react/delivery.d.ts.map +1 -0
  115. package/dist/esm/react/index.d.ts +3 -2
  116. package/dist/esm/react/index.d.ts.map +1 -1
  117. package/dist/esm/react/pause-signals-context.d.ts +16 -2
  118. package/dist/esm/react/pause-signals-context.d.ts.map +1 -1
  119. package/dist/esm/react/props-hash.d.ts +20 -0
  120. package/dist/esm/react/props-hash.d.ts.map +1 -0
  121. package/dist/esm/react/use-reactive.d.ts +6 -3
  122. package/dist/esm/react/use-reactive.d.ts.map +1 -1
  123. package/dist/esm/transform/async.d.ts.map +1 -1
  124. package/dist/esm/transform/callback.d.ts.map +1 -1
  125. package/dist/esm/transform/promise.d.ts.map +1 -1
  126. package/dist/esm/transform/use-reactive.d.ts.map +1 -1
  127. package/dist/esm/transform/utils.d.ts +1 -1
  128. package/dist/esm/transform/utils.d.ts.map +1 -1
  129. package/dist/esm/types.d.ts +20 -1
  130. package/dist/esm/types.d.ts.map +1 -1
  131. package/dist/esm/utils.d.ts +17 -1
  132. package/dist/esm/utils.d.ts.map +1 -1
  133. package/package.json +1 -1
  134. package/dist/cjs/development/config-B0MtLBgx.js +0 -21
  135. package/dist/cjs/development/config-B0MtLBgx.js.map +0 -1
  136. package/dist/cjs/development/debug-C46WDxhL.js.map +0 -1
  137. package/dist/cjs/development/snapshot-CbZ6IH3B.js.map +0 -1
  138. package/dist/cjs/production/config-B0MtLBgx.js +0 -21
  139. package/dist/cjs/production/config-B0MtLBgx.js.map +0 -1
  140. package/dist/cjs/production/contexts-CM3QLfV8.js.map +0 -1
  141. package/dist/cjs/production/snapshot-DWwH7_9y.js.map +0 -1
  142. package/dist/esm/development/config-CPQL7hX-.js +0 -22
  143. package/dist/esm/development/config-CPQL7hX-.js.map +0 -1
  144. package/dist/esm/development/debug-BTLbgTPK.js.map +0 -1
  145. package/dist/esm/development/snapshot-CkndI4Hh.js.map +0 -1
  146. package/dist/esm/production/config-CPQL7hX-.js +0 -22
  147. package/dist/esm/production/config-CPQL7hX-.js.map +0 -1
  148. package/dist/esm/production/contexts-FxCndlvf.js.map +0 -1
  149. package/dist/esm/production/snapshot-CdCaJJ0L.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { s as scheduleFlush$1, r as runBatch } from "./config-CPQL7hX-.js";
1
+ import { a as scheduleFlush$1, r as runBatch, b as getRenderLeaseTtl, M as MAX_TIMEOUT } from "./config-CQLKpPRj.js";
2
2
  let UNKNOWN_SIGNAL_ID = 0;
3
3
  const UNKNOWN_SIGNAL_NAMES = /* @__PURE__ */ new Map();
4
4
  function getUnknownSignalFnName(fn) {
@@ -427,12 +427,12 @@ function watchSignal(signal2) {
427
427
  }
428
428
  activateSignal(signal2);
429
429
  }
430
- function unwatchSignal(signal2) {
430
+ function unwatchSignal(signal2, options = {}) {
431
431
  const { watchCount } = signal2;
432
432
  const newWatchCount = Math.max(watchCount - 1, 0);
433
433
  signal2.watchCount = newWatchCount;
434
434
  if (newWatchCount === 0) {
435
- scheduleDeactivate(signal2);
435
+ scheduleDeactivate(signal2, options);
436
436
  }
437
437
  }
438
438
  function activateSignal(signal2) {
@@ -442,22 +442,22 @@ function activateSignal(signal2) {
442
442
  checkSignal(signal2);
443
443
  }
444
444
  }
445
- function deactivateSignal(signal2) {
445
+ function deactivateSignal(signal2, options = {}) {
446
446
  signal2._isActive = false;
447
447
  for (const dep of signal2.deps.keys()) {
448
448
  const newWatchCount = Math.max(dep.watchCount - 1, 0);
449
449
  dep.watchCount = newWatchCount;
450
450
  if (newWatchCount === 0) {
451
- deactivateSignal(dep);
451
+ deactivateSignal(dep, options);
452
452
  }
453
453
  }
454
454
  if (isRelay(signal2)) {
455
- signal2._value?.();
455
+ signal2._value?.(options);
456
456
  }
457
457
  }
458
458
  let PENDING_PULLS = /* @__PURE__ */ new Set();
459
459
  let PENDING_ASYNC_PULLS = [];
460
- let PENDING_DEACTIVE = /* @__PURE__ */ new Set();
460
+ let PENDING_DEACTIVE = /* @__PURE__ */ new Map();
461
461
  let PENDING_LISTENERS = [];
462
462
  let PENDING_TRACERS = [];
463
463
  const microtask = () => Promise.resolve();
@@ -481,8 +481,9 @@ const scheduleAsyncPull = (signal2) => {
481
481
  PENDING_ASYNC_PULLS.push(signal2);
482
482
  scheduleFlush();
483
483
  };
484
- const scheduleDeactivate = (signal2) => {
485
- PENDING_DEACTIVE.add(signal2);
484
+ const scheduleDeactivate = (signal2, options = {}) => {
485
+ const existing = PENDING_DEACTIVE.get(signal2);
486
+ PENDING_DEACTIVE.set(signal2, existing === void 0 ? options : { isPausing: Boolean(existing.isPausing && options.isPausing) });
486
487
  scheduleFlush();
487
488
  };
488
489
  const cancelDeactivate = (signal2) => {
@@ -517,8 +518,8 @@ const flushWatchers = async () => {
517
518
  }
518
519
  currentFlush = null;
519
520
  runBatch(() => {
520
- for (const signal2 of PENDING_DEACTIVE) {
521
- deactivateSignal(signal2);
521
+ for (const [signal2, options] of PENDING_DEACTIVE) {
522
+ deactivateSignal(signal2, options);
522
523
  }
523
524
  PENDING_DEACTIVE.clear();
524
525
  for (const signal2 of PENDING_LISTENERS) {
@@ -1298,11 +1299,11 @@ function createRelay(activate, scope, opts) {
1298
1299
  const p = new ReactivePromiseImpl();
1299
1300
  let active = false;
1300
1301
  let currentSub;
1301
- const unsubscribe = () => {
1302
+ const unsubscribe = (options) => {
1302
1303
  if (typeof currentSub === "function") {
1303
1304
  currentSub();
1304
1305
  } else if (currentSub !== void 0) {
1305
- currentSub.deactivate?.();
1306
+ currentSub.deactivate?.(options);
1306
1307
  }
1307
1308
  const signal2 = p["_signal"];
1308
1309
  signal2.subs = /* @__PURE__ */ new Map();
@@ -1602,32 +1603,43 @@ function hashNumber(num, seed = 0) {
1602
1603
  h ^= h >>> 16;
1603
1604
  return h >>> 0;
1604
1605
  }
1605
- function hashArray(arr, seen) {
1606
- let h = ARRAY;
1606
+ function mixHash(h, k) {
1607
1607
  const c1 = 3432918353;
1608
1608
  const c2 = 461845907;
1609
- for (const item of arr) {
1610
- let k = hashValue(item, seen);
1611
- k = imul(k, c1);
1612
- k = k << 15 | k >>> 17;
1613
- k = imul(k, c2);
1614
- h ^= k;
1615
- h = h << 13 | h >>> 19;
1616
- h = imul(h, 5) + 3864292196;
1617
- }
1618
- h ^= arr.length;
1609
+ const n = 3864292196;
1610
+ k = imul(k, c1);
1611
+ k = k << 15 | k >>> 17;
1612
+ k = imul(k, c2);
1613
+ h ^= k;
1614
+ h = h << 13 | h >>> 19;
1615
+ return imul(h, 5) + n | 0;
1616
+ }
1617
+ function finalizeHash(h, length) {
1618
+ const fmix1 = 2246822507;
1619
+ const fmix2 = 3266489909;
1620
+ h ^= length;
1619
1621
  h ^= h >>> 16;
1620
- h = imul(h, 2246822507);
1622
+ h = imul(h, fmix1);
1621
1623
  h ^= h >>> 13;
1622
- h = imul(h, 3266489909);
1624
+ h = imul(h, fmix2);
1623
1625
  h ^= h >>> 16;
1624
1626
  return h >>> 0;
1625
1627
  }
1628
+ function hashArray(arr, seen) {
1629
+ let h = ARRAY_SEED;
1630
+ for (const item of arr) {
1631
+ h = mixHash(h, hashValue(item, seen));
1632
+ }
1633
+ return finalizeHash(h, arr.length);
1634
+ }
1626
1635
  function hashObject(obj, seen) {
1636
+ return hashObjectKeys(obj, Object.keys(obj), seen);
1637
+ }
1638
+ function hashObjectKeys(obj, keys, seen) {
1639
+ const keyMultiplier = 2654435769;
1627
1640
  let sum = OBJECT;
1628
- const keys = Object.keys(obj);
1629
1641
  for (const key of keys) {
1630
- sum += imul(hashValue(key, seen), 2654435769) ^ hashValue(obj[key], seen);
1642
+ sum += imul(hashValue(key, seen), keyMultiplier) ^ hashValue(obj[key], seen);
1631
1643
  }
1632
1644
  return sum >>> 0;
1633
1645
  }
@@ -1639,9 +1651,10 @@ function hashSet(set, seen) {
1639
1651
  return sum >>> 0;
1640
1652
  }
1641
1653
  function hashMap(map, seen) {
1654
+ const keyMultiplier = 2654435769;
1642
1655
  let sum = MAP;
1643
1656
  for (const [key, value] of map) {
1644
- sum += imul(hashValue(key, seen), 2654435769) ^ hashValue(value, seen);
1657
+ sum += imul(hashValue(key, seen), keyMultiplier) ^ hashValue(value, seen);
1645
1658
  }
1646
1659
  return sum >>> 0;
1647
1660
  }
@@ -1680,7 +1693,7 @@ const FALSE = hashStr(
1680
1693
  3
1681
1694
  /* HashType.FALSE */
1682
1695
  );
1683
- const ARRAY = hashStr(
1696
+ const ARRAY_SEED = hashStr(
1684
1697
  "array",
1685
1698
  7
1686
1699
  /* HashType.ARRAY */
@@ -1844,6 +1857,95 @@ function stringifyValue(value) {
1844
1857
  return getObjectId(value);
1845
1858
  }
1846
1859
  }
1860
+ let young = /* @__PURE__ */ new Set();
1861
+ let old = /* @__PURE__ */ new Set();
1862
+ let timer;
1863
+ const pinned = /* @__PURE__ */ new Map();
1864
+ const SUSPENDED_LEASE_HOLD_TTLS = 30;
1865
+ function armTimer() {
1866
+ timer = setTimeout(sweepLeases, getRenderLeaseTtl());
1867
+ timer.unref?.();
1868
+ }
1869
+ function sweepLeases() {
1870
+ timer = void 0;
1871
+ const expired = old;
1872
+ for (const signal2 of expired) {
1873
+ signal2._releaseLease();
1874
+ }
1875
+ expired.clear();
1876
+ old = young;
1877
+ young = expired;
1878
+ if (old.size > 0) {
1879
+ armTimer();
1880
+ }
1881
+ }
1882
+ function addLease(signal2) {
1883
+ if (!pinned.delete(signal2)) {
1884
+ old.delete(signal2);
1885
+ }
1886
+ young.add(signal2);
1887
+ if (timer === void 0) {
1888
+ armTimer();
1889
+ }
1890
+ }
1891
+ function removeLease(signal2) {
1892
+ if (!young.delete(signal2) && !old.delete(signal2)) {
1893
+ pinned.delete(signal2);
1894
+ }
1895
+ }
1896
+ function pinLease(signal2) {
1897
+ if (!signal2._isLeased) {
1898
+ return void 0;
1899
+ }
1900
+ young.delete(signal2);
1901
+ old.delete(signal2);
1902
+ const token = {};
1903
+ pinned.set(signal2, token);
1904
+ return token;
1905
+ }
1906
+ function unpinLease(signal2, token) {
1907
+ if (pinned.get(signal2) === token && signal2._isLeased) {
1908
+ addLease(signal2);
1909
+ }
1910
+ }
1911
+ function holdLeaseUntilSettled(signal2, thenable) {
1912
+ const token = pinLease(signal2);
1913
+ if (token === void 0) {
1914
+ return;
1915
+ }
1916
+ const renew = () => unpinLease(signal2, token);
1917
+ thenable.then(renew, renew);
1918
+ }
1919
+ function holdSuspendedLease(signal2) {
1920
+ const token = pinLease(signal2);
1921
+ if (token === void 0) {
1922
+ return;
1923
+ }
1924
+ const hold = setTimeout(() => unpinLease(signal2, token), Math.min(getRenderLeaseTtl() * SUSPENDED_LEASE_HOLD_TTLS, MAX_TIMEOUT));
1925
+ hold.unref?.();
1926
+ }
1927
+ function releaseAbandonedAttempt(signal2) {
1928
+ const token = pinned.get(signal2);
1929
+ if (token !== void 0) {
1930
+ unpinLease(signal2, token);
1931
+ }
1932
+ }
1933
+ function releaseRenderLeases() {
1934
+ if (timer !== void 0) {
1935
+ clearTimeout(timer);
1936
+ timer = void 0;
1937
+ }
1938
+ const leases = [...old, ...young, ...pinned.keys()];
1939
+ old = /* @__PURE__ */ new Set();
1940
+ young = /* @__PURE__ */ new Set();
1941
+ pinned.clear();
1942
+ for (const signal2 of leases) {
1943
+ signal2._releaseLease();
1944
+ }
1945
+ }
1946
+ function getRenderLeaseCount() {
1947
+ return young.size + old.size + pinned.size;
1948
+ }
1847
1949
  let ID = 0;
1848
1950
  function createReactiveDefinition(id, desc, compute, equals, isRelay2, paramKey, tracer) {
1849
1951
  const def = {
@@ -1916,6 +2018,9 @@ class ReactiveSignal {
1916
2018
  this.flags &= -33;
1917
2019
  }
1918
2020
  }
2021
+ get _isLeased() {
2022
+ return (this.flags & 128) !== 0;
2023
+ }
1919
2024
  get _isLazy() {
1920
2025
  return (this.flags & 64) !== 0;
1921
2026
  }
@@ -1930,6 +2035,7 @@ class ReactiveSignal {
1930
2035
  return this._listeners ?? (this._listeners = {
1931
2036
  updatedAt: 0,
1932
2037
  current: /* @__PURE__ */ new Map(),
2038
+ pausedReaders: 0,
1933
2039
  cachedBoundAdd: this.addListener.bind(this)
1934
2040
  });
1935
2041
  }
@@ -1937,7 +2043,8 @@ class ReactiveSignal {
1937
2043
  return getSignal(this);
1938
2044
  }
1939
2045
  addListener(listener, opts) {
1940
- const { current } = this.listeners;
2046
+ const meta = this.listeners;
2047
+ const { current } = meta;
1941
2048
  if (!current.has(listener)) {
1942
2049
  let effective = listener;
1943
2050
  if (opts?.skipInitial) {
@@ -1950,23 +2057,39 @@ class ReactiveSignal {
1950
2057
  listener();
1951
2058
  };
1952
2059
  }
1953
- if (!this._isListener) {
1954
- watchSignal(this);
1955
- this.flags |= 16;
2060
+ const flags = this.flags;
2061
+ current.set(listener, effective);
2062
+ const unpaused = meta.pausedReaders < current.size;
2063
+ if ((flags & 16) === 0) {
2064
+ this.flags = flags | 16;
2065
+ } else if ((flags & 128) !== 0 && (unpaused || (flags & 256) === 0)) {
2066
+ this.flags = flags & -129;
2067
+ removeLease(this);
2068
+ }
2069
+ if (unpaused) {
2070
+ this._takeListenerWatch();
2071
+ } else {
2072
+ this._pauseListenerWatch();
1956
2073
  }
1957
2074
  if (this.watchCount > 0) {
1958
2075
  schedulePull(this);
1959
2076
  }
1960
- current.set(listener, effective);
1961
2077
  }
1962
2078
  return () => {
1963
2079
  if (current.has(listener)) {
1964
2080
  current.delete(listener);
1965
2081
  if (current.size === 0) {
2082
+ const flags = this.flags;
2083
+ if ((flags & 128) !== 0)
2084
+ return;
1966
2085
  cancelPull(this);
1967
- unwatchSignal(this);
1968
- this.flags &= -17;
1969
- this.listeners.updatedAt = 0;
2086
+ this.flags = flags & -273;
2087
+ if ((flags & 256) !== 0) {
2088
+ unwatchSignal(this);
2089
+ }
2090
+ meta.updatedAt = 0;
2091
+ } else if (meta.pausedReaders >= current.size) {
2092
+ this._pauseListenerWatch();
1970
2093
  }
1971
2094
  }
1972
2095
  };
@@ -1974,15 +2097,99 @@ class ReactiveSignal {
1974
2097
  // This method is used in React hooks specifically. It returns a bound add method
1975
2098
  // that is cached to avoid creating a new one on each call, and it eagerly sets
1976
2099
  // the listener as watched so that relays that are accessed will be activated.
2100
+ //
2101
+ // The eager watch is a lease (see `lease.ts`): the commit's subscription claims it, and a
2102
+ // discarded render's lease expires. Each render of a still-leased signal extends it.
1977
2103
  addListenerLazy(watch = true) {
1978
- if (!this._isListener) {
2104
+ const flags = this.flags;
2105
+ if ((flags & 16) === 0) {
1979
2106
  if (watch) {
1980
2107
  watchSignal(this);
2108
+ this.flags |= 16 | 128 | 256;
2109
+ } else {
2110
+ this.flags |= 16 | 128;
2111
+ }
2112
+ addLease(this);
2113
+ } else if ((flags & 128) !== 0 || watch && (flags & 256) === 0) {
2114
+ if (watch && (flags & 256) === 0) {
2115
+ watchSignal(this);
2116
+ this.flags |= 256;
1981
2117
  }
1982
- this.flags |= 16;
2118
+ this.flags |= 128;
2119
+ addLease(this);
1983
2120
  }
1984
2121
  return this.listeners.cachedBoundAdd;
1985
2122
  }
2123
+ /** Drops the listener watch; listeners stay subscribed. */
2124
+ _pauseWatch() {
2125
+ const flags = this.flags;
2126
+ if ((flags & 256) !== 0) {
2127
+ this.flags = flags & -257;
2128
+ unwatchSignal(this, { isPausing: true });
2129
+ }
2130
+ }
2131
+ /** Retakes the listener watch, pulling changes missed while unwatched. */
2132
+ _resumeWatch() {
2133
+ if ((this.flags & 16) !== 0 && this._takeListenerWatch()) {
2134
+ schedulePull(this);
2135
+ }
2136
+ }
2137
+ _takeListenerWatch() {
2138
+ if ((this.flags & 256) !== 0) {
2139
+ return false;
2140
+ }
2141
+ watchSignal(this);
2142
+ this.flags |= 256;
2143
+ return true;
2144
+ }
2145
+ /** `deferred` reconciles in a microtask, for a reader that unregisters before it unsubscribes. */
2146
+ _addPausedReaders(delta, deferred = false) {
2147
+ this.listeners.pausedReaders += delta;
2148
+ if (deferred) {
2149
+ queueMicrotask(() => this._reconcilePausedReaders());
2150
+ } else {
2151
+ this._reconcilePausedReaders();
2152
+ }
2153
+ }
2154
+ _reconcilePausedReaders() {
2155
+ const { current, pausedReaders } = this.listeners;
2156
+ if (current.size === 0)
2157
+ return;
2158
+ if (pausedReaders < current.size) {
2159
+ this._resumeWatch();
2160
+ } else {
2161
+ this._pauseListenerWatch();
2162
+ }
2163
+ }
2164
+ /** Pauses for the listeners' sake; an unclaimed render lease's watch belongs to its render. */
2165
+ _pauseListenerWatch() {
2166
+ if ((this.flags & 128) === 0) {
2167
+ this._pauseWatch();
2168
+ }
2169
+ }
2170
+ /** Releases an unclaimed render lease; a no-op once claimed. */
2171
+ _releaseLease() {
2172
+ const flags = this.flags;
2173
+ if ((flags & 128) === 0) {
2174
+ return;
2175
+ }
2176
+ const meta = this._listeners;
2177
+ if (meta !== null && meta.current.size > 0) {
2178
+ this.flags = flags & -129;
2179
+ if (meta.pausedReaders >= meta.current.size) {
2180
+ this._pauseWatch();
2181
+ }
2182
+ return;
2183
+ }
2184
+ this.flags = flags & -401;
2185
+ if (meta !== null) {
2186
+ meta.updatedAt = 0;
2187
+ }
2188
+ cancelPull(this);
2189
+ if ((flags & 256) !== 0) {
2190
+ unwatchSignal(this);
2191
+ }
2192
+ }
1986
2193
  }
1987
2194
  const runListeners = (signal2) => {
1988
2195
  const { listeners } = signal2;
@@ -2123,26 +2330,36 @@ const getScopeOwner = (obj) => {
2123
2330
  return scope;
2124
2331
  };
2125
2332
  export {
2126
- settled as A,
2127
- context as B,
2128
- getContext as C,
2129
- withContexts as D,
2130
- setGlobalContexts as E,
2131
- clearGlobalContexts as F,
2132
- setScopeOwner as G,
2133
- setTracing as H,
2134
- createTracer as I,
2135
- createTracerFromId as J,
2136
- removeTracer as K,
2137
- Tracer as L,
2138
- SignalType as M,
2139
- getTracerProxy as N,
2140
- scheduleTracer as O,
2333
+ getRenderLeaseCount as $,
2334
+ ARRAY_SEED as A,
2335
+ getSignal as B,
2336
+ unwatchSignal as C,
2337
+ registerCustomHash as D,
2338
+ setReactivePromise as E,
2339
+ notifier as F,
2340
+ isSignal as G,
2341
+ callback as H,
2342
+ settled as I,
2343
+ context as J,
2344
+ getContext as K,
2345
+ withContexts as L,
2346
+ setGlobalContexts as M,
2347
+ clearGlobalContexts as N,
2348
+ setScopeOwner as O,
2349
+ setTracing as P,
2350
+ createTracer as Q,
2141
2351
  ReactivePromise as R,
2142
2352
  SignalScope as S,
2143
- TracerEventType as T,
2353
+ createTracerFromId as T,
2354
+ removeTracer as U,
2144
2355
  VisualizerNode as V,
2356
+ TracerEventType as W,
2357
+ Tracer as X,
2358
+ SignalType as Y,
2359
+ getTracerProxy as Z,
2360
+ scheduleTracer as _,
2145
2361
  generatorResultToPromiseWithConsumer as a,
2362
+ releaseRenderLeases as a0,
2146
2363
  getCurrentConsumer as b,
2147
2364
  createReactiveSignal as c,
2148
2365
  setRequestScopeGetter as d,
@@ -2154,19 +2371,19 @@ export {
2154
2371
  isReactivePromise as j,
2155
2372
  getGlobalScope as k,
2156
2373
  hashValue as l,
2157
- schedulePull as m,
2158
- isPromise as n,
2159
- isThennable as o,
2160
- signal as p,
2161
- getSignal as q,
2162
- runSignal as r,
2374
+ getObjectHash as m,
2375
+ hashObjectKeys as n,
2376
+ mixHash as o,
2377
+ finalizeHash as p,
2378
+ checkSignal as q,
2379
+ isPromise as r,
2163
2380
  setCurrentConsumer as s,
2164
- registerCustomHash as t,
2165
- unwatchSignal as u,
2166
- setReactivePromise as v,
2167
- watchSignal as w,
2168
- notifier as x,
2169
- isSignal as y,
2170
- callback as z
2381
+ isThennable as t,
2382
+ runSignal as u,
2383
+ holdLeaseUntilSettled as v,
2384
+ holdSuspendedLease as w,
2385
+ releaseAbandonedAttempt as x,
2386
+ signal as y,
2387
+ watchSignal as z
2171
2388
  };
2172
- //# sourceMappingURL=debug-BTLbgTPK.js.map
2389
+ //# sourceMappingURL=debug-C3HD8WcT.js.map