@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
|
@@ -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;
|
|
@@ -460,7 +460,7 @@ var Observable = class extends Subscription {
|
|
|
460
460
|
|
|
461
461
|
// src/lib/signal/graph/detect.ts
|
|
462
462
|
var __BROWSER_PROD__ = typeof window === "undefined" ? false : window.__FLUIXI_PROD__ === true;
|
|
463
|
-
var __DEV__ = typeof process === "undefined" ? __BROWSER_PROD__ :
|
|
463
|
+
var __DEV__ = typeof process === "undefined" ? __BROWSER_PROD__ : process.env.NODE_ENV !== "production";
|
|
464
464
|
var $SIGNAL = /* @__PURE__ */ Symbol.for("signal");
|
|
465
465
|
var $MEMO = /* @__PURE__ */ Symbol.for("memo");
|
|
466
466
|
var $RESOURCE = /* @__PURE__ */ Symbol.for("resource");
|
|
@@ -494,7 +494,7 @@ function makeArrayFlat(values) {
|
|
|
494
494
|
}
|
|
495
495
|
|
|
496
496
|
// src/version.generated.ts
|
|
497
|
-
var VERSION = "1.0.0-alpha.
|
|
497
|
+
var VERSION = "1.0.0-alpha.106";
|
|
498
498
|
|
|
499
499
|
// src/lib/signal/graph/state.ts
|
|
500
500
|
var MAJOR = VERSION.split(".")[0];
|
|
@@ -636,6 +636,7 @@ var Computed = class extends Source {
|
|
|
636
636
|
super();
|
|
637
637
|
this._threw = false;
|
|
638
638
|
this._initialized = false;
|
|
639
|
+
this._disposed = false;
|
|
639
640
|
this.state = DIRTY;
|
|
640
641
|
/** Nodes this computation read on its last run. Rebuilt on every run. */
|
|
641
642
|
this.sources = null;
|
|
@@ -651,8 +652,23 @@ var Computed = class extends Source {
|
|
|
651
652
|
if (this._threw) throw this._error;
|
|
652
653
|
return this._value;
|
|
653
654
|
}
|
|
655
|
+
/**
|
|
656
|
+
* Unlink from every source, for good. Without this, a source outlives the
|
|
657
|
+
* computation and keeps it (and everything its function captured) reachable
|
|
658
|
+
* through its observers set: a disposed list row stayed in memory that way.
|
|
659
|
+
* The last value stays readable; the node simply never updates again.
|
|
660
|
+
*/
|
|
661
|
+
dispose() {
|
|
662
|
+
if (this._disposed) return;
|
|
663
|
+
this._disposed = true;
|
|
664
|
+
if (this.sources) {
|
|
665
|
+
for (const s of this.sources) s.observers?.delete(this);
|
|
666
|
+
this.sources = null;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
654
669
|
/** Settle, if CHECK, verify sources; if DIRTY (or never run), recompute. */
|
|
655
670
|
updateIfNecessary() {
|
|
671
|
+
if (this._disposed) return;
|
|
656
672
|
if (this.state === CHECK) {
|
|
657
673
|
if (this.sources) {
|
|
658
674
|
for (const s of this.sources) {
|
|
@@ -696,7 +712,7 @@ var Computed = class extends Source {
|
|
|
696
712
|
reportReactiveRun(this);
|
|
697
713
|
if (changed) {
|
|
698
714
|
this.version++;
|
|
699
|
-
if (this.observers) for (const o of
|
|
715
|
+
if (this.observers) for (const o of this.observers) o.markDirty(DIRTY);
|
|
700
716
|
notifyWatchers(this);
|
|
701
717
|
}
|
|
702
718
|
}
|
|
@@ -710,7 +726,7 @@ var Computed = class extends Source {
|
|
|
710
726
|
const wasClean = this.state === CLEAN;
|
|
711
727
|
this.state = level;
|
|
712
728
|
if (wasClean) {
|
|
713
|
-
if (this.observers) for (const o of
|
|
729
|
+
if (this.observers) for (const o of this.observers) o.markDirty(CHECK);
|
|
714
730
|
notifyWatchers(this);
|
|
715
731
|
}
|
|
716
732
|
}
|
|
@@ -749,6 +765,10 @@ var Watcher = class {
|
|
|
749
765
|
this._pending.clear();
|
|
750
766
|
return out;
|
|
751
767
|
}
|
|
768
|
+
/** Drain pending without the array, for callers that only need it empty. */
|
|
769
|
+
clearPending() {
|
|
770
|
+
this._pending.clear();
|
|
771
|
+
}
|
|
752
772
|
/** @internal, a watched node became non-clean. Edge-triggered: notify once. */
|
|
753
773
|
_notify(node) {
|
|
754
774
|
if (!this._watched.has(node) || this._pending.has(node)) return;
|
|
@@ -887,14 +907,14 @@ var EffectNode = class {
|
|
|
887
907
|
if (typeof r === "function") (this.owner.cleanups ??= []).push(r);
|
|
888
908
|
});
|
|
889
909
|
});
|
|
890
|
-
reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
|
|
910
|
+
if (isObserved()) reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
|
|
891
911
|
this.watcher = new Watcher(() => enqueue(this));
|
|
892
912
|
this.run();
|
|
893
913
|
this.watcher.watch(this.computed);
|
|
894
914
|
}
|
|
895
915
|
run() {
|
|
896
916
|
if (this.disposed) return;
|
|
897
|
-
this.watcher.
|
|
917
|
+
this.watcher.clearPending();
|
|
898
918
|
try {
|
|
899
919
|
this.computed.get();
|
|
900
920
|
} catch (e) {
|
|
@@ -911,6 +931,7 @@ var EffectNode = class {
|
|
|
911
931
|
this.disposed = true;
|
|
912
932
|
reportReactiveDispose(this.computed);
|
|
913
933
|
this.watcher.unwatch(this.computed);
|
|
934
|
+
this.computed.dispose();
|
|
914
935
|
disposeOwner(this.owner);
|
|
915
936
|
}
|
|
916
937
|
};
|
|
@@ -949,13 +970,15 @@ function createSignal(value, options) {
|
|
|
949
970
|
},
|
|
950
971
|
enumerable: false
|
|
951
972
|
});
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
973
|
+
if (isObserved()) {
|
|
974
|
+
reportReactiveNode({
|
|
975
|
+
kind: "signal",
|
|
976
|
+
node: state,
|
|
977
|
+
handle: read,
|
|
978
|
+
name: options?.name,
|
|
979
|
+
set: write
|
|
980
|
+
});
|
|
981
|
+
}
|
|
959
982
|
if (isObserved()) onCleanup(() => reportReactiveDispose(state));
|
|
960
983
|
return [read, write];
|
|
961
984
|
}
|
|
@@ -979,8 +1002,11 @@ function createMemo(fn, value, options) {
|
|
|
979
1002
|
const read = (() => c.get());
|
|
980
1003
|
Object.defineProperty(read, $SIGNAL2, { value: true, enumerable: true });
|
|
981
1004
|
Object.defineProperty(read, $MEMO2, { value: true, enumerable: true });
|
|
982
|
-
reportReactiveNode({ kind: "memo", node: c, handle: read, name: options?.name });
|
|
983
|
-
|
|
1005
|
+
if (isObserved()) reportReactiveNode({ kind: "memo", node: c, handle: read, name: options?.name });
|
|
1006
|
+
onCleanup(() => {
|
|
1007
|
+
c.dispose();
|
|
1008
|
+
if (isObserved()) reportReactiveDispose(c);
|
|
1009
|
+
});
|
|
984
1010
|
return read;
|
|
985
1011
|
}
|
|
986
1012
|
function createEffect(fn, value, options) {
|
|
@@ -2448,6 +2474,20 @@ function clearCachedResources(name, cache = currentResourceCache()) {
|
|
|
2448
2474
|
}
|
|
2449
2475
|
|
|
2450
2476
|
// src/lib/signal/list.ts
|
|
2477
|
+
function lazyIndex(initial) {
|
|
2478
|
+
let current = initial;
|
|
2479
|
+
let state = null;
|
|
2480
|
+
return {
|
|
2481
|
+
index: () => {
|
|
2482
|
+
if (!state) state = createSignal(current, { name: "row index" });
|
|
2483
|
+
return state[0]();
|
|
2484
|
+
},
|
|
2485
|
+
set: (n) => {
|
|
2486
|
+
current = n;
|
|
2487
|
+
if (state) state[1](n);
|
|
2488
|
+
}
|
|
2489
|
+
};
|
|
2490
|
+
}
|
|
2451
2491
|
function mapArray(list, mapFn, options) {
|
|
2452
2492
|
let items = [];
|
|
2453
2493
|
onCleanup(() => {
|
|
@@ -2477,9 +2517,9 @@ function mapArray(list, mapFn, options) {
|
|
|
2477
2517
|
let rendered, setIndex, dispose2;
|
|
2478
2518
|
createRoot((d) => {
|
|
2479
2519
|
dispose2 = d;
|
|
2480
|
-
const
|
|
2481
|
-
setIndex =
|
|
2482
|
-
rendered = mapFn(value, index);
|
|
2520
|
+
const idx = lazyIndex(i);
|
|
2521
|
+
setIndex = idx.set;
|
|
2522
|
+
rendered = mapFn(value, idx.index);
|
|
2483
2523
|
});
|
|
2484
2524
|
const entry = { item: value, rendered, dispose: dispose2, setIndex };
|
|
2485
2525
|
result.push(entry);
|
|
@@ -2519,21 +2559,19 @@ function keyArray(list, keyFn, mapFn, options) {
|
|
|
2519
2559
|
const reuse = prevByKey.get(key);
|
|
2520
2560
|
if (reuse && !usedKeys.has(key)) {
|
|
2521
2561
|
reuse.setIndex(i);
|
|
2562
|
+
reuse.setItem(next[i]);
|
|
2522
2563
|
resultEntries.push(reuse);
|
|
2523
2564
|
} else {
|
|
2524
|
-
let rendered, setIndex, dispose2;
|
|
2565
|
+
let rendered, setIndex, setItem, dispose2;
|
|
2525
2566
|
createRoot((d) => {
|
|
2526
2567
|
dispose2 = d;
|
|
2527
|
-
const
|
|
2528
|
-
setIndex =
|
|
2529
|
-
const item =
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
return v !== void 0 && v !== null ? v : prev;
|
|
2533
|
-
}, next[i]);
|
|
2534
|
-
rendered = mapFn(item, index);
|
|
2568
|
+
const idx = lazyIndex(i);
|
|
2569
|
+
setIndex = idx.set;
|
|
2570
|
+
const [item, writeItem] = createSignal(next[i]);
|
|
2571
|
+
setItem = (v) => writeItem(() => v);
|
|
2572
|
+
rendered = mapFn(item, idx.index);
|
|
2535
2573
|
});
|
|
2536
|
-
resultEntries.push({ rendered, dispose: dispose2, setIndex });
|
|
2574
|
+
resultEntries.push({ rendered, dispose: dispose2, setIndex, setItem });
|
|
2537
2575
|
}
|
|
2538
2576
|
resultKeys.push(key);
|
|
2539
2577
|
usedKeys.add(key);
|
|
@@ -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
|
|
|
3
3
|
// src/lib/predicates.ts
|
|
4
4
|
function isFunction(value) {
|
|
@@ -358,7 +358,7 @@ var Observable = class extends Subscription {
|
|
|
358
358
|
|
|
359
359
|
// src/lib/signal/graph/detect.ts
|
|
360
360
|
var __BROWSER_PROD__ = typeof window === "undefined" ? false : window.__FLUIXI_PROD__ === true;
|
|
361
|
-
var __DEV__ = typeof process === "undefined" ? __BROWSER_PROD__ :
|
|
361
|
+
var __DEV__ = typeof process === "undefined" ? __BROWSER_PROD__ : process.env.NODE_ENV !== "production";
|
|
362
362
|
var $SIGNAL = /* @__PURE__ */ Symbol.for("signal");
|
|
363
363
|
var $MEMO = /* @__PURE__ */ Symbol.for("memo");
|
|
364
364
|
var $RESOURCE = /* @__PURE__ */ Symbol.for("resource");
|
|
@@ -392,7 +392,7 @@ function makeArrayFlat(values) {
|
|
|
392
392
|
}
|
|
393
393
|
|
|
394
394
|
// src/version.generated.ts
|
|
395
|
-
var VERSION = "1.0.0-alpha.
|
|
395
|
+
var VERSION = "1.0.0-alpha.106";
|
|
396
396
|
|
|
397
397
|
// src/lib/signal/graph/state.ts
|
|
398
398
|
var MAJOR = VERSION.split(".")[0];
|
|
@@ -534,6 +534,7 @@ var Computed = class extends Source {
|
|
|
534
534
|
super();
|
|
535
535
|
this._threw = false;
|
|
536
536
|
this._initialized = false;
|
|
537
|
+
this._disposed = false;
|
|
537
538
|
this.state = DIRTY;
|
|
538
539
|
/** Nodes this computation read on its last run. Rebuilt on every run. */
|
|
539
540
|
this.sources = null;
|
|
@@ -549,8 +550,23 @@ var Computed = class extends Source {
|
|
|
549
550
|
if (this._threw) throw this._error;
|
|
550
551
|
return this._value;
|
|
551
552
|
}
|
|
553
|
+
/**
|
|
554
|
+
* Unlink from every source, for good. Without this, a source outlives the
|
|
555
|
+
* computation and keeps it (and everything its function captured) reachable
|
|
556
|
+
* through its observers set: a disposed list row stayed in memory that way.
|
|
557
|
+
* The last value stays readable; the node simply never updates again.
|
|
558
|
+
*/
|
|
559
|
+
dispose() {
|
|
560
|
+
if (this._disposed) return;
|
|
561
|
+
this._disposed = true;
|
|
562
|
+
if (this.sources) {
|
|
563
|
+
for (const s of this.sources) s.observers?.delete(this);
|
|
564
|
+
this.sources = null;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
552
567
|
/** Settle, if CHECK, verify sources; if DIRTY (or never run), recompute. */
|
|
553
568
|
updateIfNecessary() {
|
|
569
|
+
if (this._disposed) return;
|
|
554
570
|
if (this.state === CHECK) {
|
|
555
571
|
if (this.sources) {
|
|
556
572
|
for (const s of this.sources) {
|
|
@@ -594,7 +610,7 @@ var Computed = class extends Source {
|
|
|
594
610
|
reportReactiveRun(this);
|
|
595
611
|
if (changed) {
|
|
596
612
|
this.version++;
|
|
597
|
-
if (this.observers) for (const o of
|
|
613
|
+
if (this.observers) for (const o of this.observers) o.markDirty(DIRTY);
|
|
598
614
|
notifyWatchers(this);
|
|
599
615
|
}
|
|
600
616
|
}
|
|
@@ -608,7 +624,7 @@ var Computed = class extends Source {
|
|
|
608
624
|
const wasClean = this.state === CLEAN;
|
|
609
625
|
this.state = level;
|
|
610
626
|
if (wasClean) {
|
|
611
|
-
if (this.observers) for (const o of
|
|
627
|
+
if (this.observers) for (const o of this.observers) o.markDirty(CHECK);
|
|
612
628
|
notifyWatchers(this);
|
|
613
629
|
}
|
|
614
630
|
}
|
|
@@ -647,6 +663,10 @@ var Watcher = class {
|
|
|
647
663
|
this._pending.clear();
|
|
648
664
|
return out;
|
|
649
665
|
}
|
|
666
|
+
/** Drain pending without the array, for callers that only need it empty. */
|
|
667
|
+
clearPending() {
|
|
668
|
+
this._pending.clear();
|
|
669
|
+
}
|
|
650
670
|
/** @internal, a watched node became non-clean. Edge-triggered: notify once. */
|
|
651
671
|
_notify(node) {
|
|
652
672
|
if (!this._watched.has(node) || this._pending.has(node)) return;
|
|
@@ -785,14 +805,14 @@ var EffectNode = class {
|
|
|
785
805
|
if (typeof r === "function") (this.owner.cleanups ??= []).push(r);
|
|
786
806
|
});
|
|
787
807
|
});
|
|
788
|
-
reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
|
|
808
|
+
if (isObserved()) reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
|
|
789
809
|
this.watcher = new Watcher(() => enqueue(this));
|
|
790
810
|
this.run();
|
|
791
811
|
this.watcher.watch(this.computed);
|
|
792
812
|
}
|
|
793
813
|
run() {
|
|
794
814
|
if (this.disposed) return;
|
|
795
|
-
this.watcher.
|
|
815
|
+
this.watcher.clearPending();
|
|
796
816
|
try {
|
|
797
817
|
this.computed.get();
|
|
798
818
|
} catch (e) {
|
|
@@ -809,6 +829,7 @@ var EffectNode = class {
|
|
|
809
829
|
this.disposed = true;
|
|
810
830
|
reportReactiveDispose(this.computed);
|
|
811
831
|
this.watcher.unwatch(this.computed);
|
|
832
|
+
this.computed.dispose();
|
|
812
833
|
disposeOwner(this.owner);
|
|
813
834
|
}
|
|
814
835
|
};
|
|
@@ -847,13 +868,15 @@ function createSignal(value, options) {
|
|
|
847
868
|
},
|
|
848
869
|
enumerable: false
|
|
849
870
|
});
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
871
|
+
if (isObserved()) {
|
|
872
|
+
reportReactiveNode({
|
|
873
|
+
kind: "signal",
|
|
874
|
+
node: state,
|
|
875
|
+
handle: read,
|
|
876
|
+
name: options?.name,
|
|
877
|
+
set: write
|
|
878
|
+
});
|
|
879
|
+
}
|
|
857
880
|
if (isObserved()) onCleanup(() => reportReactiveDispose(state));
|
|
858
881
|
return [read, write];
|
|
859
882
|
}
|
|
@@ -877,8 +900,11 @@ function createMemo(fn, value, options) {
|
|
|
877
900
|
const read = (() => c.get());
|
|
878
901
|
Object.defineProperty(read, $SIGNAL2, { value: true, enumerable: true });
|
|
879
902
|
Object.defineProperty(read, $MEMO2, { value: true, enumerable: true });
|
|
880
|
-
reportReactiveNode({ kind: "memo", node: c, handle: read, name: options?.name });
|
|
881
|
-
|
|
903
|
+
if (isObserved()) reportReactiveNode({ kind: "memo", node: c, handle: read, name: options?.name });
|
|
904
|
+
onCleanup(() => {
|
|
905
|
+
c.dispose();
|
|
906
|
+
if (isObserved()) reportReactiveDispose(c);
|
|
907
|
+
});
|
|
882
908
|
return read;
|
|
883
909
|
}
|
|
884
910
|
function createEffect(fn, value, options) {
|
|
@@ -2346,6 +2372,20 @@ function clearCachedResources(name, cache = currentResourceCache()) {
|
|
|
2346
2372
|
}
|
|
2347
2373
|
|
|
2348
2374
|
// src/lib/signal/list.ts
|
|
2375
|
+
function lazyIndex(initial) {
|
|
2376
|
+
let current = initial;
|
|
2377
|
+
let state = null;
|
|
2378
|
+
return {
|
|
2379
|
+
index: () => {
|
|
2380
|
+
if (!state) state = createSignal(current, { name: "row index" });
|
|
2381
|
+
return state[0]();
|
|
2382
|
+
},
|
|
2383
|
+
set: (n) => {
|
|
2384
|
+
current = n;
|
|
2385
|
+
if (state) state[1](n);
|
|
2386
|
+
}
|
|
2387
|
+
};
|
|
2388
|
+
}
|
|
2349
2389
|
function mapArray(list, mapFn, options) {
|
|
2350
2390
|
let items = [];
|
|
2351
2391
|
onCleanup(() => {
|
|
@@ -2375,9 +2415,9 @@ function mapArray(list, mapFn, options) {
|
|
|
2375
2415
|
let rendered, setIndex, dispose2;
|
|
2376
2416
|
createRoot((d) => {
|
|
2377
2417
|
dispose2 = d;
|
|
2378
|
-
const
|
|
2379
|
-
setIndex =
|
|
2380
|
-
rendered = mapFn(value, index);
|
|
2418
|
+
const idx = lazyIndex(i);
|
|
2419
|
+
setIndex = idx.set;
|
|
2420
|
+
rendered = mapFn(value, idx.index);
|
|
2381
2421
|
});
|
|
2382
2422
|
const entry = { item: value, rendered, dispose: dispose2, setIndex };
|
|
2383
2423
|
result.push(entry);
|
|
@@ -2417,21 +2457,19 @@ function keyArray(list, keyFn, mapFn, options) {
|
|
|
2417
2457
|
const reuse = prevByKey.get(key);
|
|
2418
2458
|
if (reuse && !usedKeys.has(key)) {
|
|
2419
2459
|
reuse.setIndex(i);
|
|
2460
|
+
reuse.setItem(next[i]);
|
|
2420
2461
|
resultEntries.push(reuse);
|
|
2421
2462
|
} else {
|
|
2422
|
-
let rendered, setIndex, dispose2;
|
|
2463
|
+
let rendered, setIndex, setItem, dispose2;
|
|
2423
2464
|
createRoot((d) => {
|
|
2424
2465
|
dispose2 = d;
|
|
2425
|
-
const
|
|
2426
|
-
setIndex =
|
|
2427
|
-
const item =
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
return v !== void 0 && v !== null ? v : prev;
|
|
2431
|
-
}, next[i]);
|
|
2432
|
-
rendered = mapFn(item, index);
|
|
2466
|
+
const idx = lazyIndex(i);
|
|
2467
|
+
setIndex = idx.set;
|
|
2468
|
+
const [item, writeItem] = createSignal(next[i]);
|
|
2469
|
+
setItem = (v) => writeItem(() => v);
|
|
2470
|
+
rendered = mapFn(item, idx.index);
|
|
2433
2471
|
});
|
|
2434
|
-
resultEntries.push({ rendered, dispose: dispose2, setIndex });
|
|
2472
|
+
resultEntries.push({ rendered, dispose: dispose2, setIndex, setItem });
|
|
2435
2473
|
}
|
|
2436
2474
|
resultKeys.push(key);
|
|
2437
2475
|
usedKeys.add(key);
|
|
@@ -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;
|
|
@@ -106,7 +106,7 @@ __export(index_exports, {
|
|
|
106
106
|
module.exports = __toCommonJS(index_exports);
|
|
107
107
|
|
|
108
108
|
// src/version.generated.ts
|
|
109
|
-
var VERSION = "1.0.0-alpha.
|
|
109
|
+
var VERSION = "1.0.0-alpha.106";
|
|
110
110
|
|
|
111
111
|
// src/lib/signal/graph/state.ts
|
|
112
112
|
var MAJOR = VERSION.split(".")[0];
|
|
@@ -302,6 +302,7 @@ var Computed = class extends Source {
|
|
|
302
302
|
super();
|
|
303
303
|
this._threw = false;
|
|
304
304
|
this._initialized = false;
|
|
305
|
+
this._disposed = false;
|
|
305
306
|
this.state = DIRTY;
|
|
306
307
|
/** Nodes this computation read on its last run. Rebuilt on every run. */
|
|
307
308
|
this.sources = null;
|
|
@@ -317,8 +318,23 @@ var Computed = class extends Source {
|
|
|
317
318
|
if (this._threw) throw this._error;
|
|
318
319
|
return this._value;
|
|
319
320
|
}
|
|
321
|
+
/**
|
|
322
|
+
* Unlink from every source, for good. Without this, a source outlives the
|
|
323
|
+
* computation and keeps it (and everything its function captured) reachable
|
|
324
|
+
* through its observers set: a disposed list row stayed in memory that way.
|
|
325
|
+
* The last value stays readable; the node simply never updates again.
|
|
326
|
+
*/
|
|
327
|
+
dispose() {
|
|
328
|
+
if (this._disposed) return;
|
|
329
|
+
this._disposed = true;
|
|
330
|
+
if (this.sources) {
|
|
331
|
+
for (const s of this.sources) s.observers?.delete(this);
|
|
332
|
+
this.sources = null;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
320
335
|
/** Settle, if CHECK, verify sources; if DIRTY (or never run), recompute. */
|
|
321
336
|
updateIfNecessary() {
|
|
337
|
+
if (this._disposed) return;
|
|
322
338
|
if (this.state === CHECK) {
|
|
323
339
|
if (this.sources) {
|
|
324
340
|
for (const s of this.sources) {
|
|
@@ -362,7 +378,7 @@ var Computed = class extends Source {
|
|
|
362
378
|
reportReactiveRun(this);
|
|
363
379
|
if (changed) {
|
|
364
380
|
this.version++;
|
|
365
|
-
if (this.observers) for (const o of
|
|
381
|
+
if (this.observers) for (const o of this.observers) o.markDirty(DIRTY);
|
|
366
382
|
notifyWatchers(this);
|
|
367
383
|
}
|
|
368
384
|
}
|
|
@@ -376,7 +392,7 @@ var Computed = class extends Source {
|
|
|
376
392
|
const wasClean = this.state === CLEAN;
|
|
377
393
|
this.state = level;
|
|
378
394
|
if (wasClean) {
|
|
379
|
-
if (this.observers) for (const o of
|
|
395
|
+
if (this.observers) for (const o of this.observers) o.markDirty(CHECK);
|
|
380
396
|
notifyWatchers(this);
|
|
381
397
|
}
|
|
382
398
|
}
|
|
@@ -415,6 +431,10 @@ var Watcher = class {
|
|
|
415
431
|
this._pending.clear();
|
|
416
432
|
return out;
|
|
417
433
|
}
|
|
434
|
+
/** Drain pending without the array, for callers that only need it empty. */
|
|
435
|
+
clearPending() {
|
|
436
|
+
this._pending.clear();
|
|
437
|
+
}
|
|
418
438
|
/** @internal, a watched node became non-clean. Edge-triggered: notify once. */
|
|
419
439
|
_notify(node) {
|
|
420
440
|
if (!this._watched.has(node) || this._pending.has(node)) return;
|
|
@@ -632,14 +652,14 @@ var EffectNode = class {
|
|
|
632
652
|
if (typeof r === "function") (this.owner.cleanups ??= []).push(r);
|
|
633
653
|
});
|
|
634
654
|
});
|
|
635
|
-
reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
|
|
655
|
+
if (isObserved()) reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
|
|
636
656
|
this.watcher = new Watcher(() => enqueue(this));
|
|
637
657
|
this.run();
|
|
638
658
|
this.watcher.watch(this.computed);
|
|
639
659
|
}
|
|
640
660
|
run() {
|
|
641
661
|
if (this.disposed) return;
|
|
642
|
-
this.watcher.
|
|
662
|
+
this.watcher.clearPending();
|
|
643
663
|
try {
|
|
644
664
|
this.computed.get();
|
|
645
665
|
} catch (e) {
|
|
@@ -656,6 +676,7 @@ var EffectNode = class {
|
|
|
656
676
|
this.disposed = true;
|
|
657
677
|
reportReactiveDispose(this.computed);
|
|
658
678
|
this.watcher.unwatch(this.computed);
|
|
679
|
+
this.computed.dispose();
|
|
659
680
|
disposeOwner(this.owner);
|
|
660
681
|
}
|
|
661
682
|
};
|
|
@@ -694,13 +715,15 @@ function createSignal(value, options) {
|
|
|
694
715
|
},
|
|
695
716
|
enumerable: false
|
|
696
717
|
});
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
718
|
+
if (isObserved()) {
|
|
719
|
+
reportReactiveNode({
|
|
720
|
+
kind: "signal",
|
|
721
|
+
node: state,
|
|
722
|
+
handle: read,
|
|
723
|
+
name: options?.name,
|
|
724
|
+
set: write
|
|
725
|
+
});
|
|
726
|
+
}
|
|
704
727
|
if (isObserved()) onCleanup(() => reportReactiveDispose(state));
|
|
705
728
|
return [read, write];
|
|
706
729
|
}
|
|
@@ -724,8 +747,11 @@ function createMemo(fn, value, options) {
|
|
|
724
747
|
const read = (() => c.get());
|
|
725
748
|
Object.defineProperty(read, $SIGNAL, { value: true, enumerable: true });
|
|
726
749
|
Object.defineProperty(read, $MEMO, { value: true, enumerable: true });
|
|
727
|
-
reportReactiveNode({ kind: "memo", node: c, handle: read, name: options?.name });
|
|
728
|
-
|
|
750
|
+
if (isObserved()) reportReactiveNode({ kind: "memo", node: c, handle: read, name: options?.name });
|
|
751
|
+
onCleanup(() => {
|
|
752
|
+
c.dispose();
|
|
753
|
+
if (isObserved()) reportReactiveDispose(c);
|
|
754
|
+
});
|
|
729
755
|
return read;
|
|
730
756
|
}
|
|
731
757
|
function createEffect(fn, value, options) {
|
|
@@ -782,6 +808,20 @@ function on(deps, fn, options) {
|
|
|
782
808
|
}
|
|
783
809
|
|
|
784
810
|
// src/lib/signal/list.ts
|
|
811
|
+
function lazyIndex(initial) {
|
|
812
|
+
let current = initial;
|
|
813
|
+
let state = null;
|
|
814
|
+
return {
|
|
815
|
+
index: () => {
|
|
816
|
+
if (!state) state = createSignal(current, { name: "row index" });
|
|
817
|
+
return state[0]();
|
|
818
|
+
},
|
|
819
|
+
set: (n) => {
|
|
820
|
+
current = n;
|
|
821
|
+
if (state) state[1](n);
|
|
822
|
+
}
|
|
823
|
+
};
|
|
824
|
+
}
|
|
785
825
|
function mapArray(list, mapFn, options) {
|
|
786
826
|
let items = [];
|
|
787
827
|
onCleanup(() => {
|
|
@@ -811,9 +851,9 @@ function mapArray(list, mapFn, options) {
|
|
|
811
851
|
let rendered, setIndex, dispose;
|
|
812
852
|
createRoot((d) => {
|
|
813
853
|
dispose = d;
|
|
814
|
-
const
|
|
815
|
-
setIndex =
|
|
816
|
-
rendered = mapFn(value, index);
|
|
854
|
+
const idx = lazyIndex(i);
|
|
855
|
+
setIndex = idx.set;
|
|
856
|
+
rendered = mapFn(value, idx.index);
|
|
817
857
|
});
|
|
818
858
|
const entry = { item: value, rendered, dispose, setIndex };
|
|
819
859
|
result.push(entry);
|
|
@@ -853,21 +893,19 @@ function keyArray(list, keyFn, mapFn, options) {
|
|
|
853
893
|
const reuse = prevByKey.get(key);
|
|
854
894
|
if (reuse && !usedKeys.has(key)) {
|
|
855
895
|
reuse.setIndex(i);
|
|
896
|
+
reuse.setItem(next[i]);
|
|
856
897
|
resultEntries.push(reuse);
|
|
857
898
|
} else {
|
|
858
|
-
let rendered, setIndex, dispose;
|
|
899
|
+
let rendered, setIndex, setItem, dispose;
|
|
859
900
|
createRoot((d) => {
|
|
860
901
|
dispose = d;
|
|
861
|
-
const
|
|
862
|
-
setIndex =
|
|
863
|
-
const item =
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
return v !== void 0 && v !== null ? v : prev;
|
|
867
|
-
}, next[i]);
|
|
868
|
-
rendered = mapFn(item, index);
|
|
902
|
+
const idx = lazyIndex(i);
|
|
903
|
+
setIndex = idx.set;
|
|
904
|
+
const [item, writeItem] = createSignal(next[i]);
|
|
905
|
+
setItem = (v) => writeItem(() => v);
|
|
906
|
+
rendered = mapFn(item, idx.index);
|
|
869
907
|
});
|
|
870
|
-
resultEntries.push({ rendered, dispose, setIndex });
|
|
908
|
+
resultEntries.push({ rendered, dispose, setIndex, setItem });
|
|
871
909
|
}
|
|
872
910
|
resultKeys.push(key);
|
|
873
911
|
usedKeys.add(key);
|
|
@@ -917,7 +955,7 @@ function indexArray(list, mapFn, options) {
|
|
|
917
955
|
|
|
918
956
|
// src/lib/signal/graph/detect.ts
|
|
919
957
|
var __BROWSER_PROD__ = typeof window === "undefined" ? false : window.__FLUIXI_PROD__ === true;
|
|
920
|
-
var __DEV__ = typeof process === "undefined" ? __BROWSER_PROD__ :
|
|
958
|
+
var __DEV__ = typeof process === "undefined" ? __BROWSER_PROD__ : process.env.NODE_ENV !== "production";
|
|
921
959
|
var $SIGNAL2 = /* @__PURE__ */ Symbol.for("signal");
|
|
922
960
|
var $MEMO2 = /* @__PURE__ */ Symbol.for("memo");
|
|
923
961
|
var $RESOURCE = /* @__PURE__ */ Symbol.for("resource");
|