@fluixi/reactive 1.0.0-alpha.105 → 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/cdn/reactive.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/predicates.ts
|
|
5
5
|
function isFunction(value) {
|
|
@@ -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;
|
|
@@ -966,14 +986,14 @@ var EffectNode = class {
|
|
|
966
986
|
if (typeof r === "function") (this.owner.cleanups ??= []).push(r);
|
|
967
987
|
});
|
|
968
988
|
});
|
|
969
|
-
reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
|
|
989
|
+
if (isObserved()) reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
|
|
970
990
|
this.watcher = new Watcher(() => enqueue(this));
|
|
971
991
|
this.run();
|
|
972
992
|
this.watcher.watch(this.computed);
|
|
973
993
|
}
|
|
974
994
|
run() {
|
|
975
995
|
if (this.disposed) return;
|
|
976
|
-
this.watcher.
|
|
996
|
+
this.watcher.clearPending();
|
|
977
997
|
try {
|
|
978
998
|
this.computed.get();
|
|
979
999
|
} catch (e) {
|
|
@@ -990,6 +1010,7 @@ var EffectNode = class {
|
|
|
990
1010
|
this.disposed = true;
|
|
991
1011
|
reportReactiveDispose(this.computed);
|
|
992
1012
|
this.watcher.unwatch(this.computed);
|
|
1013
|
+
this.computed.dispose();
|
|
993
1014
|
disposeOwner(this.owner);
|
|
994
1015
|
}
|
|
995
1016
|
};
|
|
@@ -1028,13 +1049,15 @@ function createSignal(value, options) {
|
|
|
1028
1049
|
},
|
|
1029
1050
|
enumerable: false
|
|
1030
1051
|
});
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1052
|
+
if (isObserved()) {
|
|
1053
|
+
reportReactiveNode({
|
|
1054
|
+
kind: "signal",
|
|
1055
|
+
node: state,
|
|
1056
|
+
handle: read,
|
|
1057
|
+
name: options?.name,
|
|
1058
|
+
set: write
|
|
1059
|
+
});
|
|
1060
|
+
}
|
|
1038
1061
|
if (isObserved()) onCleanup(() => reportReactiveDispose(state));
|
|
1039
1062
|
return [read, write];
|
|
1040
1063
|
}
|
|
@@ -1058,8 +1081,11 @@ function createMemo(fn, value, options) {
|
|
|
1058
1081
|
const read = (() => c.get());
|
|
1059
1082
|
Object.defineProperty(read, $SIGNAL, { value: true, enumerable: true });
|
|
1060
1083
|
Object.defineProperty(read, $MEMO, { value: true, enumerable: true });
|
|
1061
|
-
reportReactiveNode({ kind: "memo", node: c, handle: read, name: options?.name });
|
|
1062
|
-
|
|
1084
|
+
if (isObserved()) reportReactiveNode({ kind: "memo", node: c, handle: read, name: options?.name });
|
|
1085
|
+
onCleanup(() => {
|
|
1086
|
+
c.dispose();
|
|
1087
|
+
if (isObserved()) reportReactiveDispose(c);
|
|
1088
|
+
});
|
|
1063
1089
|
return read;
|
|
1064
1090
|
}
|
|
1065
1091
|
function createEffect(fn, value, options) {
|
|
@@ -1116,6 +1142,20 @@ function on(deps, fn, options) {
|
|
|
1116
1142
|
}
|
|
1117
1143
|
|
|
1118
1144
|
// src/lib/signal/list.ts
|
|
1145
|
+
function lazyIndex(initial) {
|
|
1146
|
+
let current = initial;
|
|
1147
|
+
let state = null;
|
|
1148
|
+
return {
|
|
1149
|
+
index: () => {
|
|
1150
|
+
if (!state) state = createSignal(current, { name: "row index" });
|
|
1151
|
+
return state[0]();
|
|
1152
|
+
},
|
|
1153
|
+
set: (n) => {
|
|
1154
|
+
current = n;
|
|
1155
|
+
if (state) state[1](n);
|
|
1156
|
+
}
|
|
1157
|
+
};
|
|
1158
|
+
}
|
|
1119
1159
|
function mapArray(list, mapFn, options) {
|
|
1120
1160
|
let items = [];
|
|
1121
1161
|
onCleanup(() => {
|
|
@@ -1145,9 +1185,9 @@ function mapArray(list, mapFn, options) {
|
|
|
1145
1185
|
let rendered, setIndex, dispose;
|
|
1146
1186
|
createRoot((d) => {
|
|
1147
1187
|
dispose = d;
|
|
1148
|
-
const
|
|
1149
|
-
setIndex =
|
|
1150
|
-
rendered = mapFn(value, index);
|
|
1188
|
+
const idx = lazyIndex(i);
|
|
1189
|
+
setIndex = idx.set;
|
|
1190
|
+
rendered = mapFn(value, idx.index);
|
|
1151
1191
|
});
|
|
1152
1192
|
const entry = { item: value, rendered, dispose, setIndex };
|
|
1153
1193
|
result.push(entry);
|
|
@@ -1187,21 +1227,19 @@ function keyArray(list, keyFn, mapFn, options) {
|
|
|
1187
1227
|
const reuse = prevByKey.get(key);
|
|
1188
1228
|
if (reuse && !usedKeys.has(key)) {
|
|
1189
1229
|
reuse.setIndex(i);
|
|
1230
|
+
reuse.setItem(next[i]);
|
|
1190
1231
|
resultEntries.push(reuse);
|
|
1191
1232
|
} else {
|
|
1192
|
-
let rendered, setIndex, dispose;
|
|
1233
|
+
let rendered, setIndex, setItem, dispose;
|
|
1193
1234
|
createRoot((d) => {
|
|
1194
1235
|
dispose = d;
|
|
1195
|
-
const
|
|
1196
|
-
setIndex =
|
|
1197
|
-
const item =
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
return v !== void 0 && v !== null ? v : prev;
|
|
1201
|
-
}, next[i]);
|
|
1202
|
-
rendered = mapFn(item, index);
|
|
1236
|
+
const idx = lazyIndex(i);
|
|
1237
|
+
setIndex = idx.set;
|
|
1238
|
+
const [item, writeItem] = createSignal(next[i]);
|
|
1239
|
+
setItem = (v) => writeItem(() => v);
|
|
1240
|
+
rendered = mapFn(item, idx.index);
|
|
1203
1241
|
});
|
|
1204
|
-
resultEntries.push({ rendered, dispose, setIndex });
|
|
1242
|
+
resultEntries.push({ rendered, dispose, setIndex, setItem });
|
|
1205
1243
|
}
|
|
1206
1244
|
resultKeys.push(key);
|
|
1207
1245
|
usedKeys.add(key);
|
|
@@ -1251,7 +1289,7 @@ function indexArray(list, mapFn, options) {
|
|
|
1251
1289
|
|
|
1252
1290
|
// src/lib/signal/graph/detect.ts
|
|
1253
1291
|
var __BROWSER_PROD__ = typeof window === "undefined" ? false : window.__FLUIXI_PROD__ === true;
|
|
1254
|
-
var __DEV__ = typeof process === "undefined" ? __BROWSER_PROD__ :
|
|
1292
|
+
var __DEV__ = typeof process === "undefined" ? __BROWSER_PROD__ : process.env.NODE_ENV !== "production";
|
|
1255
1293
|
var $SIGNAL2 = /* @__PURE__ */ Symbol.for("signal");
|
|
1256
1294
|
var $MEMO2 = /* @__PURE__ */ Symbol.for("memo");
|
|
1257
1295
|
var $RESOURCE = /* @__PURE__ */ Symbol.for("resource");
|
|
@@ -2070,12 +2108,14 @@ var Store = class {
|
|
|
2070
2108
|
OWNERS.set(initialState, { store: this, name: options.name ?? "store" });
|
|
2071
2109
|
ROOTS.set(initialState, initialState);
|
|
2072
2110
|
}
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2111
|
+
if (isObserved()) {
|
|
2112
|
+
reportReactiveNode({
|
|
2113
|
+
kind: "store",
|
|
2114
|
+
node: this,
|
|
2115
|
+
handle: () => this.root,
|
|
2116
|
+
name: options.name
|
|
2117
|
+
});
|
|
2118
|
+
}
|
|
2079
2119
|
}
|
|
2080
2120
|
get state() {
|
|
2081
2121
|
return box(this.root);
|
package/dist/cdn/signal.cjs
CHANGED
|
@@ -27,7 +27,7 @@ __export(signal_exports, {
|
|
|
27
27
|
module.exports = __toCommonJS(signal_exports);
|
|
28
28
|
|
|
29
29
|
// src/version.generated.ts
|
|
30
|
-
var VERSION = "1.0.0-alpha.
|
|
30
|
+
var VERSION = "1.0.0-alpha.106";
|
|
31
31
|
|
|
32
32
|
// src/lib/signal/graph/state.ts
|
|
33
33
|
var MAJOR = VERSION.split(".")[0];
|
|
@@ -153,6 +153,7 @@ var Computed = class extends Source {
|
|
|
153
153
|
super();
|
|
154
154
|
this._threw = false;
|
|
155
155
|
this._initialized = false;
|
|
156
|
+
this._disposed = false;
|
|
156
157
|
this.state = DIRTY;
|
|
157
158
|
/** Nodes this computation read on its last run. Rebuilt on every run. */
|
|
158
159
|
this.sources = null;
|
|
@@ -168,8 +169,23 @@ var Computed = class extends Source {
|
|
|
168
169
|
if (this._threw) throw this._error;
|
|
169
170
|
return this._value;
|
|
170
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* Unlink from every source, for good. Without this, a source outlives the
|
|
174
|
+
* computation and keeps it (and everything its function captured) reachable
|
|
175
|
+
* through its observers set: a disposed list row stayed in memory that way.
|
|
176
|
+
* The last value stays readable; the node simply never updates again.
|
|
177
|
+
*/
|
|
178
|
+
dispose() {
|
|
179
|
+
if (this._disposed) return;
|
|
180
|
+
this._disposed = true;
|
|
181
|
+
if (this.sources) {
|
|
182
|
+
for (const s of this.sources) s.observers?.delete(this);
|
|
183
|
+
this.sources = null;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
171
186
|
/** Settle, if CHECK, verify sources; if DIRTY (or never run), recompute. */
|
|
172
187
|
updateIfNecessary() {
|
|
188
|
+
if (this._disposed) return;
|
|
173
189
|
if (this.state === CHECK) {
|
|
174
190
|
if (this.sources) {
|
|
175
191
|
for (const s of this.sources) {
|
|
@@ -213,7 +229,7 @@ var Computed = class extends Source {
|
|
|
213
229
|
reportReactiveRun(this);
|
|
214
230
|
if (changed) {
|
|
215
231
|
this.version++;
|
|
216
|
-
if (this.observers) for (const o of
|
|
232
|
+
if (this.observers) for (const o of this.observers) o.markDirty(DIRTY);
|
|
217
233
|
notifyWatchers(this);
|
|
218
234
|
}
|
|
219
235
|
}
|
|
@@ -227,7 +243,7 @@ var Computed = class extends Source {
|
|
|
227
243
|
const wasClean = this.state === CLEAN;
|
|
228
244
|
this.state = level;
|
|
229
245
|
if (wasClean) {
|
|
230
|
-
if (this.observers) for (const o of
|
|
246
|
+
if (this.observers) for (const o of this.observers) o.markDirty(CHECK);
|
|
231
247
|
notifyWatchers(this);
|
|
232
248
|
}
|
|
233
249
|
}
|
|
@@ -266,6 +282,10 @@ var Watcher = class {
|
|
|
266
282
|
this._pending.clear();
|
|
267
283
|
return out;
|
|
268
284
|
}
|
|
285
|
+
/** Drain pending without the array, for callers that only need it empty. */
|
|
286
|
+
clearPending() {
|
|
287
|
+
this._pending.clear();
|
|
288
|
+
}
|
|
269
289
|
/** @internal, a watched node became non-clean. Edge-triggered: notify once. */
|
|
270
290
|
_notify(node) {
|
|
271
291
|
if (!this._watched.has(node) || this._pending.has(node)) return;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! @fluixi/reactive v1.0.0-alpha.
|
|
2
|
-
"use strict";var Signal=(()=>{var b=Object.defineProperty;var D=Object.getOwnPropertyDescriptor;var G=Object.getOwnPropertyNames;var K=Object.prototype.hasOwnProperty;var z=(e,t)=>{for(var n in t)b(e,n,{get:t[n],enumerable:!0})},
|
|
1
|
+
/*! @fluixi/reactive v1.0.0-alpha.106 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
|
|
2
|
+
"use strict";var Signal=(()=>{var b=Object.defineProperty;var D=Object.getOwnPropertyDescriptor;var G=Object.getOwnPropertyNames;var K=Object.prototype.hasOwnProperty;var z=(e,t)=>{for(var n in t)b(e,n,{get:t[n],enumerable:!0})},P=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of G(t))!K.call(e,s)&&s!==n&&b(e,s,{get:()=>t[s],enumerable:!(r=D(t,s))||r.enumerable});return e};var A=e=>P(b({},"__esModule",{value:!0}),e);var U={};z(U,{Computed:()=>p,State:()=>l,subtle:()=>Y});var a="1.0.0-alpha.106";var R=a.split(".")[0],_=`__fluixi_signal_state_v${R}__`,H=`__fluixi_signal_builds_v${R}__`,V=e=>{typeof queueMicrotask=="function"?queueMicrotask(e):Promise.resolve().then(e)};function m(){return{consumer:null,untracked:!1,owner:null,queue:[],scheduled:!1,flushing:!1,batchDepth:0,hostSchedule:V,onSuspend:null,onError:null,observer:null}}var w=globalThis;function F(e){let t=m(),n=e;for(let r of Object.keys(t))r in e||(n[r]=t[r]);return e}function L(){let e=w[_];return e?F(e):w[_]=m()}var o=L();(w[H]??=[]).push(a);function M(e){return o.observer=e,()=>{o.observer===e&&(o.observer=null)}}var y=[];function S(e){return o.observer?(y.push(e),!0):!1}function x(){y.pop()}function T(e){o.observer?.ran?.(e)}function O(e,t){o.observer?.wrote?.(e,t)}var W="__FLUIXI_DEVTOOLS_HOOK__",g=globalThis[W];if(typeof g?.inject=="function")try{g.inject({observeReactiveNodes:M,version:a})}catch{}var j=0,N=1,c=2,v=class{constructor(){this.observers=null;this.watchers=null;this.version=0}updateIfNecessary(){}track(){if(o.untracked)return;let t=o.consumer;t&&((this.observers??=new Set).add(t),(t.sources??=new Set).add(this))}},l=class extends v{constructor(t,n){super(),this._value=t,this._equals=n?.equals===!1?()=>!1:n?.equals??Object.is}get(){return this.track(),this._value}set(t){if(!this._equals(this._value,t)){if(this._value=t,this.version++,O(this,o.consumer),this.observers)for(let n of[...this.observers])n.markDirty(c);k(this)}}peek(){return this._value}},p=class extends v{constructor(n,r){super();this._threw=!1;this._initialized=!1;this._disposed=!1;this.state=c;this.sources=null;this._fn=n,this._equals=r?.equals===!1?()=>!1:r?.equals??Object.is}get(){if(o.consumer===this)throw new Error("Signal.Computed cannot read itself");if(this.track(),this.updateIfNecessary(),this._threw)throw this._error;return this._value}dispose(){if(!this._disposed&&(this._disposed=!0,this.sources)){for(let n of this.sources)n.observers?.delete(this);this.sources=null}}updateIfNecessary(){if(!this._disposed){if(this.state===N&&this.sources){for(let n of this.sources)if(n.updateIfNecessary(),this.state===c)break}(this.state===c||!this._initialized)&&this.recompute(),this.state=j}}recompute(){if(this.sources){for(let i of this.sources)i.observers?.delete(this);this.sources.clear()}let n=o.consumer,r=o.untracked,s=S(this);o.consumer=this,o.untracked=!1;let u,d=!1,h;try{u=this._fn()}catch(i){d=!0,h=i,u=this._value}finally{o.consumer=n,o.untracked=r,s&&x()}let I=!this._initialized||this._threw!==d||(d?h!==this._error:!this._equals(this._value,u));if(this._initialized=!0,this._threw=d,this._error=h,this._value=u,T(this),I){if(this.version++,this.observers)for(let i of this.observers)i.markDirty(c);k(this)}}markDirty(n){if(this.state>=n)return;let r=this.state===j;if(this.state=n,r){if(this.observers)for(let s of this.observers)s.markDirty(N);k(this)}}peek(){if(this.updateIfNecessary(),this._threw)throw this._error;return this._value}};function k(e){if(e.watchers)for(let t of[...e.watchers])t._notify(e)}var f=class{constructor(t){this._watched=new Set;this._pending=new Set;this._notifyFn=t}watch(...t){for(let n of t)this._watched.add(n),(n.watchers??=new Set).add(this)}unwatch(...t){for(let n of t)this._watched.delete(n),n.watchers?.delete(this),this._pending.delete(n)}getPending(){let t=[...this._pending];return this._pending.clear(),t}clearPending(){this._pending.clear()}_notify(t){if(!this._watched.has(t)||this._pending.has(t))return;let n=this._pending.size===0;this._pending.add(t),n&&this._notifyFn()}};function C(e){if(o.untracked)return e();o.untracked=!0;try{return e()}finally{o.untracked=!1}}function E(){return o.consumer}function q(e){return!!(e.observers&&e.observers.size)||!!(e.watchers&&e.watchers.size)}var Y={Watcher:f,untrack:C,currentComputed:E,hasSinks:q};return A(U);})();
|
package/dist/cdn/signal.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];
|
|
@@ -125,6 +125,7 @@ var Computed = class extends Source {
|
|
|
125
125
|
super();
|
|
126
126
|
this._threw = false;
|
|
127
127
|
this._initialized = false;
|
|
128
|
+
this._disposed = false;
|
|
128
129
|
this.state = DIRTY;
|
|
129
130
|
/** Nodes this computation read on its last run. Rebuilt on every run. */
|
|
130
131
|
this.sources = null;
|
|
@@ -140,8 +141,23 @@ var Computed = class extends Source {
|
|
|
140
141
|
if (this._threw) throw this._error;
|
|
141
142
|
return this._value;
|
|
142
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Unlink from every source, for good. Without this, a source outlives the
|
|
146
|
+
* computation and keeps it (and everything its function captured) reachable
|
|
147
|
+
* through its observers set: a disposed list row stayed in memory that way.
|
|
148
|
+
* The last value stays readable; the node simply never updates again.
|
|
149
|
+
*/
|
|
150
|
+
dispose() {
|
|
151
|
+
if (this._disposed) return;
|
|
152
|
+
this._disposed = true;
|
|
153
|
+
if (this.sources) {
|
|
154
|
+
for (const s of this.sources) s.observers?.delete(this);
|
|
155
|
+
this.sources = null;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
143
158
|
/** Settle, if CHECK, verify sources; if DIRTY (or never run), recompute. */
|
|
144
159
|
updateIfNecessary() {
|
|
160
|
+
if (this._disposed) return;
|
|
145
161
|
if (this.state === CHECK) {
|
|
146
162
|
if (this.sources) {
|
|
147
163
|
for (const s of this.sources) {
|
|
@@ -185,7 +201,7 @@ var Computed = class extends Source {
|
|
|
185
201
|
reportReactiveRun(this);
|
|
186
202
|
if (changed) {
|
|
187
203
|
this.version++;
|
|
188
|
-
if (this.observers) for (const o of
|
|
204
|
+
if (this.observers) for (const o of this.observers) o.markDirty(DIRTY);
|
|
189
205
|
notifyWatchers(this);
|
|
190
206
|
}
|
|
191
207
|
}
|
|
@@ -199,7 +215,7 @@ var Computed = class extends Source {
|
|
|
199
215
|
const wasClean = this.state === CLEAN;
|
|
200
216
|
this.state = level;
|
|
201
217
|
if (wasClean) {
|
|
202
|
-
if (this.observers) for (const o of
|
|
218
|
+
if (this.observers) for (const o of this.observers) o.markDirty(CHECK);
|
|
203
219
|
notifyWatchers(this);
|
|
204
220
|
}
|
|
205
221
|
}
|
|
@@ -238,6 +254,10 @@ var Watcher = class {
|
|
|
238
254
|
this._pending.clear();
|
|
239
255
|
return out;
|
|
240
256
|
}
|
|
257
|
+
/** Drain pending without the array, for callers that only need it empty. */
|
|
258
|
+
clearPending() {
|
|
259
|
+
this._pending.clear();
|
|
260
|
+
}
|
|
241
261
|
/** @internal, a watched node became non-clean. Edge-triggered: notify once. */
|
|
242
262
|
_notify(node) {
|
|
243
263
|
if (!this._watched.has(node) || this._pending.has(node)) return;
|
package/dist/index.cjs
CHANGED
|
@@ -158,7 +158,7 @@ __export(index_exports, {
|
|
|
158
158
|
module.exports = __toCommonJS(index_exports);
|
|
159
159
|
|
|
160
160
|
// src/version.generated.ts
|
|
161
|
-
var VERSION = "1.0.0-alpha.
|
|
161
|
+
var VERSION = "1.0.0-alpha.106";
|
|
162
162
|
|
|
163
163
|
// src/lib/predicates.ts
|
|
164
164
|
function isFunction(value) {
|
|
@@ -795,6 +795,7 @@ var Computed = class extends Source {
|
|
|
795
795
|
super();
|
|
796
796
|
this._threw = false;
|
|
797
797
|
this._initialized = false;
|
|
798
|
+
this._disposed = false;
|
|
798
799
|
this.state = DIRTY;
|
|
799
800
|
/** Nodes this computation read on its last run. Rebuilt on every run. */
|
|
800
801
|
this.sources = null;
|
|
@@ -810,8 +811,23 @@ var Computed = class extends Source {
|
|
|
810
811
|
if (this._threw) throw this._error;
|
|
811
812
|
return this._value;
|
|
812
813
|
}
|
|
814
|
+
/**
|
|
815
|
+
* Unlink from every source, for good. Without this, a source outlives the
|
|
816
|
+
* computation and keeps it (and everything its function captured) reachable
|
|
817
|
+
* through its observers set: a disposed list row stayed in memory that way.
|
|
818
|
+
* The last value stays readable; the node simply never updates again.
|
|
819
|
+
*/
|
|
820
|
+
dispose() {
|
|
821
|
+
if (this._disposed) return;
|
|
822
|
+
this._disposed = true;
|
|
823
|
+
if (this.sources) {
|
|
824
|
+
for (const s of this.sources) s.observers?.delete(this);
|
|
825
|
+
this.sources = null;
|
|
826
|
+
}
|
|
827
|
+
}
|
|
813
828
|
/** Settle, if CHECK, verify sources; if DIRTY (or never run), recompute. */
|
|
814
829
|
updateIfNecessary() {
|
|
830
|
+
if (this._disposed) return;
|
|
815
831
|
if (this.state === CHECK) {
|
|
816
832
|
if (this.sources) {
|
|
817
833
|
for (const s of this.sources) {
|
|
@@ -855,7 +871,7 @@ var Computed = class extends Source {
|
|
|
855
871
|
reportReactiveRun(this);
|
|
856
872
|
if (changed) {
|
|
857
873
|
this.version++;
|
|
858
|
-
if (this.observers) for (const o of
|
|
874
|
+
if (this.observers) for (const o of this.observers) o.markDirty(DIRTY);
|
|
859
875
|
notifyWatchers(this);
|
|
860
876
|
}
|
|
861
877
|
}
|
|
@@ -869,7 +885,7 @@ var Computed = class extends Source {
|
|
|
869
885
|
const wasClean = this.state === CLEAN;
|
|
870
886
|
this.state = level;
|
|
871
887
|
if (wasClean) {
|
|
872
|
-
if (this.observers) for (const o of
|
|
888
|
+
if (this.observers) for (const o of this.observers) o.markDirty(CHECK);
|
|
873
889
|
notifyWatchers(this);
|
|
874
890
|
}
|
|
875
891
|
}
|
|
@@ -908,6 +924,10 @@ var Watcher = class {
|
|
|
908
924
|
this._pending.clear();
|
|
909
925
|
return out;
|
|
910
926
|
}
|
|
927
|
+
/** Drain pending without the array, for callers that only need it empty. */
|
|
928
|
+
clearPending() {
|
|
929
|
+
this._pending.clear();
|
|
930
|
+
}
|
|
911
931
|
/** @internal, a watched node became non-clean. Edge-triggered: notify once. */
|
|
912
932
|
_notify(node) {
|
|
913
933
|
if (!this._watched.has(node) || this._pending.has(node)) return;
|
|
@@ -1125,14 +1145,14 @@ var EffectNode = class {
|
|
|
1125
1145
|
if (typeof r === "function") (this.owner.cleanups ??= []).push(r);
|
|
1126
1146
|
});
|
|
1127
1147
|
});
|
|
1128
|
-
reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
|
|
1148
|
+
if (isObserved()) reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
|
|
1129
1149
|
this.watcher = new Watcher(() => enqueue(this));
|
|
1130
1150
|
this.run();
|
|
1131
1151
|
this.watcher.watch(this.computed);
|
|
1132
1152
|
}
|
|
1133
1153
|
run() {
|
|
1134
1154
|
if (this.disposed) return;
|
|
1135
|
-
this.watcher.
|
|
1155
|
+
this.watcher.clearPending();
|
|
1136
1156
|
try {
|
|
1137
1157
|
this.computed.get();
|
|
1138
1158
|
} catch (e) {
|
|
@@ -1149,6 +1169,7 @@ var EffectNode = class {
|
|
|
1149
1169
|
this.disposed = true;
|
|
1150
1170
|
reportReactiveDispose(this.computed);
|
|
1151
1171
|
this.watcher.unwatch(this.computed);
|
|
1172
|
+
this.computed.dispose();
|
|
1152
1173
|
disposeOwner(this.owner);
|
|
1153
1174
|
}
|
|
1154
1175
|
};
|
|
@@ -1187,13 +1208,15 @@ function createSignal(value, options) {
|
|
|
1187
1208
|
},
|
|
1188
1209
|
enumerable: false
|
|
1189
1210
|
});
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1211
|
+
if (isObserved()) {
|
|
1212
|
+
reportReactiveNode({
|
|
1213
|
+
kind: "signal",
|
|
1214
|
+
node: state,
|
|
1215
|
+
handle: read,
|
|
1216
|
+
name: options?.name,
|
|
1217
|
+
set: write
|
|
1218
|
+
});
|
|
1219
|
+
}
|
|
1197
1220
|
if (isObserved()) onCleanup(() => reportReactiveDispose(state));
|
|
1198
1221
|
return [read, write];
|
|
1199
1222
|
}
|
|
@@ -1217,8 +1240,11 @@ function createMemo(fn, value, options) {
|
|
|
1217
1240
|
const read = (() => c.get());
|
|
1218
1241
|
Object.defineProperty(read, $SIGNAL, { value: true, enumerable: true });
|
|
1219
1242
|
Object.defineProperty(read, $MEMO, { value: true, enumerable: true });
|
|
1220
|
-
reportReactiveNode({ kind: "memo", node: c, handle: read, name: options?.name });
|
|
1221
|
-
|
|
1243
|
+
if (isObserved()) reportReactiveNode({ kind: "memo", node: c, handle: read, name: options?.name });
|
|
1244
|
+
onCleanup(() => {
|
|
1245
|
+
c.dispose();
|
|
1246
|
+
if (isObserved()) reportReactiveDispose(c);
|
|
1247
|
+
});
|
|
1222
1248
|
return read;
|
|
1223
1249
|
}
|
|
1224
1250
|
function createEffect(fn, value, options) {
|
|
@@ -1275,6 +1301,20 @@ function on(deps, fn, options) {
|
|
|
1275
1301
|
}
|
|
1276
1302
|
|
|
1277
1303
|
// src/lib/signal/list.ts
|
|
1304
|
+
function lazyIndex(initial) {
|
|
1305
|
+
let current = initial;
|
|
1306
|
+
let state = null;
|
|
1307
|
+
return {
|
|
1308
|
+
index: () => {
|
|
1309
|
+
if (!state) state = createSignal(current, { name: "row index" });
|
|
1310
|
+
return state[0]();
|
|
1311
|
+
},
|
|
1312
|
+
set: (n) => {
|
|
1313
|
+
current = n;
|
|
1314
|
+
if (state) state[1](n);
|
|
1315
|
+
}
|
|
1316
|
+
};
|
|
1317
|
+
}
|
|
1278
1318
|
function mapArray(list, mapFn, options) {
|
|
1279
1319
|
let items = [];
|
|
1280
1320
|
onCleanup(() => {
|
|
@@ -1304,9 +1344,9 @@ function mapArray(list, mapFn, options) {
|
|
|
1304
1344
|
let rendered, setIndex, dispose;
|
|
1305
1345
|
createRoot((d) => {
|
|
1306
1346
|
dispose = d;
|
|
1307
|
-
const
|
|
1308
|
-
setIndex =
|
|
1309
|
-
rendered = mapFn(value, index);
|
|
1347
|
+
const idx = lazyIndex(i);
|
|
1348
|
+
setIndex = idx.set;
|
|
1349
|
+
rendered = mapFn(value, idx.index);
|
|
1310
1350
|
});
|
|
1311
1351
|
const entry = { item: value, rendered, dispose, setIndex };
|
|
1312
1352
|
result.push(entry);
|
|
@@ -1346,21 +1386,19 @@ function keyArray(list, keyFn, mapFn, options) {
|
|
|
1346
1386
|
const reuse = prevByKey.get(key);
|
|
1347
1387
|
if (reuse && !usedKeys.has(key)) {
|
|
1348
1388
|
reuse.setIndex(i);
|
|
1389
|
+
reuse.setItem(next[i]);
|
|
1349
1390
|
resultEntries.push(reuse);
|
|
1350
1391
|
} else {
|
|
1351
|
-
let rendered, setIndex, dispose;
|
|
1392
|
+
let rendered, setIndex, setItem, dispose;
|
|
1352
1393
|
createRoot((d) => {
|
|
1353
1394
|
dispose = d;
|
|
1354
|
-
const
|
|
1355
|
-
setIndex =
|
|
1356
|
-
const item =
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
return v !== void 0 && v !== null ? v : prev;
|
|
1360
|
-
}, next[i]);
|
|
1361
|
-
rendered = mapFn(item, index);
|
|
1395
|
+
const idx = lazyIndex(i);
|
|
1396
|
+
setIndex = idx.set;
|
|
1397
|
+
const [item, writeItem] = createSignal(next[i]);
|
|
1398
|
+
setItem = (v) => writeItem(() => v);
|
|
1399
|
+
rendered = mapFn(item, idx.index);
|
|
1362
1400
|
});
|
|
1363
|
-
resultEntries.push({ rendered, dispose, setIndex });
|
|
1401
|
+
resultEntries.push({ rendered, dispose, setIndex, setItem });
|
|
1364
1402
|
}
|
|
1365
1403
|
resultKeys.push(key);
|
|
1366
1404
|
usedKeys.add(key);
|
|
@@ -1410,7 +1448,7 @@ function indexArray(list, mapFn, options) {
|
|
|
1410
1448
|
|
|
1411
1449
|
// src/lib/signal/graph/detect.ts
|
|
1412
1450
|
var __BROWSER_PROD__ = typeof window === "undefined" ? false : window.__FLUIXI_PROD__ === true;
|
|
1413
|
-
var __DEV__ = typeof process === "undefined" ? __BROWSER_PROD__ :
|
|
1451
|
+
var __DEV__ = typeof process === "undefined" ? __BROWSER_PROD__ : process.env.NODE_ENV !== "production";
|
|
1414
1452
|
var $SIGNAL2 = /* @__PURE__ */ Symbol.for("signal");
|
|
1415
1453
|
var $MEMO2 = /* @__PURE__ */ Symbol.for("memo");
|
|
1416
1454
|
var $RESOURCE = /* @__PURE__ */ Symbol.for("resource");
|
|
@@ -2222,12 +2260,14 @@ var Store = class {
|
|
|
2222
2260
|
OWNERS.set(initialState, { store: this, name: options.name ?? "store" });
|
|
2223
2261
|
ROOTS.set(initialState, initialState);
|
|
2224
2262
|
}
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2263
|
+
if (isObserved()) {
|
|
2264
|
+
reportReactiveNode({
|
|
2265
|
+
kind: "store",
|
|
2266
|
+
node: this,
|
|
2267
|
+
handle: () => this.root,
|
|
2268
|
+
name: options.name
|
|
2269
|
+
});
|
|
2270
|
+
}
|
|
2231
2271
|
}
|
|
2232
2272
|
get state() {
|
|
2233
2273
|
return box(this.root);
|