@fluixi/reactive 1.0.0-alpha.104 → 1.0.0-alpha.106

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 (82) hide show
  1. package/dist/cdn/reactive.cjs +74 -34
  2. package/dist/cdn/reactive.global.js +2 -2
  3. package/dist/cdn/reactive.mjs +74 -34
  4. package/dist/cdn/signal.cjs +23 -3
  5. package/dist/cdn/signal.global.js +2 -2
  6. package/dist/cdn/signal.mjs +23 -3
  7. package/dist/index.cjs +74 -34
  8. package/dist/index.mjs +74 -34
  9. package/dist/lib/index.cjs +75 -35
  10. package/dist/lib/index.mjs +75 -35
  11. package/dist/lib/observable/index.cjs +1 -1
  12. package/dist/lib/observable/index.mjs +1 -1
  13. package/dist/lib/signal/api.cjs +40 -14
  14. package/dist/lib/signal/api.mjs +40 -14
  15. package/dist/lib/signal/cached-resource.cjs +36 -13
  16. package/dist/lib/signal/cached-resource.mjs +36 -13
  17. package/dist/lib/signal/graph/children.cjs +25 -6
  18. package/dist/lib/signal/graph/children.mjs +25 -6
  19. package/dist/lib/signal/graph/compat.cjs +41 -15
  20. package/dist/lib/signal/graph/compat.d.ts.map +1 -1
  21. package/dist/lib/signal/graph/compat.js +20 -11
  22. package/dist/lib/signal/graph/compat.mjs +41 -15
  23. package/dist/lib/signal/graph/context-children.cjs +1 -1
  24. package/dist/lib/signal/graph/context-children.mjs +1 -1
  25. package/dist/lib/signal/graph/core.cjs +24 -4
  26. package/dist/lib/signal/graph/core.d.ts +10 -0
  27. package/dist/lib/signal/graph/core.d.ts.map +1 -1
  28. package/dist/lib/signal/graph/core.js +27 -2
  29. package/dist/lib/signal/graph/core.mjs +24 -4
  30. package/dist/lib/signal/graph/debounced.cjs +35 -12
  31. package/dist/lib/signal/graph/debounced.mjs +35 -12
  32. package/dist/lib/signal/graph/derived.cjs +35 -12
  33. package/dist/lib/signal/graph/derived.mjs +35 -12
  34. package/dist/lib/signal/graph/detect.cjs +1 -1
  35. package/dist/lib/signal/graph/detect.mjs +1 -1
  36. package/dist/lib/signal/graph/error-boundary.cjs +10 -8
  37. package/dist/lib/signal/graph/error-boundary.mjs +10 -8
  38. package/dist/lib/signal/graph/index.cjs +24 -4
  39. package/dist/lib/signal/graph/index.mjs +24 -4
  40. package/dist/lib/signal/graph/observe.cjs +1 -1
  41. package/dist/lib/signal/graph/observe.mjs +1 -1
  42. package/dist/lib/signal/graph/resource.cjs +35 -12
  43. package/dist/lib/signal/graph/resource.mjs +35 -12
  44. package/dist/lib/signal/graph/runtime.cjs +29 -5
  45. package/dist/lib/signal/graph/runtime.d.ts.map +1 -1
  46. package/dist/lib/signal/graph/runtime.js +5 -3
  47. package/dist/lib/signal/graph/runtime.mjs +29 -5
  48. package/dist/lib/signal/graph/signal-next.cjs +67 -29
  49. package/dist/lib/signal/graph/signal-next.mjs +67 -29
  50. package/dist/lib/signal/graph/state.cjs +1 -1
  51. package/dist/lib/signal/graph/state.mjs +1 -1
  52. package/dist/lib/signal/graph/suspense.cjs +10 -8
  53. package/dist/lib/signal/graph/suspense.mjs +10 -8
  54. package/dist/lib/signal/index-legacy.cjs +67 -29
  55. package/dist/lib/signal/index-legacy.mjs +67 -29
  56. package/dist/lib/signal/index.cjs +67 -29
  57. package/dist/lib/signal/index.mjs +67 -29
  58. package/dist/lib/signal/list.cjs +58 -25
  59. package/dist/lib/signal/list.d.ts +3 -8
  60. package/dist/lib/signal/list.d.ts.map +1 -1
  61. package/dist/lib/signal/list.js +40 -18
  62. package/dist/lib/signal/list.mjs +58 -25
  63. package/dist/lib/signal/resource-api.cjs +35 -12
  64. package/dist/lib/signal/resource-api.mjs +35 -12
  65. package/dist/lib/signal/signal.cjs +41 -15
  66. package/dist/lib/signal/signal.mjs +41 -15
  67. package/dist/lib/signal/utilities.cjs +41 -15
  68. package/dist/lib/signal/utilities.mjs +41 -15
  69. package/dist/lib/store/api.cjs +9 -7
  70. package/dist/lib/store/api.mjs +9 -7
  71. package/dist/lib/store/index.cjs +10 -8
  72. package/dist/lib/store/index.mjs +10 -8
  73. package/dist/lib/store/store.cjs +9 -7
  74. package/dist/lib/store/store.d.ts.map +1 -1
  75. package/dist/lib/store/store.js +8 -6
  76. package/dist/lib/store/store.mjs +9 -7
  77. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  78. package/dist/version.generated.cjs +2 -2
  79. package/dist/version.generated.d.ts +1 -1
  80. package/dist/version.generated.js +1 -1
  81. package/dist/version.generated.mjs +2 -2
  82. package/package.json +2 -2
@@ -45,7 +45,7 @@ __export(observe_exports, {
45
45
  module.exports = __toCommonJS(observe_exports);
46
46
 
47
47
  // src/version.generated.ts
48
- var VERSION = "1.0.0-alpha.104";
48
+ var VERSION = "1.0.0-alpha.106";
49
49
 
50
50
  // src/lib/signal/graph/state.ts
51
51
  var MAJOR = VERSION.split(".")[0];
@@ -1,5 +1,5 @@
1
1
  // src/version.generated.ts
2
- var VERSION = "1.0.0-alpha.104";
2
+ var VERSION = "1.0.0-alpha.106";
3
3
 
4
4
  // src/lib/signal/graph/state.ts
5
5
  var MAJOR = VERSION.split(".")[0];
@@ -25,7 +25,7 @@ __export(resource_exports, {
25
25
  module.exports = __toCommonJS(resource_exports);
26
26
 
27
27
  // src/version.generated.ts
28
- var VERSION = "1.0.0-alpha.104";
28
+ var VERSION = "1.0.0-alpha.106";
29
29
 
30
30
  // src/lib/signal/graph/state.ts
31
31
  var MAJOR = VERSION.split(".")[0];
@@ -167,6 +167,7 @@ var Computed = class extends Source {
167
167
  super();
168
168
  this._threw = false;
169
169
  this._initialized = false;
170
+ this._disposed = false;
170
171
  this.state = DIRTY;
171
172
  /** Nodes this computation read on its last run. Rebuilt on every run. */
172
173
  this.sources = null;
@@ -182,8 +183,23 @@ var Computed = class extends Source {
182
183
  if (this._threw) throw this._error;
183
184
  return this._value;
184
185
  }
186
+ /**
187
+ * Unlink from every source, for good. Without this, a source outlives the
188
+ * computation and keeps it (and everything its function captured) reachable
189
+ * through its observers set: a disposed list row stayed in memory that way.
190
+ * The last value stays readable; the node simply never updates again.
191
+ */
192
+ dispose() {
193
+ if (this._disposed) return;
194
+ this._disposed = true;
195
+ if (this.sources) {
196
+ for (const s of this.sources) s.observers?.delete(this);
197
+ this.sources = null;
198
+ }
199
+ }
185
200
  /** Settle, if CHECK, verify sources; if DIRTY (or never run), recompute. */
186
201
  updateIfNecessary() {
202
+ if (this._disposed) return;
187
203
  if (this.state === CHECK) {
188
204
  if (this.sources) {
189
205
  for (const s of this.sources) {
@@ -227,7 +243,7 @@ var Computed = class extends Source {
227
243
  reportReactiveRun(this);
228
244
  if (changed) {
229
245
  this.version++;
230
- if (this.observers) for (const o of [...this.observers]) o.markDirty(DIRTY);
246
+ if (this.observers) for (const o of this.observers) o.markDirty(DIRTY);
231
247
  notifyWatchers(this);
232
248
  }
233
249
  }
@@ -241,7 +257,7 @@ var Computed = class extends Source {
241
257
  const wasClean = this.state === CLEAN;
242
258
  this.state = level;
243
259
  if (wasClean) {
244
- if (this.observers) for (const o of [...this.observers]) o.markDirty(CHECK);
260
+ if (this.observers) for (const o of this.observers) o.markDirty(CHECK);
245
261
  notifyWatchers(this);
246
262
  }
247
263
  }
@@ -280,6 +296,10 @@ var Watcher = class {
280
296
  this._pending.clear();
281
297
  return out;
282
298
  }
299
+ /** Drain pending without the array, for callers that only need it empty. */
300
+ clearPending() {
301
+ this._pending.clear();
302
+ }
283
303
  /** @internal, a watched node became non-clean. Edge-triggered: notify once. */
284
304
  _notify(node) {
285
305
  if (!this._watched.has(node) || this._pending.has(node)) return;
@@ -397,14 +417,14 @@ var EffectNode = class {
397
417
  if (typeof r === "function") (this.owner.cleanups ??= []).push(r);
398
418
  });
399
419
  });
400
- reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
420
+ if (isObserved()) reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
401
421
  this.watcher = new Watcher(() => enqueue(this));
402
422
  this.run();
403
423
  this.watcher.watch(this.computed);
404
424
  }
405
425
  run() {
406
426
  if (this.disposed) return;
407
- this.watcher.getPending();
427
+ this.watcher.clearPending();
408
428
  try {
409
429
  this.computed.get();
410
430
  } catch (e) {
@@ -421,6 +441,7 @@ var EffectNode = class {
421
441
  this.disposed = true;
422
442
  reportReactiveDispose(this.computed);
423
443
  this.watcher.unwatch(this.computed);
444
+ this.computed.dispose();
424
445
  disposeOwner(this.owner);
425
446
  }
426
447
  };
@@ -455,13 +476,15 @@ function createSignal(value, options) {
455
476
  },
456
477
  enumerable: false
457
478
  });
458
- reportReactiveNode({
459
- kind: "signal",
460
- node: state,
461
- handle: read,
462
- name: options?.name,
463
- set: write
464
- });
479
+ if (isObserved()) {
480
+ reportReactiveNode({
481
+ kind: "signal",
482
+ node: state,
483
+ handle: read,
484
+ name: options?.name,
485
+ set: write
486
+ });
487
+ }
465
488
  if (isObserved()) onCleanup(() => reportReactiveDispose(state));
466
489
  return [read, write];
467
490
  }
@@ -1,5 +1,5 @@
1
1
  // src/version.generated.ts
2
- var VERSION = "1.0.0-alpha.104";
2
+ var VERSION = "1.0.0-alpha.106";
3
3
 
4
4
  // src/lib/signal/graph/state.ts
5
5
  var MAJOR = VERSION.split(".")[0];
@@ -141,6 +141,7 @@ var Computed = class extends Source {
141
141
  super();
142
142
  this._threw = false;
143
143
  this._initialized = false;
144
+ this._disposed = false;
144
145
  this.state = DIRTY;
145
146
  /** Nodes this computation read on its last run. Rebuilt on every run. */
146
147
  this.sources = null;
@@ -156,8 +157,23 @@ var Computed = class extends Source {
156
157
  if (this._threw) throw this._error;
157
158
  return this._value;
158
159
  }
160
+ /**
161
+ * Unlink from every source, for good. Without this, a source outlives the
162
+ * computation and keeps it (and everything its function captured) reachable
163
+ * through its observers set: a disposed list row stayed in memory that way.
164
+ * The last value stays readable; the node simply never updates again.
165
+ */
166
+ dispose() {
167
+ if (this._disposed) return;
168
+ this._disposed = true;
169
+ if (this.sources) {
170
+ for (const s of this.sources) s.observers?.delete(this);
171
+ this.sources = null;
172
+ }
173
+ }
159
174
  /** Settle, if CHECK, verify sources; if DIRTY (or never run), recompute. */
160
175
  updateIfNecessary() {
176
+ if (this._disposed) return;
161
177
  if (this.state === CHECK) {
162
178
  if (this.sources) {
163
179
  for (const s of this.sources) {
@@ -201,7 +217,7 @@ var Computed = class extends Source {
201
217
  reportReactiveRun(this);
202
218
  if (changed) {
203
219
  this.version++;
204
- if (this.observers) for (const o of [...this.observers]) o.markDirty(DIRTY);
220
+ if (this.observers) for (const o of this.observers) o.markDirty(DIRTY);
205
221
  notifyWatchers(this);
206
222
  }
207
223
  }
@@ -215,7 +231,7 @@ var Computed = class extends Source {
215
231
  const wasClean = this.state === CLEAN;
216
232
  this.state = level;
217
233
  if (wasClean) {
218
- if (this.observers) for (const o of [...this.observers]) o.markDirty(CHECK);
234
+ if (this.observers) for (const o of this.observers) o.markDirty(CHECK);
219
235
  notifyWatchers(this);
220
236
  }
221
237
  }
@@ -254,6 +270,10 @@ var Watcher = class {
254
270
  this._pending.clear();
255
271
  return out;
256
272
  }
273
+ /** Drain pending without the array, for callers that only need it empty. */
274
+ clearPending() {
275
+ this._pending.clear();
276
+ }
257
277
  /** @internal, a watched node became non-clean. Edge-triggered: notify once. */
258
278
  _notify(node) {
259
279
  if (!this._watched.has(node) || this._pending.has(node)) return;
@@ -371,14 +391,14 @@ var EffectNode = class {
371
391
  if (typeof r === "function") (this.owner.cleanups ??= []).push(r);
372
392
  });
373
393
  });
374
- reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
394
+ if (isObserved()) reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
375
395
  this.watcher = new Watcher(() => enqueue(this));
376
396
  this.run();
377
397
  this.watcher.watch(this.computed);
378
398
  }
379
399
  run() {
380
400
  if (this.disposed) return;
381
- this.watcher.getPending();
401
+ this.watcher.clearPending();
382
402
  try {
383
403
  this.computed.get();
384
404
  } catch (e) {
@@ -395,6 +415,7 @@ var EffectNode = class {
395
415
  this.disposed = true;
396
416
  reportReactiveDispose(this.computed);
397
417
  this.watcher.unwatch(this.computed);
418
+ this.computed.dispose();
398
419
  disposeOwner(this.owner);
399
420
  }
400
421
  };
@@ -429,13 +450,15 @@ function createSignal(value, options) {
429
450
  },
430
451
  enumerable: false
431
452
  });
432
- reportReactiveNode({
433
- kind: "signal",
434
- node: state,
435
- handle: read,
436
- name: options?.name,
437
- set: write
438
- });
453
+ if (isObserved()) {
454
+ reportReactiveNode({
455
+ kind: "signal",
456
+ node: state,
457
+ handle: read,
458
+ name: options?.name,
459
+ set: write
460
+ });
461
+ }
439
462
  if (isObserved()) onCleanup(() => reportReactiveDispose(state));
440
463
  return [read, write];
441
464
  }
@@ -44,7 +44,7 @@ __export(runtime_exports, {
44
44
  module.exports = __toCommonJS(runtime_exports);
45
45
 
46
46
  // src/version.generated.ts
47
- var VERSION = "1.0.0-alpha.104";
47
+ var VERSION = "1.0.0-alpha.106";
48
48
 
49
49
  // src/lib/signal/graph/state.ts
50
50
  var MAJOR = VERSION.split(".")[0];
@@ -133,6 +133,9 @@ if (typeof hook?.inject === "function") {
133
133
  } catch {
134
134
  }
135
135
  }
136
+ function isObserved() {
137
+ return G.observer != null;
138
+ }
136
139
 
137
140
  // src/lib/signal/graph/core.ts
138
141
  var CLEAN = 0;
@@ -165,6 +168,7 @@ var Computed = class extends Source {
165
168
  super();
166
169
  this._threw = false;
167
170
  this._initialized = false;
171
+ this._disposed = false;
168
172
  this.state = DIRTY;
169
173
  /** Nodes this computation read on its last run. Rebuilt on every run. */
170
174
  this.sources = null;
@@ -180,8 +184,23 @@ var Computed = class extends Source {
180
184
  if (this._threw) throw this._error;
181
185
  return this._value;
182
186
  }
187
+ /**
188
+ * Unlink from every source, for good. Without this, a source outlives the
189
+ * computation and keeps it (and everything its function captured) reachable
190
+ * through its observers set: a disposed list row stayed in memory that way.
191
+ * The last value stays readable; the node simply never updates again.
192
+ */
193
+ dispose() {
194
+ if (this._disposed) return;
195
+ this._disposed = true;
196
+ if (this.sources) {
197
+ for (const s of this.sources) s.observers?.delete(this);
198
+ this.sources = null;
199
+ }
200
+ }
183
201
  /** Settle, if CHECK, verify sources; if DIRTY (or never run), recompute. */
184
202
  updateIfNecessary() {
203
+ if (this._disposed) return;
185
204
  if (this.state === CHECK) {
186
205
  if (this.sources) {
187
206
  for (const s of this.sources) {
@@ -225,7 +244,7 @@ var Computed = class extends Source {
225
244
  reportReactiveRun(this);
226
245
  if (changed) {
227
246
  this.version++;
228
- if (this.observers) for (const o of [...this.observers]) o.markDirty(DIRTY);
247
+ if (this.observers) for (const o of this.observers) o.markDirty(DIRTY);
229
248
  notifyWatchers(this);
230
249
  }
231
250
  }
@@ -239,7 +258,7 @@ var Computed = class extends Source {
239
258
  const wasClean = this.state === CLEAN;
240
259
  this.state = level;
241
260
  if (wasClean) {
242
- if (this.observers) for (const o of [...this.observers]) o.markDirty(CHECK);
261
+ if (this.observers) for (const o of this.observers) o.markDirty(CHECK);
243
262
  notifyWatchers(this);
244
263
  }
245
264
  }
@@ -278,6 +297,10 @@ var Watcher = class {
278
297
  this._pending.clear();
279
298
  return out;
280
299
  }
300
+ /** Drain pending without the array, for callers that only need it empty. */
301
+ clearPending() {
302
+ this._pending.clear();
303
+ }
281
304
  /** @internal, a watched node became non-clean. Edge-triggered: notify once. */
282
305
  _notify(node) {
283
306
  if (!this._watched.has(node) || this._pending.has(node)) return;
@@ -489,14 +512,14 @@ var EffectNode = class {
489
512
  if (typeof r === "function") (this.owner.cleanups ??= []).push(r);
490
513
  });
491
514
  });
492
- reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
515
+ if (isObserved()) reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
493
516
  this.watcher = new Watcher(() => enqueue(this));
494
517
  this.run();
495
518
  this.watcher.watch(this.computed);
496
519
  }
497
520
  run() {
498
521
  if (this.disposed) return;
499
- this.watcher.getPending();
522
+ this.watcher.clearPending();
500
523
  try {
501
524
  this.computed.get();
502
525
  } catch (e) {
@@ -513,6 +536,7 @@ var EffectNode = class {
513
536
  this.disposed = true;
514
537
  reportReactiveDispose(this.computed);
515
538
  this.watcher.unwatch(this.computed);
539
+ this.computed.dispose();
516
540
  disposeOwner(this.owner);
517
541
  }
518
542
  };
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../../src/lib/signal/graph/runtime.ts"],"names":[],"mappings":"AA8BA,MAAM,WAAW,KAAK;IACpB,QAAQ,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC;IACnC,KAAK,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,KAAK,GAAG,IAAI,CAAC;IACrB,mFAAmF;IACnF,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACtC;+EAC2E;IAC3E,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,KAAK,GAAG,IAAI,GAAG,KAAK,CAI5D;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,UAAO,GAAG,IAAI,CAE7D;AAED,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,GAAG,OAAO,CAE5D;AAUD,MAAM,WAAW,OAAO,CAAC,CAAC;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,CAAC,GAAG,SAAS,CAAC;IAC5B,0GAA0G;IAI1G,QAAQ,EAAE,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,CAAC,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,GAAG,CAAC;CAC7E;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAyB5E;AAED,qEAAqE;AACrE,wBAAgB,UAAU,CAAC,CAAC,EAAE,OAAO,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,CAAC,CAAA;CAAE,GAAG,CAAC,GAAG,SAAS,CAYtF;AAED,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,CAO1F;AAED,qEAAqE;AACrE,wBAAgB,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAW3E;AAGD,kFAAkF;AAClF,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,CAAC,GAAG,IAAI,GACpE,IAAI,CAEN;AAED,+FAA+F;AAC/F,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAMhE;AAED,0FAA0F;AAC1F,wBAAgB,eAAe,CAC7B,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,KAAK,OAAO,CAAC,GAAG,IAAI,GAC5D,IAAI,CAEN;AAED,wBAAgB,QAAQ,IAAI,KAAK,GAAG,IAAI,CAEvC;AAED,2FAA2F;AAC3F,wBAAgB,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,IAAI,CAI1D;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAQnE;AAED,uDAAuD;AACvD,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI,CAO9C;AAmBD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAU/D;AAGD,wBAAgB,YAAY,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI,CAEzE;AAYD,qDAAqD;AACrD,wBAAgB,SAAS,IAAI,IAAI,CAmChC;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAEjC;AAED,gEAAgE;AAChE,wBAAgB,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAOvC;AAoED,0FAA0F;AAC1F,wBAAgB,MAAM,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,EAAE,MAAM,UAAQ,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,IAAI,CAK/F"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../../src/lib/signal/graph/runtime.ts"],"names":[],"mappings":"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"}
@@ -20,7 +20,7 @@
20
20
  */
21
21
  import { Computed, Watcher, untrack } from './core.js';
22
22
  import { G } from './state.js';
23
- import { reportReactiveContext, reportReactiveContextCreated, reportReactiveDispose, reportReactiveNode, } from './observe.js';
23
+ import { isObserved, reportReactiveContext, reportReactiveContextCreated, reportReactiveDispose, reportReactiveNode, } from './observe.js';
24
24
  /**
25
25
  * A child scope of `parent`, attached so the parent's teardown disposes it too.
26
26
  *
@@ -313,7 +313,8 @@ class EffectNode {
313
313
  // Before the first run, so a watcher counts that run like every later one. A render
314
314
  // effect is reported too, marked as plumbing: it is not worth drawing, but a node made
315
315
  // inside one has to be able to find its way back to the component that caused it.
316
- reportReactiveNode({ kind: 'effect', node: this.computed, handle: this, internal: !report, ...(name ? { name } : {}) });
316
+ if (isObserved())
317
+ reportReactiveNode({ kind: 'effect', node: this.computed, handle: this, internal: !report, ...(name ? { name } : {}) });
317
318
  // The watcher only schedules; the recompute happens on flush.
318
319
  this.watcher = new Watcher(() => enqueue(this));
319
320
  this.run(); // initial synchronous run (Solid semantics)
@@ -322,7 +323,7 @@ class EffectNode {
322
323
  run() {
323
324
  if (this.disposed)
324
325
  return;
325
- this.watcher.getPending(); // clear pending; reading re-arms the watcher
326
+ this.watcher.clearPending(); // clear pending; reading re-arms the watcher
326
327
  try {
327
328
  this.computed.get(); // recompute if dirty (re-runs the effect body)
328
329
  }
@@ -346,6 +347,7 @@ class EffectNode {
346
347
  this.disposed = true;
347
348
  reportReactiveDispose(this.computed);
348
349
  this.watcher.unwatch(this.computed);
350
+ this.computed.dispose();
349
351
  disposeOwner(this.owner);
350
352
  }
351
353
  }
@@ -1,5 +1,5 @@
1
1
  // src/version.generated.ts
2
- var VERSION = "1.0.0-alpha.104";
2
+ var VERSION = "1.0.0-alpha.106";
3
3
 
4
4
  // src/lib/signal/graph/state.ts
5
5
  var MAJOR = VERSION.split(".")[0];
@@ -88,6 +88,9 @@ if (typeof hook?.inject === "function") {
88
88
  } catch {
89
89
  }
90
90
  }
91
+ function isObserved() {
92
+ return G.observer != null;
93
+ }
91
94
 
92
95
  // src/lib/signal/graph/core.ts
93
96
  var CLEAN = 0;
@@ -120,6 +123,7 @@ var Computed = class extends Source {
120
123
  super();
121
124
  this._threw = false;
122
125
  this._initialized = false;
126
+ this._disposed = false;
123
127
  this.state = DIRTY;
124
128
  /** Nodes this computation read on its last run. Rebuilt on every run. */
125
129
  this.sources = null;
@@ -135,8 +139,23 @@ var Computed = class extends Source {
135
139
  if (this._threw) throw this._error;
136
140
  return this._value;
137
141
  }
142
+ /**
143
+ * Unlink from every source, for good. Without this, a source outlives the
144
+ * computation and keeps it (and everything its function captured) reachable
145
+ * through its observers set: a disposed list row stayed in memory that way.
146
+ * The last value stays readable; the node simply never updates again.
147
+ */
148
+ dispose() {
149
+ if (this._disposed) return;
150
+ this._disposed = true;
151
+ if (this.sources) {
152
+ for (const s of this.sources) s.observers?.delete(this);
153
+ this.sources = null;
154
+ }
155
+ }
138
156
  /** Settle, if CHECK, verify sources; if DIRTY (or never run), recompute. */
139
157
  updateIfNecessary() {
158
+ if (this._disposed) return;
140
159
  if (this.state === CHECK) {
141
160
  if (this.sources) {
142
161
  for (const s of this.sources) {
@@ -180,7 +199,7 @@ var Computed = class extends Source {
180
199
  reportReactiveRun(this);
181
200
  if (changed) {
182
201
  this.version++;
183
- if (this.observers) for (const o of [...this.observers]) o.markDirty(DIRTY);
202
+ if (this.observers) for (const o of this.observers) o.markDirty(DIRTY);
184
203
  notifyWatchers(this);
185
204
  }
186
205
  }
@@ -194,7 +213,7 @@ var Computed = class extends Source {
194
213
  const wasClean = this.state === CLEAN;
195
214
  this.state = level;
196
215
  if (wasClean) {
197
- if (this.observers) for (const o of [...this.observers]) o.markDirty(CHECK);
216
+ if (this.observers) for (const o of this.observers) o.markDirty(CHECK);
198
217
  notifyWatchers(this);
199
218
  }
200
219
  }
@@ -233,6 +252,10 @@ var Watcher = class {
233
252
  this._pending.clear();
234
253
  return out;
235
254
  }
255
+ /** Drain pending without the array, for callers that only need it empty. */
256
+ clearPending() {
257
+ this._pending.clear();
258
+ }
236
259
  /** @internal, a watched node became non-clean. Edge-triggered: notify once. */
237
260
  _notify(node) {
238
261
  if (!this._watched.has(node) || this._pending.has(node)) return;
@@ -444,14 +467,14 @@ var EffectNode = class {
444
467
  if (typeof r === "function") (this.owner.cleanups ??= []).push(r);
445
468
  });
446
469
  });
447
- reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
470
+ if (isObserved()) reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
448
471
  this.watcher = new Watcher(() => enqueue(this));
449
472
  this.run();
450
473
  this.watcher.watch(this.computed);
451
474
  }
452
475
  run() {
453
476
  if (this.disposed) return;
454
- this.watcher.getPending();
477
+ this.watcher.clearPending();
455
478
  try {
456
479
  this.computed.get();
457
480
  } catch (e) {
@@ -468,6 +491,7 @@ var EffectNode = class {
468
491
  this.disposed = true;
469
492
  reportReactiveDispose(this.computed);
470
493
  this.watcher.unwatch(this.computed);
494
+ this.computed.dispose();
471
495
  disposeOwner(this.owner);
472
496
  }
473
497
  };