@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.
- package/dist/cdn/reactive.cjs +74 -34
- package/dist/cdn/reactive.global.js +2 -2
- package/dist/cdn/reactive.mjs +74 -34
- package/dist/cdn/signal.cjs +23 -3
- package/dist/cdn/signal.global.js +2 -2
- package/dist/cdn/signal.mjs +23 -3
- package/dist/index.cjs +74 -34
- package/dist/index.mjs +74 -34
- package/dist/lib/index.cjs +75 -35
- package/dist/lib/index.mjs +75 -35
- package/dist/lib/observable/index.cjs +1 -1
- package/dist/lib/observable/index.mjs +1 -1
- package/dist/lib/signal/api.cjs +40 -14
- package/dist/lib/signal/api.mjs +40 -14
- package/dist/lib/signal/cached-resource.cjs +36 -13
- package/dist/lib/signal/cached-resource.mjs +36 -13
- package/dist/lib/signal/graph/children.cjs +25 -6
- package/dist/lib/signal/graph/children.mjs +25 -6
- package/dist/lib/signal/graph/compat.cjs +41 -15
- package/dist/lib/signal/graph/compat.d.ts.map +1 -1
- package/dist/lib/signal/graph/compat.js +20 -11
- package/dist/lib/signal/graph/compat.mjs +41 -15
- package/dist/lib/signal/graph/context-children.cjs +1 -1
- package/dist/lib/signal/graph/context-children.mjs +1 -1
- package/dist/lib/signal/graph/core.cjs +24 -4
- package/dist/lib/signal/graph/core.d.ts +10 -0
- package/dist/lib/signal/graph/core.d.ts.map +1 -1
- package/dist/lib/signal/graph/core.js +27 -2
- package/dist/lib/signal/graph/core.mjs +24 -4
- package/dist/lib/signal/graph/debounced.cjs +35 -12
- package/dist/lib/signal/graph/debounced.mjs +35 -12
- package/dist/lib/signal/graph/derived.cjs +35 -12
- package/dist/lib/signal/graph/derived.mjs +35 -12
- package/dist/lib/signal/graph/detect.cjs +1 -1
- package/dist/lib/signal/graph/detect.mjs +1 -1
- package/dist/lib/signal/graph/error-boundary.cjs +10 -8
- package/dist/lib/signal/graph/error-boundary.mjs +10 -8
- package/dist/lib/signal/graph/index.cjs +24 -4
- package/dist/lib/signal/graph/index.mjs +24 -4
- package/dist/lib/signal/graph/observe.cjs +1 -1
- package/dist/lib/signal/graph/observe.mjs +1 -1
- package/dist/lib/signal/graph/resource.cjs +35 -12
- package/dist/lib/signal/graph/resource.mjs +35 -12
- package/dist/lib/signal/graph/runtime.cjs +29 -5
- package/dist/lib/signal/graph/runtime.d.ts.map +1 -1
- package/dist/lib/signal/graph/runtime.js +5 -3
- package/dist/lib/signal/graph/runtime.mjs +29 -5
- package/dist/lib/signal/graph/signal-next.cjs +67 -29
- package/dist/lib/signal/graph/signal-next.mjs +67 -29
- package/dist/lib/signal/graph/state.cjs +1 -1
- package/dist/lib/signal/graph/state.mjs +1 -1
- package/dist/lib/signal/graph/suspense.cjs +10 -8
- package/dist/lib/signal/graph/suspense.mjs +10 -8
- package/dist/lib/signal/index-legacy.cjs +67 -29
- package/dist/lib/signal/index-legacy.mjs +67 -29
- package/dist/lib/signal/index.cjs +67 -29
- package/dist/lib/signal/index.mjs +67 -29
- package/dist/lib/signal/list.cjs +58 -25
- package/dist/lib/signal/list.d.ts +3 -8
- package/dist/lib/signal/list.d.ts.map +1 -1
- package/dist/lib/signal/list.js +40 -18
- package/dist/lib/signal/list.mjs +58 -25
- package/dist/lib/signal/resource-api.cjs +35 -12
- package/dist/lib/signal/resource-api.mjs +35 -12
- package/dist/lib/signal/signal.cjs +41 -15
- package/dist/lib/signal/signal.mjs +41 -15
- package/dist/lib/signal/utilities.cjs +41 -15
- package/dist/lib/signal/utilities.mjs +41 -15
- package/dist/lib/store/api.cjs +9 -7
- package/dist/lib/store/api.mjs +9 -7
- package/dist/lib/store/index.cjs +10 -8
- package/dist/lib/store/index.mjs +10 -8
- package/dist/lib/store/store.cjs +9 -7
- package/dist/lib/store/store.d.ts.map +1 -1
- package/dist/lib/store/store.js +8 -6
- package/dist/lib/store/store.mjs +9 -7
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/dist/version.generated.cjs +2 -2
- package/dist/version.generated.d.ts +1 -1
- package/dist/version.generated.js +1 -1
- package/dist/version.generated.mjs +2 -2
- package/package.json +2 -2
package/dist/lib/signal/api.cjs
CHANGED
|
@@ -32,7 +32,7 @@ __export(api_exports, {
|
|
|
32
32
|
module.exports = __toCommonJS(api_exports);
|
|
33
33
|
|
|
34
34
|
// src/version.generated.ts
|
|
35
|
-
var VERSION = "1.0.0-alpha.
|
|
35
|
+
var VERSION = "1.0.0-alpha.106";
|
|
36
36
|
|
|
37
37
|
// src/lib/signal/graph/state.ts
|
|
38
38
|
var MAJOR = VERSION.split(".")[0];
|
|
@@ -182,6 +182,7 @@ var Computed = class extends Source {
|
|
|
182
182
|
super();
|
|
183
183
|
this._threw = false;
|
|
184
184
|
this._initialized = false;
|
|
185
|
+
this._disposed = false;
|
|
185
186
|
this.state = DIRTY;
|
|
186
187
|
/** Nodes this computation read on its last run. Rebuilt on every run. */
|
|
187
188
|
this.sources = null;
|
|
@@ -197,8 +198,23 @@ var Computed = class extends Source {
|
|
|
197
198
|
if (this._threw) throw this._error;
|
|
198
199
|
return this._value;
|
|
199
200
|
}
|
|
201
|
+
/**
|
|
202
|
+
* Unlink from every source, for good. Without this, a source outlives the
|
|
203
|
+
* computation and keeps it (and everything its function captured) reachable
|
|
204
|
+
* through its observers set: a disposed list row stayed in memory that way.
|
|
205
|
+
* The last value stays readable; the node simply never updates again.
|
|
206
|
+
*/
|
|
207
|
+
dispose() {
|
|
208
|
+
if (this._disposed) return;
|
|
209
|
+
this._disposed = true;
|
|
210
|
+
if (this.sources) {
|
|
211
|
+
for (const s of this.sources) s.observers?.delete(this);
|
|
212
|
+
this.sources = null;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
200
215
|
/** Settle, if CHECK, verify sources; if DIRTY (or never run), recompute. */
|
|
201
216
|
updateIfNecessary() {
|
|
217
|
+
if (this._disposed) return;
|
|
202
218
|
if (this.state === CHECK) {
|
|
203
219
|
if (this.sources) {
|
|
204
220
|
for (const s of this.sources) {
|
|
@@ -242,7 +258,7 @@ var Computed = class extends Source {
|
|
|
242
258
|
reportReactiveRun(this);
|
|
243
259
|
if (changed) {
|
|
244
260
|
this.version++;
|
|
245
|
-
if (this.observers) for (const o of
|
|
261
|
+
if (this.observers) for (const o of this.observers) o.markDirty(DIRTY);
|
|
246
262
|
notifyWatchers(this);
|
|
247
263
|
}
|
|
248
264
|
}
|
|
@@ -256,7 +272,7 @@ var Computed = class extends Source {
|
|
|
256
272
|
const wasClean = this.state === CLEAN;
|
|
257
273
|
this.state = level;
|
|
258
274
|
if (wasClean) {
|
|
259
|
-
if (this.observers) for (const o of
|
|
275
|
+
if (this.observers) for (const o of this.observers) o.markDirty(CHECK);
|
|
260
276
|
notifyWatchers(this);
|
|
261
277
|
}
|
|
262
278
|
}
|
|
@@ -295,6 +311,10 @@ var Watcher = class {
|
|
|
295
311
|
this._pending.clear();
|
|
296
312
|
return out;
|
|
297
313
|
}
|
|
314
|
+
/** Drain pending without the array, for callers that only need it empty. */
|
|
315
|
+
clearPending() {
|
|
316
|
+
this._pending.clear();
|
|
317
|
+
}
|
|
298
318
|
/** @internal, a watched node became non-clean. Edge-triggered: notify once. */
|
|
299
319
|
_notify(node) {
|
|
300
320
|
if (!this._watched.has(node) || this._pending.has(node)) return;
|
|
@@ -448,14 +468,14 @@ var EffectNode = class {
|
|
|
448
468
|
if (typeof r === "function") (this.owner.cleanups ??= []).push(r);
|
|
449
469
|
});
|
|
450
470
|
});
|
|
451
|
-
reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
|
|
471
|
+
if (isObserved()) reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
|
|
452
472
|
this.watcher = new Watcher(() => enqueue(this));
|
|
453
473
|
this.run();
|
|
454
474
|
this.watcher.watch(this.computed);
|
|
455
475
|
}
|
|
456
476
|
run() {
|
|
457
477
|
if (this.disposed) return;
|
|
458
|
-
this.watcher.
|
|
478
|
+
this.watcher.clearPending();
|
|
459
479
|
try {
|
|
460
480
|
this.computed.get();
|
|
461
481
|
} catch (e) {
|
|
@@ -472,6 +492,7 @@ var EffectNode = class {
|
|
|
472
492
|
this.disposed = true;
|
|
473
493
|
reportReactiveDispose(this.computed);
|
|
474
494
|
this.watcher.unwatch(this.computed);
|
|
495
|
+
this.computed.dispose();
|
|
475
496
|
disposeOwner(this.owner);
|
|
476
497
|
}
|
|
477
498
|
};
|
|
@@ -510,13 +531,15 @@ function createSignal(value, options) {
|
|
|
510
531
|
},
|
|
511
532
|
enumerable: false
|
|
512
533
|
});
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
534
|
+
if (isObserved()) {
|
|
535
|
+
reportReactiveNode({
|
|
536
|
+
kind: "signal",
|
|
537
|
+
node: state,
|
|
538
|
+
handle: read,
|
|
539
|
+
name: options?.name,
|
|
540
|
+
set: write
|
|
541
|
+
});
|
|
542
|
+
}
|
|
520
543
|
if (isObserved()) onCleanup(() => reportReactiveDispose(state));
|
|
521
544
|
return [read, write];
|
|
522
545
|
}
|
|
@@ -540,8 +563,11 @@ function createMemo(fn, value, options) {
|
|
|
540
563
|
const read = (() => c.get());
|
|
541
564
|
Object.defineProperty(read, $SIGNAL, { value: true, enumerable: true });
|
|
542
565
|
Object.defineProperty(read, $MEMO, { value: true, enumerable: true });
|
|
543
|
-
reportReactiveNode({ kind: "memo", node: c, handle: read, name: options?.name });
|
|
544
|
-
|
|
566
|
+
if (isObserved()) reportReactiveNode({ kind: "memo", node: c, handle: read, name: options?.name });
|
|
567
|
+
onCleanup(() => {
|
|
568
|
+
c.dispose();
|
|
569
|
+
if (isObserved()) reportReactiveDispose(c);
|
|
570
|
+
});
|
|
545
571
|
return read;
|
|
546
572
|
}
|
|
547
573
|
function createEffect(fn, value, options) {
|
package/dist/lib/signal/api.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/version.generated.ts
|
|
2
|
-
var VERSION = "1.0.0-alpha.
|
|
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];
|
|
@@ -149,6 +149,7 @@ var Computed = class extends Source {
|
|
|
149
149
|
super();
|
|
150
150
|
this._threw = false;
|
|
151
151
|
this._initialized = false;
|
|
152
|
+
this._disposed = false;
|
|
152
153
|
this.state = DIRTY;
|
|
153
154
|
/** Nodes this computation read on its last run. Rebuilt on every run. */
|
|
154
155
|
this.sources = null;
|
|
@@ -164,8 +165,23 @@ var Computed = class extends Source {
|
|
|
164
165
|
if (this._threw) throw this._error;
|
|
165
166
|
return this._value;
|
|
166
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* Unlink from every source, for good. Without this, a source outlives the
|
|
170
|
+
* computation and keeps it (and everything its function captured) reachable
|
|
171
|
+
* through its observers set: a disposed list row stayed in memory that way.
|
|
172
|
+
* The last value stays readable; the node simply never updates again.
|
|
173
|
+
*/
|
|
174
|
+
dispose() {
|
|
175
|
+
if (this._disposed) return;
|
|
176
|
+
this._disposed = true;
|
|
177
|
+
if (this.sources) {
|
|
178
|
+
for (const s of this.sources) s.observers?.delete(this);
|
|
179
|
+
this.sources = null;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
167
182
|
/** Settle, if CHECK, verify sources; if DIRTY (or never run), recompute. */
|
|
168
183
|
updateIfNecessary() {
|
|
184
|
+
if (this._disposed) return;
|
|
169
185
|
if (this.state === CHECK) {
|
|
170
186
|
if (this.sources) {
|
|
171
187
|
for (const s of this.sources) {
|
|
@@ -209,7 +225,7 @@ var Computed = class extends Source {
|
|
|
209
225
|
reportReactiveRun(this);
|
|
210
226
|
if (changed) {
|
|
211
227
|
this.version++;
|
|
212
|
-
if (this.observers) for (const o of
|
|
228
|
+
if (this.observers) for (const o of this.observers) o.markDirty(DIRTY);
|
|
213
229
|
notifyWatchers(this);
|
|
214
230
|
}
|
|
215
231
|
}
|
|
@@ -223,7 +239,7 @@ var Computed = class extends Source {
|
|
|
223
239
|
const wasClean = this.state === CLEAN;
|
|
224
240
|
this.state = level;
|
|
225
241
|
if (wasClean) {
|
|
226
|
-
if (this.observers) for (const o of
|
|
242
|
+
if (this.observers) for (const o of this.observers) o.markDirty(CHECK);
|
|
227
243
|
notifyWatchers(this);
|
|
228
244
|
}
|
|
229
245
|
}
|
|
@@ -262,6 +278,10 @@ var Watcher = class {
|
|
|
262
278
|
this._pending.clear();
|
|
263
279
|
return out;
|
|
264
280
|
}
|
|
281
|
+
/** Drain pending without the array, for callers that only need it empty. */
|
|
282
|
+
clearPending() {
|
|
283
|
+
this._pending.clear();
|
|
284
|
+
}
|
|
265
285
|
/** @internal, a watched node became non-clean. Edge-triggered: notify once. */
|
|
266
286
|
_notify(node) {
|
|
267
287
|
if (!this._watched.has(node) || this._pending.has(node)) return;
|
|
@@ -415,14 +435,14 @@ var EffectNode = class {
|
|
|
415
435
|
if (typeof r === "function") (this.owner.cleanups ??= []).push(r);
|
|
416
436
|
});
|
|
417
437
|
});
|
|
418
|
-
reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
|
|
438
|
+
if (isObserved()) reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
|
|
419
439
|
this.watcher = new Watcher(() => enqueue(this));
|
|
420
440
|
this.run();
|
|
421
441
|
this.watcher.watch(this.computed);
|
|
422
442
|
}
|
|
423
443
|
run() {
|
|
424
444
|
if (this.disposed) return;
|
|
425
|
-
this.watcher.
|
|
445
|
+
this.watcher.clearPending();
|
|
426
446
|
try {
|
|
427
447
|
this.computed.get();
|
|
428
448
|
} catch (e) {
|
|
@@ -439,6 +459,7 @@ var EffectNode = class {
|
|
|
439
459
|
this.disposed = true;
|
|
440
460
|
reportReactiveDispose(this.computed);
|
|
441
461
|
this.watcher.unwatch(this.computed);
|
|
462
|
+
this.computed.dispose();
|
|
442
463
|
disposeOwner(this.owner);
|
|
443
464
|
}
|
|
444
465
|
};
|
|
@@ -477,13 +498,15 @@ function createSignal(value, options) {
|
|
|
477
498
|
},
|
|
478
499
|
enumerable: false
|
|
479
500
|
});
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
501
|
+
if (isObserved()) {
|
|
502
|
+
reportReactiveNode({
|
|
503
|
+
kind: "signal",
|
|
504
|
+
node: state,
|
|
505
|
+
handle: read,
|
|
506
|
+
name: options?.name,
|
|
507
|
+
set: write
|
|
508
|
+
});
|
|
509
|
+
}
|
|
487
510
|
if (isObserved()) onCleanup(() => reportReactiveDispose(state));
|
|
488
511
|
return [read, write];
|
|
489
512
|
}
|
|
@@ -507,8 +530,11 @@ function createMemo(fn, value, options) {
|
|
|
507
530
|
const read = (() => c.get());
|
|
508
531
|
Object.defineProperty(read, $SIGNAL, { value: true, enumerable: true });
|
|
509
532
|
Object.defineProperty(read, $MEMO, { value: true, enumerable: true });
|
|
510
|
-
reportReactiveNode({ kind: "memo", node: c, handle: read, name: options?.name });
|
|
511
|
-
|
|
533
|
+
if (isObserved()) reportReactiveNode({ kind: "memo", node: c, handle: read, name: options?.name });
|
|
534
|
+
onCleanup(() => {
|
|
535
|
+
c.dispose();
|
|
536
|
+
if (isObserved()) reportReactiveDispose(c);
|
|
537
|
+
});
|
|
512
538
|
return read;
|
|
513
539
|
}
|
|
514
540
|
function createEffect(fn, value, options) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @fluixi/reactive v1.0.0-alpha.
|
|
1
|
+
/*! @fluixi/reactive v1.0.0-alpha.106 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
|
|
2
2
|
"use strict";
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -28,7 +28,7 @@ __export(cached_resource_exports, {
|
|
|
28
28
|
module.exports = __toCommonJS(cached_resource_exports);
|
|
29
29
|
|
|
30
30
|
// src/version.generated.ts
|
|
31
|
-
var VERSION = "1.0.0-alpha.
|
|
31
|
+
var VERSION = "1.0.0-alpha.106";
|
|
32
32
|
|
|
33
33
|
// src/lib/signal/graph/state.ts
|
|
34
34
|
var MAJOR = VERSION.split(".")[0];
|
|
@@ -170,6 +170,7 @@ var Computed = class extends Source {
|
|
|
170
170
|
super();
|
|
171
171
|
this._threw = false;
|
|
172
172
|
this._initialized = false;
|
|
173
|
+
this._disposed = false;
|
|
173
174
|
this.state = DIRTY;
|
|
174
175
|
/** Nodes this computation read on its last run. Rebuilt on every run. */
|
|
175
176
|
this.sources = null;
|
|
@@ -185,8 +186,23 @@ var Computed = class extends Source {
|
|
|
185
186
|
if (this._threw) throw this._error;
|
|
186
187
|
return this._value;
|
|
187
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* Unlink from every source, for good. Without this, a source outlives the
|
|
191
|
+
* computation and keeps it (and everything its function captured) reachable
|
|
192
|
+
* through its observers set: a disposed list row stayed in memory that way.
|
|
193
|
+
* The last value stays readable; the node simply never updates again.
|
|
194
|
+
*/
|
|
195
|
+
dispose() {
|
|
196
|
+
if (this._disposed) return;
|
|
197
|
+
this._disposed = true;
|
|
198
|
+
if (this.sources) {
|
|
199
|
+
for (const s of this.sources) s.observers?.delete(this);
|
|
200
|
+
this.sources = null;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
188
203
|
/** Settle, if CHECK, verify sources; if DIRTY (or never run), recompute. */
|
|
189
204
|
updateIfNecessary() {
|
|
205
|
+
if (this._disposed) return;
|
|
190
206
|
if (this.state === CHECK) {
|
|
191
207
|
if (this.sources) {
|
|
192
208
|
for (const s of this.sources) {
|
|
@@ -230,7 +246,7 @@ var Computed = class extends Source {
|
|
|
230
246
|
reportReactiveRun(this);
|
|
231
247
|
if (changed) {
|
|
232
248
|
this.version++;
|
|
233
|
-
if (this.observers) for (const o of
|
|
249
|
+
if (this.observers) for (const o of this.observers) o.markDirty(DIRTY);
|
|
234
250
|
notifyWatchers(this);
|
|
235
251
|
}
|
|
236
252
|
}
|
|
@@ -244,7 +260,7 @@ var Computed = class extends Source {
|
|
|
244
260
|
const wasClean = this.state === CLEAN;
|
|
245
261
|
this.state = level;
|
|
246
262
|
if (wasClean) {
|
|
247
|
-
if (this.observers) for (const o of
|
|
263
|
+
if (this.observers) for (const o of this.observers) o.markDirty(CHECK);
|
|
248
264
|
notifyWatchers(this);
|
|
249
265
|
}
|
|
250
266
|
}
|
|
@@ -283,6 +299,10 @@ var Watcher = class {
|
|
|
283
299
|
this._pending.clear();
|
|
284
300
|
return out;
|
|
285
301
|
}
|
|
302
|
+
/** Drain pending without the array, for callers that only need it empty. */
|
|
303
|
+
clearPending() {
|
|
304
|
+
this._pending.clear();
|
|
305
|
+
}
|
|
286
306
|
/** @internal, a watched node became non-clean. Edge-triggered: notify once. */
|
|
287
307
|
_notify(node) {
|
|
288
308
|
if (!this._watched.has(node) || this._pending.has(node)) return;
|
|
@@ -400,14 +420,14 @@ var EffectNode = class {
|
|
|
400
420
|
if (typeof r === "function") (this.owner.cleanups ??= []).push(r);
|
|
401
421
|
});
|
|
402
422
|
});
|
|
403
|
-
reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
|
|
423
|
+
if (isObserved()) reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
|
|
404
424
|
this.watcher = new Watcher(() => enqueue(this));
|
|
405
425
|
this.run();
|
|
406
426
|
this.watcher.watch(this.computed);
|
|
407
427
|
}
|
|
408
428
|
run() {
|
|
409
429
|
if (this.disposed) return;
|
|
410
|
-
this.watcher.
|
|
430
|
+
this.watcher.clearPending();
|
|
411
431
|
try {
|
|
412
432
|
this.computed.get();
|
|
413
433
|
} catch (e) {
|
|
@@ -424,6 +444,7 @@ var EffectNode = class {
|
|
|
424
444
|
this.disposed = true;
|
|
425
445
|
reportReactiveDispose(this.computed);
|
|
426
446
|
this.watcher.unwatch(this.computed);
|
|
447
|
+
this.computed.dispose();
|
|
427
448
|
disposeOwner(this.owner);
|
|
428
449
|
}
|
|
429
450
|
};
|
|
@@ -458,13 +479,15 @@ function createSignal(value, options) {
|
|
|
458
479
|
},
|
|
459
480
|
enumerable: false
|
|
460
481
|
});
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
482
|
+
if (isObserved()) {
|
|
483
|
+
reportReactiveNode({
|
|
484
|
+
kind: "signal",
|
|
485
|
+
node: state,
|
|
486
|
+
handle: read,
|
|
487
|
+
name: options?.name,
|
|
488
|
+
set: write
|
|
489
|
+
});
|
|
490
|
+
}
|
|
468
491
|
if (isObserved()) onCleanup(() => reportReactiveDispose(state));
|
|
469
492
|
return [read, write];
|
|
470
493
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/*! @fluixi/reactive v1.0.0-alpha.
|
|
1
|
+
/*! @fluixi/reactive v1.0.0-alpha.106 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
|
|
2
2
|
|
|
3
3
|
// src/version.generated.ts
|
|
4
|
-
var VERSION = "1.0.0-alpha.
|
|
4
|
+
var VERSION = "1.0.0-alpha.106";
|
|
5
5
|
|
|
6
6
|
// src/lib/signal/graph/state.ts
|
|
7
7
|
var MAJOR = VERSION.split(".")[0];
|
|
@@ -143,6 +143,7 @@ var Computed = class extends Source {
|
|
|
143
143
|
super();
|
|
144
144
|
this._threw = false;
|
|
145
145
|
this._initialized = false;
|
|
146
|
+
this._disposed = false;
|
|
146
147
|
this.state = DIRTY;
|
|
147
148
|
/** Nodes this computation read on its last run. Rebuilt on every run. */
|
|
148
149
|
this.sources = null;
|
|
@@ -158,8 +159,23 @@ var Computed = class extends Source {
|
|
|
158
159
|
if (this._threw) throw this._error;
|
|
159
160
|
return this._value;
|
|
160
161
|
}
|
|
162
|
+
/**
|
|
163
|
+
* Unlink from every source, for good. Without this, a source outlives the
|
|
164
|
+
* computation and keeps it (and everything its function captured) reachable
|
|
165
|
+
* through its observers set: a disposed list row stayed in memory that way.
|
|
166
|
+
* The last value stays readable; the node simply never updates again.
|
|
167
|
+
*/
|
|
168
|
+
dispose() {
|
|
169
|
+
if (this._disposed) return;
|
|
170
|
+
this._disposed = true;
|
|
171
|
+
if (this.sources) {
|
|
172
|
+
for (const s of this.sources) s.observers?.delete(this);
|
|
173
|
+
this.sources = null;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
161
176
|
/** Settle, if CHECK, verify sources; if DIRTY (or never run), recompute. */
|
|
162
177
|
updateIfNecessary() {
|
|
178
|
+
if (this._disposed) return;
|
|
163
179
|
if (this.state === CHECK) {
|
|
164
180
|
if (this.sources) {
|
|
165
181
|
for (const s of this.sources) {
|
|
@@ -203,7 +219,7 @@ var Computed = class extends Source {
|
|
|
203
219
|
reportReactiveRun(this);
|
|
204
220
|
if (changed) {
|
|
205
221
|
this.version++;
|
|
206
|
-
if (this.observers) for (const o of
|
|
222
|
+
if (this.observers) for (const o of this.observers) o.markDirty(DIRTY);
|
|
207
223
|
notifyWatchers(this);
|
|
208
224
|
}
|
|
209
225
|
}
|
|
@@ -217,7 +233,7 @@ var Computed = class extends Source {
|
|
|
217
233
|
const wasClean = this.state === CLEAN;
|
|
218
234
|
this.state = level;
|
|
219
235
|
if (wasClean) {
|
|
220
|
-
if (this.observers) for (const o of
|
|
236
|
+
if (this.observers) for (const o of this.observers) o.markDirty(CHECK);
|
|
221
237
|
notifyWatchers(this);
|
|
222
238
|
}
|
|
223
239
|
}
|
|
@@ -256,6 +272,10 @@ var Watcher = class {
|
|
|
256
272
|
this._pending.clear();
|
|
257
273
|
return out;
|
|
258
274
|
}
|
|
275
|
+
/** Drain pending without the array, for callers that only need it empty. */
|
|
276
|
+
clearPending() {
|
|
277
|
+
this._pending.clear();
|
|
278
|
+
}
|
|
259
279
|
/** @internal, a watched node became non-clean. Edge-triggered: notify once. */
|
|
260
280
|
_notify(node) {
|
|
261
281
|
if (!this._watched.has(node) || this._pending.has(node)) return;
|
|
@@ -373,14 +393,14 @@ var EffectNode = class {
|
|
|
373
393
|
if (typeof r === "function") (this.owner.cleanups ??= []).push(r);
|
|
374
394
|
});
|
|
375
395
|
});
|
|
376
|
-
reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
|
|
396
|
+
if (isObserved()) reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
|
|
377
397
|
this.watcher = new Watcher(() => enqueue(this));
|
|
378
398
|
this.run();
|
|
379
399
|
this.watcher.watch(this.computed);
|
|
380
400
|
}
|
|
381
401
|
run() {
|
|
382
402
|
if (this.disposed) return;
|
|
383
|
-
this.watcher.
|
|
403
|
+
this.watcher.clearPending();
|
|
384
404
|
try {
|
|
385
405
|
this.computed.get();
|
|
386
406
|
} catch (e) {
|
|
@@ -397,6 +417,7 @@ var EffectNode = class {
|
|
|
397
417
|
this.disposed = true;
|
|
398
418
|
reportReactiveDispose(this.computed);
|
|
399
419
|
this.watcher.unwatch(this.computed);
|
|
420
|
+
this.computed.dispose();
|
|
400
421
|
disposeOwner(this.owner);
|
|
401
422
|
}
|
|
402
423
|
};
|
|
@@ -431,13 +452,15 @@ function createSignal(value, options) {
|
|
|
431
452
|
},
|
|
432
453
|
enumerable: false
|
|
433
454
|
});
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
455
|
+
if (isObserved()) {
|
|
456
|
+
reportReactiveNode({
|
|
457
|
+
kind: "signal",
|
|
458
|
+
node: state,
|
|
459
|
+
handle: read,
|
|
460
|
+
name: options?.name,
|
|
461
|
+
set: write
|
|
462
|
+
});
|
|
463
|
+
}
|
|
441
464
|
if (isObserved()) onCleanup(() => reportReactiveDispose(state));
|
|
442
465
|
return [read, write];
|
|
443
466
|
}
|
|
@@ -25,7 +25,7 @@ __export(children_exports, {
|
|
|
25
25
|
module.exports = __toCommonJS(children_exports);
|
|
26
26
|
|
|
27
27
|
// src/version.generated.ts
|
|
28
|
-
var VERSION = "1.0.0-alpha.
|
|
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];
|
|
@@ -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
|
|
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
|
|
234
|
+
if (this.observers) for (const o of this.observers) o.markDirty(CHECK);
|
|
219
235
|
notifyWatchers(this);
|
|
220
236
|
}
|
|
221
237
|
}
|
|
@@ -290,14 +306,17 @@ function createMemo(fn, value, options) {
|
|
|
290
306
|
const read = (() => c.get());
|
|
291
307
|
Object.defineProperty(read, $SIGNAL, { value: true, enumerable: true });
|
|
292
308
|
Object.defineProperty(read, $MEMO, { value: true, enumerable: true });
|
|
293
|
-
reportReactiveNode({ kind: "memo", node: c, handle: read, name: options?.name });
|
|
294
|
-
|
|
309
|
+
if (isObserved()) reportReactiveNode({ kind: "memo", node: c, handle: read, name: options?.name });
|
|
310
|
+
onCleanup(() => {
|
|
311
|
+
c.dispose();
|
|
312
|
+
if (isObserved()) reportReactiveDispose(c);
|
|
313
|
+
});
|
|
295
314
|
return read;
|
|
296
315
|
}
|
|
297
316
|
|
|
298
317
|
// src/lib/signal/graph/detect.ts
|
|
299
318
|
var __BROWSER_PROD__ = typeof window === "undefined" ? false : window.__FLUIXI_PROD__ === true;
|
|
300
|
-
var __DEV__ = typeof process === "undefined" ? __BROWSER_PROD__ :
|
|
319
|
+
var __DEV__ = typeof process === "undefined" ? __BROWSER_PROD__ : process.env.NODE_ENV !== "production";
|
|
301
320
|
var $SIGNAL2 = /* @__PURE__ */ Symbol.for("signal");
|
|
302
321
|
function isSignal(value) {
|
|
303
322
|
return typeof value === "function" && value[$SIGNAL2] === true;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/version.generated.ts
|
|
2
|
-
var VERSION = "1.0.0-alpha.
|
|
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];
|
|
@@ -115,6 +115,7 @@ var Computed = class extends Source {
|
|
|
115
115
|
super();
|
|
116
116
|
this._threw = false;
|
|
117
117
|
this._initialized = false;
|
|
118
|
+
this._disposed = false;
|
|
118
119
|
this.state = DIRTY;
|
|
119
120
|
/** Nodes this computation read on its last run. Rebuilt on every run. */
|
|
120
121
|
this.sources = null;
|
|
@@ -130,8 +131,23 @@ var Computed = class extends Source {
|
|
|
130
131
|
if (this._threw) throw this._error;
|
|
131
132
|
return this._value;
|
|
132
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Unlink from every source, for good. Without this, a source outlives the
|
|
136
|
+
* computation and keeps it (and everything its function captured) reachable
|
|
137
|
+
* through its observers set: a disposed list row stayed in memory that way.
|
|
138
|
+
* The last value stays readable; the node simply never updates again.
|
|
139
|
+
*/
|
|
140
|
+
dispose() {
|
|
141
|
+
if (this._disposed) return;
|
|
142
|
+
this._disposed = true;
|
|
143
|
+
if (this.sources) {
|
|
144
|
+
for (const s of this.sources) s.observers?.delete(this);
|
|
145
|
+
this.sources = null;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
133
148
|
/** Settle, if CHECK, verify sources; if DIRTY (or never run), recompute. */
|
|
134
149
|
updateIfNecessary() {
|
|
150
|
+
if (this._disposed) return;
|
|
135
151
|
if (this.state === CHECK) {
|
|
136
152
|
if (this.sources) {
|
|
137
153
|
for (const s of this.sources) {
|
|
@@ -175,7 +191,7 @@ var Computed = class extends Source {
|
|
|
175
191
|
reportReactiveRun(this);
|
|
176
192
|
if (changed) {
|
|
177
193
|
this.version++;
|
|
178
|
-
if (this.observers) for (const o of
|
|
194
|
+
if (this.observers) for (const o of this.observers) o.markDirty(DIRTY);
|
|
179
195
|
notifyWatchers(this);
|
|
180
196
|
}
|
|
181
197
|
}
|
|
@@ -189,7 +205,7 @@ var Computed = class extends Source {
|
|
|
189
205
|
const wasClean = this.state === CLEAN;
|
|
190
206
|
this.state = level;
|
|
191
207
|
if (wasClean) {
|
|
192
|
-
if (this.observers) for (const o of
|
|
208
|
+
if (this.observers) for (const o of this.observers) o.markDirty(CHECK);
|
|
193
209
|
notifyWatchers(this);
|
|
194
210
|
}
|
|
195
211
|
}
|
|
@@ -264,14 +280,17 @@ function createMemo(fn, value, options) {
|
|
|
264
280
|
const read = (() => c.get());
|
|
265
281
|
Object.defineProperty(read, $SIGNAL, { value: true, enumerable: true });
|
|
266
282
|
Object.defineProperty(read, $MEMO, { value: true, enumerable: true });
|
|
267
|
-
reportReactiveNode({ kind: "memo", node: c, handle: read, name: options?.name });
|
|
268
|
-
|
|
283
|
+
if (isObserved()) reportReactiveNode({ kind: "memo", node: c, handle: read, name: options?.name });
|
|
284
|
+
onCleanup(() => {
|
|
285
|
+
c.dispose();
|
|
286
|
+
if (isObserved()) reportReactiveDispose(c);
|
|
287
|
+
});
|
|
269
288
|
return read;
|
|
270
289
|
}
|
|
271
290
|
|
|
272
291
|
// src/lib/signal/graph/detect.ts
|
|
273
292
|
var __BROWSER_PROD__ = typeof window === "undefined" ? false : window.__FLUIXI_PROD__ === true;
|
|
274
|
-
var __DEV__ = typeof process === "undefined" ? __BROWSER_PROD__ :
|
|
293
|
+
var __DEV__ = typeof process === "undefined" ? __BROWSER_PROD__ : process.env.NODE_ENV !== "production";
|
|
275
294
|
var $SIGNAL2 = /* @__PURE__ */ Symbol.for("signal");
|
|
276
295
|
function isSignal(value) {
|
|
277
296
|
return typeof value === "function" && value[$SIGNAL2] === true;
|