@pyreon/reactivity 0.23.0 → 0.24.1

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.
@@ -0,0 +1,280 @@
1
+ //#region src/reactive-devtools.ts
2
+ /**
3
+ * Time constant for the rate1s EWMA (milliseconds). Tuned for the "hot
4
+ * path debugging" use case: a 1-second time constant means a burst of
5
+ * fires shows up immediately, then decays to 1/e (~0.37×) after one
6
+ * second of silence, ~5% after 3 seconds, ~0.7% after 5 seconds.
7
+ *
8
+ * @internal — exported for tests + tunability.
9
+ */
10
+ const LPIH_RATE_TAU_MS = 1e3;
11
+ let _active = false;
12
+ let _nextId = 1;
13
+ const _byId = /* @__PURE__ */ new Map();
14
+ const _subId = /* @__PURE__ */ new WeakMap();
15
+ /** @internal — finalizer callback; prunes the record when a node is GC'd. */
16
+ function _rdPrune(id) {
17
+ _byId.delete(id);
18
+ }
19
+ const _finalizer = new FinalizationRegistry(_rdPrune);
20
+ const FIRE_CAP = 512;
21
+ let _fireBuf = null;
22
+ let _fireCount = 0;
23
+ const PREVIEW_MAX = 60;
24
+ function preview(v) {
25
+ let s;
26
+ try {
27
+ if (v === null) return "null";
28
+ if (v === void 0) return "undefined";
29
+ const t = typeof v;
30
+ if (t === "string") s = JSON.stringify(v);
31
+ else if (t === "number" || t === "boolean" || t === "bigint") s = String(v);
32
+ else if (t === "function") s = `[Function ${v.name || "anonymous"}]`;
33
+ else if (t === "symbol") s = v.toString();
34
+ else if (Array.isArray(v)) s = `Array(${v.length})`;
35
+ else {
36
+ const ctor = v.constructor?.name;
37
+ let keys = [];
38
+ try {
39
+ keys = Object.keys(v).slice(0, 3);
40
+ } catch {
41
+ keys = [];
42
+ }
43
+ s = `${ctor && ctor !== "Object" ? `${ctor} ` : ""}{${keys.join(", ")}${keys.length === 3 ? ", …" : ""}}`;
44
+ }
45
+ } catch {
46
+ s = "[unstringifiable]";
47
+ }
48
+ return s.length > PREVIEW_MAX ? `${s.slice(0, PREVIEW_MAX)}…` : s;
49
+ }
50
+ /** Activate the bridge. Idempotent. Called when a devtools client attaches. */
51
+ function activateReactiveDevtools() {
52
+ _active = true;
53
+ }
54
+ /**
55
+ * Deactivate + drop all retained state. Called when the devtools client
56
+ * disconnects so a closed panel leaves zero residue.
57
+ */
58
+ function deactivateReactiveDevtools() {
59
+ _active = false;
60
+ _byId.clear();
61
+ _fireBuf = null;
62
+ _fireCount = 0;
63
+ }
64
+ function isReactiveDevtoolsActive() {
65
+ return _active;
66
+ }
67
+ /**
68
+ * Parse the user's call site from `new Error().stack`. Returns undefined
69
+ * when devtools isn't active (zero-cost early-return — no Error allocated)
70
+ * OR when the stack format isn't recognized.
71
+ *
72
+ * `skipFrames` is the number of caller-frames to skip past _captureCallerLocation
73
+ * itself. The framework's hot-path callers (signal / computedLazy / effect)
74
+ * pass their own depth so the captured frame is the USER's call to
75
+ * `signal()` / `computed()` / `effect()`, not the framework's internals.
76
+ *
77
+ * Recognized stack formats:
78
+ * - V8 (Chrome / Node / Bun): ` at fn (file:line:col)`
79
+ * - V8 (anonymous): ` at file:line:col`
80
+ * - JSC (Safari) + SpiderMonkey: `fn@file:line:col`
81
+ *
82
+ * @internal
83
+ */
84
+ function _captureCallerLocation(skipFrames) {
85
+ if (!_active) return void 0;
86
+ const raw = (/* @__PURE__ */ new Error()).stack;
87
+ if (!raw) return void 0;
88
+ const lines = raw.split("\n");
89
+ const target = lines[(lines[0] && lines[0].trim().startsWith("Error") ? 1 : 0) + 1 + skipFrames];
90
+ if (!target) return void 0;
91
+ return parseStackLine(target);
92
+ }
93
+ function parseStackLine(line) {
94
+ const v8Paren = line.match(/\(([^()]+):(\d+):(\d+)\)\s*$/);
95
+ if (v8Paren && v8Paren[1] && v8Paren[2] && v8Paren[3]) {
96
+ const file = v8Paren[1];
97
+ const lineN = Number.parseInt(v8Paren[2], 10);
98
+ const col = Number.parseInt(v8Paren[3], 10);
99
+ if (Number.isFinite(lineN) && Number.isFinite(col)) return {
100
+ file,
101
+ line: lineN,
102
+ col
103
+ };
104
+ }
105
+ const v8Bare = line.match(/at\s+([^\s()]+):(\d+):(\d+)\s*$/);
106
+ if (v8Bare && v8Bare[1] && v8Bare[2] && v8Bare[3]) {
107
+ const file = v8Bare[1];
108
+ const lineN = Number.parseInt(v8Bare[2], 10);
109
+ const col = Number.parseInt(v8Bare[3], 10);
110
+ if (Number.isFinite(lineN) && Number.isFinite(col)) return {
111
+ file,
112
+ line: lineN,
113
+ col
114
+ };
115
+ }
116
+ const jsc = line.match(/@([^@\s]+):(\d+):(\d+)\s*$/);
117
+ if (jsc && jsc[1] && jsc[2] && jsc[3]) {
118
+ const file = jsc[1];
119
+ const lineN = Number.parseInt(jsc[2], 10);
120
+ const col = Number.parseInt(jsc[3], 10);
121
+ if (Number.isFinite(lineN) && Number.isFinite(col)) return {
122
+ file,
123
+ line: lineN,
124
+ col
125
+ };
126
+ }
127
+ }
128
+ /**
129
+ * Register a signal/computed/effect node. `host` is the object carrying
130
+ * the `_s` subscriber Set (the signal read fn itself, or a computed's
131
+ * internal host). `sub` is the notify closure (`recompute`/`run`) whose
132
+ * identity appears in upstream `_s` Sets — used to resolve edges.
133
+ *
134
+ * @internal
135
+ */
136
+ function _rdRegister(node, kind, host, sub, label, loc) {
137
+ if (!_active) return void 0;
138
+ const id = _nextId++;
139
+ _byId.set(id, {
140
+ id,
141
+ kind,
142
+ name: label ?? `${kind === "signal" ? "signal" : kind}#${id}`,
143
+ ref: new WeakRef(node),
144
+ hostRef: host ? new WeakRef(host) : null,
145
+ fires: 0,
146
+ lastFire: null,
147
+ loc,
148
+ rate1s: 0
149
+ });
150
+ if (sub) _subId.set(sub, id);
151
+ _finalizer.register(node, id);
152
+ Object.defineProperty(node, "__pxRdId", {
153
+ value: id,
154
+ enumerable: false,
155
+ configurable: true
156
+ });
157
+ return id;
158
+ }
159
+ /**
160
+ * Record that a node fired (signal write / computed recompute / effect
161
+ * run). Bumps counters + appends to the bounded fire buffer.
162
+ *
163
+ * @internal
164
+ */
165
+ function _rdRecordFire(node) {
166
+ if (!_active) return;
167
+ const id = node.__pxRdId;
168
+ if (id === void 0) return;
169
+ const rec = _byId.get(id);
170
+ const ts = typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
171
+ if (rec) {
172
+ rec.fires++;
173
+ if (rec.lastFire !== null) {
174
+ const dt = ts - rec.lastFire;
175
+ const decay = Math.exp(-dt / LPIH_RATE_TAU_MS);
176
+ rec.rate1s = rec.rate1s * decay + 1;
177
+ } else rec.rate1s = 1;
178
+ rec.lastFire = ts;
179
+ }
180
+ if (_fireBuf === null) _fireBuf = new Array(FIRE_CAP);
181
+ _fireBuf[_fireCount % FIRE_CAP] = {
182
+ id,
183
+ ts
184
+ };
185
+ _fireCount++;
186
+ }
187
+ function resolveSubId(sub) {
188
+ const direct = sub.__pxRdId;
189
+ if (direct !== void 0) return direct;
190
+ return _subId.get(sub);
191
+ }
192
+ /**
193
+ * Fresh snapshot of the live reactive graph. Edges are recomputed from
194
+ * each live node's current subscriber Set — always consistent with the
195
+ * framework's real subscription state, no incremental drift.
196
+ */
197
+ function getReactiveGraph() {
198
+ const nodes = [];
199
+ const edges = [];
200
+ for (const rec of _byId.values()) {
201
+ const node = rec.ref.deref();
202
+ if (!node) continue;
203
+ const subs = (rec.hostRef?.deref() ?? null)?._s ?? null;
204
+ const valueStr = rec.kind === "effect" ? "" : preview(node._v);
205
+ nodes.push({
206
+ id: rec.id,
207
+ kind: rec.kind,
208
+ name: rec.name,
209
+ value: valueStr,
210
+ subscribers: subs?.size ?? 0,
211
+ fires: rec.fires,
212
+ lastFire: rec.lastFire,
213
+ ...rec.loc ? { loc: rec.loc } : {}
214
+ });
215
+ if (subs) for (const cb of subs) {
216
+ const to = resolveSubId(cb);
217
+ if (to !== void 0) edges.push({
218
+ from: rec.id,
219
+ to
220
+ });
221
+ }
222
+ }
223
+ return {
224
+ nodes,
225
+ edges
226
+ };
227
+ }
228
+ /**
229
+ * Aggregate fire counts by source-location — powers Live Program Inlay
230
+ * Hints. Walks the live node registry, keys each node by its captured
231
+ * `loc`, and returns one summary per unique `file:line:col`. Nodes
232
+ * without a captured location are skipped (their fires are still
233
+ * visible via `getReactiveGraph()` and `getReactiveFires()` for the
234
+ * existing graph / timeline surfaces).
235
+ *
236
+ * Returns a fresh array, JSON-serializable, safe to ship across the
237
+ * devtools-host bridge or to write into an LSP cache file.
238
+ */
239
+ function getFireSummaries() {
240
+ const byKey = /* @__PURE__ */ new Map();
241
+ const nowTs = typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
242
+ for (const rec of _byId.values()) {
243
+ if (!rec.loc) continue;
244
+ if (!rec.ref.deref()) continue;
245
+ const k = `${rec.loc.file}:${rec.loc.line}:${rec.loc.col}`;
246
+ const decayedRate = rec.lastFire !== null ? rec.rate1s * Math.exp(-(nowTs - rec.lastFire) / LPIH_RATE_TAU_MS) : 0;
247
+ const existing = byKey.get(k);
248
+ if (existing) {
249
+ existing.count += rec.fires;
250
+ existing.rate1s += decayedRate;
251
+ if (rec.lastFire !== null && (existing.lastFire === null || rec.lastFire > existing.lastFire)) {
252
+ existing.lastFire = rec.lastFire;
253
+ existing.kind = rec.kind;
254
+ }
255
+ } else byKey.set(k, {
256
+ loc: rec.loc,
257
+ count: rec.fires,
258
+ lastFire: rec.lastFire,
259
+ kind: rec.kind,
260
+ rate1s: decayedRate
261
+ });
262
+ }
263
+ return [...byKey.values()];
264
+ }
265
+ /** Bounded recent-fire timeline (oldest → newest). Fresh copy. */
266
+ function getReactiveFires() {
267
+ if (_fireBuf === null || _fireCount === 0) return [];
268
+ if (_fireCount <= FIRE_CAP) return _fireBuf.slice(0, _fireCount);
269
+ const start = _fireCount % FIRE_CAP;
270
+ const out = [];
271
+ for (let i = 0; i < FIRE_CAP; i++) {
272
+ const e = _fireBuf[(start + i) % FIRE_CAP];
273
+ if (e) out.push(e);
274
+ }
275
+ return out;
276
+ }
277
+
278
+ //#endregion
279
+ export { deactivateReactiveDevtools as a, getReactiveGraph as c, activateReactiveDevtools as i, isReactiveDevtoolsActive as l, _rdRecordFire as n, getFireSummaries as o, _rdRegister as r, getReactiveFires as s, _captureCallerLocation as t };
280
+ //# sourceMappingURL=reactive-devtools-BCpGoGZ5.js.map
@@ -5386,7 +5386,7 @@ var drawChart = (function (exports) {
5386
5386
  </script>
5387
5387
  <script>
5388
5388
  /*<!--*/
5389
- const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src","children":[{"uid":"c60e3531-1","name":"batch.ts"},{"uid":"c60e3531-3","name":"cell.ts"},{"uid":"c60e3531-5","name":"reactive-devtools.ts"},{"uid":"c60e3531-7","name":"scope.ts"},{"uid":"c60e3531-9","name":"tracking.ts"},{"uid":"c60e3531-11","name":"effect.ts"},{"uid":"c60e3531-13","name":"computed.ts"},{"uid":"c60e3531-15","name":"createSelector.ts"},{"uid":"c60e3531-17","name":"debug.ts"},{"uid":"c60e3531-19","name":"reactive-trace.ts"},{"uid":"c60e3531-21","name":"signal.ts"},{"uid":"c60e3531-23","name":"store.ts"},{"uid":"c60e3531-25","name":"reconcile.ts"},{"uid":"c60e3531-27","name":"resource.ts"},{"uid":"c60e3531-29","name":"watch.ts"},{"uid":"c60e3531-31","name":"index.ts"}]}]}],"isRoot":true},"nodeParts":{"c60e3531-1":{"renderedLength":3016,"gzipLength":1167,"brotliLength":0,"metaUid":"c60e3531-0"},"c60e3531-3":{"renderedLength":1636,"gzipLength":786,"brotliLength":0,"metaUid":"c60e3531-2"},"c60e3531-5":{"renderedLength":4438,"gzipLength":1940,"brotliLength":0,"metaUid":"c60e3531-4"},"c60e3531-7":{"renderedLength":3026,"gzipLength":1226,"brotliLength":0,"metaUid":"c60e3531-6"},"c60e3531-9":{"renderedLength":2227,"gzipLength":858,"brotliLength":0,"metaUid":"c60e3531-8"},"c60e3531-11":{"renderedLength":7605,"gzipLength":2433,"brotliLength":0,"metaUid":"c60e3531-10"},"c60e3531-13":{"renderedLength":4983,"gzipLength":1524,"brotliLength":0,"metaUid":"c60e3531-12"},"c60e3531-15":{"renderedLength":2244,"gzipLength":981,"brotliLength":0,"metaUid":"c60e3531-14"},"c60e3531-17":{"renderedLength":2469,"gzipLength":1092,"brotliLength":0,"metaUid":"c60e3531-16"},"c60e3531-19":{"renderedLength":2721,"gzipLength":1363,"brotliLength":0,"metaUid":"c60e3531-18"},"c60e3531-21":{"renderedLength":3535,"gzipLength":1513,"brotliLength":0,"metaUid":"c60e3531-20"},"c60e3531-23":{"renderedLength":5232,"gzipLength":1867,"brotliLength":0,"metaUid":"c60e3531-22"},"c60e3531-25":{"renderedLength":2278,"gzipLength":940,"brotliLength":0,"metaUid":"c60e3531-24"},"c60e3531-27":{"renderedLength":1205,"gzipLength":524,"brotliLength":0,"metaUid":"c60e3531-26"},"c60e3531-29":{"renderedLength":1249,"gzipLength":582,"brotliLength":0,"metaUid":"c60e3531-28"},"c60e3531-31":{"renderedLength":0,"gzipLength":0,"brotliLength":0,"metaUid":"c60e3531-30"}},"nodeMetas":{"c60e3531-0":{"id":"/src/batch.ts","moduleParts":{"index.js":"c60e3531-1"},"imported":[],"importedBy":[{"uid":"c60e3531-30"},{"uid":"c60e3531-12"},{"uid":"c60e3531-20"},{"uid":"c60e3531-8"}]},"c60e3531-2":{"id":"/src/cell.ts","moduleParts":{"index.js":"c60e3531-3"},"imported":[],"importedBy":[{"uid":"c60e3531-30"}]},"c60e3531-4":{"id":"/src/reactive-devtools.ts","moduleParts":{"index.js":"c60e3531-5"},"imported":[],"importedBy":[{"uid":"c60e3531-30"},{"uid":"c60e3531-12"},{"uid":"c60e3531-10"},{"uid":"c60e3531-20"}]},"c60e3531-6":{"id":"/src/scope.ts","moduleParts":{"index.js":"c60e3531-7"},"imported":[],"importedBy":[{"uid":"c60e3531-30"},{"uid":"c60e3531-12"},{"uid":"c60e3531-10"}]},"c60e3531-8":{"id":"/src/tracking.ts","moduleParts":{"index.js":"c60e3531-9"},"imported":[{"uid":"c60e3531-0"}],"importedBy":[{"uid":"c60e3531-30"},{"uid":"c60e3531-12"},{"uid":"c60e3531-14"},{"uid":"c60e3531-10"},{"uid":"c60e3531-26"},{"uid":"c60e3531-20"}]},"c60e3531-10":{"id":"/src/effect.ts","moduleParts":{"index.js":"c60e3531-11"},"imported":[{"uid":"c60e3531-4"},{"uid":"c60e3531-6"},{"uid":"c60e3531-8"}],"importedBy":[{"uid":"c60e3531-30"},{"uid":"c60e3531-12"},{"uid":"c60e3531-14"},{"uid":"c60e3531-26"},{"uid":"c60e3531-28"}]},"c60e3531-12":{"id":"/src/computed.ts","moduleParts":{"index.js":"c60e3531-13"},"imported":[{"uid":"c60e3531-0"},{"uid":"c60e3531-10"},{"uid":"c60e3531-4"},{"uid":"c60e3531-6"},{"uid":"c60e3531-8"}],"importedBy":[{"uid":"c60e3531-30"}]},"c60e3531-14":{"id":"/src/createSelector.ts","moduleParts":{"index.js":"c60e3531-15"},"imported":[{"uid":"c60e3531-10"},{"uid":"c60e3531-8"}],"importedBy":[{"uid":"c60e3531-30"}]},"c60e3531-16":{"id":"/src/debug.ts","moduleParts":{"index.js":"c60e3531-17"},"imported":[],"importedBy":[{"uid":"c60e3531-30"},{"uid":"c60e3531-20"}]},"c60e3531-18":{"id":"/src/reactive-trace.ts","moduleParts":{"index.js":"c60e3531-19"},"imported":[],"importedBy":[{"uid":"c60e3531-30"},{"uid":"c60e3531-20"}]},"c60e3531-20":{"id":"/src/signal.ts","moduleParts":{"index.js":"c60e3531-21"},"imported":[{"uid":"c60e3531-0"},{"uid":"c60e3531-16"},{"uid":"c60e3531-4"},{"uid":"c60e3531-18"},{"uid":"c60e3531-8"}],"importedBy":[{"uid":"c60e3531-30"},{"uid":"c60e3531-26"},{"uid":"c60e3531-22"}]},"c60e3531-22":{"id":"/src/store.ts","moduleParts":{"index.js":"c60e3531-23"},"imported":[{"uid":"c60e3531-20"}],"importedBy":[{"uid":"c60e3531-30"},{"uid":"c60e3531-24"}]},"c60e3531-24":{"id":"/src/reconcile.ts","moduleParts":{"index.js":"c60e3531-25"},"imported":[{"uid":"c60e3531-22"}],"importedBy":[{"uid":"c60e3531-30"}]},"c60e3531-26":{"id":"/src/resource.ts","moduleParts":{"index.js":"c60e3531-27"},"imported":[{"uid":"c60e3531-10"},{"uid":"c60e3531-20"},{"uid":"c60e3531-8"}],"importedBy":[{"uid":"c60e3531-30"}]},"c60e3531-28":{"id":"/src/watch.ts","moduleParts":{"index.js":"c60e3531-29"},"imported":[{"uid":"c60e3531-10"}],"importedBy":[{"uid":"c60e3531-30"}]},"c60e3531-30":{"id":"/src/index.ts","moduleParts":{"index.js":"c60e3531-31"},"imported":[{"uid":"c60e3531-0"},{"uid":"c60e3531-2"},{"uid":"c60e3531-12"},{"uid":"c60e3531-14"},{"uid":"c60e3531-16"},{"uid":"c60e3531-4"},{"uid":"c60e3531-18"},{"uid":"c60e3531-10"},{"uid":"c60e3531-24"},{"uid":"c60e3531-26"},{"uid":"c60e3531-6"},{"uid":"c60e3531-20"},{"uid":"c60e3531-22"},{"uid":"c60e3531-8"},{"uid":"c60e3531-28"}],"importedBy":[],"isEntry":true}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
5389
+ const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src","children":[{"uid":"8f0a5281-1","name":"batch.ts"},{"uid":"8f0a5281-3","name":"cell.ts"},{"uid":"8f0a5281-5","name":"scope.ts"},{"uid":"8f0a5281-7","name":"tracking.ts"},{"uid":"8f0a5281-9","name":"effect.ts"},{"uid":"8f0a5281-11","name":"computed.ts"},{"uid":"8f0a5281-13","name":"createSelector.ts"},{"uid":"8f0a5281-15","name":"debug.ts"},{"uid":"8f0a5281-17","name":"reactive-trace.ts"},{"uid":"8f0a5281-19","name":"signal.ts"},{"uid":"8f0a5281-21","name":"store.ts"},{"uid":"8f0a5281-23","name":"reconcile.ts"},{"uid":"8f0a5281-25","name":"resource.ts"},{"uid":"8f0a5281-27","name":"watch.ts"},{"uid":"8f0a5281-29","name":"index.ts"}]}]},{"name":"lpih.js","children":[{"name":"src/lpih.ts","uid":"8f0a5281-31"}]},{"name":"_chunks/reactive-devtools-BCpGoGZ5.js","children":[{"name":"src/reactive-devtools.ts","uid":"8f0a5281-33"}]}],"isRoot":true},"nodeParts":{"8f0a5281-1":{"renderedLength":3016,"gzipLength":1167,"brotliLength":0,"metaUid":"8f0a5281-0"},"8f0a5281-3":{"renderedLength":1636,"gzipLength":786,"brotliLength":0,"metaUid":"8f0a5281-2"},"8f0a5281-5":{"renderedLength":3026,"gzipLength":1226,"brotliLength":0,"metaUid":"8f0a5281-4"},"8f0a5281-7":{"renderedLength":2227,"gzipLength":858,"brotliLength":0,"metaUid":"8f0a5281-6"},"8f0a5281-9":{"renderedLength":7697,"gzipLength":2469,"brotliLength":0,"metaUid":"8f0a5281-8"},"8f0a5281-11":{"renderedLength":5143,"gzipLength":1570,"brotliLength":0,"metaUid":"8f0a5281-10"},"8f0a5281-13":{"renderedLength":2244,"gzipLength":981,"brotliLength":0,"metaUid":"8f0a5281-12"},"8f0a5281-15":{"renderedLength":2469,"gzipLength":1092,"brotliLength":0,"metaUid":"8f0a5281-14"},"8f0a5281-17":{"renderedLength":2721,"gzipLength":1363,"brotliLength":0,"metaUid":"8f0a5281-16"},"8f0a5281-19":{"renderedLength":3643,"gzipLength":1554,"brotliLength":0,"metaUid":"8f0a5281-18"},"8f0a5281-21":{"renderedLength":5232,"gzipLength":1867,"brotliLength":0,"metaUid":"8f0a5281-20"},"8f0a5281-23":{"renderedLength":2278,"gzipLength":940,"brotliLength":0,"metaUid":"8f0a5281-22"},"8f0a5281-25":{"renderedLength":1205,"gzipLength":524,"brotliLength":0,"metaUid":"8f0a5281-24"},"8f0a5281-27":{"renderedLength":1249,"gzipLength":582,"brotliLength":0,"metaUid":"8f0a5281-26"},"8f0a5281-29":{"renderedLength":0,"gzipLength":0,"brotliLength":0,"metaUid":"8f0a5281-28"},"8f0a5281-31":{"renderedLength":6380,"gzipLength":2579,"brotliLength":0,"metaUid":"8f0a5281-30"},"8f0a5281-33":{"renderedLength":8588,"gzipLength":3409,"brotliLength":0,"metaUid":"8f0a5281-32"}},"nodeMetas":{"8f0a5281-0":{"id":"/src/batch.ts","moduleParts":{"index.js":"8f0a5281-1"},"imported":[],"importedBy":[{"uid":"8f0a5281-28"},{"uid":"8f0a5281-10"},{"uid":"8f0a5281-18"},{"uid":"8f0a5281-6"}]},"8f0a5281-2":{"id":"/src/cell.ts","moduleParts":{"index.js":"8f0a5281-3"},"imported":[],"importedBy":[{"uid":"8f0a5281-28"}]},"8f0a5281-4":{"id":"/src/scope.ts","moduleParts":{"index.js":"8f0a5281-5"},"imported":[],"importedBy":[{"uid":"8f0a5281-28"},{"uid":"8f0a5281-10"},{"uid":"8f0a5281-8"}]},"8f0a5281-6":{"id":"/src/tracking.ts","moduleParts":{"index.js":"8f0a5281-7"},"imported":[{"uid":"8f0a5281-0"}],"importedBy":[{"uid":"8f0a5281-28"},{"uid":"8f0a5281-10"},{"uid":"8f0a5281-12"},{"uid":"8f0a5281-8"},{"uid":"8f0a5281-24"},{"uid":"8f0a5281-18"}]},"8f0a5281-8":{"id":"/src/effect.ts","moduleParts":{"index.js":"8f0a5281-9"},"imported":[{"uid":"8f0a5281-32"},{"uid":"8f0a5281-4"},{"uid":"8f0a5281-6"}],"importedBy":[{"uid":"8f0a5281-28"},{"uid":"8f0a5281-10"},{"uid":"8f0a5281-12"},{"uid":"8f0a5281-24"},{"uid":"8f0a5281-26"}]},"8f0a5281-10":{"id":"/src/computed.ts","moduleParts":{"index.js":"8f0a5281-11"},"imported":[{"uid":"8f0a5281-0"},{"uid":"8f0a5281-8"},{"uid":"8f0a5281-32"},{"uid":"8f0a5281-4"},{"uid":"8f0a5281-6"}],"importedBy":[{"uid":"8f0a5281-28"}]},"8f0a5281-12":{"id":"/src/createSelector.ts","moduleParts":{"index.js":"8f0a5281-13"},"imported":[{"uid":"8f0a5281-8"},{"uid":"8f0a5281-6"}],"importedBy":[{"uid":"8f0a5281-28"}]},"8f0a5281-14":{"id":"/src/debug.ts","moduleParts":{"index.js":"8f0a5281-15"},"imported":[],"importedBy":[{"uid":"8f0a5281-28"},{"uid":"8f0a5281-18"}]},"8f0a5281-16":{"id":"/src/reactive-trace.ts","moduleParts":{"index.js":"8f0a5281-17"},"imported":[],"importedBy":[{"uid":"8f0a5281-28"},{"uid":"8f0a5281-18"}]},"8f0a5281-18":{"id":"/src/signal.ts","moduleParts":{"index.js":"8f0a5281-19"},"imported":[{"uid":"8f0a5281-0"},{"uid":"8f0a5281-14"},{"uid":"8f0a5281-32"},{"uid":"8f0a5281-16"},{"uid":"8f0a5281-6"}],"importedBy":[{"uid":"8f0a5281-28"},{"uid":"8f0a5281-24"},{"uid":"8f0a5281-20"}]},"8f0a5281-20":{"id":"/src/store.ts","moduleParts":{"index.js":"8f0a5281-21"},"imported":[{"uid":"8f0a5281-18"}],"importedBy":[{"uid":"8f0a5281-28"},{"uid":"8f0a5281-22"}]},"8f0a5281-22":{"id":"/src/reconcile.ts","moduleParts":{"index.js":"8f0a5281-23"},"imported":[{"uid":"8f0a5281-20"}],"importedBy":[{"uid":"8f0a5281-28"}]},"8f0a5281-24":{"id":"/src/resource.ts","moduleParts":{"index.js":"8f0a5281-25"},"imported":[{"uid":"8f0a5281-8"},{"uid":"8f0a5281-18"},{"uid":"8f0a5281-6"}],"importedBy":[{"uid":"8f0a5281-28"}]},"8f0a5281-26":{"id":"/src/watch.ts","moduleParts":{"index.js":"8f0a5281-27"},"imported":[{"uid":"8f0a5281-8"}],"importedBy":[{"uid":"8f0a5281-28"}]},"8f0a5281-28":{"id":"/src/index.ts","moduleParts":{"index.js":"8f0a5281-29"},"imported":[{"uid":"8f0a5281-0"},{"uid":"8f0a5281-2"},{"uid":"8f0a5281-10"},{"uid":"8f0a5281-12"},{"uid":"8f0a5281-14"},{"uid":"8f0a5281-32"},{"uid":"8f0a5281-16"},{"uid":"8f0a5281-8"},{"uid":"8f0a5281-22"},{"uid":"8f0a5281-24"},{"uid":"8f0a5281-4"},{"uid":"8f0a5281-18"},{"uid":"8f0a5281-20"},{"uid":"8f0a5281-6"},{"uid":"8f0a5281-26"}],"importedBy":[],"isEntry":true},"8f0a5281-30":{"id":"/src/lpih.ts","moduleParts":{"lpih.js":"8f0a5281-31"},"imported":[{"uid":"8f0a5281-32"},{"uid":"8f0a5281-34","dynamic":true}],"importedBy":[],"isEntry":true},"8f0a5281-32":{"id":"/src/reactive-devtools.ts","moduleParts":{"_chunks/reactive-devtools-BCpGoGZ5.js":"8f0a5281-33"},"imported":[],"importedBy":[{"uid":"8f0a5281-28"},{"uid":"8f0a5281-10"},{"uid":"8f0a5281-8"},{"uid":"8f0a5281-18"},{"uid":"8f0a5281-30"}]},"8f0a5281-34":{"id":"node:fs/promises","moduleParts":{},"imported":[],"importedBy":[{"uid":"8f0a5281-30"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
5390
5390
 
5391
5391
  const run = () => {
5392
5392
  const width = window.innerWidth;
package/lib/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ import { a as deactivateReactiveDevtools, c as getReactiveGraph, i as activateReactiveDevtools, l as isReactiveDevtoolsActive, n as _rdRecordFire, o as getFireSummaries, r as _rdRegister, s as getReactiveFires, t as _captureCallerLocation } from "./_chunks/reactive-devtools-BCpGoGZ5.js";
2
+
1
3
  //#region src/batch.ts
2
4
  const __DEV__ = process.env.NODE_ENV !== "production";
3
5
  let batchDepth = 0;
@@ -149,169 +151,6 @@ function cell(value) {
149
151
  return new Cell(value);
150
152
  }
151
153
 
152
- //#endregion
153
- //#region src/reactive-devtools.ts
154
- let _active = false;
155
- let _nextId = 1;
156
- const _byId = /* @__PURE__ */ new Map();
157
- const _subId = /* @__PURE__ */ new WeakMap();
158
- /** @internal — finalizer callback; prunes the record when a node is GC'd. */
159
- function _rdPrune(id) {
160
- _byId.delete(id);
161
- }
162
- const _finalizer = new FinalizationRegistry(_rdPrune);
163
- const FIRE_CAP = 512;
164
- let _fireBuf = null;
165
- let _fireCount = 0;
166
- const PREVIEW_MAX$1 = 60;
167
- function preview$1(v) {
168
- let s;
169
- try {
170
- if (v === null) return "null";
171
- if (v === void 0) return "undefined";
172
- const t = typeof v;
173
- if (t === "string") s = JSON.stringify(v);
174
- else if (t === "number" || t === "boolean" || t === "bigint") s = String(v);
175
- else if (t === "function") s = `[Function ${v.name || "anonymous"}]`;
176
- else if (t === "symbol") s = v.toString();
177
- else if (Array.isArray(v)) s = `Array(${v.length})`;
178
- else {
179
- const ctor = v.constructor?.name;
180
- let keys = [];
181
- try {
182
- keys = Object.keys(v).slice(0, 3);
183
- } catch {
184
- keys = [];
185
- }
186
- s = `${ctor && ctor !== "Object" ? `${ctor} ` : ""}{${keys.join(", ")}${keys.length === 3 ? ", …" : ""}}`;
187
- }
188
- } catch {
189
- s = "[unstringifiable]";
190
- }
191
- return s.length > PREVIEW_MAX$1 ? `${s.slice(0, PREVIEW_MAX$1)}…` : s;
192
- }
193
- /** Activate the bridge. Idempotent. Called when a devtools client attaches. */
194
- function activateReactiveDevtools() {
195
- _active = true;
196
- }
197
- /**
198
- * Deactivate + drop all retained state. Called when the devtools client
199
- * disconnects so a closed panel leaves zero residue.
200
- */
201
- function deactivateReactiveDevtools() {
202
- _active = false;
203
- _byId.clear();
204
- _fireBuf = null;
205
- _fireCount = 0;
206
- }
207
- function isReactiveDevtoolsActive() {
208
- return _active;
209
- }
210
- /**
211
- * Register a signal/computed/effect node. `host` is the object carrying
212
- * the `_s` subscriber Set (the signal read fn itself, or a computed's
213
- * internal host). `sub` is the notify closure (`recompute`/`run`) whose
214
- * identity appears in upstream `_s` Sets — used to resolve edges.
215
- *
216
- * @internal
217
- */
218
- function _rdRegister(node, kind, host, sub, label) {
219
- if (!_active) return void 0;
220
- const id = _nextId++;
221
- _byId.set(id, {
222
- id,
223
- kind,
224
- name: label ?? `${kind === "signal" ? "signal" : kind}#${id}`,
225
- ref: new WeakRef(node),
226
- hostRef: host ? new WeakRef(host) : null,
227
- fires: 0,
228
- lastFire: null
229
- });
230
- if (sub) _subId.set(sub, id);
231
- _finalizer.register(node, id);
232
- Object.defineProperty(node, "__pxRdId", {
233
- value: id,
234
- enumerable: false,
235
- configurable: true
236
- });
237
- return id;
238
- }
239
- /**
240
- * Record that a node fired (signal write / computed recompute / effect
241
- * run). Bumps counters + appends to the bounded fire buffer.
242
- *
243
- * @internal
244
- */
245
- function _rdRecordFire(node) {
246
- if (!_active) return;
247
- const id = node.__pxRdId;
248
- if (id === void 0) return;
249
- const rec = _byId.get(id);
250
- const ts = typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
251
- if (rec) {
252
- rec.fires++;
253
- rec.lastFire = ts;
254
- }
255
- if (_fireBuf === null) _fireBuf = new Array(FIRE_CAP);
256
- _fireBuf[_fireCount % FIRE_CAP] = {
257
- id,
258
- ts
259
- };
260
- _fireCount++;
261
- }
262
- function resolveSubId(sub) {
263
- const direct = sub.__pxRdId;
264
- if (direct !== void 0) return direct;
265
- return _subId.get(sub);
266
- }
267
- /**
268
- * Fresh snapshot of the live reactive graph. Edges are recomputed from
269
- * each live node's current subscriber Set — always consistent with the
270
- * framework's real subscription state, no incremental drift.
271
- */
272
- function getReactiveGraph() {
273
- const nodes = [];
274
- const edges = [];
275
- for (const rec of _byId.values()) {
276
- const node = rec.ref.deref();
277
- if (!node) continue;
278
- const subs = (rec.hostRef?.deref() ?? null)?._s ?? null;
279
- const valueStr = rec.kind === "effect" ? "" : preview$1(node._v);
280
- nodes.push({
281
- id: rec.id,
282
- kind: rec.kind,
283
- name: rec.name,
284
- value: valueStr,
285
- subscribers: subs?.size ?? 0,
286
- fires: rec.fires,
287
- lastFire: rec.lastFire
288
- });
289
- if (subs) for (const cb of subs) {
290
- const to = resolveSubId(cb);
291
- if (to !== void 0) edges.push({
292
- from: rec.id,
293
- to
294
- });
295
- }
296
- }
297
- return {
298
- nodes,
299
- edges
300
- };
301
- }
302
- /** Bounded recent-fire timeline (oldest → newest). Fresh copy. */
303
- function getReactiveFires() {
304
- if (_fireBuf === null || _fireCount === 0) return [];
305
- if (_fireCount <= FIRE_CAP) return _fireBuf.slice(0, _fireCount);
306
- const start = _fireCount % FIRE_CAP;
307
- const out = [];
308
- for (let i = 0; i < FIRE_CAP; i++) {
309
- const e = _fireBuf[(start + i) % FIRE_CAP];
310
- if (e) out.push(e);
311
- }
312
- return out;
313
- }
314
-
315
154
  //#endregion
316
155
  //#region src/scope.ts
317
156
  var EffectScope = class {
@@ -560,7 +399,7 @@ function cleanupLocalDeps$1(deps, fn) {
560
399
  deps.length = 0;
561
400
  }
562
401
  }
563
- function effect(fn) {
402
+ function effect(fn, options) {
564
403
  if (process.env.NODE_ENV !== "production") {
565
404
  if (fn.constructor && fn.constructor.name === "AsyncFunction") console.warn("[pyreon] effect() received an async function. Signal reads after the first `await` are NOT tracked — only the synchronous prefix is. Read every tracked signal BEFORE any await, or split into separate effects, or use `watch(source, asyncCb)` for async-in-callback patterns.");
566
405
  }
@@ -628,7 +467,7 @@ function effect(fn) {
628
467
  if (!isFirstRun) scope?.notifyEffectRan();
629
468
  isFirstRun = false;
630
469
  };
631
- if (process.env.NODE_ENV !== "production") _rdRegister(run, "effect", null, run, void 0);
470
+ if (process.env.NODE_ENV !== "production") _rdRegister(run, "effect", null, run, void 0, options?.__sourceLocation ?? _captureCallerLocation(1));
632
471
  run();
633
472
  const e = { dispose() {
634
473
  runCleanup();
@@ -727,7 +566,7 @@ function renderEffect(fn) {
727
566
  }
728
567
  } else renderEffectFullTrack(deps, run, trackedFn);
729
568
  };
730
- if (process.env.NODE_ENV !== "production") _rdRegister(run, "effect", null, run, void 0);
569
+ if (process.env.NODE_ENV !== "production") _rdRegister(run, "effect", null, run, void 0, _captureCallerLocation(1));
731
570
  run();
732
571
  const dispose = () => {
733
572
  if (disposed) return;
@@ -759,7 +598,8 @@ function computed(fn, options) {
759
598
  if (process.env.NODE_ENV !== "production") {
760
599
  if (fn.constructor && fn.constructor.name === "AsyncFunction") console.warn("[pyreon] computed() received an async function. The result type becomes `Computed<Promise<T>>`, and signal reads after the first `await` are NOT tracked. Use `createResource` for async-derived state, or compute synchronously over a signal that holds the awaited value.");
761
600
  }
762
- return options?.equals ? computedWithEquals(fn, options.equals) : computedLazy(fn);
601
+ const loc = options?.__sourceLocation;
602
+ return options?.equals ? computedWithEquals(fn, options.equals, loc) : computedLazy(fn, loc);
763
603
  }
764
604
  /**
765
605
  * Default computed — lazy evaluation with deferred cleanup.
@@ -771,7 +611,7 @@ function computed(fn, options) {
771
611
  * in diamond patterns (a→b,c→d: b notifies d, c tries to notify d again —
772
612
  * skipped because d is already dirty).
773
613
  */
774
- function computedLazy(fn) {
614
+ function computedLazy(fn, injectedLoc) {
775
615
  let value;
776
616
  let dirty = true;
777
617
  let disposed = false;
@@ -832,7 +672,7 @@ function computedLazy(fn) {
832
672
  set.delete(updater);
833
673
  };
834
674
  };
835
- if (process.env.NODE_ENV !== "production") _rdRegister(read, "derived", host, recompute, void 0);
675
+ if (process.env.NODE_ENV !== "production") _rdRegister(read, "derived", host, recompute, void 0, injectedLoc ?? _captureCallerLocation(2));
836
676
  getCurrentScope()?.add({ dispose: read.dispose });
837
677
  return read;
838
678
  }
@@ -842,7 +682,7 @@ function computedLazy(fn) {
842
682
  * Re-evaluates immediately when deps change and only notifies downstream
843
683
  * if `equals(prev, next)` returns false.
844
684
  */
845
- function computedWithEquals(fn, equals) {
685
+ function computedWithEquals(fn, equals, injectedLoc) {
846
686
  let value;
847
687
  let dirty = true;
848
688
  let initialized = false;
@@ -910,7 +750,7 @@ function computedWithEquals(fn, equals) {
910
750
  set.delete(updater);
911
751
  };
912
752
  };
913
- if (process.env.NODE_ENV !== "production") _rdRegister(read, "derived", host, recompute, void 0);
753
+ if (process.env.NODE_ENV !== "production") _rdRegister(read, "derived", host, recompute, void 0, injectedLoc ?? _captureCallerLocation(2));
914
754
  getCurrentScope()?.add({ dispose: read.dispose });
915
755
  return read;
916
756
  }
@@ -1275,7 +1115,10 @@ function signal(initialValue, options) {
1275
1115
  read.direct = _directFn;
1276
1116
  read.debug = _debug;
1277
1117
  read.label = options?.name;
1278
- if (process.env.NODE_ENV !== "production") _rdRegister(read, "signal", read, null, read.label);
1118
+ if (process.env.NODE_ENV !== "production") {
1119
+ const loc = options?.__sourceLocation ? options.__sourceLocation : _captureCallerLocation(1);
1120
+ _rdRegister(read, "signal", read, null, read.label, loc);
1121
+ }
1279
1122
  return read;
1280
1123
  }
1281
1124
 
@@ -1596,5 +1439,5 @@ function watch(source, callback, opts = {}) {
1596
1439
  }
1597
1440
 
1598
1441
  //#endregion
1599
- export { Cell, EffectScope, _bind, activateReactiveDevtools, batch, cell, clearReactiveTrace, computed, createResource, createSelector, createStore, deactivateReactiveDevtools, effect, effectScope, getCurrentScope, getReactiveFires, getReactiveGraph, getReactiveTrace, inspectSignal, isReactiveDevtoolsActive, isStore, markRaw, nextTick, onCleanup, onScopeDispose, onSignalUpdate, reconcile, renderEffect, runUntracked, runUntracked as untrack, setCurrentScope, setErrorHandler, setSnapshotCapture, shallowReactive, signal, watch, why };
1442
+ export { Cell, EffectScope, _bind, activateReactiveDevtools, batch, cell, clearReactiveTrace, computed, createResource, createSelector, createStore, deactivateReactiveDevtools, effect, effectScope, getCurrentScope, getFireSummaries, getReactiveFires, getReactiveGraph, getReactiveTrace, inspectSignal, isReactiveDevtoolsActive, isStore, markRaw, nextTick, onCleanup, onScopeDispose, onSignalUpdate, reconcile, renderEffect, runUntracked, runUntracked as untrack, setCurrentScope, setErrorHandler, setSnapshotCapture, shallowReactive, signal, watch, why };
1600
1443
  //# sourceMappingURL=index.js.map