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,5 +1,5 @@
1
1
  "use strict";
2
- const config = require("./config-B0MtLBgx.js");
2
+ const config = require("./config-BHvmcsLQ.js");
3
3
  let CURRENT_CONSUMER;
4
4
  const setCurrentConsumer = (consumer) => {
5
5
  CURRENT_CONSUMER = consumer;
@@ -100,12 +100,12 @@ function watchSignal(signal2) {
100
100
  }
101
101
  activateSignal(signal2);
102
102
  }
103
- function unwatchSignal(signal2) {
103
+ function unwatchSignal(signal2, options = {}) {
104
104
  const { watchCount } = signal2;
105
105
  const newWatchCount = Math.max(watchCount - 1, 0);
106
106
  signal2.watchCount = newWatchCount;
107
107
  if (newWatchCount === 0) {
108
- scheduleDeactivate(signal2);
108
+ scheduleDeactivate(signal2, options);
109
109
  }
110
110
  }
111
111
  function activateSignal(signal2) {
@@ -115,22 +115,22 @@ function activateSignal(signal2) {
115
115
  checkSignal(signal2);
116
116
  }
117
117
  }
118
- function deactivateSignal(signal2) {
118
+ function deactivateSignal(signal2, options = {}) {
119
119
  signal2._isActive = false;
120
120
  for (const dep of signal2.deps.keys()) {
121
121
  const newWatchCount = Math.max(dep.watchCount - 1, 0);
122
122
  dep.watchCount = newWatchCount;
123
123
  if (newWatchCount === 0) {
124
- deactivateSignal(dep);
124
+ deactivateSignal(dep, options);
125
125
  }
126
126
  }
127
127
  if (isRelay(signal2)) {
128
- signal2._value?.();
128
+ signal2._value?.(options);
129
129
  }
130
130
  }
131
131
  let PENDING_PULLS = /* @__PURE__ */ new Set();
132
132
  let PENDING_ASYNC_PULLS = [];
133
- let PENDING_DEACTIVE = /* @__PURE__ */ new Set();
133
+ let PENDING_DEACTIVE = /* @__PURE__ */ new Map();
134
134
  let PENDING_LISTENERS = [];
135
135
  const microtask = () => Promise.resolve();
136
136
  let currentFlush = null;
@@ -153,8 +153,9 @@ const scheduleAsyncPull = (signal2) => {
153
153
  PENDING_ASYNC_PULLS.push(signal2);
154
154
  scheduleFlush();
155
155
  };
156
- const scheduleDeactivate = (signal2) => {
157
- PENDING_DEACTIVE.add(signal2);
156
+ const scheduleDeactivate = (signal2, options = {}) => {
157
+ const existing = PENDING_DEACTIVE.get(signal2);
158
+ PENDING_DEACTIVE.set(signal2, existing === void 0 ? options : { isPausing: Boolean(existing.isPausing && options.isPausing) });
158
159
  scheduleFlush();
159
160
  };
160
161
  const cancelDeactivate = (signal2) => {
@@ -185,8 +186,8 @@ const flushWatchers = async () => {
185
186
  }
186
187
  currentFlush = null;
187
188
  config.runBatch(() => {
188
- for (const signal2 of PENDING_DEACTIVE) {
189
- deactivateSignal(signal2);
189
+ for (const [signal2, options] of PENDING_DEACTIVE) {
190
+ deactivateSignal(signal2, options);
190
191
  }
191
192
  PENDING_DEACTIVE.clear();
192
193
  for (const signal2 of PENDING_LISTENERS) {
@@ -928,11 +929,11 @@ function createRelay(activate, scope, opts) {
928
929
  const p = new ReactivePromiseImpl();
929
930
  let active = false;
930
931
  let currentSub;
931
- const unsubscribe = () => {
932
+ const unsubscribe = (options) => {
932
933
  if (typeof currentSub === "function") {
933
934
  currentSub();
934
935
  } else if (currentSub !== void 0) {
935
- currentSub.deactivate?.();
936
+ currentSub.deactivate?.(options);
936
937
  }
937
938
  const signal2 = p["_signal"];
938
939
  signal2.subs = /* @__PURE__ */ new Map();
@@ -1204,32 +1205,43 @@ function hashNumber(num, seed = 0) {
1204
1205
  h ^= h >>> 16;
1205
1206
  return h >>> 0;
1206
1207
  }
1207
- function hashArray(arr, seen) {
1208
- let h = ARRAY;
1208
+ function mixHash(h, k) {
1209
1209
  const c1 = 3432918353;
1210
1210
  const c2 = 461845907;
1211
- for (const item of arr) {
1212
- let k = hashValue(item, seen);
1213
- k = imul(k, c1);
1214
- k = k << 15 | k >>> 17;
1215
- k = imul(k, c2);
1216
- h ^= k;
1217
- h = h << 13 | h >>> 19;
1218
- h = imul(h, 5) + 3864292196;
1219
- }
1220
- h ^= arr.length;
1211
+ const n = 3864292196;
1212
+ k = imul(k, c1);
1213
+ k = k << 15 | k >>> 17;
1214
+ k = imul(k, c2);
1215
+ h ^= k;
1216
+ h = h << 13 | h >>> 19;
1217
+ return imul(h, 5) + n | 0;
1218
+ }
1219
+ function finalizeHash(h, length) {
1220
+ const fmix1 = 2246822507;
1221
+ const fmix2 = 3266489909;
1222
+ h ^= length;
1221
1223
  h ^= h >>> 16;
1222
- h = imul(h, 2246822507);
1224
+ h = imul(h, fmix1);
1223
1225
  h ^= h >>> 13;
1224
- h = imul(h, 3266489909);
1226
+ h = imul(h, fmix2);
1225
1227
  h ^= h >>> 16;
1226
1228
  return h >>> 0;
1227
1229
  }
1230
+ function hashArray(arr, seen) {
1231
+ let h = ARRAY_SEED;
1232
+ for (const item of arr) {
1233
+ h = mixHash(h, hashValue(item, seen));
1234
+ }
1235
+ return finalizeHash(h, arr.length);
1236
+ }
1228
1237
  function hashObject(obj, seen) {
1238
+ return hashObjectKeys(obj, Object.keys(obj), seen);
1239
+ }
1240
+ function hashObjectKeys(obj, keys, seen) {
1241
+ const keyMultiplier = 2654435769;
1229
1242
  let sum = OBJECT;
1230
- const keys = Object.keys(obj);
1231
1243
  for (const key of keys) {
1232
- sum += imul(hashValue(key, seen), 2654435769) ^ hashValue(obj[key], seen);
1244
+ sum += imul(hashValue(key, seen), keyMultiplier) ^ hashValue(obj[key], seen);
1233
1245
  }
1234
1246
  return sum >>> 0;
1235
1247
  }
@@ -1241,9 +1253,10 @@ function hashSet(set, seen) {
1241
1253
  return sum >>> 0;
1242
1254
  }
1243
1255
  function hashMap(map, seen) {
1256
+ const keyMultiplier = 2654435769;
1244
1257
  let sum = MAP;
1245
1258
  for (const [key, value] of map) {
1246
- sum += imul(hashValue(key, seen), 2654435769) ^ hashValue(value, seen);
1259
+ sum += imul(hashValue(key, seen), keyMultiplier) ^ hashValue(value, seen);
1247
1260
  }
1248
1261
  return sum >>> 0;
1249
1262
  }
@@ -1282,7 +1295,7 @@ const FALSE = hashStr(
1282
1295
  3
1283
1296
  /* HashType.FALSE */
1284
1297
  );
1285
- const ARRAY = hashStr(
1298
+ const ARRAY_SEED = hashStr(
1286
1299
  "array",
1287
1300
  7
1288
1301
  /* HashType.ARRAY */
@@ -1394,6 +1407,95 @@ function hashReactiveFn(fn, args) {
1394
1407
  h = h << 13 | h >>> 19;
1395
1408
  return imul(h, 5) + 3864292196 >>> 0;
1396
1409
  }
1410
+ let young = /* @__PURE__ */ new Set();
1411
+ let old = /* @__PURE__ */ new Set();
1412
+ let timer;
1413
+ const pinned = /* @__PURE__ */ new Map();
1414
+ const SUSPENDED_LEASE_HOLD_TTLS = 30;
1415
+ function armTimer() {
1416
+ timer = setTimeout(sweepLeases, config.getRenderLeaseTtl());
1417
+ timer.unref?.();
1418
+ }
1419
+ function sweepLeases() {
1420
+ timer = void 0;
1421
+ const expired = old;
1422
+ for (const signal2 of expired) {
1423
+ signal2._releaseLease();
1424
+ }
1425
+ expired.clear();
1426
+ old = young;
1427
+ young = expired;
1428
+ if (old.size > 0) {
1429
+ armTimer();
1430
+ }
1431
+ }
1432
+ function addLease(signal2) {
1433
+ if (!pinned.delete(signal2)) {
1434
+ old.delete(signal2);
1435
+ }
1436
+ young.add(signal2);
1437
+ if (timer === void 0) {
1438
+ armTimer();
1439
+ }
1440
+ }
1441
+ function removeLease(signal2) {
1442
+ if (!young.delete(signal2) && !old.delete(signal2)) {
1443
+ pinned.delete(signal2);
1444
+ }
1445
+ }
1446
+ function pinLease(signal2) {
1447
+ if (!signal2._isLeased) {
1448
+ return void 0;
1449
+ }
1450
+ young.delete(signal2);
1451
+ old.delete(signal2);
1452
+ const token = {};
1453
+ pinned.set(signal2, token);
1454
+ return token;
1455
+ }
1456
+ function unpinLease(signal2, token) {
1457
+ if (pinned.get(signal2) === token && signal2._isLeased) {
1458
+ addLease(signal2);
1459
+ }
1460
+ }
1461
+ function holdLeaseUntilSettled(signal2, thenable) {
1462
+ const token = pinLease(signal2);
1463
+ if (token === void 0) {
1464
+ return;
1465
+ }
1466
+ const renew = () => unpinLease(signal2, token);
1467
+ thenable.then(renew, renew);
1468
+ }
1469
+ function holdSuspendedLease(signal2) {
1470
+ const token = pinLease(signal2);
1471
+ if (token === void 0) {
1472
+ return;
1473
+ }
1474
+ const hold = setTimeout(() => unpinLease(signal2, token), Math.min(config.getRenderLeaseTtl() * SUSPENDED_LEASE_HOLD_TTLS, config.MAX_TIMEOUT));
1475
+ hold.unref?.();
1476
+ }
1477
+ function releaseAbandonedAttempt(signal2) {
1478
+ const token = pinned.get(signal2);
1479
+ if (token !== void 0) {
1480
+ unpinLease(signal2, token);
1481
+ }
1482
+ }
1483
+ function releaseRenderLeases() {
1484
+ if (timer !== void 0) {
1485
+ clearTimeout(timer);
1486
+ timer = void 0;
1487
+ }
1488
+ const leases = [...old, ...young, ...pinned.keys()];
1489
+ old = /* @__PURE__ */ new Set();
1490
+ young = /* @__PURE__ */ new Set();
1491
+ pinned.clear();
1492
+ for (const signal2 of leases) {
1493
+ signal2._releaseLease();
1494
+ }
1495
+ }
1496
+ function getRenderLeaseCount() {
1497
+ return young.size + old.size + pinned.size;
1498
+ }
1397
1499
  let ID = 0;
1398
1500
  function createReactiveDefinition(id, desc, compute, equals, isRelay2, paramKey, tracer) {
1399
1501
  const def = {
@@ -1453,6 +1555,9 @@ class ReactiveSignal {
1453
1555
  this.flags &= -33;
1454
1556
  }
1455
1557
  }
1558
+ get _isLeased() {
1559
+ return (this.flags & 128) !== 0;
1560
+ }
1456
1561
  get _isLazy() {
1457
1562
  return (this.flags & 64) !== 0;
1458
1563
  }
@@ -1467,6 +1572,7 @@ class ReactiveSignal {
1467
1572
  return this._listeners ?? (this._listeners = {
1468
1573
  updatedAt: 0,
1469
1574
  current: /* @__PURE__ */ new Map(),
1575
+ pausedReaders: 0,
1470
1576
  cachedBoundAdd: this.addListener.bind(this)
1471
1577
  });
1472
1578
  }
@@ -1474,7 +1580,8 @@ class ReactiveSignal {
1474
1580
  return getSignal(this);
1475
1581
  }
1476
1582
  addListener(listener, opts) {
1477
- const { current } = this.listeners;
1583
+ const meta = this.listeners;
1584
+ const { current } = meta;
1478
1585
  if (!current.has(listener)) {
1479
1586
  let effective = listener;
1480
1587
  if (opts?.skipInitial) {
@@ -1487,23 +1594,39 @@ class ReactiveSignal {
1487
1594
  listener();
1488
1595
  };
1489
1596
  }
1490
- if (!this._isListener) {
1491
- watchSignal(this);
1492
- this.flags |= 16;
1597
+ const flags = this.flags;
1598
+ current.set(listener, effective);
1599
+ const unpaused = meta.pausedReaders < current.size;
1600
+ if ((flags & 16) === 0) {
1601
+ this.flags = flags | 16;
1602
+ } else if ((flags & 128) !== 0 && (unpaused || (flags & 256) === 0)) {
1603
+ this.flags = flags & -129;
1604
+ removeLease(this);
1605
+ }
1606
+ if (unpaused) {
1607
+ this._takeListenerWatch();
1608
+ } else {
1609
+ this._pauseListenerWatch();
1493
1610
  }
1494
1611
  if (this.watchCount > 0) {
1495
1612
  schedulePull(this);
1496
1613
  }
1497
- current.set(listener, effective);
1498
1614
  }
1499
1615
  return () => {
1500
1616
  if (current.has(listener)) {
1501
1617
  current.delete(listener);
1502
1618
  if (current.size === 0) {
1619
+ const flags = this.flags;
1620
+ if ((flags & 128) !== 0)
1621
+ return;
1503
1622
  cancelPull(this);
1504
- unwatchSignal(this);
1505
- this.flags &= -17;
1506
- this.listeners.updatedAt = 0;
1623
+ this.flags = flags & -273;
1624
+ if ((flags & 256) !== 0) {
1625
+ unwatchSignal(this);
1626
+ }
1627
+ meta.updatedAt = 0;
1628
+ } else if (meta.pausedReaders >= current.size) {
1629
+ this._pauseListenerWatch();
1507
1630
  }
1508
1631
  }
1509
1632
  };
@@ -1511,15 +1634,99 @@ class ReactiveSignal {
1511
1634
  // This method is used in React hooks specifically. It returns a bound add method
1512
1635
  // that is cached to avoid creating a new one on each call, and it eagerly sets
1513
1636
  // the listener as watched so that relays that are accessed will be activated.
1637
+ //
1638
+ // The eager watch is a lease (see `lease.ts`): the commit's subscription claims it, and a
1639
+ // discarded render's lease expires. Each render of a still-leased signal extends it.
1514
1640
  addListenerLazy(watch = true) {
1515
- if (!this._isListener) {
1641
+ const flags = this.flags;
1642
+ if ((flags & 16) === 0) {
1516
1643
  if (watch) {
1517
1644
  watchSignal(this);
1645
+ this.flags |= 16 | 128 | 256;
1646
+ } else {
1647
+ this.flags |= 16 | 128;
1518
1648
  }
1519
- this.flags |= 16;
1649
+ addLease(this);
1650
+ } else if ((flags & 128) !== 0 || watch && (flags & 256) === 0) {
1651
+ if (watch && (flags & 256) === 0) {
1652
+ watchSignal(this);
1653
+ this.flags |= 256;
1654
+ }
1655
+ this.flags |= 128;
1656
+ addLease(this);
1520
1657
  }
1521
1658
  return this.listeners.cachedBoundAdd;
1522
1659
  }
1660
+ /** Drops the listener watch; listeners stay subscribed. */
1661
+ _pauseWatch() {
1662
+ const flags = this.flags;
1663
+ if ((flags & 256) !== 0) {
1664
+ this.flags = flags & -257;
1665
+ unwatchSignal(this, { isPausing: true });
1666
+ }
1667
+ }
1668
+ /** Retakes the listener watch, pulling changes missed while unwatched. */
1669
+ _resumeWatch() {
1670
+ if ((this.flags & 16) !== 0 && this._takeListenerWatch()) {
1671
+ schedulePull(this);
1672
+ }
1673
+ }
1674
+ _takeListenerWatch() {
1675
+ if ((this.flags & 256) !== 0) {
1676
+ return false;
1677
+ }
1678
+ watchSignal(this);
1679
+ this.flags |= 256;
1680
+ return true;
1681
+ }
1682
+ /** `deferred` reconciles in a microtask, for a reader that unregisters before it unsubscribes. */
1683
+ _addPausedReaders(delta, deferred = false) {
1684
+ this.listeners.pausedReaders += delta;
1685
+ if (deferred) {
1686
+ queueMicrotask(() => this._reconcilePausedReaders());
1687
+ } else {
1688
+ this._reconcilePausedReaders();
1689
+ }
1690
+ }
1691
+ _reconcilePausedReaders() {
1692
+ const { current, pausedReaders } = this.listeners;
1693
+ if (current.size === 0)
1694
+ return;
1695
+ if (pausedReaders < current.size) {
1696
+ this._resumeWatch();
1697
+ } else {
1698
+ this._pauseListenerWatch();
1699
+ }
1700
+ }
1701
+ /** Pauses for the listeners' sake; an unclaimed render lease's watch belongs to its render. */
1702
+ _pauseListenerWatch() {
1703
+ if ((this.flags & 128) === 0) {
1704
+ this._pauseWatch();
1705
+ }
1706
+ }
1707
+ /** Releases an unclaimed render lease; a no-op once claimed. */
1708
+ _releaseLease() {
1709
+ const flags = this.flags;
1710
+ if ((flags & 128) === 0) {
1711
+ return;
1712
+ }
1713
+ const meta = this._listeners;
1714
+ if (meta !== null && meta.current.size > 0) {
1715
+ this.flags = flags & -129;
1716
+ if (meta.pausedReaders >= meta.current.size) {
1717
+ this._pauseWatch();
1718
+ }
1719
+ return;
1720
+ }
1721
+ this.flags = flags & -401;
1722
+ if (meta !== null) {
1723
+ meta.updatedAt = 0;
1724
+ }
1725
+ cancelPull(this);
1726
+ if ((flags & 256) !== 0) {
1727
+ unwatchSignal(this);
1728
+ }
1729
+ }
1523
1730
  }
1524
1731
  const runListeners = (signal2) => {
1525
1732
  const { listeners } = signal2;
@@ -1659,31 +1866,41 @@ const getScopeOwner = (obj) => {
1659
1866
  }
1660
1867
  return scope;
1661
1868
  };
1869
+ exports.ARRAY_SEED = ARRAY_SEED;
1662
1870
  exports.ReactivePromise = ReactivePromise;
1663
1871
  exports.SignalScope = SignalScope;
1664
1872
  exports.callback = callback;
1873
+ exports.checkSignal = checkSignal;
1665
1874
  exports.clearGlobalContexts = clearGlobalContexts;
1666
1875
  exports.context = context;
1667
1876
  exports.createReactiveDefinition = createReactiveDefinition;
1668
1877
  exports.createReactiveSignal = createReactiveSignal;
1669
1878
  exports.createRelay = createRelay;
1670
1879
  exports.createTask = createTask;
1880
+ exports.finalizeHash = finalizeHash;
1671
1881
  exports.generatorResultToPromiseWithConsumer = generatorResultToPromiseWithConsumer;
1672
1882
  exports.getContext = getContext;
1673
1883
  exports.getCurrentConsumer = getCurrentConsumer;
1674
1884
  exports.getCurrentScope = getCurrentScope;
1675
1885
  exports.getGlobalScope = getGlobalScope;
1886
+ exports.getObjectHash = getObjectHash;
1887
+ exports.getRenderLeaseCount = getRenderLeaseCount;
1676
1888
  exports.getScopeOwner = getScopeOwner;
1677
1889
  exports.getSignal = getSignal;
1890
+ exports.hashObjectKeys = hashObjectKeys;
1678
1891
  exports.hashValue = hashValue;
1892
+ exports.holdLeaseUntilSettled = holdLeaseUntilSettled;
1893
+ exports.holdSuspendedLease = holdSuspendedLease;
1679
1894
  exports.isPromise = isPromise;
1680
1895
  exports.isReactivePromise = isReactivePromise;
1681
1896
  exports.isSignal = isSignal;
1682
1897
  exports.isThennable = isThennable;
1898
+ exports.mixHash = mixHash;
1683
1899
  exports.notifier = notifier;
1684
1900
  exports.registerCustomHash = registerCustomHash;
1901
+ exports.releaseAbandonedAttempt = releaseAbandonedAttempt;
1902
+ exports.releaseRenderLeases = releaseRenderLeases;
1685
1903
  exports.runSignal = runSignal;
1686
- exports.schedulePull = schedulePull;
1687
1904
  exports.scheduleTracer = scheduleTracer;
1688
1905
  exports.setCurrentConsumer = setCurrentConsumer;
1689
1906
  exports.setGlobalContexts = setGlobalContexts;
@@ -1695,4 +1912,4 @@ exports.signal = signal;
1695
1912
  exports.unwatchSignal = unwatchSignal;
1696
1913
  exports.watchSignal = watchSignal;
1697
1914
  exports.withContexts = withContexts;
1698
- //# sourceMappingURL=contexts-CM3QLfV8.js.map
1915
+ //# sourceMappingURL=contexts-waczQzHZ.js.map