vite-devtools-svelte 0.6.0 → 0.6.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.
- package/dist/analyzers/html.d.ts +24 -0
- package/dist/analyzers/og.d.ts +2 -5
- package/dist/analyzers/project.d.ts +1 -0
- package/dist/analyzers/routes.d.ts +6 -0
- package/dist/analyzers/script.d.ts +26 -0
- package/dist/analyzers/source.d.ts +8 -3
- package/dist/analyzers/text.d.ts +6 -0
- package/dist/client/assets/ApiPlayground-r3PMCbhw.js +3 -0
- package/dist/client/assets/Assets-F6ySiRNw.js +1 -0
- package/dist/client/assets/BuildAnalysis-Ci5Or0e4.js +1 -0
- package/dist/client/assets/CaptureNotice-DNYJjRjY.js +1 -0
- package/dist/client/assets/{Components-Co50xTrv.css → Components-DcHDCSmh.css} +1 -1
- package/dist/client/assets/Components-DzrFq-Jl.js +2 -0
- package/dist/client/assets/DataTable-C8wIHfdk.js +1 -0
- package/dist/client/assets/ErrorDashboard-DvBrkCGu.js +1 -0
- package/dist/client/assets/FpsMonitor-Bot5x4nP.js +1 -0
- package/dist/client/assets/FpsMonitor-D0MLqumc.css +1 -0
- package/dist/client/assets/Inspect-TF2sVdn4.js +4 -0
- package/dist/client/assets/Inspector-pD5_jg0-.js +1 -0
- package/dist/client/assets/LiveControls-BDWnVlkm.js +1 -0
- package/dist/client/assets/LoadProfiler-9jiBcPzy.css +1 -0
- package/dist/client/assets/LoadProfiler-RcwiKanZ.js +1 -0
- package/dist/client/assets/ModuleGraph-BscNTo-U.js +1 -0
- package/dist/client/assets/OGPreview-Ca39RUrW.js +1 -0
- package/dist/client/assets/Overview-CNCVS-EJ.js +1 -0
- package/dist/client/assets/Panel-BoUvB1nh.js +1 -0
- package/dist/client/assets/ReactiveGraph-BInCBdAu.css +1 -0
- package/dist/client/assets/ReactiveGraph-BmQbARuQ.js +17 -0
- package/dist/client/assets/RefreshButton-QYzgSJG9.js +1 -0
- package/dist/client/assets/RenderProfiler-Brp8i8K4.js +1 -0
- package/dist/client/assets/RenderProfiler-C0XQZUzw.css +1 -0
- package/dist/client/assets/ResourceEmpty-BBhK6GZB.js +1 -0
- package/dist/client/assets/Routes-BS5YDx3C.js +1 -0
- package/dist/client/assets/SearchField-C1RVVJht.js +1 -0
- package/dist/client/assets/Segmented-CK2euuus.js +1 -0
- package/dist/client/assets/SplitView-D7jY4n9A.js +1 -0
- package/dist/client/assets/StatList-Cd2sByRK.js +1 -0
- package/dist/client/assets/StatList-CwVfs0x8.css +1 -0
- package/dist/client/assets/StateTimeline-CaYBN88_.js +1 -0
- package/dist/client/assets/TreeView-T5wWFSLQ.js +1 -0
- package/dist/client/assets/VirtualList-CLxNqdaN.js +1 -0
- package/dist/client/assets/browser-agent-rpc-BXhoSh1z-DrvKG05N.js +1 -0
- package/dist/client/assets/capture.svelte-CetYVdiG.js +1 -0
- package/dist/client/assets/{collections-uqk9p1aQ.js → collections-BtFss6Lo.js} +1 -1
- package/dist/client/assets/index-BBFupqc_.js +3 -0
- package/dist/client/assets/index-C_6yCKMs.css +1 -0
- package/dist/client/assets/kind-options-BLIV2wQY.js +1 -0
- package/dist/client/assets/nanoid-Cya-tyvy.js +1 -0
- package/dist/client/assets/reactive-BQ_s2f5H.js +1 -0
- package/dist/client/assets/reactive-selection.svelte-DI6qEBmx.js +1 -0
- package/dist/client/assets/resource-f-V9vBwK.css +1 -0
- package/dist/client/assets/resource.svelte-GBY8qvgR.js +5 -0
- package/dist/client/assets/versions-Dmo1-Hsc.js +1 -0
- package/dist/client/index.html +5 -2
- package/dist/index.mjs +1739 -1529
- package/dist/index.mjs.map +1 -1
- package/dist/mcp/http.d.ts +24 -0
- package/dist/mcp/server.d.ts +6 -12
- package/dist/mcp/sessions.d.ts +20 -17
- package/dist/mcp/stats.d.ts +13 -0
- package/dist/plugin.d.ts +0 -6
- package/dist/runtime/transform.d.ts +2 -2
- package/dist/server/collector.d.ts +54 -109
- package/dist/server/compiler-warnings.d.ts +13 -0
- package/dist/server/devframe.d.ts +9 -9
- package/dist/server/load-profile.d.ts +12 -0
- package/dist/server/mount.d.ts +2 -0
- package/dist/server/payload.d.ts +11 -0
- package/dist/server/reactive.d.ts +30 -0
- package/dist/server/ring.d.ts +11 -0
- package/dist/server/security.d.ts +3 -1
- package/dist/server/state-timeline.d.ts +72 -0
- package/package.json +1 -1
- package/dist/client/assets/ApiPlayground-qRDX0tRk.js +0 -3
- package/dist/client/assets/Assets-yTFLB7w2.js +0 -1
- package/dist/client/assets/BuildAnalysis-C6yO6EJN.js +0 -1
- package/dist/client/assets/CaptureNotice-DykEK0Kp.js +0 -1
- package/dist/client/assets/Components-BTG8jKec.js +0 -2
- package/dist/client/assets/DataTable-C5C0HrMd.js +0 -1
- package/dist/client/assets/ErrorDashboard-DHdptxQP.js +0 -1
- package/dist/client/assets/FpsMonitor-BmS11Tn7.css +0 -1
- package/dist/client/assets/FpsMonitor-G1xRBjK3.js +0 -1
- package/dist/client/assets/Inspect-Ba_b5o73.js +0 -4
- package/dist/client/assets/Inspector-mTvtYmwt.js +0 -1
- package/dist/client/assets/LiveControls-nrc1-cBk.js +0 -1
- package/dist/client/assets/LoadProfiler-cg28l5zW.css +0 -1
- package/dist/client/assets/LoadProfiler-eYXaLPba.js +0 -1
- package/dist/client/assets/ModuleGraph-Dp-bJUnD.js +0 -1
- package/dist/client/assets/OGPreview-BzZ_MAg7.js +0 -1
- package/dist/client/assets/Overview-Cbi5ayT1.js +0 -1
- package/dist/client/assets/Panel-CKQaY_Qq.js +0 -1
- package/dist/client/assets/ReactiveGraph-Bq_aP4uo.css +0 -1
- package/dist/client/assets/ReactiveGraph-CQpsrwa7.js +0 -19
- package/dist/client/assets/RenderProfiler-CCG8KJ2a.js +0 -1
- package/dist/client/assets/RenderProfiler-CS1FAvX6.css +0 -1
- package/dist/client/assets/Routes-Dg3ZrLhJ.js +0 -1
- package/dist/client/assets/SearchField-B5EQ5IIf.js +0 -1
- package/dist/client/assets/Segmented-Dz1OdcPr.js +0 -1
- package/dist/client/assets/SplitView-CxRUXpY5.js +0 -1
- package/dist/client/assets/StateTimeline-CLt2yN8k.js +0 -1
- package/dist/client/assets/TreeView-BYOJBzxO.js +0 -1
- package/dist/client/assets/VirtualList-Bfn8is0p.js +0 -1
- package/dist/client/assets/browser-agent-rpc-BXhoSh1z-CuoUGU_3.js +0 -1
- package/dist/client/assets/capture.svelte-BLIttZ2Z.js +0 -1
- package/dist/client/assets/format-BEILGi1v.js +0 -1
- package/dist/client/assets/index-BmEfdt6W.css +0 -1
- package/dist/client/assets/index-Cf5oAFpK.js +0 -7
- package/dist/client/assets/reactive-DuxZv-g7.js +0 -1
- package/dist/client/assets/reactive-selection.svelte-iv05jhlt.js +0 -1
- package/dist/client/assets/versions-Bd19hz8p.js +0 -1
package/dist/index.mjs
CHANGED
|
@@ -2,54 +2,154 @@ import e from "node:crypto";
|
|
|
2
2
|
import t from "node:path";
|
|
3
3
|
import { launchEditor as n } from "devframe/utils/launch-editor";
|
|
4
4
|
import r from "node:fs";
|
|
5
|
-
import {
|
|
6
|
-
import { StreamableHTTPServerTransport as
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import { initDevframe as
|
|
15
|
-
import { DEVTOOLS_MOUNT_PATH as
|
|
5
|
+
import { Visitor as i, parseSync as a } from "vite";
|
|
6
|
+
import { StreamableHTTPServerTransport as o } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
7
|
+
import { McpServer as s } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
8
|
+
import { z as c } from "zod";
|
|
9
|
+
import { createRequire as l } from "node:module";
|
|
10
|
+
import { defineDevframe as u, defineRpcFunction as d } from "devframe";
|
|
11
|
+
import f from "node:dns/promises";
|
|
12
|
+
import p from "node:net";
|
|
13
|
+
import m from "node:os";
|
|
14
|
+
import { initDevframe as h } from "devframe/initiate";
|
|
15
|
+
import { DEVTOOLS_MOUNT_PATH as g } from "@vitejs/devtools-kit/constants";
|
|
16
|
+
//#region src/analyzers/script.ts
|
|
17
|
+
function ee(e) {
|
|
18
|
+
let t = [];
|
|
19
|
+
for (let { offset: n, code: r } of ne(e)) {
|
|
20
|
+
let e = a("script.ts", r);
|
|
21
|
+
e.errors.length === 0 && t.push({
|
|
22
|
+
offset: n,
|
|
23
|
+
code: r,
|
|
24
|
+
result: e
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
return t;
|
|
28
|
+
}
|
|
29
|
+
function _(e, t, n) {
|
|
30
|
+
if (Array.isArray(e)) {
|
|
31
|
+
for (let r of e) _(r, t, n);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (typeof e != "object" || !e || !("type" in e)) return;
|
|
35
|
+
let r = e;
|
|
36
|
+
t(r, n);
|
|
37
|
+
let i = r.type === "ClassDeclaration" || r.type === "ClassExpression" ? r.id?.name : n;
|
|
38
|
+
for (let e in r) {
|
|
39
|
+
let n = r[e];
|
|
40
|
+
typeof n == "object" && n && _(n, t, i);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
var te = /* @__PURE__ */ new Set([
|
|
44
|
+
">",
|
|
45
|
+
"/",
|
|
46
|
+
" ",
|
|
47
|
+
" ",
|
|
48
|
+
"\n",
|
|
49
|
+
"\r",
|
|
50
|
+
"\f"
|
|
51
|
+
]);
|
|
52
|
+
function ne(e) {
|
|
53
|
+
let t = [], n = e.indexOf("<");
|
|
54
|
+
for (; n !== -1;) {
|
|
55
|
+
if (e.startsWith("<!--", n)) {
|
|
56
|
+
let t = e.indexOf("-->", n + 4);
|
|
57
|
+
if (t === -1) break;
|
|
58
|
+
n = e.indexOf("<", t + 3);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (e.startsWith("<script", n) && te.has(e[n + 7] ?? "")) {
|
|
62
|
+
let r = re(e, n + 7), i = r === -1 ? -1 : e.indexOf("<\/script", r);
|
|
63
|
+
if (i === -1) break;
|
|
64
|
+
t.push({
|
|
65
|
+
offset: r,
|
|
66
|
+
code: e.slice(r, i)
|
|
67
|
+
}), n = e.indexOf("<", i + 1);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
n = e.indexOf("<", n + 1);
|
|
71
|
+
}
|
|
72
|
+
return t.length > 0 ? t : [{
|
|
73
|
+
offset: 0,
|
|
74
|
+
code: e
|
|
75
|
+
}];
|
|
76
|
+
}
|
|
77
|
+
function re(e, t) {
|
|
78
|
+
let n = "";
|
|
79
|
+
for (let r = t; r < e.length; r++) {
|
|
80
|
+
let t = e[r];
|
|
81
|
+
if (n) t === n && (n = "");
|
|
82
|
+
else if (t === "\"" || t === "'") n = t;
|
|
83
|
+
else if (t === ">") return r + 1;
|
|
84
|
+
}
|
|
85
|
+
return -1;
|
|
86
|
+
}
|
|
87
|
+
//#endregion
|
|
16
88
|
//#region src/analyzers/components.ts
|
|
17
|
-
|
|
89
|
+
var ie = /* @__PURE__ */ new Map();
|
|
90
|
+
function v(e) {
|
|
18
91
|
let n = t.join(e, "src");
|
|
19
92
|
if (!r.existsSync(n)) return [];
|
|
20
93
|
let i = [];
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
94
|
+
oe(n, i);
|
|
95
|
+
let a = /* @__PURE__ */ new Map(), o = i.map((n) => {
|
|
96
|
+
let r = /* @__PURE__ */ new Set();
|
|
97
|
+
for (let i of ae(n, a)) {
|
|
98
|
+
let a = le(i, t.dirname(n), e);
|
|
99
|
+
a && r.add(t.relative(e, a));
|
|
100
|
+
}
|
|
27
101
|
return {
|
|
28
102
|
file: t.relative(e, n),
|
|
29
|
-
name:
|
|
30
|
-
imports:
|
|
103
|
+
name: t.basename(n, ".svelte"),
|
|
104
|
+
imports: [...r]
|
|
31
105
|
};
|
|
32
106
|
});
|
|
107
|
+
return ie = a, o;
|
|
33
108
|
}
|
|
34
|
-
function
|
|
35
|
-
let
|
|
36
|
-
|
|
37
|
-
let i =
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
109
|
+
function ae(e, t) {
|
|
110
|
+
let n;
|
|
111
|
+
try {
|
|
112
|
+
let { mtimeMs: t, size: i } = r.statSync(e);
|
|
113
|
+
n = ie.get(e), (n?.mtimeMs !== t || n.size !== i) && (n = {
|
|
114
|
+
mtimeMs: t,
|
|
115
|
+
size: i,
|
|
116
|
+
specifiers: se(r.readFileSync(e, "utf-8"))
|
|
117
|
+
});
|
|
118
|
+
} catch {
|
|
119
|
+
return [];
|
|
42
120
|
}
|
|
121
|
+
return t.set(e, n), n.specifiers;
|
|
43
122
|
}
|
|
44
|
-
function
|
|
45
|
-
let i
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
123
|
+
function oe(e, n) {
|
|
124
|
+
for (let i of r.readdirSync(e, { withFileTypes: !0 })) {
|
|
125
|
+
let r = t.join(e, i.name);
|
|
126
|
+
if (i.isDirectory()) {
|
|
127
|
+
if (i.name === "node_modules" || i.name === ".svelte-kit") continue;
|
|
128
|
+
oe(r, n);
|
|
129
|
+
} else i.name.endsWith(".svelte") && n.push(r);
|
|
49
130
|
}
|
|
50
|
-
return [...i];
|
|
51
131
|
}
|
|
52
|
-
function
|
|
132
|
+
function se(e) {
|
|
133
|
+
let t = [];
|
|
134
|
+
if (!e.includes(".svelte")) return t;
|
|
135
|
+
for (let { code: n, result: r } of ee(e)) {
|
|
136
|
+
let { module: e } = r;
|
|
137
|
+
for (let { moduleRequest: n, entries: r } of e.staticImports) (r.length === 0 || r.some((e) => !e.isType)) && t.push(n.value);
|
|
138
|
+
for (let { entries: n } of e.staticExports) for (let { moduleRequest: e, isType: r } of n) e && !r && t.push(e.value);
|
|
139
|
+
for (let { moduleRequest: r } of e.dynamicImports) {
|
|
140
|
+
let e = ce(n.slice(r.start, r.end));
|
|
141
|
+
e !== void 0 && t.push(e);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return t.filter((e) => e.endsWith(".svelte"));
|
|
145
|
+
}
|
|
146
|
+
function ce(e) {
|
|
147
|
+
let t = e[0];
|
|
148
|
+
if (t !== "\"" && t !== "'" && t !== "`") return;
|
|
149
|
+
let n = e.slice(1, -1);
|
|
150
|
+
return e.length >= 2 && e.endsWith(t) && !n.includes(t) && !n.includes("\\") && !(t === "`" && n.includes("${")) ? n : void 0;
|
|
151
|
+
}
|
|
152
|
+
function le(e, n, i) {
|
|
53
153
|
if (e.startsWith("$lib/") || e.startsWith("#lib/")) {
|
|
54
154
|
let n = t.join(i, "src", "lib", e.slice(5));
|
|
55
155
|
return r.existsSync(n) ? n : null;
|
|
@@ -60,98 +160,96 @@ function te(e, n, i) {
|
|
|
60
160
|
}
|
|
61
161
|
return null;
|
|
62
162
|
}
|
|
63
|
-
function ne(e) {
|
|
64
|
-
return t.basename(e, ".svelte");
|
|
65
|
-
}
|
|
66
163
|
//#endregion
|
|
67
164
|
//#region src/analyzers/project.ts
|
|
68
|
-
var
|
|
69
|
-
function
|
|
165
|
+
var ue = 5e3, y;
|
|
166
|
+
function b(e) {
|
|
70
167
|
let t = Date.now();
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
168
|
+
return (y?.root !== e || t - y.at >= ue) && (y = {
|
|
169
|
+
root: e,
|
|
170
|
+
at: t,
|
|
171
|
+
info: pe(e)
|
|
172
|
+
}), y.info;
|
|
74
173
|
}
|
|
75
|
-
function
|
|
174
|
+
function x(e) {
|
|
76
175
|
return typeof e == "string" && e !== "" ? e : void 0;
|
|
77
176
|
}
|
|
78
|
-
function
|
|
177
|
+
function S(e) {
|
|
79
178
|
return typeof e == "object" && !!e && !Array.isArray(e);
|
|
80
179
|
}
|
|
81
|
-
function
|
|
180
|
+
function de(e) {
|
|
82
181
|
let t = {};
|
|
83
|
-
if (!
|
|
182
|
+
if (!S(e)) return t;
|
|
84
183
|
for (let [n, r] of Object.entries(e)) typeof r == "string" && (t[n] = r);
|
|
85
184
|
return t;
|
|
86
185
|
}
|
|
87
|
-
function
|
|
186
|
+
function fe(e) {
|
|
88
187
|
let t = {};
|
|
89
188
|
try {
|
|
90
189
|
t = JSON.parse(r.readFileSync(e, "utf-8"));
|
|
91
190
|
} catch {}
|
|
92
|
-
let n =
|
|
191
|
+
let n = S(t) ? t : {};
|
|
93
192
|
return {
|
|
94
|
-
name:
|
|
95
|
-
version:
|
|
96
|
-
dependencies:
|
|
97
|
-
devDependencies:
|
|
193
|
+
name: x(n.name),
|
|
194
|
+
version: x(n.version),
|
|
195
|
+
dependencies: de(n.dependencies),
|
|
196
|
+
devDependencies: de(n.devDependencies)
|
|
98
197
|
};
|
|
99
198
|
}
|
|
100
|
-
function
|
|
101
|
-
let n =
|
|
199
|
+
function pe(e) {
|
|
200
|
+
let n = fe(t.join(e, "package.json")), r = n.dependencies, i = n.devDependencies, a = (t) => me(e, t) ?? x(r[t]) ?? x(i[t]) ?? "unknown";
|
|
102
201
|
return {
|
|
103
202
|
name: n.name ?? t.basename(e),
|
|
104
203
|
version: n.version ?? "0.0.0",
|
|
105
|
-
svelteVersion:
|
|
106
|
-
sveltekitVersion:
|
|
107
|
-
viteVersion:
|
|
204
|
+
svelteVersion: a("svelte"),
|
|
205
|
+
sveltekitVersion: a("@sveltejs/kit"),
|
|
206
|
+
viteVersion: a("vite"),
|
|
108
207
|
dependencies: r,
|
|
109
208
|
devDependencies: i,
|
|
110
|
-
routesDir:
|
|
111
|
-
staticDir:
|
|
209
|
+
routesDir: he(e, "src/routes", "src/pages"),
|
|
210
|
+
staticDir: he(e, "static", "public")
|
|
112
211
|
};
|
|
113
212
|
}
|
|
114
|
-
function
|
|
213
|
+
function me(e, n) {
|
|
115
214
|
try {
|
|
116
|
-
let i = t.join(e, "node_modules", n, "package.json");
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
} catch {}
|
|
215
|
+
let i = JSON.parse(r.readFileSync(t.join(e, "node_modules", n, "package.json"), "utf-8"));
|
|
216
|
+
return S(i) ? x(i.version) : void 0;
|
|
217
|
+
} catch {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
122
220
|
}
|
|
123
|
-
function
|
|
124
|
-
let
|
|
125
|
-
|
|
126
|
-
return t.join(e, "src", "routes");
|
|
221
|
+
function he(e, ...n) {
|
|
222
|
+
let i = n.map((n) => t.join(e, n));
|
|
223
|
+
return i.find((e) => r.existsSync(e)) ?? i[0];
|
|
127
224
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
225
|
+
var ge = "0123456789abcdefABCDEF", _e = `${ge}ghijklmnopqrstuvwxyzGHIJKLMNOPQRSTUVWXYZ_`;
|
|
226
|
+
function C(e, t) {
|
|
227
|
+
if (e === "") return !1;
|
|
228
|
+
for (let n of e) if (!t.includes(n)) return !1;
|
|
229
|
+
return !0;
|
|
132
230
|
}
|
|
133
231
|
//#endregion
|
|
134
232
|
//#region src/analyzers/routes.ts
|
|
135
|
-
function
|
|
233
|
+
function ve(e) {
|
|
136
234
|
if (!r.existsSync(e)) return [];
|
|
137
235
|
let t = [];
|
|
138
|
-
return
|
|
236
|
+
return ye(e, e, t), t.toSorted((e, t) => e.path.localeCompare(t.path) || e.id.localeCompare(t.id));
|
|
139
237
|
}
|
|
140
|
-
function
|
|
238
|
+
function ye(e, n, i) {
|
|
141
239
|
let a = r.readdirSync(e, { withFileTypes: !0 }), o = [];
|
|
142
240
|
for (let r of a) {
|
|
143
241
|
if (r.isDirectory()) {
|
|
144
|
-
|
|
242
|
+
ye(t.join(e, r.name), n, i);
|
|
145
243
|
continue;
|
|
146
244
|
}
|
|
147
|
-
let a =
|
|
245
|
+
let a = be(r.name);
|
|
148
246
|
a && o.push({
|
|
149
247
|
type: a,
|
|
150
248
|
path: t.join(e, r.name)
|
|
151
249
|
});
|
|
152
250
|
}
|
|
153
251
|
if (o.length > 0) {
|
|
154
|
-
let r = t.relative(n, e).split(t.sep).join("/"), { routePath: a, params: s } =
|
|
252
|
+
let r = t.relative(n, e).split(t.sep).join("/"), { routePath: a, params: s } = xe(r);
|
|
155
253
|
i.push({
|
|
156
254
|
id: r || "/",
|
|
157
255
|
path: a,
|
|
@@ -169,98 +267,157 @@ function fe(e, n, i) {
|
|
|
169
267
|
});
|
|
170
268
|
}
|
|
171
269
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
function
|
|
270
|
+
function be(e) {
|
|
271
|
+
let t = e.lastIndexOf("."), n = e.slice(t + 1);
|
|
272
|
+
if (!e.startsWith("+") || n !== "svelte" && n !== "js" && n !== "ts") return null;
|
|
273
|
+
let r = e.slice(1, t), i = r.endsWith(".server");
|
|
274
|
+
i && (r = r.slice(0, -7));
|
|
275
|
+
let a = r.indexOf("@"), o = a !== -1, s = o ? r.slice(0, a) : r;
|
|
276
|
+
return n === "svelte" ? i ? null : s === "page" ? "page" : s === "layout" ? "layout" : s === "error" && !o ? "error" : null : o ? null : s === "server" ? i ? null : "endpoint" : s === "page" ? i ? "page-load-server" : "page-load" : s === "layout" ? i ? "layout-load-server" : "layout-load" : null;
|
|
277
|
+
}
|
|
278
|
+
function xe(e) {
|
|
181
279
|
let t = [], n = [];
|
|
182
|
-
for (let r of e.split("/"))
|
|
280
|
+
for (let r of e.split("/")) {
|
|
281
|
+
let e = r.length > 2 && r.startsWith("(") && r.endsWith(")");
|
|
282
|
+
r && !e && n.push(Se(r, t));
|
|
283
|
+
}
|
|
183
284
|
return {
|
|
184
285
|
routePath: "/" + n.join("/"),
|
|
185
286
|
params: t
|
|
186
287
|
};
|
|
187
288
|
}
|
|
188
|
-
function
|
|
289
|
+
function Se(e, t) {
|
|
189
290
|
let n = "", r = 0;
|
|
190
|
-
for (;
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
let i = e.startsWith("[[", r), a = e.indexOf(i ? "]]" : "]", r);
|
|
196
|
-
if (a === -1) {
|
|
197
|
-
n += e.slice(r);
|
|
291
|
+
for (let i = e.indexOf("["); i !== -1; i = e.indexOf("[", r)) {
|
|
292
|
+
n += e.slice(r, i);
|
|
293
|
+
let a = e.startsWith("[[", i), o = e.indexOf(a ? "]]" : "]", i);
|
|
294
|
+
if (o === -1) {
|
|
295
|
+
r = i;
|
|
198
296
|
break;
|
|
199
297
|
}
|
|
200
|
-
let
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
r
|
|
211
|
-
}
|
|
212
|
-
|
|
298
|
+
let s = e.slice(i + (a ? 2 : 1), o);
|
|
299
|
+
r = o + (a ? 2 : 1), n += (a ? null : we(s)) ?? Ce(s, a, t) ?? e.slice(i, r);
|
|
300
|
+
}
|
|
301
|
+
return n + e.slice(r);
|
|
302
|
+
}
|
|
303
|
+
function Ce(e, t, n) {
|
|
304
|
+
let r = e.startsWith("..."), [i = "", a, o] = e.slice(r ? 3 : 0).split("=");
|
|
305
|
+
return !C(i, _e) || a !== void 0 && !C(a, _e) || o !== void 0 ? null : (n.push(a === void 0 ? {
|
|
306
|
+
name: i,
|
|
307
|
+
optional: t,
|
|
308
|
+
rest: r
|
|
309
|
+
} : {
|
|
310
|
+
name: i,
|
|
311
|
+
optional: t,
|
|
312
|
+
rest: r,
|
|
313
|
+
matcher: a
|
|
314
|
+
}), r ? `*${i}` : `:${i}${t ? "?" : ""}`);
|
|
213
315
|
}
|
|
214
|
-
function
|
|
215
|
-
let t =
|
|
216
|
-
if (t
|
|
217
|
-
let
|
|
218
|
-
if (!n) return null;
|
|
219
|
-
let r = Number.parseInt(n[1], 16);
|
|
316
|
+
function we(e) {
|
|
317
|
+
let t = e.slice(0, 2).toLowerCase(), n = e.slice(2);
|
|
318
|
+
if (!(t === "x+" ? n.length === 2 : t === "u+" && n.length >= 4 && n.length <= 6) || !C(n, ge)) return null;
|
|
319
|
+
let r = Number.parseInt(n, 16);
|
|
220
320
|
return r <= 1114111 ? String.fromCodePoint(r) : null;
|
|
221
321
|
}
|
|
222
322
|
//#endregion
|
|
323
|
+
//#region src/mcp/http.ts
|
|
324
|
+
var Te = "/__svelte-devtools/mcp";
|
|
325
|
+
function Ee(t, n) {
|
|
326
|
+
if (typeof t != "string") return !1;
|
|
327
|
+
let r = Buffer.from(t), i = Buffer.from(n);
|
|
328
|
+
return r.length === i.length && e.timingSafeEqual(r, i);
|
|
329
|
+
}
|
|
330
|
+
var De = (e) => e instanceof Error ? e.stack ?? e.message : String(e);
|
|
331
|
+
function Oe(e) {
|
|
332
|
+
let { token: t, collector: n, logger: r } = e, i = (e, t) => {
|
|
333
|
+
r.error(`[svelte-devtools] MCP handler error: ${De(t)}`), !e.headersSent && (e.statusCode = 500, e.setHeader("Content-Type", "application/json"), e.end(JSON.stringify({ error: String(t) })));
|
|
334
|
+
}, a = async (a, s) => {
|
|
335
|
+
if (!Ee(a.headers["x-svelte-devtools-token"], t)) {
|
|
336
|
+
s.statusCode = 403, s.end("Forbidden");
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
n.lease("mcp", 6e4) && await n.waitForSnapshot(1e3);
|
|
340
|
+
let c = e.createServer(), l = new o({
|
|
341
|
+
sessionIdGenerator: void 0,
|
|
342
|
+
enableJsonResponse: !0
|
|
343
|
+
});
|
|
344
|
+
l.onerror = (e) => {
|
|
345
|
+
r.error(`[svelte-devtools] MCP transport error: ${De(e)}`);
|
|
346
|
+
};
|
|
347
|
+
try {
|
|
348
|
+
await c.connect(l), await l.handleRequest(a, s);
|
|
349
|
+
} catch (e) {
|
|
350
|
+
i(s, e);
|
|
351
|
+
} finally {
|
|
352
|
+
await l.close().catch(() => {}), await c.close().catch(() => {});
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
return (e, t) => {
|
|
356
|
+
a(e, t).catch((e) => i(t, e));
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
//#endregion
|
|
360
|
+
//#region src/mcp/stats.ts
|
|
361
|
+
function w(e) {
|
|
362
|
+
return e.length === 0 ? 0 : e.reduce((e, t) => e + t, 0) / e.length;
|
|
363
|
+
}
|
|
364
|
+
function T(e, t) {
|
|
365
|
+
return e.length === 0 ? t : e.reduce((e, t) => Math.min(e, t), Infinity);
|
|
366
|
+
}
|
|
367
|
+
function ke(e, t) {
|
|
368
|
+
return e.length === 0 ? t : e.reduce((e, t) => Math.max(e, t), -Infinity);
|
|
369
|
+
}
|
|
370
|
+
function E(e) {
|
|
371
|
+
return Math.round(e * 100) / 100;
|
|
372
|
+
}
|
|
373
|
+
function D(e) {
|
|
374
|
+
return e.renderCount > 0 ? e.totalRenderTime / e.renderCount : 0;
|
|
375
|
+
}
|
|
376
|
+
//#endregion
|
|
223
377
|
//#region src/mcp/issues.ts
|
|
224
|
-
var
|
|
378
|
+
var Ae = {
|
|
225
379
|
avgRenderTimeMs: 4,
|
|
226
380
|
renderCount: 30,
|
|
227
381
|
loadDurationMs: 200,
|
|
228
382
|
fpsDropThreshold: 40,
|
|
229
383
|
effectMaxDeps: 8
|
|
230
384
|
};
|
|
231
|
-
function
|
|
232
|
-
let t = { ...
|
|
233
|
-
for (let n of Object.keys(
|
|
385
|
+
function je(e) {
|
|
386
|
+
let t = { ...Ae };
|
|
387
|
+
for (let n of Object.keys(Ae)) {
|
|
234
388
|
let r = e[n];
|
|
235
389
|
r !== void 0 && (t[n] = r);
|
|
236
390
|
}
|
|
237
391
|
return t;
|
|
238
392
|
}
|
|
239
|
-
function
|
|
240
|
-
|
|
393
|
+
function O(e, t, n, r) {
|
|
394
|
+
return e >= t * r ? "high" : e >= t * n ? "medium" : "low";
|
|
395
|
+
}
|
|
396
|
+
function Me(e, t = {}) {
|
|
397
|
+
let n = je(t), r = [];
|
|
241
398
|
for (let t of e.renderProfiles) {
|
|
242
|
-
let e = t
|
|
399
|
+
let e = D(t);
|
|
243
400
|
e >= n.avgRenderTimeMs && r.push({
|
|
244
401
|
id: `slow-render:${t.file}:${t.componentId}`,
|
|
245
402
|
kind: "slow-component-render",
|
|
246
|
-
severity: e
|
|
403
|
+
severity: O(e, n.avgRenderTimeMs, 2, 4),
|
|
247
404
|
summary: `${t.name} averages ${e.toFixed(2)}ms per render (${t.renderCount} renders)`,
|
|
248
405
|
file: t.file,
|
|
249
406
|
metric: {
|
|
250
|
-
avgRenderTimeMs:
|
|
407
|
+
avgRenderTimeMs: E(e),
|
|
251
408
|
renderCount: t.renderCount,
|
|
252
|
-
totalRenderTimeMs:
|
|
409
|
+
totalRenderTimeMs: E(t.totalRenderTime)
|
|
253
410
|
},
|
|
254
411
|
suggestedTool: "get_render_profile"
|
|
255
412
|
}), t.renderCount >= n.renderCount && r.push({
|
|
256
413
|
id: `over-render:${t.file}:${t.componentId}`,
|
|
257
414
|
kind: "over-rendered-component",
|
|
258
|
-
severity: t.renderCount
|
|
415
|
+
severity: O(t.renderCount, n.renderCount, 3, 8),
|
|
259
416
|
summary: `${t.name} rendered ${t.renderCount} times`,
|
|
260
417
|
file: t.file,
|
|
261
418
|
metric: {
|
|
262
419
|
renderCount: t.renderCount,
|
|
263
|
-
avgRenderTimeMs:
|
|
420
|
+
avgRenderTimeMs: E(e)
|
|
264
421
|
},
|
|
265
422
|
suggestedTool: "get_component_hotspots"
|
|
266
423
|
});
|
|
@@ -268,18 +425,18 @@ function xe(e, t = {}) {
|
|
|
268
425
|
for (let t of e.loadProfiles) t.duration >= n.loadDurationMs && r.push({
|
|
269
426
|
id: `slow-load:${t.route}:${t.timestamp}`,
|
|
270
427
|
kind: "slow-load",
|
|
271
|
-
severity: t.duration
|
|
428
|
+
severity: O(t.duration, n.loadDurationMs, 2, 5),
|
|
272
429
|
summary: `${t.type} load for ${t.route} took ${t.duration.toFixed(0)}ms`,
|
|
273
430
|
file: t.file,
|
|
274
431
|
metric: {
|
|
275
|
-
durationMs:
|
|
432
|
+
durationMs: E(t.duration),
|
|
276
433
|
dataSizeBytes: t.dataSize
|
|
277
434
|
},
|
|
278
435
|
suggestedTool: "get_load_waterfall"
|
|
279
436
|
});
|
|
280
437
|
let i = e.fpsSamples.filter((e) => e.fps < n.fpsDropThreshold);
|
|
281
438
|
if (i.length > 0) {
|
|
282
|
-
let t = i.
|
|
439
|
+
let t = T(i.map((e) => e.fps), 0);
|
|
283
440
|
r.push({
|
|
284
441
|
id: `fps-drops:${e.fpsSamples[0]?.timestamp ?? 0}`,
|
|
285
442
|
kind: "fps-drop",
|
|
@@ -293,30 +450,26 @@ function xe(e, t = {}) {
|
|
|
293
450
|
suggestedTool: "get_fps_drops"
|
|
294
451
|
});
|
|
295
452
|
}
|
|
296
|
-
let
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
suggestedTool: "get_reactive_graph_problems"
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
return r.toSorted(Ce);
|
|
453
|
+
for (let t of Ie(e.reactiveGraph, n.effectMaxDeps)) r.push({
|
|
454
|
+
id: `effect-deps:${t.id}`,
|
|
455
|
+
kind: "effect-overconnected",
|
|
456
|
+
severity: O(t.depCount, n.effectMaxDeps, 2, 3),
|
|
457
|
+
summary: `effect "${t.name}" depends on ${t.depCount} reactive values`,
|
|
458
|
+
file: t.file,
|
|
459
|
+
metric: { depCount: t.depCount },
|
|
460
|
+
suggestedTool: "get_reactive_graph_problems"
|
|
461
|
+
});
|
|
462
|
+
return r.toSorted(Pe);
|
|
310
463
|
}
|
|
311
|
-
var
|
|
464
|
+
var Ne = {
|
|
312
465
|
high: 0,
|
|
313
466
|
medium: 1,
|
|
314
467
|
low: 2
|
|
315
468
|
};
|
|
316
|
-
function
|
|
317
|
-
return
|
|
469
|
+
function Pe(e, t) {
|
|
470
|
+
return Ne[e.severity] - Ne[t.severity];
|
|
318
471
|
}
|
|
319
|
-
function
|
|
472
|
+
function Fe(e) {
|
|
320
473
|
let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Set();
|
|
321
474
|
for (let i of e.edges) {
|
|
322
475
|
let e = JSON.stringify([i.from, i.to]);
|
|
@@ -327,39 +480,41 @@ function we(e) {
|
|
|
327
480
|
outDegree: n
|
|
328
481
|
};
|
|
329
482
|
}
|
|
330
|
-
function
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
id: t.id,
|
|
339
|
-
name: t.name,
|
|
340
|
-
file: t.componentFile,
|
|
483
|
+
function Ie(e, t) {
|
|
484
|
+
let { inDegree: n } = Fe(e), r = [];
|
|
485
|
+
for (let i of e.nodes) {
|
|
486
|
+
let e = n.get(i.id) ?? 0;
|
|
487
|
+
i.type === "effect" && e >= t && r.push({
|
|
488
|
+
id: i.id,
|
|
489
|
+
name: i.name,
|
|
490
|
+
file: i.componentFile,
|
|
341
491
|
depCount: e
|
|
342
|
-
})
|
|
343
|
-
id: t.id,
|
|
344
|
-
name: t.name,
|
|
345
|
-
file: t.componentFile
|
|
346
|
-
}) : e === 0 && c === 0 && !t.untrackedDeps && s.push({
|
|
347
|
-
id: t.id,
|
|
348
|
-
name: t.name,
|
|
349
|
-
type: t.type,
|
|
350
|
-
file: t.componentFile
|
|
351
|
-
}));
|
|
492
|
+
});
|
|
352
493
|
}
|
|
494
|
+
return r;
|
|
495
|
+
}
|
|
496
|
+
function Le(e, t = {}) {
|
|
497
|
+
let { inDegree: n, outDegree: r } = Fe(e), i = [], a = [];
|
|
498
|
+
for (let t of e.nodes) t.type !== "template" && (t.type === "derived" && t.unevaluated ? i.push({
|
|
499
|
+
id: t.id,
|
|
500
|
+
name: t.name,
|
|
501
|
+
file: t.componentFile
|
|
502
|
+
}) : !n.has(t.id) && !r.has(t.id) && !t.untrackedDeps && a.push({
|
|
503
|
+
id: t.id,
|
|
504
|
+
name: t.name,
|
|
505
|
+
type: t.type,
|
|
506
|
+
file: t.componentFile
|
|
507
|
+
}));
|
|
353
508
|
return {
|
|
354
|
-
effects:
|
|
355
|
-
orphanDeriveds:
|
|
356
|
-
isolatedNodes:
|
|
509
|
+
effects: Ie(e, je(t).effectMaxDeps),
|
|
510
|
+
orphanDeriveds: i,
|
|
511
|
+
isolatedNodes: a
|
|
357
512
|
};
|
|
358
513
|
}
|
|
359
514
|
//#endregion
|
|
360
515
|
//#region src/mcp/sessions.ts
|
|
361
|
-
var
|
|
362
|
-
function
|
|
516
|
+
var Re = 1, ze = 5, Be = 1, Ve = 30;
|
|
517
|
+
function He(e) {
|
|
363
518
|
return {
|
|
364
519
|
renderProfiles: e.getRenderProfiles().map((e) => ({
|
|
365
520
|
componentId: e.componentId,
|
|
@@ -373,14 +528,22 @@ function w(e) {
|
|
|
373
528
|
takenAt: Date.now()
|
|
374
529
|
};
|
|
375
530
|
}
|
|
376
|
-
function
|
|
377
|
-
return Math.abs(e) < t ? "unchanged" :
|
|
531
|
+
function Ue(e, t, n) {
|
|
532
|
+
return Math.abs(e) < t ? "unchanged" : e < 0 === n ? "improved" : "regressed";
|
|
378
533
|
}
|
|
379
|
-
var
|
|
380
|
-
function
|
|
381
|
-
|
|
534
|
+
var We = "0123456789abcdefghijklmnopqrstuvwxyz", Ge = "0123456789abcdef";
|
|
535
|
+
function Ke(e, t) {
|
|
536
|
+
for (let n of e) if (!t.includes(n)) return !1;
|
|
537
|
+
return !0;
|
|
538
|
+
}
|
|
539
|
+
function k(e) {
|
|
540
|
+
if (typeof e != "string") return !1;
|
|
541
|
+
let t = e.split("_");
|
|
542
|
+
if (t.length !== 3 || t[0] !== "s") return !1;
|
|
543
|
+
let [, n = "", r = ""] = t;
|
|
544
|
+
return n.length > 0 && n.length <= 16 && Ke(n, We) && r.length === 6 && Ke(r, Ge);
|
|
382
545
|
}
|
|
383
|
-
var
|
|
546
|
+
var qe = class {
|
|
384
547
|
sessions = /* @__PURE__ */ new Map();
|
|
385
548
|
active = null;
|
|
386
549
|
persistDir;
|
|
@@ -395,135 +558,128 @@ var je = class {
|
|
|
395
558
|
label: t,
|
|
396
559
|
startedAt: Date.now(),
|
|
397
560
|
persist: n,
|
|
398
|
-
startSnapshot:
|
|
561
|
+
startSnapshot: He(this.getters),
|
|
399
562
|
loadProfiles: [],
|
|
400
563
|
fpsSamples: []
|
|
401
564
|
};
|
|
402
565
|
return this.sessions.set(r, i), this.active = r, i;
|
|
403
566
|
}
|
|
567
|
+
get activeRecord() {
|
|
568
|
+
return this.active === null ? void 0 : this.sessions.get(this.active);
|
|
569
|
+
}
|
|
404
570
|
recordLoadProfile(e) {
|
|
405
|
-
|
|
406
|
-
let t = this.sessions.get(this.active);
|
|
407
|
-
t && t.loadProfiles.push(e);
|
|
571
|
+
this.activeRecord?.loadProfiles.push(e);
|
|
408
572
|
}
|
|
409
573
|
recordFpsSample(e) {
|
|
410
|
-
|
|
411
|
-
let t = this.sessions.get(this.active);
|
|
412
|
-
t && t.fpsSamples.push(e);
|
|
574
|
+
this.activeRecord?.fpsSamples.push(e);
|
|
413
575
|
}
|
|
414
576
|
end(e) {
|
|
415
577
|
if (!this.active) throw Error("No active session");
|
|
416
|
-
let t = this.
|
|
578
|
+
let t = this.activeRecord;
|
|
417
579
|
if (!t) throw Error("Active session missing from store");
|
|
418
|
-
return t.endedAt = Date.now(), t.endSnapshot =
|
|
580
|
+
return t.endedAt = Date.now(), t.endSnapshot = He(this.getters), this.active = null, e === "discard" ? this.sessions.delete(t.id) : (e === "disk" || t.persist) && this.persistToDisk(t), t;
|
|
419
581
|
}
|
|
420
582
|
get(e) {
|
|
421
|
-
|
|
583
|
+
if (k(e)) return this.sessions.get(e) ?? this.loadFromDisk(e);
|
|
422
584
|
}
|
|
423
585
|
list() {
|
|
424
|
-
let e =
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
});
|
|
586
|
+
let e = (e, t) => ({
|
|
587
|
+
id: e.id,
|
|
588
|
+
label: e.label,
|
|
589
|
+
startedAt: e.startedAt,
|
|
590
|
+
endedAt: e.endedAt,
|
|
591
|
+
persisted: t,
|
|
592
|
+
active: this.active === e.id
|
|
593
|
+
}), t = [...this.sessions.values()].map((t) => e(t, r.existsSync(this.pathFor(t.id))));
|
|
433
594
|
try {
|
|
434
|
-
|
|
595
|
+
for (let n of r.readdirSync(this.persistDir)) {
|
|
435
596
|
if (!n.endsWith(".json")) continue;
|
|
436
597
|
let r = n.slice(0, -5);
|
|
437
|
-
if (!
|
|
598
|
+
if (!k(r) || this.sessions.has(r)) continue;
|
|
438
599
|
let i = this.loadFromDisk(r);
|
|
439
|
-
i && t.push(
|
|
440
|
-
id: i.id,
|
|
441
|
-
label: i.label,
|
|
442
|
-
startedAt: i.startedAt,
|
|
443
|
-
endedAt: i.endedAt,
|
|
444
|
-
persisted: !0,
|
|
445
|
-
active: !1
|
|
446
|
-
});
|
|
600
|
+
i && t.push(e(i, !0));
|
|
447
601
|
}
|
|
448
602
|
} catch {}
|
|
449
603
|
return t.toSorted((e, t) => t.startedAt - e.startedAt);
|
|
450
604
|
}
|
|
451
605
|
delete(e) {
|
|
452
|
-
if (!
|
|
606
|
+
if (!k(e)) return !1;
|
|
453
607
|
let t = this.sessions.delete(e), n = !1;
|
|
454
608
|
try {
|
|
455
|
-
|
|
456
|
-
r.existsSync(t) && (r.unlinkSync(t), n = !0);
|
|
609
|
+
r.unlinkSync(this.pathFor(e)), n = !0;
|
|
457
610
|
} catch {}
|
|
458
611
|
return this.active === e && (this.active = null), t || n;
|
|
459
612
|
}
|
|
460
|
-
delta(e) {
|
|
461
|
-
let t = this.get(e);
|
|
462
|
-
if (!t) throw Error(`Session not found: ${e}`);
|
|
463
|
-
return this.deltaOf(t);
|
|
464
|
-
}
|
|
465
613
|
deltaOf(e) {
|
|
466
614
|
if (!e.endSnapshot || e.endedAt === void 0) throw Error(`Session ${e.id} has not been ended yet`);
|
|
467
615
|
let t = new Map(e.startSnapshot.renderProfiles.map((e) => [e.componentId, e])), n = e.endSnapshot.renderProfiles.map((e) => {
|
|
468
|
-
let n = t.get(e.componentId), r =
|
|
616
|
+
let n = t.get(e.componentId), r = e.renderCount - (n?.renderCount ?? 0), i = e.totalRenderTime - (n?.totalRenderTime ?? 0);
|
|
469
617
|
return {
|
|
470
618
|
componentId: e.componentId,
|
|
471
619
|
file: e.file,
|
|
472
620
|
name: e.name,
|
|
473
|
-
renderCountDelta:
|
|
474
|
-
totalRenderTimeDelta:
|
|
475
|
-
avgRenderTimeDelta:
|
|
621
|
+
renderCountDelta: r,
|
|
622
|
+
totalRenderTimeDelta: i,
|
|
623
|
+
avgRenderTimeDelta: r > 0 ? i / r : 0
|
|
476
624
|
};
|
|
477
|
-
}).filter((e) => e.renderCountDelta > 0).toSorted((e, t) => t.totalRenderTimeDelta - e.totalRenderTimeDelta), r = e.loadProfiles.map((e) => e.duration), i =
|
|
625
|
+
}).filter((e) => e.renderCountDelta > 0).toSorted((e, t) => t.totalRenderTimeDelta - e.totalRenderTimeDelta), r = e.loadProfiles.map((e) => e.duration), i = e.fpsSamples.map((e) => e.fps);
|
|
478
626
|
return {
|
|
479
627
|
durationMs: e.endedAt - e.startedAt,
|
|
480
628
|
components: n,
|
|
481
629
|
loadProfiles: {
|
|
482
630
|
count: e.loadProfiles.length,
|
|
483
|
-
avgDuration:
|
|
484
|
-
p95Duration:
|
|
631
|
+
avgDuration: w(r),
|
|
632
|
+
p95Duration: Je(r, 95)
|
|
485
633
|
},
|
|
486
634
|
fps: {
|
|
487
|
-
samples:
|
|
488
|
-
avg:
|
|
489
|
-
min:
|
|
490
|
-
drops:
|
|
635
|
+
samples: i.length,
|
|
636
|
+
avg: w(i),
|
|
637
|
+
min: T(i, 0),
|
|
638
|
+
drops: i.filter((e) => e < Ve).length
|
|
491
639
|
}
|
|
492
640
|
};
|
|
493
641
|
}
|
|
642
|
+
delta(e) {
|
|
643
|
+
return this.deltaOf(this.found(e));
|
|
644
|
+
}
|
|
645
|
+
found(e) {
|
|
646
|
+
let t = this.get(e);
|
|
647
|
+
if (!t) throw Error(`Session not found: ${e}`);
|
|
648
|
+
return t;
|
|
649
|
+
}
|
|
494
650
|
compare(e, t) {
|
|
495
|
-
let n = this.
|
|
651
|
+
let n = this.found(e), r = this.found(t), i = this.deltaOf(n), a = this.deltaOf(r), o = i.components.reduce((e, t) => e + t.totalRenderTimeDelta, 0), s = a.components.reduce((e, t) => e + t.totalRenderTimeDelta, 0), c = s - o, l = a.loadProfiles.avgDuration - i.loadProfiles.avgDuration, u = a.fps.avg - i.fps.avg;
|
|
496
652
|
return {
|
|
497
653
|
a: {
|
|
498
|
-
id:
|
|
499
|
-
label:
|
|
654
|
+
id: n.id,
|
|
655
|
+
label: n.label
|
|
500
656
|
},
|
|
501
657
|
b: {
|
|
502
|
-
id:
|
|
503
|
-
label:
|
|
658
|
+
id: r.id,
|
|
659
|
+
label: r.label
|
|
504
660
|
},
|
|
505
661
|
render: {
|
|
506
662
|
totalRenderTimeDeltaA: o,
|
|
507
663
|
totalRenderTimeDeltaB: s,
|
|
508
664
|
diff: c,
|
|
509
|
-
verdict:
|
|
665
|
+
verdict: Ue(c, Re, !0)
|
|
510
666
|
},
|
|
511
667
|
load: {
|
|
512
|
-
avgA:
|
|
513
|
-
avgB:
|
|
668
|
+
avgA: i.loadProfiles.avgDuration,
|
|
669
|
+
avgB: a.loadProfiles.avgDuration,
|
|
514
670
|
diff: l,
|
|
515
|
-
verdict:
|
|
671
|
+
verdict: Ue(l, ze, !0)
|
|
516
672
|
},
|
|
517
673
|
fps: {
|
|
518
|
-
avgA:
|
|
519
|
-
avgB:
|
|
674
|
+
avgA: i.fps.avg,
|
|
675
|
+
avgB: a.fps.avg,
|
|
520
676
|
diff: u,
|
|
521
|
-
verdict:
|
|
677
|
+
verdict: Ue(u, Be, !1)
|
|
522
678
|
}
|
|
523
679
|
};
|
|
524
680
|
}
|
|
525
681
|
pathFor(e) {
|
|
526
|
-
if (!
|
|
682
|
+
if (!k(e)) throw Error("Invalid session id");
|
|
527
683
|
let n = t.resolve(this.persistDir, `${e}.json`);
|
|
528
684
|
if (t.dirname(n) !== this.persistDir) throw Error("Invalid session id");
|
|
529
685
|
return n;
|
|
@@ -536,32 +692,29 @@ var je = class {
|
|
|
536
692
|
loadFromDisk(e) {
|
|
537
693
|
try {
|
|
538
694
|
let t = r.readFileSync(this.pathFor(e), "utf-8"), n = JSON.parse(t);
|
|
539
|
-
return
|
|
695
|
+
return Xe(n) && n.id === e ? n : void 0;
|
|
540
696
|
} catch {
|
|
541
697
|
return;
|
|
542
698
|
}
|
|
543
699
|
}
|
|
544
700
|
};
|
|
545
|
-
function
|
|
546
|
-
return e.length === 0 ? 0 : e.reduce((e, t) => e + t, 0) / e.length;
|
|
547
|
-
}
|
|
548
|
-
function Ne(e, t) {
|
|
701
|
+
function Je(e, t) {
|
|
549
702
|
if (e.length === 0) return 0;
|
|
550
703
|
let n = e.toSorted((e, t) => e - t);
|
|
551
704
|
return n[Math.max(1, Math.ceil(t / 100 * n.length)) - 1];
|
|
552
705
|
}
|
|
553
|
-
var
|
|
554
|
-
function
|
|
555
|
-
return
|
|
706
|
+
var A = (e) => typeof e == "object" && !!e, j = (e) => typeof e == "number" && Number.isFinite(e);
|
|
707
|
+
function Ye(e) {
|
|
708
|
+
return A(e) && Array.isArray(e.renderProfiles) && e.renderProfiles.every((e) => A(e) && j(e.componentId) && typeof e.file == "string" && typeof e.name == "string" && j(e.renderCount) && j(e.totalRenderTime));
|
|
556
709
|
}
|
|
557
|
-
function
|
|
558
|
-
return
|
|
710
|
+
function Xe(e) {
|
|
711
|
+
return A(e) && typeof e.id == "string" && typeof e.label == "string" && j(e.startedAt) && (e.endedAt === void 0 || j(e.endedAt)) && Ye(e.startSnapshot) && (e.endSnapshot === void 0 || Ye(e.endSnapshot)) && Array.isArray(e.loadProfiles) && e.loadProfiles.every((e) => A(e) && j(e.duration)) && Array.isArray(e.fpsSamples) && e.fpsSamples.every((e) => A(e) && j(e.fps));
|
|
559
712
|
}
|
|
560
|
-
var
|
|
713
|
+
var Ze = {
|
|
561
714
|
default: 2048,
|
|
562
715
|
max: 32768
|
|
563
716
|
};
|
|
564
|
-
function
|
|
717
|
+
function Qe(e, t) {
|
|
565
718
|
let n;
|
|
566
719
|
try {
|
|
567
720
|
n = JSON.stringify(e);
|
|
@@ -574,73 +727,78 @@ function Le(e, t) {
|
|
|
574
727
|
preview: n.slice(0, Math.min(200, t))
|
|
575
728
|
};
|
|
576
729
|
}
|
|
577
|
-
var
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
730
|
+
var M = c.string().max(64).refine(k, "not a session id");
|
|
731
|
+
function N(e) {
|
|
732
|
+
return { content: [{
|
|
733
|
+
type: "text",
|
|
734
|
+
text: typeof e == "string" ? e : JSON.stringify(e, null, 2)
|
|
735
|
+
}] };
|
|
736
|
+
}
|
|
737
|
+
var $e = (e) => ({
|
|
738
|
+
...N(e),
|
|
739
|
+
isError: !0
|
|
740
|
+
});
|
|
741
|
+
function et(e) {
|
|
742
|
+
let t = new s({
|
|
583
743
|
name: "vite-devtools-svelte",
|
|
584
744
|
version: "0.1.0"
|
|
585
745
|
});
|
|
586
|
-
|
|
746
|
+
return t.registerTool("list_performance_issues", {
|
|
587
747
|
title: "List performance issues",
|
|
588
748
|
description: "Cross-cuts render/reactive/load/fps metrics and returns ranked issues. The entry point for AI-driven performance audits. Each issue carries `suggestedTool` naming the detail tool to call next.",
|
|
589
749
|
inputSchema: {
|
|
590
|
-
avgRenderTimeMs:
|
|
591
|
-
renderCount:
|
|
592
|
-
loadDurationMs:
|
|
593
|
-
fpsDropThreshold:
|
|
594
|
-
effectMaxDeps:
|
|
750
|
+
avgRenderTimeMs: c.number().positive().optional(),
|
|
751
|
+
renderCount: c.number().int().min(1).optional(),
|
|
752
|
+
loadDurationMs: c.number().positive().optional(),
|
|
753
|
+
fpsDropThreshold: c.number().min(1).max(120).optional(),
|
|
754
|
+
effectMaxDeps: c.number().int().min(1).optional()
|
|
595
755
|
}
|
|
596
756
|
}, async (t) => {
|
|
597
|
-
let n =
|
|
757
|
+
let n = Me({
|
|
598
758
|
renderProfiles: e.getRenderProfiles(),
|
|
599
|
-
reactiveGraph:
|
|
759
|
+
reactiveGraph: await e.getReactiveGraph(),
|
|
600
760
|
loadProfiles: e.getLoadProfiles(),
|
|
601
761
|
fpsSamples: e.getFpsSamples()
|
|
602
|
-
},
|
|
603
|
-
return
|
|
604
|
-
count:
|
|
605
|
-
issues:
|
|
762
|
+
}, t);
|
|
763
|
+
return N({
|
|
764
|
+
count: n.length,
|
|
765
|
+
issues: n
|
|
606
766
|
});
|
|
607
767
|
}), t.registerTool("get_component_hotspots", {
|
|
608
768
|
title: "Component render hotspots",
|
|
609
769
|
description: "Top components by total render time, with render count and per-render average.",
|
|
610
|
-
inputSchema: { topN:
|
|
611
|
-
}, ({ topN: t = 20 }) =>
|
|
770
|
+
inputSchema: { topN: c.number().int().min(1).max(200).optional() }
|
|
771
|
+
}, ({ topN: t = 20 }) => N(e.getRenderProfiles().map((e) => ({
|
|
612
772
|
file: e.file,
|
|
613
773
|
name: e.name,
|
|
614
774
|
componentId: e.componentId,
|
|
615
775
|
renderCount: e.renderCount,
|
|
616
|
-
totalRenderTimeMs:
|
|
617
|
-
avgRenderTimeMs:
|
|
618
|
-
lastRenderTimeMs:
|
|
776
|
+
totalRenderTimeMs: E(e.totalRenderTime),
|
|
777
|
+
avgRenderTimeMs: E(D(e)),
|
|
778
|
+
lastRenderTimeMs: E(e.lastRenderTime),
|
|
619
779
|
lastRenderAt: e.lastRenderAt
|
|
620
780
|
})).toSorted((e, t) => t.totalRenderTimeMs - e.totalRenderTimeMs).slice(0, t))), t.registerTool("get_reactive_graph_problems", {
|
|
621
781
|
title: "Reactive graph problems",
|
|
622
782
|
description: "Classified reactive graph issues: over-connected effects, orphan deriveds (declared but never evaluated so far — may still be read later, e.g. in a branch not shown yet), isolated nodes (no tracked dependency or reader; reads from the markup count as readers). Returns categories instead of the full graph.",
|
|
623
|
-
inputSchema: { effectMaxDeps:
|
|
624
|
-
}, async ({ effectMaxDeps: t }) =>
|
|
783
|
+
inputSchema: { effectMaxDeps: c.number().int().min(1).optional() }
|
|
784
|
+
}, async ({ effectMaxDeps: t }) => N(Le(await e.getReactiveGraph(), { effectMaxDeps: t }))), t.registerTool("get_load_waterfall", {
|
|
625
785
|
title: "SvelteKit load waterfall",
|
|
626
786
|
description: "Load profiles grouped by route, with timing and data size. Optionally filtered by route.",
|
|
627
|
-
inputSchema: { route:
|
|
787
|
+
inputSchema: { route: c.string().optional() }
|
|
628
788
|
}, ({ route: t }) => {
|
|
629
|
-
let n = e.getLoadProfiles();
|
|
630
|
-
t && (n = n.filter((e) => e.route === t));
|
|
631
|
-
let r = /* @__PURE__ */ new Map();
|
|
789
|
+
let n = e.getLoadProfiles().filter((e) => !t || e.route === t), r = /* @__PURE__ */ new Map();
|
|
632
790
|
for (let e of n) {
|
|
633
|
-
let t = r.get(e.route)
|
|
634
|
-
t.push(e)
|
|
791
|
+
let t = r.get(e.route);
|
|
792
|
+
t ? t.push(e) : r.set(e.route, [e]);
|
|
635
793
|
}
|
|
636
|
-
return
|
|
794
|
+
return N([...r].map(([e, t]) => {
|
|
637
795
|
let n = t.map((e) => e.duration);
|
|
638
796
|
return {
|
|
639
797
|
route: e,
|
|
640
798
|
file: t[0]?.file,
|
|
641
799
|
count: t.length,
|
|
642
|
-
avgDuration:
|
|
643
|
-
maxDuration:
|
|
800
|
+
avgDuration: E(w(n)),
|
|
801
|
+
maxDuration: E(ke(n, 0)),
|
|
644
802
|
totalDataBytes: t.reduce((e, t) => e + t.dataSize, 0),
|
|
645
803
|
samples: t
|
|
646
804
|
};
|
|
@@ -649,28 +807,23 @@ function Re(e) {
|
|
|
649
807
|
title: "FPS drops",
|
|
650
808
|
description: "Samples whose FPS fell below `threshold`. Returns timestamp + fps for each.",
|
|
651
809
|
inputSchema: {
|
|
652
|
-
threshold:
|
|
653
|
-
sinceMs:
|
|
810
|
+
threshold: c.number().min(1).max(120).optional(),
|
|
811
|
+
sinceMs: c.number().nonnegative().optional()
|
|
654
812
|
}
|
|
655
813
|
}, ({ threshold: t = 40, sinceMs: n }) => {
|
|
656
|
-
let r = e.getFpsSamples();
|
|
657
|
-
|
|
658
|
-
let e = Date.now() - n;
|
|
659
|
-
r = r.filter((t) => t.timestamp >= e);
|
|
660
|
-
}
|
|
661
|
-
let i = r.filter((e) => e.fps < t);
|
|
662
|
-
return A({
|
|
814
|
+
let r = n === void 0 ? -Infinity : Date.now() - n, i = e.getFpsSamples().filter((e) => e.timestamp >= r), a = i.filter((e) => e.fps < t);
|
|
815
|
+
return N({
|
|
663
816
|
threshold: t,
|
|
664
|
-
sampleCount:
|
|
665
|
-
dropCount:
|
|
666
|
-
minFps:
|
|
667
|
-
drops:
|
|
817
|
+
sampleCount: i.length,
|
|
818
|
+
dropCount: a.length,
|
|
819
|
+
minFps: T(a.map((e) => e.fps), null),
|
|
820
|
+
drops: a
|
|
668
821
|
});
|
|
669
822
|
}), t.registerTool("get_render_profile", {
|
|
670
823
|
title: "Render profile for a specific file",
|
|
671
824
|
description: "Returns render profile entries matching the given component file (substring match).",
|
|
672
|
-
inputSchema: { file:
|
|
673
|
-
}, ({ file: t }) =>
|
|
825
|
+
inputSchema: { file: c.string() }
|
|
826
|
+
}, ({ file: t }) => N(e.getRenderProfiles().filter((e) => e.file.includes(t)).map((e) => ({
|
|
674
827
|
componentId: e.componentId,
|
|
675
828
|
file: e.file,
|
|
676
829
|
name: e.name,
|
|
@@ -679,30 +832,28 @@ function Re(e) {
|
|
|
679
832
|
totalRenderTime: e.totalRenderTime,
|
|
680
833
|
lastRenderTime: e.lastRenderTime,
|
|
681
834
|
lastRenderAt: e.lastRenderAt,
|
|
682
|
-
totalRenderTimeMs:
|
|
683
|
-
avgRenderTimeMs:
|
|
835
|
+
totalRenderTimeMs: E(e.totalRenderTime),
|
|
836
|
+
avgRenderTimeMs: E(D(e))
|
|
684
837
|
})))), t.registerTool("get_project_info", {
|
|
685
838
|
title: "Project info",
|
|
686
839
|
description: "Package name/version, Svelte / SvelteKit / Vite versions, dependency lists.",
|
|
687
840
|
inputSchema: {}
|
|
688
|
-
}, () =>
|
|
841
|
+
}, () => N(e.getProject())), t.registerTool("get_routes", {
|
|
689
842
|
title: "SvelteKit routes",
|
|
690
843
|
description: "Static analysis of the SvelteKit routes tree.",
|
|
691
844
|
inputSchema: {}
|
|
692
|
-
}, () =>
|
|
845
|
+
}, () => N(e.getRoutes())), t.registerTool("get_live_components", {
|
|
693
846
|
title: "Currently mounted components",
|
|
694
847
|
description: "Component instances with file, parent, mounted status as currently mounted in the browser (an array, parents first). With `includeMeta: true` the answer is `{ epoch, total, captured, truncated, components }` instead, limited to `limit` (default 1000): component ids are only valid within that `epoch` (one page load), so pass both to get_reactive_scope.",
|
|
695
848
|
inputSchema: {
|
|
696
|
-
includeMeta:
|
|
697
|
-
limit:
|
|
849
|
+
includeMeta: c.boolean().optional(),
|
|
850
|
+
limit: c.number().int().min(1).max(5e4).optional()
|
|
698
851
|
}
|
|
699
852
|
}, ({ includeMeta: t, limit: n }) => {
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
let r = e.getLiveSnapshot(), i = n ?? 1e3;
|
|
705
|
-
return A({
|
|
853
|
+
let r = e.getLiveSnapshot();
|
|
854
|
+
if (!t) return N(r.components.slice(0, n));
|
|
855
|
+
let i = n ?? 1e3;
|
|
856
|
+
return N({
|
|
706
857
|
epoch: r.epoch,
|
|
707
858
|
total: r.total,
|
|
708
859
|
captured: r.components.length,
|
|
@@ -713,86 +864,64 @@ function Re(e) {
|
|
|
713
864
|
title: "Component import graph",
|
|
714
865
|
description: "Static import relations between .svelte components.",
|
|
715
866
|
inputSchema: {}
|
|
716
|
-
}, () =>
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
inputSchema: {
|
|
760
|
-
since: o.number().int().nonnegative().optional(),
|
|
761
|
-
limit: o.number().int().min(1).max(500).optional(),
|
|
762
|
-
maxValueChars: o.number().int().min(16).max(Ie.max).optional()
|
|
763
|
-
}
|
|
764
|
-
}, ({ since: e, limit: t, maxValueChars: r }) => {
|
|
765
|
-
let i = n(e), a = t ?? 100, o = r ?? Ie.default, s = Math.max(0, i.changes.length - a), c = i.changes.slice(s).map((e) => ({
|
|
766
|
-
...e,
|
|
767
|
-
oldValue: Le(e.oldValue, o),
|
|
768
|
-
newValue: Le(e.newValue, o)
|
|
769
|
-
}));
|
|
770
|
-
return A({
|
|
771
|
-
...i,
|
|
772
|
-
changes: c,
|
|
773
|
-
omitted: s,
|
|
774
|
-
maxValueChars: o
|
|
775
|
-
});
|
|
867
|
+
}, () => N(e.getComponentRelations())), t.registerTool("get_reactive_summary", {
|
|
868
|
+
title: "Reactive overview (top components)",
|
|
869
|
+
description: "Busiest component instances from runtime counters over all instances, without capturing the graph. Counts are sampled state changes (at most one per state per 200 ms) and renders within the window, not rates. Tracked: state created during component init and shared state of .svelte.js/.ts modules (rows with kind \"module\"; their componentId is a module scope id, usable with get_reactive_scope). `rows` + `other` add up to the totals; null means unknown. Use get_reactive_scope with a componentId to look at one instance. The same request is answered from a cache for up to 1 s; `window.until` says when the answer was computed.",
|
|
870
|
+
inputSchema: {
|
|
871
|
+
topK: c.number().int().min(1).max(200).optional(),
|
|
872
|
+
windowMs: c.number().int().min(1e3).max(6e4).optional()
|
|
873
|
+
}
|
|
874
|
+
}, async ({ topK: t, windowMs: n }) => N(await e.getReactiveSummary({
|
|
875
|
+
topK: t,
|
|
876
|
+
windowMs: n
|
|
877
|
+
}))), t.registerTool("get_reactive_scope", {
|
|
878
|
+
title: "Reactive graph of one component",
|
|
879
|
+
description: "$state/$derived/$effect nodes of one component instance and their direct neighbours, built in the app within the caps. Edges mean 'can affect' (current dependencies), not a recorded cause. `componentId` requires the `epoch` it came from (get_live_components with includeMeta): after a reload the answer is empty with staleReason 'epoch-changed' instead of another instance. Omit componentId only for the whole-app graph (capped; see total/truncated). The same request may be answered from a cache for up to 1 s; `computedAt` says when the app built the graph (null when unknown or for an empty fallback). `stale: true` only marks a fallback after the app did not answer (an earlier answer with its own computedAt, or empty).",
|
|
880
|
+
inputSchema: {
|
|
881
|
+
componentId: c.number().int().nonnegative().optional(),
|
|
882
|
+
epoch: c.string().max(200).optional(),
|
|
883
|
+
maxNodes: c.number().int().min(1).max(5e3).optional(),
|
|
884
|
+
maxEdges: c.number().int().min(1).max(2e4).optional()
|
|
885
|
+
}
|
|
886
|
+
}, async ({ componentId: t, epoch: n, maxNodes: r, maxEdges: i }) => t !== void 0 && n === void 0 ? $e("componentId requires epoch (from get_live_components with includeMeta: true)") : N(await e.getReactiveScope({
|
|
887
|
+
componentId: t,
|
|
888
|
+
epoch: n,
|
|
889
|
+
maxNodes: r,
|
|
890
|
+
maxEdges: i
|
|
891
|
+
}))), t.registerTool("get_state_timeline", {
|
|
892
|
+
title: "State changes since a cursor",
|
|
893
|
+
description: "Sampled $state changes (200 ms) after `since` (the cursor from the previous call). Contains values of state in the running app. `reset: true` means the cursor was stale and this is the whole buffer. At most `limit` newest entries are returned; `omitted` counts older ones in the range that were left out. Values larger than `maxValueChars` (JSON) are replaced by a size summary. Timestamps are detection times, so order within about a second is not causal.",
|
|
894
|
+
inputSchema: {
|
|
895
|
+
since: c.number().int().nonnegative().optional(),
|
|
896
|
+
limit: c.number().int().min(1).max(500).optional(),
|
|
897
|
+
maxValueChars: c.number().int().min(16).max(Ze.max).optional()
|
|
898
|
+
}
|
|
899
|
+
}, ({ since: t, limit: n = 100, maxValueChars: r = Ze.default }) => {
|
|
900
|
+
let i = e.getStateTimelineDelta(t), a = Math.max(0, i.changes.length - n), o = i.changes.slice(a).map((e) => ({
|
|
901
|
+
...e,
|
|
902
|
+
oldValue: Qe(e.oldValue, r),
|
|
903
|
+
newValue: Qe(e.newValue, r)
|
|
904
|
+
}));
|
|
905
|
+
return N({
|
|
906
|
+
...i,
|
|
907
|
+
changes: o,
|
|
908
|
+
omitted: a,
|
|
909
|
+
maxValueChars: r
|
|
776
910
|
});
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
description: "Per dataset: captured count, total (null = unknown), truncated, selection policy and dropped counts by reason. Read this before drawing conclusions from capped data.",
|
|
783
|
-
inputSchema: {}
|
|
784
|
-
}, () => A(n()));
|
|
785
|
-
}
|
|
786
|
-
return t.registerTool("start_session", {
|
|
911
|
+
}), t.registerTool("get_capture_info", {
|
|
912
|
+
title: "What the DevTools hold versus what the app reported",
|
|
913
|
+
description: "Per dataset: captured count, total (null = unknown), truncated, selection policy and dropped counts by reason. Read this before drawing conclusions from capped data.",
|
|
914
|
+
inputSchema: {}
|
|
915
|
+
}, () => N(e.getCaptureInfo())), t.registerTool("start_session", {
|
|
787
916
|
title: "Start measurement session",
|
|
788
917
|
description: "Begin capturing metrics under a labelled session. Required before compare_sessions. Set `persist:true` to write to disk on end; otherwise the session lives in memory only.",
|
|
789
918
|
inputSchema: {
|
|
790
|
-
label:
|
|
791
|
-
persist:
|
|
919
|
+
label: c.string().max(256),
|
|
920
|
+
persist: c.boolean().optional()
|
|
792
921
|
}
|
|
793
922
|
}, ({ label: t, persist: n = !1 }) => {
|
|
794
923
|
let r = e.sessions.start(t, n);
|
|
795
|
-
return
|
|
924
|
+
return N({
|
|
796
925
|
id: r.id,
|
|
797
926
|
label: r.label,
|
|
798
927
|
startedAt: r.startedAt,
|
|
@@ -801,89 +930,420 @@ function Re(e) {
|
|
|
801
930
|
}), t.registerTool("end_session", {
|
|
802
931
|
title: "End current measurement session",
|
|
803
932
|
description: "Closes the active session and returns its delta. `keep` decides disposal: \"memory\" keeps it for this dev-server lifetime, \"disk\" writes to .vite-devtools-svelte/sessions/, \"discard\" deletes it.",
|
|
804
|
-
inputSchema: { keep:
|
|
933
|
+
inputSchema: { keep: c.enum([
|
|
805
934
|
"memory",
|
|
806
935
|
"disk",
|
|
807
936
|
"discard"
|
|
808
937
|
]).optional() }
|
|
809
938
|
}, ({ keep: t = "memory" }) => {
|
|
810
|
-
let n = e.sessions.end(t)
|
|
811
|
-
return
|
|
939
|
+
let n = e.sessions.end(t);
|
|
940
|
+
return N({
|
|
812
941
|
id: n.id,
|
|
813
942
|
label: n.label,
|
|
814
943
|
startedAt: n.startedAt,
|
|
815
944
|
endedAt: n.endedAt,
|
|
816
945
|
keep: t,
|
|
817
|
-
delta:
|
|
946
|
+
delta: e.sessions.deltaOf(n)
|
|
818
947
|
});
|
|
819
948
|
}), t.registerTool("compare_sessions", {
|
|
820
949
|
title: "Compare two sessions",
|
|
821
950
|
description: "Diff render / load / fps metrics between two ended sessions. Each section carries `verdict`: improved | regressed | unchanged.",
|
|
822
951
|
inputSchema: {
|
|
823
|
-
a:
|
|
824
|
-
b:
|
|
952
|
+
a: M,
|
|
953
|
+
b: M
|
|
825
954
|
}
|
|
826
|
-
}, ({ a: t, b: n }) =>
|
|
955
|
+
}, ({ a: t, b: n }) => N(e.sessions.compare(t, n))), t.registerTool("list_sessions", {
|
|
827
956
|
title: "List sessions",
|
|
828
957
|
description: "In-memory + on-disk sessions, most recent first.",
|
|
829
958
|
inputSchema: {}
|
|
830
|
-
}, () =>
|
|
959
|
+
}, () => N(e.sessions.list())), t.registerTool("load_session", {
|
|
831
960
|
title: "Load a session by id",
|
|
832
961
|
description: "Returns the full session record (including delta if ended) by id.",
|
|
833
|
-
inputSchema: { id:
|
|
962
|
+
inputSchema: { id: M }
|
|
834
963
|
}, ({ id: t }) => {
|
|
835
964
|
let n = e.sessions.get(t);
|
|
836
|
-
if (!n) return {
|
|
837
|
-
...A(`Session not found: ${t}`),
|
|
838
|
-
isError: !0
|
|
839
|
-
};
|
|
965
|
+
if (!n) return $e(`Session not found: ${t}`);
|
|
840
966
|
let r = n.endedAt === void 0 ? null : e.sessions.deltaOf(n);
|
|
841
|
-
return
|
|
967
|
+
return N({
|
|
842
968
|
...n,
|
|
843
969
|
delta: r
|
|
844
970
|
});
|
|
845
971
|
}), t.registerTool("delete_session", {
|
|
846
972
|
title: "Delete a session",
|
|
847
973
|
description: "Removes a session from memory and disk.",
|
|
848
|
-
inputSchema: { id:
|
|
849
|
-
}, ({ id: t }) =>
|
|
850
|
-
}
|
|
851
|
-
function ze(e) {
|
|
852
|
-
return e.length === 0 ? 0 : e.reduce((e, t) => e + t, 0) / e.length;
|
|
853
|
-
}
|
|
854
|
-
function j(e) {
|
|
855
|
-
return Math.round(e * 100) / 100;
|
|
974
|
+
inputSchema: { id: M }
|
|
975
|
+
}, ({ id: t }) => N({ deleted: e.sessions.delete(t) })), t;
|
|
856
976
|
}
|
|
857
977
|
//#endregion
|
|
858
978
|
//#region src/runtime/client.js?raw
|
|
859
|
-
var Be = "// FNV-1a over UTF-16 code units: cheap change detection for large snapshots.\nfunction __hash(str) {\n let h = 0x811c9dc5\n for (let i = 0; i < str.length; i++) {\n // oxlint-disable-next-line unicorn/prefer-code-point -- hashes UTF-16 code units on purpose (one per index, no surrogate decoding)\n h ^= str.charCodeAt(i)\n h = Math.imul(h, 0x01000193)\n }\n return (h >>> 0).toString(36)\n}\n\n// Wire shape of one component in a components message.\nfunction __componentEntry(instance) {\n return {\n id: instance.id,\n file: instance.file,\n name: instance.name,\n parentId: instance.parentId,\n mounted: instance.mounted,\n }\n}\n\n// An integer within [lo, hi], or `d` when `v` is not a finite number.\nfunction __clampInt(v, lo, hi, d) {\n const n = Math.floor(Number(v))\n return Number.isFinite(n) ? Math.min(hi, Math.max(lo, n)) : d\n}\n\nif (typeof window !== 'undefined' && !window.__SVELTE_DEVTOOLS__) {\n const __NO_VALUE = Symbol('no value')\n // State timeline ring (§6.7 C): every read sees at most 500 entries and\n // __TIMELINE_BYTES (also the server's buffer budget). The raw array may\n // hold up to __TIMELINE_TRIM_AT (2 x the 500 cap) between bulk trims.\n const __TIMELINE_BYTES = 4 * 1024 * 1024\n const __TIMELINE_TRIM_AT = 1000\n const __SVELTE_DT = {\n _nextId: 0,\n _instances: new Map(),\n _stack: [],\n _pendingParent: undefined,\n _pendingFile: null,\n _debounceTimer: null,\n _listeners: new Set(),\n\n // Phase 2: Profiling data\n _profiles: new Map(),\n _initStartTimes: new Map(),\n _profileDebounceTimer: null,\n\n // Phase 2: Reactive graph data\n _reactiveNodes: new Map(),\n _reactiveProxies: new Map(),\n\n // componentId -> Set<nodeId>. Lets unmount purge a component's reactive\n // nodes without scanning every node of the app (was O(components x nodes)).\n _nodesByComponent: new Map(),\n\n // Phase 3: State timeline\n _stateTimeline: [],\n _stateSnapshots: new Map(),\n _timelineDebounceTimer: null,\n // signal (or proxy marker) -> nodeId, set at track time and removed by\n // _forgetNode: a scoped graph resolves dependencies without scanning\n // every node (§6.7 D).\n _idBySignal: new WeakMap(),\n // proxy -> nodeId (tag_proxy nodes; the marker above is per node)\n _idByProxy: new WeakMap(),\n // Svelte component context -> component id (set by the wrapper on mount)\n _idByContext: new WeakMap(),\n // componentId -> (name -> last suffix) for names declared more than once\n // per instance ({@const} in {#each} items, several $state class instances)\n _nameSeq: new Map(),\n // Module scopes: signals created while a .svelte.js/.ts module body runs\n // (shared state such as `export const cart = $state(...)`) belong to a\n // scope per module file. Ids come from the component id counter (never\n // reused, non-negative) but scopes are not components: they are not in\n // _instances / the component tree, and live as long as the page.\n _modules: new Map(),\n _moduleByFile: new Map(),\n // $state node name -> (scope id -> Set<nodeId>): resolves a proxy's property source\n // (labelled '<name>.prop' by Svelte in dev) to the node of its proxy —\n // a tag_proxy node, or a state signal holding a proxy (reassigned object\n // state, class fields)\n _proxyNames: new Map(),\n // file of the module body running now (set by the module transform)\n _moduleFile: null,\n // componentId -> { effect, effect_pre } counters: effect names are\n // numbered per component, so instances of one file match\n _effectSeq: new Map(),\n // Every tracked node id (dense, swap-remove like _pollIds) for the\n // incremental liveness sweep, and its cursor.\n _sweepIds: [],\n _sweepIndex: new Map(),\n _sweepCursor: 0,\n // Polling bookkeeping (§6.7 D): $state node ids in a dense array kept up\n // to date incrementally (_pollIndex: nodeId -> position; removal is\n // swap-with-last), a cursor carried across ticks, nodes found changed but\n // not yet serialized (_pollDirty), and per-node change hints\n // (nodeId -> { ref, wv, nextCheckAt }).\n _pollIds: [],\n _pollIndex: new Map(),\n _pollCursor: 0,\n _pollDirty: new Set(),\n // Full-sweep bookkeeping: how long the last complete pass over all $state\n // nodes took (ms), for disclosure (= the worst-case detection delay).\n _pollSweep: { startedAt: 0, lastMs: null, nodes: 0 },\n _pollMeta: new Map(),\n _deepCredit: 0,\n _lastSnapshotSize: new Map(),\n _timelineSeq: 0,\n _pushedSeq: 0,\n _timelineReset: false,\n _entryInfo: new WeakMap(),\n // Sum of _entryInfo.bytes over _stateTimeline (runtime byte budget).\n _timelineBytes: 0,\n // Disclosure since the last push (§6.7 C): unsent entries the ring removed\n // (by count / by bytes) and changes recorded only as a size summary.\n _timelineDropped: { 'runtime-count': 0, 'runtime-bytes': 0 },\n _valueTooLarge: 0,\n\n // Overview aggregate (§6.7 I/J), O(1) per event: registered nodes per\n // component and type (+ app totals), and per-component activity in a\n // ring of 60 one-second buckets (sampled changes, renders, render ms,\n // plus how long sampling ran in that second).\n _nodeCounts: new Map(),\n _nodeTotals: { state: 0, derived: 0, effect: 0 },\n _activity: [],\n _epoch: Math.random().toString(36).slice(2) + Date.now().toString(36),\n\n // --- Activity subscription (docs/devframe-migration.md §6.3) ---\n // Inactive until the server says a DevTools client (UI tab or MCP lease)\n // is watching: no state polling, FPS rAF loop, or periodic HMR sends.\n _active: false,\n _componentsCost: { ms: 0, bytes: 0 },\n _componentDeltas: false,\n _pendingAdded: new Set(),\n _pendingRemoved: new Set(),\n _lastFullAt: 0,\n _resync: false,\n _profilesCost: { ms: 0, bytes: 0 },\n // = collector LIMITS.renderProfiles (pinned by a unit test): the server\n // keeps only the newest entries, so sending more is wasted bytes.\n _profileCap: 5000,\n _sampling: null,\n _baselining: false,\n // Polled state nodes not observed yet (no seed value). Their first\n // observation is a seed, not a change: no timeline entry, no activity\n // count, no drops — the old value is unknown, not null (review B-1/B-2).\n _unseeded: new Set(),\n // pendingNodes last sent on a state-timeline message (null = none yet)\n _sentPendingNodes: null,\n _fpsGen: 0,\n\n register(file) {\n const id = this._nextId++\n // Parent: the wrapper's context-derived hint (components created by a\n // later block update, review B1b) when it names a live instance, else\n // the synchronous init stack (children created during the parent's own\n // init, before the parent is mapped).\n const hint = this._pendingParent\n this._pendingParent = undefined\n const parentId =\n hint !== undefined && hint !== null && this._instances.has(hint)\n ? hint\n : this._stack.length > 0\n ? this._stack.at(-1)\n : null\n const baseName = file.slice(file.lastIndexOf('/') + 1).replace('.svelte', '')\n const name = baseName === '' ? 'Unknown' : baseName\n // children is a Set so unmounting one row of a 5 000-row list is O(1).\n this._instances.set(id, { id, file, name, parentId, mounted: true, children: new Set() })\n if (parentId !== null) {\n const parent = this._instances.get(parentId)\n if (parent) parent.children.add(id)\n }\n this._stack.push(id)\n if (this._active) this._pendingAdded.add(id)\n this._scheduleUpdate()\n return id\n },\n\n registered(id) {\n const idx = this._stack.indexOf(id)\n if (idx !== -1) this._stack.splice(idx, 1)\n },\n\n mount(id) {\n const instance = this._instances.get(id)\n if (instance && !instance.mounted) {\n instance.mounted = true\n if (this._active) this._pendingAdded.add(id)\n this._scheduleUpdate()\n }\n },\n\n unmount(id) {\n const instance = this._instances.get(id)\n if (instance) {\n if (instance.parentId !== null) {\n const parent = this._instances.get(instance.parentId)\n if (parent) parent.children.delete(id)\n }\n this._removeChildren(id)\n this._cleanupComponent(id)\n }\n this._scheduleUpdate()\n this._scheduleProfileUpdate()\n },\n\n // Remounts get a fresh id, so entries keyed by a dead id would otherwise\n // survive forever — every per-component map must be purged here.\n _cleanupComponent(id) {\n // Delta bookkeeping: an id added and removed between two pushes was\n // never sent, so it cancels out.\n if (this._active && !this._pendingAdded.delete(id)) this._pendingRemoved.add(id)\n this._cleanupReactiveNodes(id)\n this._effectSeq.delete(id)\n this._nameSeq.delete(id)\n this._instances.delete(id)\n this._profiles.delete(id)\n this._initStartTimes.delete(id)\n },\n\n _cleanupReactiveNodes(componentId) {\n const nodeIds = this._nodesByComponent.get(componentId)\n if (!nodeIds) return\n this._nodesByComponent.delete(componentId)\n // a copy: _forgetNode() deletes from this set\n for (const nodeId of Array.from(nodeIds)) this._forgetNode(nodeId)\n },\n\n _forgetNode(nodeId) {\n const entry = this._reactiveNodes.get(nodeId)\n if (entry) {\n this._countNode(entry.meta.componentId, entry.meta.type, -1)\n const set = this._nodesByComponent.get(entry.meta.componentId)\n if (set) set.delete(nodeId)\n }\n const signal = entry?.signal?.deref()\n if (signal && this._idBySignal.get(signal) === nodeId) this._idBySignal.delete(signal)\n const proxy = this._reactiveProxies.get(nodeId)?.deref()\n if (proxy && this._idByProxy.get(proxy) === nodeId) this._idByProxy.delete(proxy)\n if (entry?.meta.type === 'state') {\n const named = this._proxyNames.get(entry.meta.name)\n const inScope = named?.get(entry.meta.componentId)\n if (inScope) {\n inScope.delete(nodeId)\n if (inScope.size === 0) named.delete(entry.meta.componentId)\n if (named.size === 0) this._proxyNames.delete(entry.meta.name)\n }\n }\n this._pollRemove(nodeId)\n this._sweepRemove(nodeId)\n this._pollDirty.delete(nodeId)\n this._reactiveNodes.delete(nodeId)\n this._reactiveProxies.delete(nodeId)\n this._stateSnapshots.delete(nodeId)\n if (this._stateSnapshotStrs) this._stateSnapshotStrs.delete(nodeId)\n this._pollMeta.delete(nodeId)\n this._lastSnapshotSize.delete(nodeId)\n },\n\n // A component instance or a module scope that is still live.\n _scopeLive(id) {\n return this._instances.has(id) || this._modules.has(id)\n },\n\n _scopeFile(id) {\n const scope = this._instances.get(id) ?? this._modules.get(id)\n return scope ? scope.file : ''\n },\n\n _enterModule(file) {\n this._moduleFile = file\n // a module body that throws (or awaits) never reaches _leaveModule\n queueMicrotask(() => {\n if (this._moduleFile === file) this._moduleFile = null\n })\n },\n\n _leaveModule() {\n this._moduleFile = null\n },\n\n trackModuleSignal(kind, target, name) {\n const file = this._moduleFile\n let id = this._moduleByFile.get(file)\n if (id === undefined) {\n id = this._nextId++\n const lastSegment = file.slice(file.lastIndexOf('/') + 1)\n const base = lastSegment === '' ? file : lastSegment\n this._modules.set(id, { id, file, name: base, kind: 'module' })\n this._moduleByFile.set(file, id)\n }\n if (kind === 'proxy') this.trackProxy(target, name, id, null)\n else if (kind === 'derived') this.trackDerived(target, name, id, null)\n else this.trackState(target, name, id, null)\n },\n\n // A node is live while its signal is reachable, its component is mounted,\n // and the effect it was created in (an {#each} item, an effect run) has\n // not been destroyed. Svelte nulls effect.fn when it destroys an effect\n // (internal/client destroy_effect), which is checked instead of the\n // internal DESTROYED flag value. Returns the signal or null.\n _liveSignal(nodeId) {\n const entry = this._reactiveNodes.get(nodeId)\n if (!entry) return null\n const signal = entry.signal.deref()\n if (signal && this._scopeLive(entry.meta.componentId) && this._ownerAlive(entry)) {\n if (!entry.effect) return signal\n // a bound effect is destroyed when Svelte clears its callback\n if (signal.fn !== null) return signal\n }\n this._forgetNode(nodeId)\n return null\n },\n\n _ownerAlive(entry) {\n if (!entry.owner) return true\n const owner = entry.owner.deref()\n return !!owner && owner.fn !== null\n },\n\n _sweepAdd(nodeId) {\n if (this._sweepIndex.has(nodeId)) return\n this._sweepIndex.set(nodeId, this._sweepIds.length)\n this._sweepIds.push(nodeId)\n },\n\n _sweepRemove(nodeId) {\n const i = this._sweepIndex.get(nodeId)\n if (i === undefined) return\n const ids = this._sweepIds\n const last = ids.pop()\n this._sweepIndex.delete(nodeId)\n if (i < ids.length) {\n ids[i] = last\n this._sweepIndex.set(last, i)\n }\n },\n\n // Liveness of up to `max` nodes, continuing from a cursor (each poll\n // tick): nodes of destroyed {#each} items / effect runs leave the counts\n // and the graph without waiting for a graph request or GC.\n _sweepNodes(max) {\n const ids = this._sweepIds\n for (let n = 0; n < max && ids.length > 0; n++) {\n if (this._sweepCursor >= ids.length) this._sweepCursor = 0\n const nodeId = ids[this._sweepCursor]\n // a forgotten node's slot is refilled by the last id: re-check it\n if (this._liveSignal(nodeId)) this._sweepCursor++\n }\n },\n\n // Unique node id for a signal: componentId:name, or componentId:name#k\n // when this instance already holds a live node of that name for another\n // signal. The same signal (re-tagged) keeps its id.\n _nodeIdFor(identity, byIdentity, componentId, name) {\n const known = byIdentity.get(identity)\n if (known !== undefined && this._reactiveNodes.has(known)) return known\n const base = componentId + ':' + name\n if (!this._reactiveNodes.has(base) || !this._liveSignal(base)) return base\n let seq = this._nameSeq.get(componentId)\n if (!seq) {\n seq = new Map()\n this._nameSeq.set(componentId, seq)\n }\n let k = seq.get(name) ?? 1\n let id\n do {\n k++\n id = base + '#' + k\n } while (this._reactiveNodes.has(id) && this._liveSignal(id))\n seq.set(name, k)\n return id\n },\n\n _registerNode(nodeId, componentId, type, name, signalRef, owner, extra) {\n this._trackNodeCount(nodeId, componentId, type)\n const entry = {\n signal: signalRef,\n owner: owner ? new WeakRef(owner) : null,\n meta: { id: nodeId, type, name, componentId, componentFile: this._scopeFile(componentId) },\n }\n if (extra) Object.assign(entry, extra)\n this._reactiveNodes.set(nodeId, entry)\n this._indexNode(nodeId, componentId)\n this._sweepAdd(nodeId)\n return entry\n },\n\n _indexNode(nodeId, componentId) {\n let set = this._nodesByComponent.get(componentId)\n if (!set) {\n set = new Set()\n this._nodesByComponent.set(componentId, set)\n }\n set.add(nodeId)\n },\n\n _pollAdd(nodeId) {\n if (this._pollIndex.has(nodeId)) return\n if (!this._stateSnapshots.has(nodeId)) this._unseeded.add(nodeId)\n this._pollIndex.set(nodeId, this._pollIds.length)\n this._pollIds.push(nodeId)\n },\n\n // O(1): the last id takes the removed slot. If that slot is behind the\n // cursor, the moved id is visited in the next sweep instead of this one\n // (still visited within a bounded number of ticks).\n // Before a track* call replaces/creates nodeId: move the count from the\n // previous registration (same name re-tracked) to the new one.\n _trackNodeCount(nodeId, componentId, type) {\n const prev = this._reactiveNodes.get(nodeId)\n if (prev) this._countNode(prev.meta.componentId, prev.meta.type, -1)\n this._countNode(componentId, type, 1)\n },\n\n _countNode(componentId, type, d) {\n const kind = type === 'derived' || type === 'effect' ? type : 'state'\n let c = this._nodeCounts.get(componentId)\n if (!c) {\n if (d < 0) return\n c = { state: 0, derived: 0, effect: 0 }\n this._nodeCounts.set(componentId, c)\n }\n c[kind] += d\n this._nodeTotals[kind] += d\n if (c.state + c.derived + c.effect <= 0) this._nodeCounts.delete(componentId)\n },\n\n _bucket() {\n const sec = Math.floor(performance.now() / 1000)\n const slot = ((sec % 60) + 60) % 60\n let b = this._activity[slot]\n if (!b || b.second !== sec) {\n b = { second: sec, sampledMs: 0, rows: new Map() }\n this._activity[slot] = b\n }\n return b\n },\n\n _activityRow(componentId) {\n const rows = this._bucket().rows\n let r = rows.get(componentId)\n if (!r) {\n r = { changes: 0, renders: 0, renderMs: 0 }\n rows.set(componentId, r)\n }\n return r\n },\n\n _pollRemove(nodeId) {\n const i = this._pollIndex.get(nodeId)\n if (i === undefined) return\n this._unseeded.delete(nodeId)\n const ids = this._pollIds\n const last = ids.pop()\n this._pollIndex.delete(nodeId)\n if (i < ids.length) {\n ids[i] = last\n this._pollIndex.set(last, i)\n }\n },\n\n _removeChildren(parentId) {\n const parent = this._instances.get(parentId)\n if (!parent) return\n // a copy: _cleanupComponent() changes this set\n for (const childId of Array.from(parent.children)) {\n this._removeChildren(childId)\n this._cleanupComponent(childId)\n }\n },\n\n // Full-list pushes are throttled, not debounced: a pending timer is not\n // reset, so continuous churn still produces updates (a debounce would\n // starve), and the interval adapts to the last push's cost so a 10 000+\n // instance app can't spend its main thread serializing (review P3):\n // max(min, 20 x last send ms, 1 s when the last payload exceeded ~1 MB).\n _sendInterval(cost, min) {\n return Math.max(min, 20 * cost.ms, cost.bytes > 1000000 ? 1000 : 0)\n },\n\n _scheduleUpdate() {\n if (!this._active || this._debounceTimer) return\n this._debounceTimer = setTimeout(\n () => {\n this._debounceTimer = null\n this._sendUpdate()\n },\n this._sendInterval(this._componentsCost, 100),\n )\n },\n\n // components push (§6.5). Full form { epoch, components } replaces the\n // server's tree for this epoch: sent on activation, when the server does\n // not advertise componentDeltas, as a periodic checkpoint, or when the\n // delta would be larger than the tree. Otherwise the delta form\n // { epoch, added, removed } (removed ids first, ≤ 2 000 entries per\n // message, added in registration order = parents first).\n _sendUpdate(forceFull) {\n // Nobody watching: keep the registry, skip the O(N) payload. A full\n // snapshot is sent on activation (§6.3).\n if (!this._active) return\n const t0 = performance.now()\n const CHUNK = 2000\n const CHECKPOINT_MS = 30000\n const pending = this._pendingAdded.size + this._pendingRemoved.size\n const full =\n forceFull === true ||\n !this._componentDeltas ||\n t0 - this._lastFullAt >= CHECKPOINT_MS ||\n pending > this._instances.size\n let bytes = 0\n const msgs = []\n if (full) {\n const components = []\n for (const [, instance] of this._instances) {\n if (instance.mounted) {\n components.push(__componentEntry(instance))\n bytes += instance.file.length + instance.name.length + 72\n }\n }\n msgs.push({ epoch: this._epoch, reset: true, components })\n this._lastFullAt = t0\n } else if (pending > 0) {\n const removed = [...this._pendingRemoved]\n const added = []\n for (const id of this._pendingAdded) {\n const instance = this._instances.get(id)\n if (instance?.mounted) {\n added.push(__componentEntry(instance))\n bytes += instance.file.length + instance.name.length + 72\n }\n }\n bytes += removed.length * 8\n for (let r = 0; r < removed.length; r += CHUNK) {\n msgs.push({ epoch: this._epoch, added: [], removed: removed.slice(r, r + CHUNK) })\n }\n for (let a = 0; a < added.length; a += CHUNK) {\n msgs.push({ epoch: this._epoch, added: added.slice(a, a + CHUNK), removed: [] })\n }\n }\n this._pendingAdded.clear()\n this._pendingRemoved.clear()\n if (import.meta.hot) {\n for (const msg of msgs) import.meta.hot.send('svelte-devtools:components', msg)\n }\n this._componentsCost = { ms: performance.now() - t0, bytes }\n },\n\n getTree() {\n const components = []\n for (const [, instance] of this._instances) {\n if (instance.mounted) {\n components.push({\n id: instance.id,\n file: instance.file,\n name: instance.name,\n parentId: instance.parentId,\n mounted: instance.mounted,\n })\n }\n }\n return components\n },\n\n // --- Phase 2: Render Profiling ---\n\n startInit(id) {\n this._initStartTimes.set(id, performance.now())\n },\n\n endInit(id) {\n const start = this._initStartTimes.get(id)\n if (start === undefined) return\n const initTime = performance.now() - start\n this._initStartTimes.delete(id)\n const instance = this._instances.get(id)\n if (!instance) return\n this._profiles.set(id, {\n componentId: id,\n file: instance.file,\n name: instance.name,\n initTime,\n renderCount: 0,\n totalRenderTime: 0,\n lastRenderTime: 0,\n lastRenderAt: Date.now(),\n })\n this._scheduleProfileUpdate()\n },\n\n recordRender(id) {\n const profile = this._profiles.get(id)\n if (profile) {\n profile.renderCount++\n profile.lastRenderAt = Date.now()\n } else {\n const instance = this._instances.get(id)\n if (!instance) return\n this._profiles.set(id, {\n componentId: id,\n file: instance.file,\n name: instance.name,\n initTime: 0,\n renderCount: 1,\n totalRenderTime: 0,\n lastRenderTime: 0,\n lastRenderAt: Date.now(),\n })\n }\n this._activityRow(id).renders++\n this._scheduleProfileUpdate()\n },\n\n recordRenderTime(id, duration) {\n const profile = this._profiles.get(id)\n if (profile) {\n profile.totalRenderTime += duration\n profile.lastRenderTime = duration\n this._activityRow(id).renderMs += duration\n }\n },\n\n // Profiles push (review P-1 Option A; contract in\n // docs/performance-status.md). Throttled like components, but the floor\n // grows with the payload: every push carries the whole retained map, so\n // a large app coalesces bursts instead of resending ~1 MB twice a second.\n // Hard cap 2 s (contract R6): a slow serialization must not stretch the\n // latency beyond it.\n _profileInterval() {\n const cost = this._profilesCost\n return Math.min(\n 2000,\n Math.max(500, 20 * cost.ms, cost.bytes > 1000000 ? 2000 : cost.bytes > 250000 ? 1000 : 0),\n )\n },\n\n _scheduleProfileUpdate() {\n if (!this._active || this._profileDebounceTimer) return\n this._profileDebounceTimer = setTimeout(() => {\n this._profileDebounceTimer = null\n this._sendProfileUpdate()\n }, this._profileInterval())\n },\n\n // Also the forced path (activation / resync): a pending throttled push is\n // cancelled so the same state is not sent twice.\n _sendProfileUpdate() {\n if (this._profileDebounceTimer) {\n clearTimeout(this._profileDebounceTimer)\n this._profileDebounceTimer = null\n }\n if (!this._active) return\n const t0 = performance.now()\n const all = Array.from(this._profiles.values())\n // Exactly what the collector retains: its tail, in the same order.\n const profiles =\n all.length > this._profileCap ? all.slice(all.length - this._profileCap) : all\n if (import.meta.hot) {\n // total = all retained profiles; the message carries the newest-mounted\n // tail (§6.7 J IA1 capture policy 'newest-mounted').\n import.meta.hot.send('svelte-devtools:profiles', {\n epoch: this._epoch,\n profiles,\n total: all.length,\n })\n }\n // Payload size from a small sample (entries differ mainly by file path).\n const k = Math.min(8, profiles.length)\n let sampled = 0\n for (let i = 0; i < k; i++) sampled += JSON.stringify(profiles[i]).length\n const bytes = k > 0 ? Math.round((sampled / k) * profiles.length) : 0\n this._profilesCost = { ms: performance.now() - t0, bytes }\n },\n\n getProfiles() {\n return Array.from(this._profiles.values())\n },\n\n resetProfiles() {\n this._profiles.clear()\n this._scheduleProfileUpdate()\n },\n\n // --- Phase 2: Reactive Graph Tracking ---\n\n // `owner` (optional): the effect active when the signal was created; the\n // node dies with it (an {#each} item's {@const}, a class instance created\n // in an effect run).\n trackState(signal, name, componentId, owner) {\n const nodeId = this._nodeIdFor(signal, this._idBySignal, componentId, name)\n this._registerNode(nodeId, componentId, 'state', name, new WeakRef(signal), owner)\n this._idBySignal.set(signal, nodeId)\n this._nameProxyRoot(nodeId, name, componentId)\n this._pollAdd(nodeId)\n },\n\n trackProxy(proxy, name, componentId, owner) {\n const nodeId = this._nodeIdFor(proxy, this._idByProxy, componentId, name)\n this._reactiveProxies.set(nodeId, new WeakRef(proxy))\n // The proxy itself stays weakly held (_reactiveProxies). The marker is\n // held strongly so the node is not GC-dropped while the component lives;\n // _cleanupComponent removes it on unmount.\n const marker = { v: '(proxy)', _isProxy: true }\n this._registerNode(nodeId, componentId, 'state', name, { deref: () => marker }, owner)\n this._idBySignal.set(marker, nodeId)\n this._idByProxy.set(proxy, nodeId)\n this._nameProxyRoot(nodeId, name, componentId)\n this._pollAdd(nodeId)\n },\n\n trackDerived(signal, name, componentId, owner) {\n const nodeId = this._nodeIdFor(signal, this._idBySignal, componentId, name)\n this._registerNode(nodeId, componentId, 'derived', name, new WeakRef(signal), owner)\n this._idBySignal.set(signal, nodeId)\n },\n\n // A user effect object (already created). Kept for callers that have one.\n trackEffect(effect, name, componentId) {\n const nodeId = componentId + ':' + name\n const target = effect ?? { v: undefined, _isEffect: true }\n this._registerNode(\n nodeId,\n componentId,\n 'effect',\n name,\n effect ? new WeakRef(target) : { deref: () => target },\n )\n this._idBySignal.set(target, nodeId)\n return effect\n },\n\n // $effect / $effect.pre being created now (the wrapper). The effect object\n // may not exist yet (deferred to mount): the node holds a placeholder\n // until bindEffect() is called on the effect's first run. kind: 'effect'\n // | 'effect_pre'; names are effect_1, effect_pre_1, ... per component.\n trackUserEffect(kind, componentId, owner) {\n let seq = this._effectSeq.get(componentId)\n if (!seq) {\n seq = { effect: 0, effect_pre: 0 }\n this._effectSeq.set(componentId, seq)\n }\n const name = kind + '_' + ++seq[kind]\n const nodeId = componentId + ':' + name\n const placeholder = { v: undefined, _isEffect: true }\n this._registerNode(nodeId, componentId, 'effect', name, { deref: () => placeholder }, owner)\n return nodeId\n },\n\n bindEffect(nodeId, effect) {\n const entry = nodeId !== null && this._reactiveNodes.get(nodeId)\n if (!entry || !effect || typeof effect !== 'object') return\n entry.signal = new WeakRef(effect)\n entry.effect = true\n this._idBySignal.set(effect, nodeId)\n },\n\n // The component's mount hook effect (the wrapper's, created at pop): its\n // parent is the effect the component's markup effects were created in.\n setComponentEffect(id, effect) {\n const instance = this._instances.get(id)\n if (instance) instance.hook = new WeakRef(effect)\n },\n\n // Markup effects of a component: the effects of its template\n // (template_effect, {#if}/{#each}/... blocks, <svelte:head>), i.e. the\n // effects under the hook's parent created in the component's context\n // (effect.ctx), without descending into other components or the\n // tracked $effect nodes. Svelte links child effects via first/next.\n _markupEffects(id) {\n const instance = this._instances.get(id)\n const hook = instance?.hook?.deref()\n if (!hook?.ctx || !hook.parent) return []\n const ctx = hook.ctx\n const out = []\n const stack = []\n for (let e = hook.parent.first; e; e = e.next) stack.push(e)\n while (stack.length > 0) {\n const e = stack.pop()\n if (e === hook || e.ctx !== ctx) continue\n if (e.deps && !this._idBySignal.has(e)) out.push(e)\n for (let c = e.first; c; c = c.next) stack.push(c)\n }\n return out\n },\n\n // The tracked node a proxy's property source belongs to. Svelte (dev)\n // labels a proxy's sources after the proxy's path ('todos[0].text',\n // 'cart.items.length', 'todos version'); the root name is a $state node\n // name. Many live nodes may share the name (one per instance), so the\n // candidates are looked up per scope: the reader's component, then its\n // ancestors (props flow down), then module scopes, then all — each\n // narrowed by the source's value at that path (identity for objects).\n // Cost O(label + ancestry depth) for the common cases. null when\n // unresolved.\n _sourceOwner(source, readerCid, liveSignal) {\n const label = source.label\n if (typeof label !== 'string' || this._proxyNames.size === 0) return null\n let named = null\n let rest = ''\n for (let i = label.length; i > 0; i--) {\n const ch = i === label.length ? '' : label[i]\n if (ch !== '' && ch !== '.' && ch !== '[' && ch !== ' ') continue\n named = this._proxyNames.get(label.slice(0, i))\n if (named) {\n rest = label.slice(i)\n break\n }\n }\n if (!named) return null\n let path\n // live candidates whose value at the source's path is the source's\n // value; without a property path (' version'), all live candidates\n const fits = ids => {\n const live = [...ids].filter(id => liveSignal(id))\n if (live.length === 0) return live\n if (path === undefined) path = this._labelPath(rest)\n if (!path) return live\n const v = source.v\n return live.filter(id => {\n const at = this._valueAt(this._rootValue(id), path)\n return (\n at !== __NO_VALUE && (Object.is(at, v) || (typeof v === 'symbol' && at === undefined))\n )\n })\n }\n const scopes = []\n for (let cid = readerCid; cid !== null && cid !== undefined;) {\n scopes.push(cid)\n const instance = this._instances.get(cid)\n cid = instance ? instance.parentId : null\n }\n // Module scopes holding the name. Iterated from the module list, not\n // from `named`: a name shared by every row of a list (one scope per\n // instance) made this O(instances) per source, O(n²) per graph build.\n for (const cid of this._modules.keys()) if (named.has(cid)) scopes.push(cid)\n for (const cid of scopes) {\n const ids = named.get(cid)\n const found = ids ? fits(ids) : []\n if (found.length > 0) return found[0]\n }\n // not in the reader's ancestry or a module: any matching node, else the\n // nearest live one by name\n const all = []\n for (const ids of named.values()) for (const id of ids) all.push(id)\n const found = fits(all)\n if (found.length > 0) return found[0]\n for (const cid of scopes) for (const id of named.get(cid) ?? []) if (liveSignal(id)) return id\n return all.find(id => liveSignal(id)) ?? null\n },\n\n // '.items[0].text' -> ['items', '0', 'text']; null for ' version' and\n // anything else that is not a property path.\n _labelPath(rest) {\n const path = []\n const re = /\\.([A-Za-z_$][\\w$]*)|\\[(\\d+)\\]|\\['((?:[^'\\\\]|\\\\.)*)'\\]/y\n let m\n while (re.lastIndex < rest.length && (m = re.exec(rest))) path.push(m[1] ?? m[2] ?? m[3])\n return re.lastIndex === rest.length || rest.length === 0 ? path : null\n },\n\n // Own-property walk (getOwnPropertyDescriptor does not create sources on\n // a Svelte proxy, unlike reading a missing property).\n _valueAt(obj, path) {\n let v = obj\n for (const key of path) {\n if (v === null || (typeof v !== 'object' && typeof v !== 'function')) return __NO_VALUE\n let d\n try {\n d = Object.getOwnPropertyDescriptor(v, key)\n } catch {\n return __NO_VALUE\n }\n if (!d) return __NO_VALUE\n v = 'value' in d ? d.value : __NO_VALUE\n if (v === __NO_VALUE) return v\n }\n return v\n },\n\n _nameProxyRoot(nodeId, name, componentId) {\n let named = this._proxyNames.get(name)\n if (!named) {\n named = new Map()\n this._proxyNames.set(name, named)\n }\n let inScope = named.get(componentId)\n if (!inScope) {\n inScope = new Set()\n named.set(componentId, inScope)\n }\n inScope.add(nodeId)\n },\n\n // The proxy a $state node holds now (tag_proxy: the proxy itself; a\n // state signal: its current value), or undefined.\n _rootValue(nodeId) {\n const proxy = this._reactiveProxies.get(nodeId)\n if (proxy) return proxy.deref()\n const signal = this._reactiveNodes.get(nodeId)?.signal.deref()\n return signal ? signal.v : undefined\n },\n\n // A component whose init threw (the wrapper unwinds its stack): it never\n // mounted and never will, so it leaves the tree and the init stack.\n abortInit(id) {\n const idx = this._stack.indexOf(id)\n if (idx !== -1) this._stack.splice(idx, 1)\n const instance = this._instances.get(id)\n if (!instance) return\n if (instance.parentId !== null) {\n const parent = this._instances.get(instance.parentId)\n if (parent) parent.children.delete(id)\n }\n this._removeChildren(id)\n this._cleanupComponent(id)\n this._scheduleUpdate()\n },\n\n _graphNode(nodeId, entry, signal) {\n const node = { ...entry.meta }\n if (signal._isProxy) {\n const proxy = this._reactiveProxies.get(nodeId)?.deref()\n if (proxy) {\n try {\n node.value = Array.isArray(proxy)\n ? '[' + proxy.length + ']'\n : '{' + Object.keys(proxy).length + '}'\n } catch {\n node.value = '(proxy)'\n }\n }\n } else if (node.type === 'derived' && typeof signal.v === 'symbol') {\n // Svelte computes a derived lazily: until something reads it, v is\n // the UNINITIALIZED marker (a symbol)\n node.unevaluated = true\n } else if (node.type !== 'effect' && signal.v !== undefined && typeof signal.v !== 'symbol') {\n try {\n const v = signal.v\n if (\n typeof v === 'number' ||\n typeof v === 'string' ||\n typeof v === 'boolean' ||\n v === null\n ) {\n node.value = v\n } else {\n node.value = '(object)'\n }\n } catch {\n /* ignore */\n }\n }\n return node\n },\n\n // Reactive graph (§6.7 A/D). Caps are applied while building: past\n // maxNodes no node objects are created and only edges whose endpoints\n // are both included are emitted (the rest are counted in edgesOmitted).\n // - scoped (componentId): that component's nodes plus the tracked nodes\n // directly connected to them (via deps / reactions through untracked\n // intermediates). Dependencies are resolved through _idBySignal, so\n // the cost is O(scope + neighbours), not O(all nodes). The walk is\n // completed even past the cap, so total.nodes/edges are exact.\n // - global: nodes in registration order up to maxNodes ('global-head'),\n // with their incoming dependency edges. Nodes past the cap are not\n // dereferenced; total.nodes is the registered count (may include\n // nodes whose signal was already collected, nodesKind 'registered')\n // and total.edges is null when the walk stopped early (not guessed).\n // Template consumers: the compiler turns every dynamic part of the markup\n // ({expr}, attributes, {#if}/{#each}/{#key}/{#await} conditions,\n // <svelte:head>) into effects that are not tracked one by one. A read\n // from such an effect is reported as an edge to the synthetic node\n // '<componentId>:(template)' (type 'template') of the component the\n // effect belongs to (effect.ctx), so a value only the markup reads is\n // not shown without readers.\n getReactiveGraph(componentId, caps) {\n const scoped = componentId !== undefined && componentId !== null\n const maxNodes = this._graphCap(caps?.maxNodes, 5000)\n const maxEdges = this._graphCap(caps?.maxEdges, 20000)\n const live = new Map()\n // Live signal of a tracked node, or null (forgets dead / unmounted nodes).\n const liveSignal = nodeId => {\n if (live.has(nodeId)) return live.get(nodeId)\n const signal = this._liveSignal(nodeId)\n live.set(nodeId, signal)\n return signal\n }\n const idOf = dep => {\n const id = this._idBySignal.get(dep)\n return id !== undefined && liveSignal(id) === dep ? id : null\n }\n // Synthetic template nodes reached in this build: id -> componentId.\n const templates = new Map()\n // Template node of an untracked effect (no reactions: not a derived),\n // or null when its component is unknown / unmounted.\n const templateOf = effect => {\n if (!effect || 'reactions' in effect || !effect.ctx) return null\n const cid = this._idByContext.get(effect.ctx)\n if (cid === undefined || !this._instances.has(cid)) return null\n const id = cid + ':(template)'\n templates.set(id, cid)\n return id\n }\n\n const included = new Set()\n const seen = new Set()\n const edges = []\n const edgeSet = new Set()\n let edgesOmitted = 0\n let truncated = false\n const see = id => {\n seen.add(id)\n if (!included.has(id) && included.size < maxNodes) included.add(id)\n return included.has(id)\n }\n const addEdge = (from, to) => {\n const key = from + '>' + to\n if (from === to || edgeSet.has(key)) return\n edgeSet.add(key)\n const inFrom = see(from)\n const inTo = see(to)\n if (inFrom && inTo && edges.length < maxEdges) edges.push({ from, to })\n else edgesOmitted++\n }\n // Walk a signal's neighbours (deps or reactions) through untracked\n // intermediates until tracked nodes are reached. onTemplate (reactions\n // only) receives the template node of each untracked effect reached.\n // On the deps side an untracked leaf source (a proxy's property) is\n // resolved to its proxy's node (readerCid: the reading component).\n // nodeId -> dependencies on signals devtools does not track (created\n // in node_modules, e.g. SvelteKit's page state, or outside any\n // component/module body): reported so such a node is not \"isolated\"\n const untracked = new Map()\n const walk = (start, field, onHit, onTemplate, readerCid, onUntracked) => {\n if (!start) return\n const visited = new Set()\n const queue = [...start]\n // Index cursor instead of queue.shift(): shift is O(queue) per pop.\n for (let qi = 0; qi < queue.length; qi++) {\n const dep = queue[qi]\n if (!dep || visited.has(dep)) continue\n visited.add(dep)\n const id = idOf(dep)\n if (id) {\n if (onHit) onHit(id)\n } else if (dep[field]) {\n for (const d of dep[field]) queue.push(d)\n } else if (onTemplate) {\n const t = templateOf(dep)\n if (t) onTemplate(t)\n } else if (field === 'deps' && onHit && !('fn' in dep)) {\n const owner = this._sourceOwner(dep, readerCid, liveSignal)\n if (owner) onHit(owner)\n else if (onUntracked) onUntracked()\n }\n }\n }\n const nodeCid = nodeId => this._reactiveNodes.get(nodeId).meta.componentId\n const countUntracked = nodeId => () => untracked.set(nodeId, (untracked.get(nodeId) ?? 0) + 1)\n // Reads of a component's markup effects: edges into its template node\n // (filter: keep only edges from these node ids, for neighbours).\n const markupEdges = (cid, filter) => {\n const effects = this._markupEffects(cid)\n if (effects.length === 0) return\n const t = cid + ':(template)'\n for (const effect of effects) {\n walk(\n effect.deps,\n 'deps',\n id => {\n if (filter && !filter(id)) return\n templates.set(t, cid)\n addEdge(id, t)\n },\n null,\n cid,\n )\n }\n }\n\n let totalNodes = 0\n let totalEdges = null\n if (scoped) {\n // a copy: liveSignal() forgets dead nodes during the loop\n for (const nodeId of Array.from(this._nodesByComponent.get(componentId) ?? [])) {\n const signal = liveSignal(nodeId)\n if (!signal) continue\n see(nodeId)\n walk(\n signal.deps,\n 'deps',\n depId => addEdge(depId, nodeId),\n null,\n componentId,\n countUntracked(nodeId),\n )\n const toReader = rId => addEdge(nodeId, rId)\n walk(signal.reactions, 'reactions', toReader, toReader)\n }\n if (this._instances.has(componentId)) markupEdges(componentId, null)\n // Readers in direct children (props): a proxy has no reactions list\n // of its own, so its readers are found from their dependencies.\n const own = id => nodeCid(id) === componentId\n const instance = this._instances.get(componentId)\n for (const child of instance ? instance.children : []) {\n // a copy: liveSignal() forgets dead nodes during the loop\n for (const nodeId of Array.from(this._nodesByComponent.get(child) ?? [])) {\n const signal = liveSignal(nodeId)\n if (signal)\n walk(signal.deps, 'deps', depId => own(depId) && addEdge(depId, nodeId), null, child)\n }\n markupEdges(child, own)\n }\n totalNodes = seen.size\n totalEdges = edgeSet.size\n truncated = included.size < seen.size || edgesOmitted > 0\n } else {\n let complete = true\n // a copy: liveSignal() forgets dead nodes during the loop\n for (const nodeId of Array.from(this._reactiveNodes.keys())) {\n if (included.size >= maxNodes && !included.has(nodeId)) {\n complete = false\n break\n }\n const signal = liveSignal(nodeId)\n if (!signal) continue\n see(nodeId)\n walk(\n signal.deps,\n 'deps',\n depId => addEdge(depId, nodeId),\n null,\n nodeCid(nodeId),\n countUntracked(nodeId),\n )\n // tracked readers are found from their own deps; only template\n // readers need the reactions side\n walk(signal.reactions, 'reactions', null, t => addEdge(nodeId, t))\n }\n if (complete) for (const cid of this._instances.keys()) markupEdges(cid, null)\n // registered count (+ template nodes reached), minus nodes found\n // dead while building\n totalNodes = this._reactiveNodes.size + templates.size\n totalEdges = complete ? edgeSet.size : null\n truncated = !complete || edgesOmitted > 0\n }\n\n const nodes = []\n for (const nodeId of included) {\n const cid = templates.get(nodeId)\n if (cid !== undefined) {\n const instance = this._instances.get(cid)\n nodes.push({\n id: nodeId,\n type: 'template',\n name: '(template)',\n componentId: cid,\n componentFile: instance ? instance.file : '',\n })\n continue\n }\n const signal = liveSignal(nodeId)\n if (!signal) continue\n const node = this._graphNode(nodeId, this._reactiveNodes.get(nodeId), signal)\n if (untracked.has(nodeId)) node.untrackedDeps = untracked.get(nodeId)\n nodes.push(node)\n }\n return {\n scope: scoped ? componentId : null,\n nodes,\n edges,\n total: { nodes: totalNodes, nodesKind: 'registered', edges: totalEdges },\n truncated,\n edgesOmitted,\n policy: scoped ? 'scoped' : 'global-head',\n }\n },\n\n _graphCap(value, max) {\n const n = Math.floor(Number(value))\n return Number.isFinite(n) && n >= 1 ? Math.min(n, max) : max\n },\n\n // Request (§6.7 A + review M1): { requestId?, epoch?, componentId?,\n // maxNodes?, maxEdges? }. A request for another page load (epoch) is not\n // answered by this one; the reply echoes requestId and epoch. An old\n // server sends {} → global graph with the default caps (= its LIMITS).\n sendReactiveGraph(request) {\n const req = request ?? {}\n if (req.epoch !== undefined && req.epoch !== null && req.epoch !== this._epoch) return\n const cid = typeof req.componentId === 'number' ? req.componentId : null\n const graph = this.getReactiveGraph(cid, { maxNodes: req.maxNodes, maxEdges: req.maxEdges })\n graph.epoch = this._epoch\n // freshness (review): when this answer was built; caches keep it\n graph.computedAt = Date.now()\n if (req.requestId !== undefined) graph.requestId = req.requestId\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:reactive-graph', graph)\n }\n },\n\n // Overview aggregate (§6.7 I/J). Built from the activity buckets of the\n // window (whole seconds: the current partial second plus the previous\n // ones, ceil(windowMs / 1000) buckets) — cost O(components active in the\n // window), no graph, no node scan. Rows rank by sampled changes, then\n // renders, then render ms; rows + other = total (components and nodes).\n getReactiveSummary(opts) {\n const o = opts ?? {}\n const topK = __clampInt(o.topK, 1, 200, 50)\n const windowMs = __clampInt(o.windowMs, 1000, 60000, 10000)\n const nowSec = Math.floor(performance.now() / 1000)\n const agg = new Map()\n let sampledMs = 0\n for (let k = 0; k < Math.ceil(windowMs / 1000); k++) {\n const sec = nowSec - k\n const b = this._activity[((sec % 60) + 60) % 60]\n if (!b || b.second !== sec) continue\n sampledMs += b.sampledMs\n for (const [cid, r] of b.rows) {\n if (!this._scopeLive(cid)) continue\n let a = agg.get(cid)\n if (!a) {\n a = { changes: 0, renders: 0, renderMs: 0 }\n agg.set(cid, a)\n }\n a.changes += r.changes\n a.renders += r.renders\n a.renderMs += r.renderMs\n }\n }\n const ranked = [...agg].toSorted(\n (x, y) =>\n y[1].changes - x[1].changes ||\n y[1].renders - x[1].renders ||\n y[1].renderMs - x[1].renderMs ||\n x[0] - y[0],\n )\n let rowNodes = 0\n const rows = ranked.slice(0, topK).map(([cid, a]) => {\n const n = this._nodeCounts.get(cid) ?? { state: 0, derived: 0, effect: 0 }\n rowNodes += n.state + n.derived + n.effect\n const row = {\n componentId: cid,\n file: this._scopeFile(cid),\n nodes: { state: n.state, derived: n.derived, effect: n.effect },\n changes: a.changes,\n renders: a.renders,\n renderMs: Math.round(a.renderMs * 1000) / 1000,\n }\n // module scope (shared .svelte.js state), not a component instance\n if (this._modules.has(cid)) row.kind = 'module'\n return row\n })\n const t = this._nodeTotals\n // module scopes count as rows like components (rows + other = total)\n const scopes = this._instances.size + this._modules.size\n const until = Date.now()\n return {\n epoch: this._epoch,\n window: {\n ms: windowMs,\n since: until - windowMs,\n until,\n sampledActiveMs: Math.min(windowMs, sampledMs),\n },\n policy: 'sampled-200ms',\n coverage: 'component-init',\n components: { total: scopes, withActivity: agg.size },\n rows,\n other: {\n components: scopes - rows.length,\n nodes: t.state + t.derived + t.effect - rowNodes,\n },\n truncated: agg.size > topK,\n capabilities: { valueInspection: false, signalHistory: false, writeCause: false },\n // Seed coverage: changes of pending nodes are not observable yet.\n baseline: this._baselineInfo(),\n }\n },\n\n // Request { requestId?, epoch?, topK?, windowMs? } (same correlation as\n // the graph, review M1).\n sendReactiveSummary(request) {\n const req = request ?? {}\n if (req.epoch !== undefined && req.epoch !== null && req.epoch !== this._epoch) return\n const summary = this.getReactiveSummary(req)\n if (req.requestId !== undefined) summary.requestId = req.requestId\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:reactive-summary', summary)\n }\n },\n\n // --- Phase 3: State Timeline ---\n\n // Current value of a $state node: the signal value, or for tag_proxy\n // nodes (non-reassigned object/array state) the live proxy itself.\n // Returns a sentinel when the value can't be read.\n _readStateValue(nodeId, signal) {\n if (signal._isProxy) {\n const proxy = this._reactiveProxies.get(nodeId)?.deref()\n return proxy === undefined ? __NO_VALUE : proxy\n }\n const v = signal.v\n // Svelte's UNINITIALIZED marker is a symbol; functions aren't state data.\n return typeof v === 'symbol' || typeof v === 'function' ? __NO_VALUE : v\n },\n\n // Runs every 200 ms in the user's app, so it must stay cheap regardless of\n // how much state the app holds (§6.7 D).\n // 1. Hint pass, time-sliced: at most HINT_NODES $state nodes per tick,\n // continuing from a cursor carried across ticks, so a full sweep over\n // n nodes takes ceil(n / HINT_NODES) ticks (_pollSweep.lastMs is the\n // measured sweep time = worst-case detection delay). Per node O(1):\n // primitives are compared directly and recorded at once; objects\n // whose reference or Svelte write version (wv) changed are added to\n // _pollDirty, which persists across ticks until serialized.\n // 2. Serialization work is limited to BUDGET_MS per tick (dirty nodes\n // carry over, nothing is dropped).\n // 3. In-place deep mutations (proxies don't bump an outer wv) are found by\n // time-based re-checks: each object is re-verified no earlier than\n // nextCheckAt = now + max(RECHECK_MS, 50 x its serialization cost),\n // paid from a DEEP_MS-per-tick credit, so the amortized cost is bounded\n // however many large states the app holds.\n // 4. Values serializing above MAX_SNAPSHOT_CHARS are kept as length+hash\n // (not the string) and appear in the timeline as a summary.\n // Writes between two visits of a node are observed as one change (the\n // timeline is a sample, policy 'sampled-200ms'; not counted as dropped).\n _pollStateValues(baseline) {\n const HINT_NODES = 4096\n const SWEEP_NODES = 2048\n const BUDGET_MS = 2\n const DEEP_MS = 0.5\n const now = performance.now()\n if (!baseline) {\n // nodes of destroyed {#each} items / effect runs leave the counts\n this._sweepNodes(SWEEP_NODES)\n this._deepCredit = Math.min(10 * DEEP_MS, (this._deepCredit || 0) + DEEP_MS)\n // this tick samples 200 ms of wall time (window.sampledActiveMs)\n const bucket = this._bucket()\n bucket.sampledMs = Math.min(1000, bucket.sampledMs + 200)\n }\n const ids = this._pollIds\n const due = []\n const limit = Math.min(HINT_NODES, ids.length)\n for (let visited = 0; visited < limit && ids.length > 0; visited++) {\n if (this._pollCursor >= ids.length) {\n this._pollCursor = 0\n if (!baseline) {\n if (this._pollSweep.startedAt) this._pollSweep.lastMs = now - this._pollSweep.startedAt\n this._pollSweep.startedAt = now\n this._pollSweep.nodes = ids.length\n }\n }\n if (!baseline && !this._pollSweep.startedAt) this._pollSweep.startedAt = now\n const nodeId = ids[this._pollCursor]\n const entry = this._reactiveNodes.get(nodeId)\n if (entry?.meta.type !== 'state') {\n // re-tracked as another type: drop from the poll list (slot reused)\n this._pollRemove(nodeId)\n continue\n }\n if (!this._scopeLive(entry.meta.componentId)) {\n this._forgetNode(nodeId) // swaps the last id into this slot\n continue\n }\n this._pollCursor++\n const signal = entry.signal.deref()\n const value = signal ? this._readStateValue(nodeId, signal) : __NO_VALUE\n if (value === __NO_VALUE) {\n // nothing readable (collected, uninitialized, function): not pending\n this._unseeded.delete(nodeId)\n continue\n }\n if (value === null || typeof value !== 'object') {\n const had = this._stateSnapshots.has(nodeId)\n const prev = this._stateSnapshots.get(nodeId)\n if (had && Object.is(prev, value)) continue\n // Forget the object key so object -> primitive -> same object again\n // is still recorded as a change.\n if (this._stateSnapshotStrs) this._stateSnapshotStrs.delete(nodeId)\n this._pollDirty.delete(nodeId)\n if (!had) {\n // first observation: seed only\n this._stateSnapshots.set(nodeId, value)\n this._unseeded.delete(nodeId)\n continue\n }\n this._recordChange(\n nodeId,\n entry,\n prev,\n value,\n typeof value === 'string' ? 2 * value.length : 64,\n )\n continue\n }\n let meta = this._pollMeta.get(nodeId)\n if (!meta) {\n meta = { ref: undefined, wv: undefined, nextCheckAt: 0 }\n this._pollMeta.set(nodeId, meta)\n }\n if (meta.ref !== value || meta.wv !== signal.wv) this._pollDirty.add(nodeId)\n else if (now >= meta.nextCheckAt) due.push(nodeId)\n }\n const start = performance.now()\n for (const nodeId of this._pollDirty) {\n if (performance.now() - start > BUDGET_MS) return\n this._pollDirty.delete(nodeId)\n this._serializeNode(nodeId, false)\n }\n for (const nodeId of due) {\n if (this._deepCredit <= 0 || performance.now() - start > BUDGET_MS) return\n this._serializeNode(nodeId, true)\n }\n },\n\n // Activation (late consumer): nodes registered while inactive have no\n // seed yet, so a write before their first visit could not be seen as a\n // change. The first slice is seeded at activation instead of 200 ms later:\n // ONE normal pass (<= HINT_NODES nodes, the per-tick serialization budget;\n // the rest follow on the usual ticks). Seeds record nothing; readiness is\n // disclosed in the summary as baseline { complete, pendingNodes }.\n _pollBaseline() {\n this._baselining = true\n try {\n this._pollStateValues(true)\n } catch {\n /* never break activation */\n } finally {\n this._baselining = false\n }\n },\n\n _serializeNode(nodeId, deep) {\n const MAX_SNAPSHOT_CHARS = 32768\n const RECHECK_MS = 1000\n const entry = this._reactiveNodes.get(nodeId)\n const meta = this._pollMeta.get(nodeId)\n if (!entry || !meta) return\n const signal = entry.signal.deref()\n if (!signal) return\n const value = this._readStateValue(nodeId, signal)\n if (value === __NO_VALUE || value === null || typeof value !== 'object') return\n try {\n const t0 = performance.now()\n const str = JSON.stringify(value)\n const cost = performance.now() - t0\n if (deep) this._deepCredit -= cost\n meta.ref = value\n meta.wv = signal.wv\n meta.nextCheckAt = t0 + Math.max(RECHECK_MS, 50 * cost)\n // Small values keep the string (exact compare); large ones only a\n // length+hash so a 5 MB array doesn't pin 5 MB per node.\n const key =\n str === undefined\n ? ''\n : str.length > MAX_SNAPSHOT_CHARS\n ? str.length + ':' + __hash(str)\n : str\n this._stateSnapshotStrs ??= new Map()\n const hadKey = this._stateSnapshotStrs.has(nodeId)\n if (hadKey && this._stateSnapshotStrs.get(nodeId) === key) return\n this._stateSnapshotStrs.set(nodeId, key)\n const tooLarge = str !== undefined && str.length > MAX_SNAPSHOT_CHARS\n const snapshot =\n str === undefined\n ? null\n : tooLarge\n ? '(object: ' + str.length + ' chars, too large to snapshot)'\n : JSON.parse(str)\n const size = typeof snapshot === 'string' ? 64 : str.length\n if (!this._stateSnapshots.has(nodeId)) {\n // first observation: seed only (no entry, no counters)\n this._stateSnapshots.set(nodeId, snapshot)\n this._lastSnapshotSize.set(nodeId, size)\n this._unseeded.delete(nodeId)\n return\n }\n if (tooLarge) this._valueTooLarge++\n const prev = this._stateSnapshots.get(nodeId)\n this._recordChange(\n nodeId,\n entry,\n prev,\n snapshot,\n size + (this._lastSnapshotSize.get(nodeId) ?? 0),\n )\n this._lastSnapshotSize.set(nodeId, size)\n } catch {\n // non-serializable (cycles, BigInt): never observable, so not pending\n this._unseeded.delete(nodeId)\n }\n },\n\n _recordChange(nodeId, entry, oldValue, newValue, approxBytes) {\n const change = {\n id: nodeId,\n name: entry.meta.name,\n componentFile: entry.meta.componentFile,\n oldValue,\n newValue,\n timestamp: Date.now(),\n }\n // 0 (an empty string) or no estimate: assume a small value.\n const bytes = (approxBytes > 0 ? approxBytes : 64) + 192\n // seq stays runtime-internal: the server assigns its own seq (§6.4).\n this._entryInfo.set(change, { seq: ++this._timelineSeq, bytes })\n this._stateTimeline.push(change)\n this._timelineBytes += bytes\n // sampled change count (§6.7 J IA2): independent of the ring\n this._activityRow(entry.meta.componentId).changes++\n this._stateSnapshots.set(nodeId, newValue)\n // The ring (_trimTimeline) is applied in bulk, not with one splice per\n // change (a poll tick can record thousands): before every read (each\n // push — with a hot channel and an active consumer, at least every 200\n // changes — the full snapshot, getStateTimeline() and clear), and here\n // once more than __TIMELINE_TRIM_AT entries are held or the byte budget\n // is exceeded, which bounds memory when nothing reads or pushes.\n if (\n this._stateTimeline.length > __TIMELINE_TRIM_AT ||\n this._timelineBytes > __TIMELINE_BYTES\n ) {\n this._trimTimeline()\n }\n this._scheduleTimelineUpdate()\n },\n\n // Ring: at most 500 entries and __TIMELINE_BYTES (the newest entry is\n // always kept). Removed entries that were never pushed are disclosed\n // as dropped (§6.7 C); pushed ones are already on the server.\n _trimTimeline() {\n const all = this._stateTimeline\n let cut = 0\n let bytesLeft = this._timelineBytes\n while (cut < all.length - 1 && (all.length - cut > 500 || bytesLeft > __TIMELINE_BYTES)) {\n const info = this._entryInfo.get(all[cut])\n const reason = all.length - cut > 500 ? 'runtime-count' : 'runtime-bytes'\n if (info.seq > this._pushedSeq) this._timelineDropped[reason]++\n bytesLeft -= info.bytes\n cut++\n }\n if (cut > 0) {\n all.splice(0, cut)\n this._timelineBytes = bytesLeft\n }\n },\n\n // Push (§6.7 C): a throttle, not a debounce — a pending timer is never\n // re-armed, so unsent entries leave within 300 ms of the first one even\n // under continuous change — plus an immediate flush once 200 entries\n // (one message) are unsent, since one poll tick can record thousands.\n _scheduleTimelineUpdate() {\n if (!this._active || this._baselining) return\n if (this._timelineSeq - this._pushedSeq >= 200) {\n this._flushTimeline()\n return\n }\n if (this._timelineDebounceTimer) return\n this._timelineDebounceTimer = setTimeout(() => {\n this._timelineDebounceTimer = null\n this._flushTimeline()\n }, 300)\n },\n\n _flushTimeline() {\n if (this._timelineDebounceTimer) {\n clearTimeout(this._timelineDebounceTimer)\n this._timelineDebounceTimer = null\n }\n if (!import.meta.hot) return\n for (const msg of this._timelineDeltas()) {\n import.meta.hot.send('svelte-devtools:state-timeline', msg)\n }\n },\n\n // Disclosure counters since the previous push, attached to (and reset\n // by) the next message: dropped [{ reason, count }] and valueTooLarge.\n _takeTimelineDisclosure(msg) {\n msg.baseline = this._baselineInfo()\n this._sentPendingNodes = msg.baseline.pendingNodes\n const dropped = []\n for (const reason of ['runtime-count', 'runtime-bytes']) {\n const count = this._timelineDropped[reason]\n if (count > 0) dropped.push({ reason, count })\n this._timelineDropped[reason] = 0\n }\n if (dropped.length > 0) msg.dropped = dropped\n if (this._valueTooLarge > 0) msg.valueTooLarge = this._valueTooLarge\n this._valueTooLarge = 0\n return msg\n },\n\n // Seed coverage (review B-2), on every state-timeline message and the\n // summary: pendingNodes = polled $state nodes without a first sample;\n // their writes are not observable yet.\n _baselineInfo() {\n return { complete: this._unseeded.size === 0, pendingNodes: this._unseeded.size }\n },\n\n _hasTimelineDisclosure() {\n return (\n this._sentPendingNodes !== this._unseeded.size ||\n this._timelineDropped['runtime-count'] > 0 ||\n this._timelineDropped['runtime-bytes'] > 0 ||\n this._valueTooLarge > 0\n )\n },\n\n // Delta push (docs/devframe-migration.md §6.4): only entries recorded\n // since the previous push, ≤ 200 per message, tagged with a per-page-load\n // epoch; reset after clearStateTimeline(). A message with no changes is\n // still sent when there is something to disclose (all unsent dropped).\n _timelineDeltas() {\n this._trimTimeline()\n const all = this._stateTimeline\n let start = all.length\n while (start > 0 && this._entryInfo.get(all[start - 1]).seq > this._pushedSeq) start--\n const pending = all.slice(start)\n const msgs = []\n const first = this._timelineReset || this._hasTimelineDisclosure()\n // A first message goes out even with no pending changes (disclosure only).\n const end = first ? Math.max(pending.length, 1) : pending.length\n for (let i = 0; i < end; i += 200) {\n const msg = { epoch: this._epoch, changes: pending.slice(i, i + 200) }\n if (i === 0 && this._timelineReset) msg.reset = true\n if (i === 0) this._takeTimelineDisclosure(msg)\n else msg.baseline = this._baselineInfo()\n msgs.push(msg)\n }\n this._timelineReset = false\n this._pushedSeq = this._timelineSeq\n return msgs\n },\n\n // Full buffer (reset: true) — reply to request-state-timeline and the\n // activation snapshot. Newest entries first up to __TIMELINE_BYTES, the\n // server's own buffer budget, so nothing is sent that it would drop.\n _timelineFull() {\n this._trimTimeline()\n const all = this._stateTimeline\n let start = all.length\n let bytes = 0\n while (start > 0) {\n const size = this._entryInfo.get(all[start - 1]).bytes\n if (bytes + size > __TIMELINE_BYTES && start < all.length) break\n bytes += size\n start--\n }\n this._timelineReset = false\n this._pushedSeq = this._timelineSeq\n return this._takeTimelineDisclosure({\n epoch: this._epoch,\n changes: all.slice(start),\n reset: true,\n })\n },\n\n getStateTimeline() {\n this._trimTimeline()\n return this._stateTimeline\n },\n\n clearStateTimeline() {\n // Ring first: unsent entries past the cap are disclosed as dropped,\n // exactly as if they had been removed when recorded.\n this._trimTimeline()\n this._stateTimeline = []\n this._timelineBytes = 0\n this._pushedSeq = this._timelineSeq\n this._timelineReset = true\n this._scheduleTimelineUpdate()\n },\n\n // --- FPS Monitoring ---\n // Uses requestAnimationFrame to measure frame rate with minimal overhead.\n // Only stores timestamps - no allocations per frame beyond a single array push.\n _fpsFrameTimes: [],\n\n _fpsLoop(gen) {\n if (gen !== this._fpsGen) return\n this._fpsFrameTimes.push(performance.now())\n requestAnimationFrame(() => this._fpsLoop(gen))\n },\n\n _isVisible() {\n if (typeof document === 'undefined') return true\n return document.visibilityState !== 'hidden'\n },\n\n _setSubscription(data) {\n const wasActive = this._active\n this._active = !!data?.active\n this._componentDeltas = !!data?.componentDeltas\n if (!this._active) {\n this._pendingAdded.clear()\n this._pendingRemoved.clear()\n }\n // resync: the server holds no full base for this epoch (§6.5, review\n // C1), or we reconnected to a possibly restarted server.\n const resync = this._resync || !!data?.resync\n this._resync = false\n if (this._active && !wasActive) this._pollBaseline()\n if (this._active && (!wasActive || resync)) {\n // Collector state may be stale or empty (first activation, resync, or a\n // reconnect to a possibly restarted server): resend everything once, in\n // the order components -> profiles -> timeline(reset: true); the\n // reset push marks the activation snapshot complete (D4).\n this._sendUpdate(true)\n this._sendProfileUpdate()\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:state-timeline', this._timelineFull())\n }\n }\n this._syncSampling()\n },\n\n // Sampling (state poll + FPS) runs only while active AND the app tab is\n // visible.\n _syncSampling() {\n const want = this._active && this._isVisible()\n if (want && !this._sampling) {\n this._fpsFrameTimes = []\n const gen = ++this._fpsGen\n this._sampling = {\n poll: setInterval(() => {\n this._pollStateValues()\n // seed progress changed: push it even without changes (B-2)\n if (this._sentPendingNodes !== this._unseeded.size) this._scheduleTimelineUpdate()\n }, 200),\n fps: setInterval(() => {\n this._sampleFps()\n }, 500),\n }\n requestAnimationFrame(() => this._fpsLoop(gen))\n } else if (!want && this._sampling) {\n clearInterval(this._sampling.poll)\n clearInterval(this._sampling.fps)\n this._sampling = null\n this._fpsGen++\n this._fpsFrameTimes = []\n }\n },\n\n _sampleFps() {\n const now = performance.now()\n // Remove frame timestamps older than 1 second\n const cutoff = now - 1000\n let i = 0\n while (i < this._fpsFrameTimes.length && this._fpsFrameTimes[i] < cutoff) i++\n if (i > 0) this._fpsFrameTimes.splice(0, i)\n const fps = this._fpsFrameTimes.length\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:fps', { timestamp: Date.now(), fps })\n }\n },\n }\n\n window.__SVELTE_DEVTOOLS__ = __SVELTE_DT\n\n // State polling and FPS sampling start on the server's subscription\n // message (§6.3) and pause while the app tab is hidden.\n if (typeof document !== 'undefined' && typeof document.addEventListener === 'function') {\n document.addEventListener('visibilitychange', () => __SVELTE_DT._syncSampling())\n }\n\n // Phase 3: Capture runtime errors\n window.addEventListener('error', event => {\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:runtime-error', {\n message: event.message,\n file: event.filename,\n line: event.lineno,\n column: event.colno,\n stack: event.error?.stack ?? '',\n timestamp: Date.now(),\n })\n }\n })\n window.addEventListener('unhandledrejection', event => {\n if (import.meta.hot) {\n const reason = event.reason\n const message = reason?.message\n import.meta.hot.send('svelte-devtools:runtime-error', {\n // No (or an empty / non-string) message: the stringified reason.\n message: typeof message === 'string' && message !== '' ? message : String(reason),\n stack: reason?.stack ?? '',\n timestamp: Date.now(),\n })\n }\n })\n\n // Listen for reactive graph requests from server\n // Pull requests are answered regardless of the subscription state.\n if (import.meta.hot) {\n import.meta.hot.on('svelte-devtools:subscription', data => {\n __SVELTE_DT._setSubscription(data)\n })\n import.meta.hot.on('vite:ws:connect', () => {\n // The server may have restarted with an empty collector: the reply to\n // runtime-ready is treated as a fresh activation (full snapshot).\n __SVELTE_DT._resync = true\n import.meta.hot.send('svelte-devtools:runtime-ready', {})\n })\n import.meta.hot.send('svelte-devtools:runtime-ready', {})\n import.meta.hot.on('svelte-devtools:request-reactive-graph', data => {\n __SVELTE_DT.sendReactiveGraph(data)\n })\n import.meta.hot.on('svelte-devtools:request-reactive-summary', data => {\n __SVELTE_DT.sendReactiveSummary(data)\n })\n import.meta.hot.on('svelte-devtools:request-state-timeline', () => {\n import.meta.hot.send('svelte-devtools:state-timeline', __SVELTE_DT._timelineFull())\n })\n import.meta.hot.on('svelte-devtools:clear-state-timeline', () => {\n __SVELTE_DT.clearStateTimeline()\n })\n }\n}\n", Ve = "import * as __svelte_original from 'svelte/internal/client'\nexport * from 'svelte/internal/client'\n\nfunction __dt() {\n return typeof window === 'undefined' ? null : window.__SVELTE_DEVTOOLS__\n}\n\n// Component ID stack (parallel to runtime._stack but local to wrapper)\nconst __idStack = []\nfunction __currentId() {\n return __idStack.length > 0 ? __idStack.at(-1) : null\n}\n\n// Tracks the most recently created signal for type determination in tag()\nconst __pendingSignal = { ref: null, type: null }\n\n// Component context -> devtools id (review B1b). A component created later\n// by a block update ({#each}/{#if} after mount) runs outside its parent's\n// push..pop, where the runtime's init stack is empty (the wrapper stack\n// below covers the wrapped block helpers; this covers the rest). Svelte (5.56.8,\n// internal/client) exports active_effect; every effect records the\n// component context it was created in (effect.ctx) and runs with that\n// context restored. The block effect that creates the child belongs to the\n// parent's template, so active_effect.ctx at push time IS the parent's\n// context. Each context is mapped to its id once the component mounted\n// (inside its own deferred effect, where active_effect.ctx is the\n// component's own context). The map lives on the runtime (dt._idByContext)\n// so the reactive graph can name the component of any effect it reaches.\n// Weak map: no leak, no Svelte state touched.\nfunction __parentFromContext() {\n const dt = __dt()\n const effect = __svelte_original.active_effect\n const ctx = effect ? effect.ctx : null\n return dt && ctx && dt._idByContext ? dt._idByContext.get(ctx) : undefined\n}\n\n// Owner of a signal/effect created right now: the component whose init (or\n// wrapped block callback) is running, else — outside init, e.g. an effect\n// created while another effect runs — the component of the active effect.\nfunction __owner() {\n const cid = __currentId()\n if (cid !== null) return cid\n const fromContext = __parentFromContext()\n return fromContext === undefined ? null : fromContext\n}\n\n// --- Component Lifecycle ---\n//\n// Observer must not break the observed: every devtools side-effect below is\n// wrapped in try/catch so a bug or an out-of-shape runtime cannot tear down\n// the user's app. The original Svelte function is always called, and its\n// return value always returned, regardless of devtools failures.\n\nexport function push() {\n // Parent hint, read before this component's own id exists:\n // 1. the wrapper stack: the component whose init is running (children\n // rendered directly by a template, where active_effect still belongs to\n // an outer block), or the block owner re-pushed by __wrapBlockFn for a\n // later {#each}/{#if}/{#key} update (see Block Attribution below);\n // 2. else the context-derived owner, for re-creation paths the wrapper\n // does not wrap (snippet, svelte:element, ...).\n let parentHint = null\n try {\n parentHint = __currentId()\n } catch {}\n if (parentHint === null) {\n try {\n parentHint = __parentFromContext()\n } catch {}\n }\n const result = __svelte_original.push.apply(null, arguments)\n try {\n const dt = __dt()\n if (dt) {\n const file = dt._pendingFile ?? 'Unknown'\n dt._pendingFile = null\n dt._pendingParent = parentHint\n const id = dt.register(file)\n __idStack.push(id)\n dt.startInit(id)\n try {\n __svelte_original.user_effect(() => {\n try {\n const own = __svelte_original.active_effect\n if (own?.ctx) dt._idByContext.set(own.ctx, id)\n if (own) dt.setComponentEffect(id, own)\n } catch {}\n return () => {\n try {\n dt.unmount(id)\n } catch {}\n }\n })\n } catch {}\n }\n } catch {}\n return result\n}\n\nexport function pop() {\n // Capture devtools errors but ALWAYS forward to the original pop so the\n // Svelte component stack stays balanced.\n try {\n const dt = __dt()\n if (dt && __idStack.length > 0) {\n const id = __idStack.pop()\n try {\n dt.endInit(id)\n } catch {}\n try {\n dt.registered(id)\n } catch {}\n }\n } catch {}\n return __svelte_original.pop.apply(null, arguments)\n}\n\n// --- Signal Creation (type markers) ---\n\nexport function state() {\n const signal = __svelte_original.state.apply(null, arguments)\n try {\n __pendingSignal.ref = signal\n __pendingSignal.type = 'state'\n } catch {}\n return signal\n}\n\nexport function derived() {\n const signal = __svelte_original.derived.apply(null, arguments)\n try {\n __pendingSignal.ref = signal\n __pendingSignal.type = 'derived'\n } catch {}\n return signal\n}\n\nexport function proxy() {\n const p = __svelte_original.proxy.apply(null, arguments)\n try {\n __pendingSignal.ref = p\n __pendingSignal.type = 'proxy'\n } catch {}\n return p\n}\n\n// --- Signal Tagging (Svelte dev mode) ---\n\nexport function tag(signal, name) {\n const result = __svelte_original.tag.apply(null, arguments)\n try {\n const dt = __dt()\n const cid = __owner()\n const type = __pendingSignal.ref === signal ? __pendingSignal.type : 'state'\n if (dt && cid !== null) {\n const owner = __svelte_original.active_effect\n if (type === 'derived') {\n dt.trackDerived(signal, name, cid, owner)\n } else {\n dt.trackState(signal, name, cid, owner)\n }\n } else if (dt?._moduleFile) {\n // created while a .svelte.js/.ts module body runs (shared state)\n dt.trackModuleSignal(type === 'derived' ? 'derived' : 'state', signal, name)\n }\n __pendingSignal.ref = null\n __pendingSignal.type = null\n } catch {}\n return result\n}\n\nexport function tag_proxy(value, name) {\n const result = __svelte_original.tag_proxy.apply(null, arguments)\n try {\n const dt = __dt()\n const cid = __owner()\n if (dt && cid !== null) {\n dt.trackProxy(value, name, cid, __svelte_original.active_effect)\n } else if (dt?._moduleFile) {\n dt.trackModuleSignal('proxy', value, name)\n }\n __pendingSignal.ref = null\n __pendingSignal.type = null\n } catch {}\n return result\n}\n\n// --- Effect Tracking ---\n//\n// A top-level $effect in a component is deferred by Svelte until mount:\n// user_effect() returns undefined and the effect object is created later,\n// in pop(). So the node is registered now (named per component) and bound\n// to the real effect object on its first run, where active_effect IS the\n// effect; the Svelte runtime then keeps effect.deps current, which is what\n// getReactiveGraph() reads to build edges. The wrapped callback forwards\n// this, arguments and the return value (teardown) unchanged.\n\nfunction __trackUserEffect(original, kind, args) {\n let cid = null\n let dt = null\n let fn = null\n try {\n dt = __dt()\n fn = args[0]\n if (dt && typeof fn === 'function') cid = __owner()\n } catch {}\n if (cid === null) return original.apply(null, args)\n let nodeId = null\n let bound = false\n const wrapped = Array.prototype.slice.call(args)\n wrapped[0] = function () {\n if (!bound) {\n bound = true\n try {\n dt.bindEffect(nodeId, __svelte_original.active_effect)\n } catch {}\n }\n return fn.apply(this, arguments)\n }\n try {\n nodeId = dt.trackUserEffect(kind, cid, __svelte_original.active_effect)\n } catch {}\n const result = original.apply(null, wrapped)\n if (result && !bound) {\n bound = true\n try {\n dt.bindEffect(nodeId, result)\n } catch {}\n }\n return result\n}\n\nexport function user_effect() {\n return __trackUserEffect(__svelte_original.user_effect, 'effect', arguments)\n}\n\nexport function user_pre_effect() {\n return __trackUserEffect(__svelte_original.user_pre_effect, 'effect_pre', arguments)\n}\n\n// --- Render Profiling ---\n//\n// Svelte 5 has no virtual DOM: the compiler wraps every dynamic part of a\n// template in a template_effect (deferred_template_effect for <svelte:head>\n// <title>). A re-run of such an effect IS the component updating the DOM, so\n// these two functions are the measurement points for renders / render time.\n//\n// The first run of an effect is the mount-time paint, already covered by\n// initTime, so it is skipped (initialRun). One state change re-runs several\n// effects of the same component, so durations are pooled per microtask and\n// recorded once per flush: recordRender() +1, recordRenderTime() the sum.\n\nconst __pendingRenderDurations = new Map()\nlet __renderFlushScheduled = false\n\nfunction __flushRenderDurations() {\n __renderFlushScheduled = false\n const dt = __dt()\n for (const [cid, duration] of __pendingRenderDurations) {\n if (dt) {\n try {\n dt.recordRender(cid)\n } catch {}\n try {\n dt.recordRenderTime(cid, duration)\n } catch {}\n }\n }\n __pendingRenderDurations.clear()\n}\n\nfunction __recordRenderDuration(cid, duration) {\n __pendingRenderDurations.set(cid, (__pendingRenderDurations.get(cid) ?? 0) + duration)\n if (!__renderFlushScheduled) {\n __renderFlushScheduled = true\n queueMicrotask(__flushRenderDurations)\n }\n}\n\n// Returns a (possibly new) args array whose first element times each re-run\n// of the effect closure. The owning component is whatever id is on top of\n// __idStack at effect-creation time. User exceptions propagate untouched;\n// only the args are built inside try so the original is called exactly once.\nfunction __wrapTemplateEffect(args) {\n const cid = __owner()\n const fn = args[0]\n if (cid === null || typeof fn !== 'function') return args\n const wrapped = Array.prototype.slice.call(args)\n let initialRun = true\n wrapped[0] = function () {\n if (initialRun) {\n initialRun = false\n return fn.apply(this, arguments)\n }\n const start = performance.now()\n try {\n return fn.apply(this, arguments)\n } finally {\n try {\n __recordRenderDuration(cid, performance.now() - start)\n } catch {}\n }\n }\n return wrapped\n}\n\nexport function template_effect() {\n let args = arguments\n try {\n args = __wrapTemplateEffect(arguments)\n } catch {}\n return __svelte_original.template_effect.apply(null, args)\n}\n\nexport function deferred_template_effect() {\n let args = arguments\n try {\n args = __wrapTemplateEffect(arguments)\n } catch {}\n return __svelte_original.deferred_template_effect.apply(null, args)\n}\n\n// --- Block Attribution ---\n//\n// Svelte creates render effects synchronously at creation time. At mount this\n// happens during the component function (between push/pop), so __idStack has\n// the owner. But effects for {#each} items added later or re-created {#if}\n// branches are created during a batch flush, when the stack is empty — they\n// would never be attributed. Block helpers themselves ARE always called\n// during their owner's init (or inside an outer block's callback), so the\n// owner id is on the stack at block-creation time. __wrapBlock captures it\n// and re-pushes it around every function argument the block invokes later,\n// so effects created inside land on the innermost owner. Child components\n// push their own id on top, keeping nested attribution correct.\n\n// A component whose init throws (caught by <svelte:boundary>, or by the\n// block's caller) never reaches pop(): its id would stay on both stacks and\n// every later signal/child would be attributed to it. On the way out — normal\n// or thrown — the stack is cut back to its depth on entry, and ids left\n// above it are dropped as aborted inits (registered, never mounted).\nfunction __wrapBlockFn(fn, cid) {\n return function () {\n let depth = -1\n try {\n depth = __idStack.length\n __idStack.push(cid)\n } catch {}\n try {\n return fn.apply(this, arguments)\n } finally {\n if (depth !== -1) {\n try {\n if (__idStack.length > depth + 1) {\n const dt = __dt()\n const aborted = __idStack.slice(depth + 1)\n for (let i = aborted.length - 1; i >= 0; i--) {\n try {\n if (dt) dt.abortInit(aborted[i])\n } catch {}\n }\n }\n __idStack.length = depth\n } catch {}\n }\n }\n }\n}\n\nfunction __wrapBlock(args) {\n const cid = __owner()\n if (cid === null) return args\n const wrapped = Array.prototype.slice.call(args)\n for (let i = 0; i < wrapped.length; i++) {\n if (typeof wrapped[i] === 'function') wrapped[i] = __wrapBlockFn(wrapped[i], cid)\n }\n return wrapped\n}\n\nexport function each() {\n let args = arguments\n try {\n args = __wrapBlock(arguments)\n } catch {}\n return __svelte_original.each.apply(null, args)\n}\n\nexport function key() {\n let args = arguments\n try {\n args = __wrapBlock(arguments)\n } catch {}\n return __svelte_original.key.apply(null, args)\n}\n\nexport function component() {\n let args = arguments\n try {\n args = __wrapBlock(arguments)\n } catch {}\n return __svelte_original.component.apply(null, args)\n}\n\nexport function boundary() {\n let args = arguments\n try {\n args = __wrapBlock(arguments)\n } catch {}\n return __svelte_original.boundary.apply(null, args)\n}\n\n// 'if' and 'await' are reserved words, so they cannot be declared as\n// function names and are exported via aliases instead.\nfunction __if_block() {\n let args = arguments\n try {\n args = __wrapBlock(arguments)\n } catch {}\n return __svelte_original.if.apply(null, args)\n}\n\nfunction __await_block() {\n let args = arguments\n try {\n args = __wrapBlock(arguments)\n } catch {}\n return __svelte_original.await.apply(null, args)\n}\n\nexport { __if_block as if, __await_block as await }\n", M = "virtual:svelte-devtools-runtime", He = "\0virtual:svelte-devtools-runtime", Ue = "\0svelte-devtools:wrapped-client", We = Ve, Ge = Be;
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
979
|
+
var tt = "// FNV-1a over UTF-16 code units: cheap change detection for large snapshots.\nfunction __hash(str) {\n let h = 0x811c9dc5\n for (let i = 0; i < str.length; i++) {\n // oxlint-disable-next-line unicorn/prefer-code-point -- hashes UTF-16 code units on purpose (one per index, no surrogate decoding)\n h ^= str.charCodeAt(i)\n h = Math.imul(h, 0x01000193)\n }\n return (h >>> 0).toString(36)\n}\n\n// [A-Za-z_$], plus [0-9] after the first character (Svelte's identifier test\n// for proxy labels).\nfunction __isIdentChar(ch, first) {\n return (\n (ch >= 'a' && ch <= 'z') ||\n (ch >= 'A' && ch <= 'Z') ||\n ch === '_' ||\n ch === '$' ||\n (!first && ch >= '0' && ch <= '9')\n )\n}\n\n// A proxy label path segment ends at `i`: the end, or the next segment.\nfunction __segmentEnd(label, i) {\n return i === label.length || label[i] === '.' || label[i] === '['\n}\n\n// Dense id lists (an array plus id -> position) for cursor-driven sweeps.\nfunction __denseAdd(ids, index, id) {\n if (index.has(id)) return\n index.set(id, ids.length)\n ids.push(id)\n}\n\n// O(1): the last id takes the removed slot. If that slot is behind a sweep\n// cursor, the moved id is visited in the next sweep instead of this one.\nfunction __denseRemove(ids, index, id) {\n const i = index.get(id)\n if (i === undefined) return\n const last = ids.pop()\n index.delete(id)\n if (i < ids.length) {\n ids[i] = last\n index.set(last, i)\n }\n}\n\n// Ring slot (0..59) of a whole second in the activity buckets.\nfunction __slot(sec) {\n return ((sec % 60) + 60) % 60\n}\n\n// String(value), or a placeholder when it cannot be converted (a\n// null-prototype object, a throwing toString).\nfunction __describe(value) {\n try {\n return String(value)\n } catch {\n return '(unprintable value)'\n }\n}\n\n// Wire shape of one component in a components message.\nfunction __componentEntry(instance) {\n return {\n id: instance.id,\n file: instance.file,\n name: instance.name,\n parentId: instance.parentId,\n mounted: true,\n }\n}\n\n// Approximate wire size of one component entry (cost-adaptive throttling).\nfunction __componentBytes(instance) {\n return instance.file.length + instance.name.length + 72\n}\n\n// An integer within [lo, hi], or `d` when `v` is not a finite number.\nfunction __clampInt(v, lo, hi, d) {\n const n = Math.floor(Number(v))\n return Number.isFinite(n) ? Math.min(hi, Math.max(lo, n)) : d\n}\n\nif (typeof window !== 'undefined' && !window.__SVELTE_DEVTOOLS__) {\n const __NO_VALUE = Symbol('no value')\n // State timeline ring: every read sees at most 500 entries and\n // __TIMELINE_BYTES (also the server's buffer budget). The raw array may\n // hold up to __TIMELINE_TRIM_AT (2 x the 500 cap) between bulk trims.\n const __TIMELINE_BYTES = 4 * 1024 * 1024\n const __TIMELINE_TRIM_AT = 1000\n const __SVELTE_DT = {\n _nextId: 0,\n _instances: new Map(),\n _stack: [],\n _pendingParent: undefined,\n _pendingFile: null,\n _debounceTimer: null,\n\n // Render profiling\n _profiles: new Map(),\n _initStartTimes: new Map(),\n _profileDebounceTimer: null,\n\n // Reactive graph\n _reactiveNodes: new Map(),\n _reactiveProxies: new Map(),\n\n // componentId -> Set<nodeId>. Lets unmount purge a component's reactive\n // nodes without scanning every node of the app.\n _nodesByComponent: new Map(),\n\n // State timeline\n _stateTimeline: [],\n // nodeId -> last observed value (primitive or parsed snapshot), and for\n // objects the compare key (the JSON string, or length+hash when large)\n _stateSnapshots: new Map(),\n _stateSnapshotStrs: new Map(),\n _timelineDebounceTimer: null,\n // signal (or proxy marker) -> nodeId, set at track time and removed by\n // _forgetNode: a scoped graph resolves dependencies without scanning\n // every node.\n _idBySignal: new WeakMap(),\n // proxy -> nodeId (tag_proxy nodes; the marker above is per node)\n _idByProxy: new WeakMap(),\n // Svelte component context -> component id (set by the wrapper on mount)\n _idByContext: new WeakMap(),\n // componentId -> (name -> last suffix) for names declared more than once\n // per instance ({@const} in {#each} items, several $state class instances)\n _nameSeq: new Map(),\n // Module scopes: signals created while a .svelte.js/.ts module body runs\n // (shared state such as `export const cart = $state(...)`) belong to a\n // scope per module file. Ids come from the component id counter (never\n // reused, non-negative) but scopes are not components: they are not in\n // _instances / the component tree, and live as long as the page.\n _modules: new Map(),\n _moduleByFile: new Map(),\n // $state node name -> (scope id -> Set<nodeId>): resolves a proxy's property source\n // (labelled '<name>.prop' by Svelte in dev) to the node of its proxy —\n // a tag_proxy node, or a state signal holding a proxy (reassigned object\n // state, class fields)\n _proxyNames: new Map(),\n // file of the module body running now (set by the module transform)\n _moduleFile: null,\n // componentId -> { effect, effect_pre } counters: effect names are\n // numbered per component, so instances of one file match\n _effectSeq: new Map(),\n // Every tracked node id (dense, swap-remove like _pollIds) for the\n // incremental liveness sweep, and its cursor.\n _sweepIds: [],\n _sweepIndex: new Map(),\n _sweepCursor: 0,\n // Polling bookkeeping: $state node ids in a dense array kept up\n // to date incrementally (_pollIndex: nodeId -> position; removal is\n // swap-with-last), a cursor carried across ticks, nodes found changed but\n // not yet serialized (_pollDirty), and per-node change hints\n // (nodeId -> { ref, wv, nextCheckAt }).\n _pollIds: [],\n _pollIndex: new Map(),\n _pollCursor: 0,\n _pollDirty: new Set(),\n _pollMeta: new Map(),\n _deepCredit: 0,\n _lastSnapshotSize: new Map(),\n _timelineSeq: 0,\n _pushedSeq: 0,\n _timelineReset: false,\n _entryInfo: new WeakMap(),\n // Sum of _entryInfo.bytes over _stateTimeline (runtime byte budget).\n _timelineBytes: 0,\n // Disclosure since the last push: unsent entries the ring removed\n // (by count / by bytes) and changes recorded only as a size summary.\n _timelineDropped: { 'runtime-count': 0, 'runtime-bytes': 0 },\n _valueTooLarge: 0,\n\n // Overview aggregate, O(1) per event: registered nodes per\n // component and type (+ app totals), and per-component activity in a\n // ring of 60 one-second buckets (sampled changes, renders, render ms,\n // plus how long sampling ran in that second).\n _nodeCounts: new Map(),\n _nodeTotals: { state: 0, derived: 0, effect: 0 },\n _activity: [],\n _epoch: Math.random().toString(36).slice(2) + Date.now().toString(36),\n\n // Activity subscription\n // Inactive until the server says a DevTools client (UI tab or MCP lease)\n // is watching: no state polling, FPS rAF loop, or periodic HMR sends.\n _active: false,\n _componentsCost: { ms: 0, bytes: 0 },\n _componentDeltas: false,\n _pendingAdded: new Set(),\n _pendingRemoved: new Set(),\n _lastFullAt: 0,\n _resync: false,\n _profilesCost: { ms: 0, bytes: 0 },\n // = collector LIMITS.renderProfiles (pinned by a unit test): the server\n // keeps only the newest entries, so sending more is wasted bytes.\n _profileCap: 5000,\n _sampling: null,\n _baselining: false,\n // Polled state nodes not observed yet (no seed value). Their first\n // observation is a seed, not a change: no timeline entry, no activity\n // count, no drops — the old value is unknown, not null.\n _unseeded: new Set(),\n // pendingNodes last sent on a state-timeline message (null = none yet)\n _sentPendingNodes: null,\n _fpsGen: 0,\n\n register(file) {\n const id = this._nextId++\n // Parent: the wrapper's context-derived hint (components created by a\n // later block update) when it names a live instance, else\n // the synchronous init stack (children created during the parent's own\n // init, before the parent is mapped).\n const hint = this._pendingParent\n this._pendingParent = undefined\n const parentId =\n hint !== undefined && hint !== null && this._instances.has(hint)\n ? hint\n : this._stack.length > 0\n ? this._stack.at(-1)\n : null\n const baseName = file.slice(file.lastIndexOf('/') + 1)\n const name = baseName.endsWith('.svelte') ? baseName.slice(0, -'.svelte'.length) : baseName\n // children is a Set so unmounting one row of a 5 000-row list is O(1).\n this._instances.set(id, {\n id,\n file,\n name: name === '' ? 'Unknown' : name,\n parentId,\n children: new Set(),\n })\n if (parentId !== null) {\n const parent = this._instances.get(parentId)\n if (parent) parent.children.add(id)\n }\n this._stack.push(id)\n if (this._active) this._pendingAdded.add(id)\n this._scheduleUpdate()\n return id\n },\n\n // The component's init finished (pop): it leaves the init stack.\n registered(id) {\n const idx = this._stack.indexOf(id)\n if (idx !== -1) this._stack.splice(idx, 1)\n },\n\n unmount(id) {\n this._removeInstance(id)\n this._scheduleUpdate()\n this._scheduleProfileUpdate()\n },\n\n // A component whose init threw (the wrapper unwinds its stack): it never\n // mounted and never will, so it leaves the tree and the init stack.\n abortInit(id) {\n this.registered(id)\n this._removeInstance(id)\n this._scheduleUpdate()\n },\n\n // The instance and its subtree leave the tree.\n _removeInstance(id) {\n const instance = this._instances.get(id)\n if (!instance) return\n if (instance.parentId !== null) this._instances.get(instance.parentId)?.children.delete(id)\n this._removeChildren(id)\n this._cleanupComponent(id)\n },\n\n // Remounts get a fresh id, so entries keyed by a dead id would otherwise\n // survive forever — every per-component map must be purged here.\n _cleanupComponent(id) {\n // Delta bookkeeping: an id added and removed between two pushes was\n // never sent, so it cancels out.\n if (this._active && !this._pendingAdded.delete(id)) this._pendingRemoved.add(id)\n this._cleanupReactiveNodes(id)\n this._effectSeq.delete(id)\n this._nameSeq.delete(id)\n this._instances.delete(id)\n this._profiles.delete(id)\n this._initStartTimes.delete(id)\n },\n\n _cleanupReactiveNodes(componentId) {\n const nodeIds = this._nodesByComponent.get(componentId)\n if (!nodeIds) return\n this._nodesByComponent.delete(componentId)\n // a copy: _forgetNode() deletes from this set\n for (const nodeId of Array.from(nodeIds)) this._forgetNode(nodeId)\n },\n\n _forgetNode(nodeId) {\n const entry = this._reactiveNodes.get(nodeId)\n if (entry) {\n this._countNode(entry.meta.componentId, entry.meta.type, -1)\n const set = this._nodesByComponent.get(entry.meta.componentId)\n if (set) set.delete(nodeId)\n }\n const signal = entry?.signal?.deref()\n if (signal && this._idBySignal.get(signal) === nodeId) this._idBySignal.delete(signal)\n const proxy = this._reactiveProxies.get(nodeId)?.deref()\n if (proxy && this._idByProxy.get(proxy) === nodeId) this._idByProxy.delete(proxy)\n if (entry?.meta.type === 'state') {\n const named = this._proxyNames.get(entry.meta.name)\n const inScope = named?.get(entry.meta.componentId)\n if (inScope) {\n inScope.delete(nodeId)\n if (inScope.size === 0) named.delete(entry.meta.componentId)\n if (named.size === 0) this._proxyNames.delete(entry.meta.name)\n }\n }\n this._pollRemove(nodeId)\n this._sweepRemove(nodeId)\n this._pollDirty.delete(nodeId)\n this._reactiveNodes.delete(nodeId)\n this._reactiveProxies.delete(nodeId)\n this._stateSnapshots.delete(nodeId)\n this._stateSnapshotStrs.delete(nodeId)\n this._pollMeta.delete(nodeId)\n this._lastSnapshotSize.delete(nodeId)\n },\n\n // A component instance or a module scope that is still live.\n _scopeLive(id) {\n return this._instances.has(id) || this._modules.has(id)\n },\n\n _scopeFile(id) {\n const scope = this._instances.get(id) ?? this._modules.get(id)\n return scope ? scope.file : ''\n },\n\n _enterModule(file) {\n this._moduleFile = file\n // a module body that throws (or awaits) never reaches _leaveModule\n queueMicrotask(() => {\n if (this._moduleFile === file) this._moduleFile = null\n })\n },\n\n _leaveModule() {\n this._moduleFile = null\n },\n\n trackModuleSignal(kind, target, name) {\n const file = this._moduleFile\n let id = this._moduleByFile.get(file)\n if (id === undefined) {\n id = this._nextId++\n this._modules.set(id, { file })\n this._moduleByFile.set(file, id)\n }\n if (kind === 'proxy') this.trackProxy(target, name, id, null)\n else if (kind === 'derived') this.trackDerived(target, name, id, null)\n else this.trackState(target, name, id, null)\n },\n\n // A node is live while its signal is reachable, its component is mounted,\n // and the effect it was created in (an {#each} item, an effect run) has\n // not been destroyed. Svelte nulls effect.fn when it destroys an effect\n // (internal/client destroy_effect), which is checked instead of the\n // internal DESTROYED flag value. Returns the signal or null.\n _liveSignal(nodeId) {\n const entry = this._reactiveNodes.get(nodeId)\n if (!entry) return null\n const signal = entry.signal.deref()\n if (signal && this._scopeLive(entry.meta.componentId) && this._ownerAlive(entry)) {\n if (!entry.effect) return signal\n // a bound effect is destroyed when Svelte clears its callback\n if (signal.fn !== null) return signal\n }\n this._forgetNode(nodeId)\n return null\n },\n\n _ownerAlive(entry) {\n if (!entry.owner) return true\n const owner = entry.owner.deref()\n return !!owner && owner.fn !== null\n },\n\n _sweepAdd(nodeId) {\n __denseAdd(this._sweepIds, this._sweepIndex, nodeId)\n },\n\n _sweepRemove(nodeId) {\n __denseRemove(this._sweepIds, this._sweepIndex, nodeId)\n },\n\n // Liveness of up to `max` nodes, continuing from a cursor (each poll\n // tick): nodes of destroyed {#each} items / effect runs leave the counts\n // and the graph without waiting for a graph request or GC.\n _sweepNodes(max) {\n const ids = this._sweepIds\n for (let n = 0; n < max && ids.length > 0; n++) {\n if (this._sweepCursor >= ids.length) this._sweepCursor = 0\n const nodeId = ids[this._sweepCursor]\n // a forgotten node's slot is refilled by the last id: re-check it\n if (this._liveSignal(nodeId)) this._sweepCursor++\n }\n },\n\n // Unique node id for a signal: componentId:name, or componentId:name#k\n // when this instance already holds a live node of that name for another\n // signal. The same signal (re-tagged) keeps its id.\n _nodeIdFor(identity, byIdentity, componentId, name) {\n const known = byIdentity.get(identity)\n if (known !== undefined && this._reactiveNodes.has(known)) return known\n const base = componentId + ':' + name\n if (!this._reactiveNodes.has(base) || !this._liveSignal(base)) return base\n let seq = this._nameSeq.get(componentId)\n if (!seq) {\n seq = new Map()\n this._nameSeq.set(componentId, seq)\n }\n let k = seq.get(name) ?? 1\n let id\n do {\n k++\n id = base + '#' + k\n } while (this._reactiveNodes.has(id) && this._liveSignal(id))\n seq.set(name, k)\n return id\n },\n\n _registerNode(nodeId, componentId, type, name, signalRef, owner, extra) {\n this._trackNodeCount(nodeId, componentId, type)\n const entry = {\n signal: signalRef,\n owner: owner ? new WeakRef(owner) : null,\n meta: { id: nodeId, type, name, componentId, componentFile: this._scopeFile(componentId) },\n }\n if (extra) Object.assign(entry, extra)\n this._reactiveNodes.set(nodeId, entry)\n this._indexNode(nodeId, componentId)\n this._sweepAdd(nodeId)\n return entry\n },\n\n _indexNode(nodeId, componentId) {\n let set = this._nodesByComponent.get(componentId)\n if (!set) {\n set = new Set()\n this._nodesByComponent.set(componentId, set)\n }\n set.add(nodeId)\n },\n\n _pollAdd(nodeId) {\n if (this._pollIndex.has(nodeId)) return\n if (!this._stateSnapshots.has(nodeId)) this._unseeded.add(nodeId)\n __denseAdd(this._pollIds, this._pollIndex, nodeId)\n },\n\n _pollRemove(nodeId) {\n this._unseeded.delete(nodeId)\n __denseRemove(this._pollIds, this._pollIndex, nodeId)\n },\n\n // Before a track* call replaces/creates nodeId: move the count from the\n // previous registration (same name re-tracked) to the new one.\n _trackNodeCount(nodeId, componentId, type) {\n const prev = this._reactiveNodes.get(nodeId)\n if (prev) this._countNode(prev.meta.componentId, prev.meta.type, -1)\n this._countNode(componentId, type, 1)\n },\n\n _countNode(componentId, type, d) {\n const kind = type === 'derived' || type === 'effect' ? type : 'state'\n let c = this._nodeCounts.get(componentId)\n if (!c) {\n if (d < 0) return\n c = { state: 0, derived: 0, effect: 0 }\n this._nodeCounts.set(componentId, c)\n }\n c[kind] += d\n this._nodeTotals[kind] += d\n if (c.state + c.derived + c.effect <= 0) this._nodeCounts.delete(componentId)\n },\n\n _bucket() {\n const sec = Math.floor(performance.now() / 1000)\n let b = this._activity[__slot(sec)]\n if (!b || b.second !== sec) {\n b = { second: sec, sampledMs: 0, rows: new Map() }\n this._activity[__slot(sec)] = b\n }\n return b\n },\n\n _activityRow(componentId) {\n const rows = this._bucket().rows\n let r = rows.get(componentId)\n if (!r) {\n r = { changes: 0, renders: 0, renderMs: 0 }\n rows.set(componentId, r)\n }\n return r\n },\n\n _removeChildren(parentId) {\n const parent = this._instances.get(parentId)\n if (!parent) return\n // a copy: _cleanupComponent() changes this set\n for (const childId of Array.from(parent.children)) {\n this._removeChildren(childId)\n this._cleanupComponent(childId)\n }\n },\n\n // Full-list pushes are throttled, not debounced: a pending timer is not\n // reset, so continuous churn still produces updates (a debounce would\n // starve), and the interval adapts to the last push's cost so a 10 000+\n // instance app can't spend its main thread serializing:\n // max(min, 20 x last send ms, 1 s when the last payload exceeded ~1 MB).\n _sendInterval(cost, min) {\n return Math.max(min, 20 * cost.ms, cost.bytes > 1000000 ? 1000 : 0)\n },\n\n _scheduleUpdate() {\n if (!this._active || this._debounceTimer) return\n this._debounceTimer = setTimeout(\n () => {\n this._debounceTimer = null\n this._sendUpdate()\n },\n this._sendInterval(this._componentsCost, 100),\n )\n },\n\n // Components push. Full form { epoch, components } replaces the\n // server's tree for this epoch: sent on activation, when the server does\n // not advertise componentDeltas, as a periodic checkpoint, or when the\n // delta would be larger than the tree. Otherwise the delta form\n // { epoch, added, removed } (removed ids first, ≤ 2 000 entries per\n // message, added in registration order = parents first).\n _sendUpdate(forceFull) {\n // Nobody watching: keep the registry, skip the O(N) payload. A full\n // snapshot is sent on activation.\n if (!this._active) return\n const t0 = performance.now()\n const CHUNK = 2000\n const CHECKPOINT_MS = 30000\n const pending = this._pendingAdded.size + this._pendingRemoved.size\n const full =\n forceFull === true ||\n !this._componentDeltas ||\n t0 - this._lastFullAt >= CHECKPOINT_MS ||\n pending > this._instances.size\n let bytes = 0\n const msgs = []\n if (full) {\n const components = []\n for (const instance of this._instances.values()) {\n components.push(__componentEntry(instance))\n bytes += __componentBytes(instance)\n }\n msgs.push({ epoch: this._epoch, reset: true, components })\n this._lastFullAt = t0\n } else if (pending > 0) {\n const removed = [...this._pendingRemoved]\n const added = []\n for (const id of this._pendingAdded) {\n const instance = this._instances.get(id)\n if (instance) {\n added.push(__componentEntry(instance))\n bytes += __componentBytes(instance)\n }\n }\n bytes += removed.length * 8\n for (let r = 0; r < removed.length; r += CHUNK) {\n msgs.push({ epoch: this._epoch, added: [], removed: removed.slice(r, r + CHUNK) })\n }\n for (let a = 0; a < added.length; a += CHUNK) {\n msgs.push({ epoch: this._epoch, added: added.slice(a, a + CHUNK), removed: [] })\n }\n }\n this._pendingAdded.clear()\n this._pendingRemoved.clear()\n for (const msg of msgs) this._send('svelte-devtools:components', msg)\n this._componentsCost = { ms: performance.now() - t0, bytes }\n },\n\n getTree() {\n return Array.from(this._instances.values(), __componentEntry)\n },\n\n // --- Render profiling ---\n\n startInit(id) {\n this._initStartTimes.set(id, performance.now())\n },\n\n endInit(id) {\n const start = this._initStartTimes.get(id)\n if (start === undefined) return\n const initTime = performance.now() - start\n this._initStartTimes.delete(id)\n if (!this._newProfile(id, initTime)) return\n this._scheduleProfileUpdate()\n },\n\n recordRender(id) {\n const profile = this._profiles.get(id) ?? this._newProfile(id, 0)\n if (!profile) return\n profile.renderCount++\n profile.lastRenderAt = Date.now()\n this._activityRow(id).renders++\n this._scheduleProfileUpdate()\n },\n\n // A fresh profile for a live instance (null otherwise).\n _newProfile(id, initTime) {\n const instance = this._instances.get(id)\n if (!instance) return null\n const profile = {\n componentId: id,\n file: instance.file,\n name: instance.name,\n initTime,\n renderCount: 0,\n totalRenderTime: 0,\n lastRenderTime: 0,\n lastRenderAt: Date.now(),\n }\n this._profiles.set(id, profile)\n return profile\n },\n\n recordRenderTime(id, duration) {\n const profile = this._profiles.get(id)\n if (profile) {\n profile.totalRenderTime += duration\n profile.lastRenderTime = duration\n this._activityRow(id).renderMs += duration\n }\n },\n\n // Profiles push, throttled like components, but the floor grows with the\n // payload: every push carries the whole retained map, so a large app\n // coalesces bursts instead of resending ~1 MB twice a second. Hard cap\n // 2 s: a slow serialization must not stretch the latency beyond it.\n _profileInterval() {\n const cost = this._profilesCost\n return Math.min(\n 2000,\n Math.max(500, 20 * cost.ms, cost.bytes > 1000000 ? 2000 : cost.bytes > 250000 ? 1000 : 0),\n )\n },\n\n _scheduleProfileUpdate() {\n if (!this._active || this._profileDebounceTimer) return\n this._profileDebounceTimer = setTimeout(() => {\n this._profileDebounceTimer = null\n this._sendProfileUpdate()\n }, this._profileInterval())\n },\n\n // Also the forced path (activation / resync): a pending throttled push is\n // cancelled so the same state is not sent twice.\n _sendProfileUpdate() {\n if (this._profileDebounceTimer) {\n clearTimeout(this._profileDebounceTimer)\n this._profileDebounceTimer = null\n }\n if (!this._active) return\n const t0 = performance.now()\n const all = Array.from(this._profiles.values())\n // Exactly what the collector retains: its tail, in the same order.\n const profiles =\n all.length > this._profileCap ? all.slice(all.length - this._profileCap) : all\n // total = all retained profiles; the message carries the newest-mounted tail\n this._send('svelte-devtools:profiles', { epoch: this._epoch, profiles, total: all.length })\n // Payload size from a small sample (entries differ mainly by file path).\n const k = Math.min(8, profiles.length)\n let sampled = 0\n for (let i = 0; i < k; i++) sampled += JSON.stringify(profiles[i]).length\n const bytes = k > 0 ? Math.round((sampled / k) * profiles.length) : 0\n this._profilesCost = { ms: performance.now() - t0, bytes }\n },\n\n // --- Reactive graph tracking ---\n\n // `owner` (optional): the effect active when the signal was created; the\n // node dies with it (an {#each} item's {@const}, a class instance created\n // in an effect run).\n trackState(signal, name, componentId, owner) {\n const nodeId = this._nodeIdFor(signal, this._idBySignal, componentId, name)\n this._registerNode(nodeId, componentId, 'state', name, new WeakRef(signal), owner)\n this._idBySignal.set(signal, nodeId)\n this._nameProxyRoot(nodeId, name, componentId)\n this._pollAdd(nodeId)\n },\n\n trackProxy(proxy, name, componentId, owner) {\n const nodeId = this._nodeIdFor(proxy, this._idByProxy, componentId, name)\n this._reactiveProxies.set(nodeId, new WeakRef(proxy))\n // The proxy itself stays weakly held (_reactiveProxies). The marker is\n // held strongly so the node is not GC-dropped while the component lives;\n // _cleanupComponent removes it on unmount.\n const marker = { v: '(proxy)', _isProxy: true }\n this._registerNode(nodeId, componentId, 'state', name, { deref: () => marker }, owner)\n this._idBySignal.set(marker, nodeId)\n this._idByProxy.set(proxy, nodeId)\n this._nameProxyRoot(nodeId, name, componentId)\n this._pollAdd(nodeId)\n },\n\n trackDerived(signal, name, componentId, owner) {\n const nodeId = this._nodeIdFor(signal, this._idBySignal, componentId, name)\n this._registerNode(nodeId, componentId, 'derived', name, new WeakRef(signal), owner)\n this._idBySignal.set(signal, nodeId)\n },\n\n // $effect / $effect.pre being created now (the wrapper). The effect object\n // may not exist yet (deferred to mount): the node holds a placeholder\n // until bindEffect() is called on the effect's first run. kind: 'effect'\n // | 'effect_pre'; names are effect_1, effect_pre_1, ... per component.\n trackUserEffect(kind, componentId, owner) {\n let seq = this._effectSeq.get(componentId)\n if (!seq) {\n seq = { effect: 0, effect_pre: 0 }\n this._effectSeq.set(componentId, seq)\n }\n const name = kind + '_' + ++seq[kind]\n const nodeId = componentId + ':' + name\n const placeholder = { v: undefined, _isEffect: true }\n this._registerNode(nodeId, componentId, 'effect', name, { deref: () => placeholder }, owner)\n return nodeId\n },\n\n bindEffect(nodeId, effect) {\n const entry = nodeId !== null && this._reactiveNodes.get(nodeId)\n if (!entry || !effect || typeof effect !== 'object') return\n entry.signal = new WeakRef(effect)\n entry.effect = true\n this._idBySignal.set(effect, nodeId)\n },\n\n // The component's mount hook effect (the wrapper's, created at pop): its\n // parent is the effect the component's markup effects were created in.\n setComponentEffect(id, effect) {\n const instance = this._instances.get(id)\n if (instance) instance.hook = new WeakRef(effect)\n },\n\n // Markup effects of a component: the effects of its template\n // (template_effect, {#if}/{#each}/... blocks, <svelte:head>), i.e. the\n // effects under the hook's parent created in the component's context\n // (effect.ctx), without descending into other components or the\n // tracked $effect nodes. Svelte links child effects via first/next.\n _markupEffects(id) {\n const instance = this._instances.get(id)\n const hook = instance?.hook?.deref()\n if (!hook?.ctx || !hook.parent) return []\n const ctx = hook.ctx\n const out = []\n const stack = []\n for (let e = hook.parent.first; e; e = e.next) stack.push(e)\n while (stack.length > 0) {\n const e = stack.pop()\n if (e === hook || e.ctx !== ctx) continue\n if (e.deps && !this._idBySignal.has(e)) out.push(e)\n for (let c = e.first; c; c = c.next) stack.push(c)\n }\n return out\n },\n\n // The tracked node a proxy's property source belongs to. Svelte (dev)\n // labels a proxy's sources after the proxy's path ('todos[0].text',\n // 'cart.items.length', 'todos version'); the root name is a $state node\n // name. Many live nodes may share the name (one per instance), so the\n // candidates are looked up per scope: the reader's component, then its\n // ancestors (props flow down), then module scopes, then all — each\n // narrowed by the source's value at that path (identity for objects).\n // Cost O(label + ancestry depth) for the common cases. null when\n // unresolved.\n _sourceOwner(source, readerCid, liveSignal) {\n const label = source.label\n if (typeof label !== 'string' || this._proxyNames.size === 0) return null\n let named = null\n let rest = ''\n for (let i = label.length; i > 0; i--) {\n const ch = i === label.length ? '' : label[i]\n if (ch !== '' && ch !== '.' && ch !== '[' && ch !== ' ') continue\n named = this._proxyNames.get(label.slice(0, i))\n if (named) {\n rest = label.slice(i)\n break\n }\n }\n if (!named) return null\n let path\n // live candidates whose value at the source's path is the source's\n // value; without a property path (' version'), all live candidates\n const fits = ids => {\n const live = [...ids].filter(id => liveSignal(id))\n if (live.length === 0) return live\n if (path === undefined) path = this._labelPath(rest)\n if (!path) return live\n const v = source.v\n return live.filter(id => {\n const at = this._valueAt(this._rootValue(id), path)\n return (\n at !== __NO_VALUE && (Object.is(at, v) || (typeof v === 'symbol' && at === undefined))\n )\n })\n }\n const scopes = []\n for (let cid = readerCid; cid !== null && cid !== undefined;) {\n scopes.push(cid)\n const instance = this._instances.get(cid)\n cid = instance ? instance.parentId : null\n }\n // Module scopes holding the name. Iterated from the module list, not\n // from `named`: a name shared by every row of a list (one scope per\n // instance) made this O(instances) per source, O(n²) per graph build.\n for (const cid of this._modules.keys()) if (named.has(cid)) scopes.push(cid)\n for (const cid of scopes) {\n const ids = named.get(cid)\n const found = ids ? fits(ids) : []\n if (found.length > 0) return found[0]\n }\n // not in the reader's ancestry or a module: any matching node, else the\n // nearest live one by name\n const all = []\n for (const ids of named.values()) for (const id of ids) all.push(id)\n const found = fits(all)\n if (found.length > 0) return found[0]\n for (const cid of scopes) for (const id of named.get(cid) ?? []) if (liveSignal(id)) return id\n return all.find(id => liveSignal(id)) ?? null\n },\n\n // '.items[0].text' -> ['items', '0', 'text']; null for ' version' and\n // anything else that is not a property path. Svelte's labels: `.prop`\n // for an identifier, `[0]` for an index, `['prop']` otherwise — the\n // quoted name is not escaped, so it ends at the first `']` that is\n // followed by the next segment or the end.\n _labelPath(rest) {\n const path = []\n let i = 0\n while (i < rest.length) {\n let end\n if (rest[i] === '.') {\n end = i + 1\n while (end < rest.length && __isIdentChar(rest[end], end === i + 1)) end++\n if (end === i + 1) return null\n path.push(rest.slice(i + 1, end))\n } else if (rest.startsWith(\"['\", i)) {\n end = rest.indexOf(\"']\", i + 2)\n while (end !== -1 && !__segmentEnd(rest, end + 2)) end = rest.indexOf(\"']\", end + 1)\n if (end === -1) return null\n path.push(rest.slice(i + 2, end))\n end += 2\n } else if (rest[i] === '[') {\n end = i + 1\n while (end < rest.length && rest[end] >= '0' && rest[end] <= '9') end++\n if (end === i + 1 || rest[end] !== ']') return null\n path.push(rest.slice(i + 1, end))\n end++\n } else {\n return null\n }\n if (!__segmentEnd(rest, end)) return null\n i = end\n }\n return path\n },\n\n // Own-property walk (getOwnPropertyDescriptor does not create sources on\n // a Svelte proxy, unlike reading a missing property).\n _valueAt(obj, path) {\n let v = obj\n for (const key of path) {\n if (v === null || (typeof v !== 'object' && typeof v !== 'function')) return __NO_VALUE\n let d\n try {\n d = Object.getOwnPropertyDescriptor(v, key)\n } catch {\n return __NO_VALUE\n }\n if (!d) return __NO_VALUE\n v = 'value' in d ? d.value : __NO_VALUE\n if (v === __NO_VALUE) return v\n }\n return v\n },\n\n _nameProxyRoot(nodeId, name, componentId) {\n let named = this._proxyNames.get(name)\n if (!named) {\n named = new Map()\n this._proxyNames.set(name, named)\n }\n let inScope = named.get(componentId)\n if (!inScope) {\n inScope = new Set()\n named.set(componentId, inScope)\n }\n inScope.add(nodeId)\n },\n\n // The proxy a $state node holds now (tag_proxy: the proxy itself; a\n // state signal: its current value), or undefined.\n _rootValue(nodeId) {\n const proxy = this._reactiveProxies.get(nodeId)\n if (proxy) return proxy.deref()\n const signal = this._reactiveNodes.get(nodeId)?.signal.deref()\n return signal ? signal.v : undefined\n },\n\n _graphNode(nodeId, entry, signal) {\n const node = { ...entry.meta }\n if (signal._isProxy) {\n const proxy = this._reactiveProxies.get(nodeId)?.deref()\n if (proxy) {\n try {\n node.value = Array.isArray(proxy)\n ? '[' + proxy.length + ']'\n : '{' + Object.keys(proxy).length + '}'\n } catch {\n node.value = '(proxy)'\n }\n }\n } else if (node.type === 'derived' && typeof signal.v === 'symbol') {\n // Svelte computes a derived lazily: until something reads it, v is\n // the UNINITIALIZED marker (a symbol)\n node.unevaluated = true\n } else if (node.type !== 'effect' && signal.v !== undefined && typeof signal.v !== 'symbol') {\n try {\n const v = signal.v\n if (\n typeof v === 'number' ||\n typeof v === 'string' ||\n typeof v === 'boolean' ||\n v === null\n ) {\n node.value = v\n } else {\n node.value = '(object)'\n }\n } catch {\n /* ignore */\n }\n }\n return node\n },\n\n // Reactive graph. Caps are applied while building: past\n // maxNodes no node objects are created and only edges whose endpoints\n // are both included are emitted (the rest are counted in edgesOmitted).\n // - scoped (componentId): that component's nodes plus the tracked nodes\n // directly connected to them (via deps / reactions through untracked\n // intermediates). Dependencies are resolved through _idBySignal, so\n // the cost is O(scope + neighbours), not O(all nodes). The walk is\n // completed even past the cap, so total.nodes/edges are exact.\n // - global: nodes in registration order up to maxNodes ('global-head'),\n // with their incoming dependency edges. Nodes past the cap are not\n // dereferenced; total.nodes is the registered count (may include\n // nodes whose signal was already collected, nodesKind 'registered')\n // and total.edges is null when the walk stopped early (not guessed).\n // Template consumers: the compiler turns every dynamic part of the markup\n // ({expr}, attributes, {#if}/{#each}/{#key}/{#await} conditions,\n // <svelte:head>) into effects that are not tracked one by one. A read\n // from such an effect is reported as an edge to the synthetic node\n // '<componentId>:(template)' (type 'template') of the component the\n // effect belongs to (effect.ctx), so a value only the markup reads is\n // not shown without readers.\n getReactiveGraph(componentId, caps) {\n const scoped = componentId !== undefined && componentId !== null\n const maxNodes = this._graphCap(caps?.maxNodes, 5000)\n const maxEdges = this._graphCap(caps?.maxEdges, 20000)\n const live = new Map()\n // Live signal of a tracked node, or null (forgets dead / unmounted nodes).\n const liveSignal = nodeId => {\n if (live.has(nodeId)) return live.get(nodeId)\n const signal = this._liveSignal(nodeId)\n live.set(nodeId, signal)\n return signal\n }\n const idOf = dep => {\n const id = this._idBySignal.get(dep)\n return id !== undefined && liveSignal(id) === dep ? id : null\n }\n // Synthetic template nodes reached in this build: id -> componentId.\n const templates = new Map()\n // Template node of an untracked effect (no reactions: not a derived),\n // or null when its component is unknown / unmounted.\n const templateOf = effect => {\n if (!effect || 'reactions' in effect || !effect.ctx) return null\n const cid = this._idByContext.get(effect.ctx)\n if (cid === undefined || !this._instances.has(cid)) return null\n const id = cid + ':(template)'\n templates.set(id, cid)\n return id\n }\n\n const included = new Set()\n const seen = new Set()\n const edges = []\n const edgeSet = new Set()\n let edgesOmitted = 0\n let truncated = false\n const see = id => {\n seen.add(id)\n if (!included.has(id) && included.size < maxNodes) included.add(id)\n return included.has(id)\n }\n const addEdge = (from, to) => {\n const key = from + '>' + to\n if (from === to || edgeSet.has(key)) return\n edgeSet.add(key)\n const inFrom = see(from)\n const inTo = see(to)\n if (inFrom && inTo && edges.length < maxEdges) edges.push({ from, to })\n else edgesOmitted++\n }\n // Walk a signal's neighbours (deps or reactions) through untracked\n // intermediates until tracked nodes are reached. onTemplate (reactions\n // only) receives the template node of each untracked effect reached.\n // On the deps side an untracked leaf source (a proxy's property) is\n // resolved to its proxy's node (readerCid: the reading component).\n // nodeId -> dependencies on signals devtools does not track (created\n // in node_modules, e.g. SvelteKit's page state, or outside any\n // component/module body): reported so such a node is not \"isolated\"\n const untracked = new Map()\n const walk = (start, field, onHit, onTemplate, readerCid, onUntracked) => {\n if (!start) return\n const visited = new Set()\n const queue = [...start]\n // Index cursor instead of queue.shift(): shift is O(queue) per pop.\n for (let qi = 0; qi < queue.length; qi++) {\n const dep = queue[qi]\n if (!dep || visited.has(dep)) continue\n visited.add(dep)\n const id = idOf(dep)\n if (id) {\n if (onHit) onHit(id)\n } else if (dep[field]) {\n for (const d of dep[field]) queue.push(d)\n } else if (onTemplate) {\n const t = templateOf(dep)\n if (t) onTemplate(t)\n } else if (field === 'deps' && onHit && !('fn' in dep)) {\n const owner = this._sourceOwner(dep, readerCid, liveSignal)\n if (owner) onHit(owner)\n else if (onUntracked) onUntracked()\n }\n }\n }\n const nodeCid = nodeId => this._reactiveNodes.get(nodeId).meta.componentId\n const countUntracked = nodeId => () => untracked.set(nodeId, (untracked.get(nodeId) ?? 0) + 1)\n // Reads of a component's markup effects: edges into its template node\n // (filter: keep only edges from these node ids, for neighbours).\n const markupEdges = (cid, filter) => {\n const effects = this._markupEffects(cid)\n if (effects.length === 0) return\n const t = cid + ':(template)'\n for (const effect of effects) {\n walk(\n effect.deps,\n 'deps',\n id => {\n if (filter && !filter(id)) return\n templates.set(t, cid)\n addEdge(id, t)\n },\n null,\n cid,\n )\n }\n }\n\n let totalNodes = 0\n let totalEdges = null\n if (scoped) {\n // a copy: liveSignal() forgets dead nodes during the loop\n for (const nodeId of Array.from(this._nodesByComponent.get(componentId) ?? [])) {\n const signal = liveSignal(nodeId)\n if (!signal) continue\n see(nodeId)\n walk(\n signal.deps,\n 'deps',\n depId => addEdge(depId, nodeId),\n null,\n componentId,\n countUntracked(nodeId),\n )\n const toReader = rId => addEdge(nodeId, rId)\n walk(signal.reactions, 'reactions', toReader, toReader)\n }\n if (this._instances.has(componentId)) markupEdges(componentId, null)\n // Readers in direct children (props): a proxy has no reactions list\n // of its own, so its readers are found from their dependencies.\n const own = id => nodeCid(id) === componentId\n const instance = this._instances.get(componentId)\n for (const child of instance ? instance.children : []) {\n // a copy: liveSignal() forgets dead nodes during the loop\n for (const nodeId of Array.from(this._nodesByComponent.get(child) ?? [])) {\n const signal = liveSignal(nodeId)\n if (signal)\n walk(signal.deps, 'deps', depId => own(depId) && addEdge(depId, nodeId), null, child)\n }\n markupEdges(child, own)\n }\n totalNodes = seen.size\n totalEdges = edgeSet.size\n truncated = included.size < seen.size || edgesOmitted > 0\n } else {\n let complete = true\n // a copy: liveSignal() forgets dead nodes during the loop\n for (const nodeId of Array.from(this._reactiveNodes.keys())) {\n if (included.size >= maxNodes && !included.has(nodeId)) {\n complete = false\n break\n }\n const signal = liveSignal(nodeId)\n if (!signal) continue\n see(nodeId)\n walk(\n signal.deps,\n 'deps',\n depId => addEdge(depId, nodeId),\n null,\n nodeCid(nodeId),\n countUntracked(nodeId),\n )\n // tracked readers are found from their own deps; only template\n // readers need the reactions side\n walk(signal.reactions, 'reactions', null, t => addEdge(nodeId, t))\n }\n if (complete) for (const cid of this._instances.keys()) markupEdges(cid, null)\n // registered count (+ template nodes reached), minus nodes found\n // dead while building\n totalNodes = this._reactiveNodes.size + templates.size\n totalEdges = complete ? edgeSet.size : null\n truncated = !complete || edgesOmitted > 0\n }\n\n const nodes = []\n for (const nodeId of included) {\n const cid = templates.get(nodeId)\n if (cid !== undefined) {\n const instance = this._instances.get(cid)\n nodes.push({\n id: nodeId,\n type: 'template',\n name: '(template)',\n componentId: cid,\n componentFile: instance ? instance.file : '',\n })\n continue\n }\n const signal = liveSignal(nodeId)\n if (!signal) continue\n const node = this._graphNode(nodeId, this._reactiveNodes.get(nodeId), signal)\n if (untracked.has(nodeId)) node.untrackedDeps = untracked.get(nodeId)\n nodes.push(node)\n }\n return {\n scope: scoped ? componentId : null,\n nodes,\n edges,\n total: { nodes: totalNodes, nodesKind: 'registered', edges: totalEdges },\n truncated,\n edgesOmitted,\n policy: scoped ? 'scoped' : 'global-head',\n }\n },\n\n _graphCap(value, max) {\n const n = Math.floor(Number(value))\n return Number.isFinite(n) && n >= 1 ? Math.min(n, max) : max\n },\n\n // Whether a pull request names another page load (epoch): such a request\n // is not answered by this one.\n _otherEpoch(req) {\n return req.epoch !== undefined && req.epoch !== null && req.epoch !== this._epoch\n },\n\n // Request: { requestId?, epoch?, componentId?,\n // maxNodes?, maxEdges? }. The reply echoes requestId and epoch; {} asks\n // for the global graph with the default caps.\n sendReactiveGraph(request) {\n const req = request ?? {}\n if (this._otherEpoch(req)) return\n const cid = typeof req.componentId === 'number' ? req.componentId : null\n const graph = this.getReactiveGraph(cid, { maxNodes: req.maxNodes, maxEdges: req.maxEdges })\n graph.epoch = this._epoch\n // freshness: when this answer was built; caches keep it\n graph.computedAt = Date.now()\n if (req.requestId !== undefined) graph.requestId = req.requestId\n this._send('svelte-devtools:reactive-graph', graph)\n },\n\n // Overview aggregate. Built from the activity buckets of the\n // window (whole seconds: the current partial second plus the previous\n // ones, ceil(windowMs / 1000) buckets) — cost O(components active in the\n // window), no graph, no node scan. Rows rank by sampled changes, then\n // renders, then render ms; rows + other = total (components and nodes).\n getReactiveSummary(opts) {\n const o = opts ?? {}\n const topK = __clampInt(o.topK, 1, 200, 50)\n const windowMs = __clampInt(o.windowMs, 1000, 60000, 10000)\n const nowSec = Math.floor(performance.now() / 1000)\n const agg = new Map()\n let sampledMs = 0\n for (let k = 0; k < Math.ceil(windowMs / 1000); k++) {\n const sec = nowSec - k\n const b = this._activity[__slot(sec)]\n if (!b || b.second !== sec) continue\n sampledMs += b.sampledMs\n for (const [cid, r] of b.rows) {\n if (!this._scopeLive(cid)) continue\n let a = agg.get(cid)\n if (!a) {\n a = { changes: 0, renders: 0, renderMs: 0 }\n agg.set(cid, a)\n }\n a.changes += r.changes\n a.renders += r.renders\n a.renderMs += r.renderMs\n }\n }\n const ranked = [...agg].toSorted(\n (x, y) =>\n y[1].changes - x[1].changes ||\n y[1].renders - x[1].renders ||\n y[1].renderMs - x[1].renderMs ||\n x[0] - y[0],\n )\n let rowNodes = 0\n const rows = ranked.slice(0, topK).map(([cid, a]) => {\n const n = this._nodeCounts.get(cid) ?? { state: 0, derived: 0, effect: 0 }\n rowNodes += n.state + n.derived + n.effect\n const row = {\n componentId: cid,\n file: this._scopeFile(cid),\n nodes: { state: n.state, derived: n.derived, effect: n.effect },\n changes: a.changes,\n renders: a.renders,\n renderMs: Math.round(a.renderMs * 1000) / 1000,\n }\n // module scope (shared .svelte.js state), not a component instance\n if (this._modules.has(cid)) row.kind = 'module'\n return row\n })\n const t = this._nodeTotals\n // module scopes count as rows like components (rows + other = total)\n const scopes = this._instances.size + this._modules.size\n const until = Date.now()\n return {\n epoch: this._epoch,\n window: {\n ms: windowMs,\n since: until - windowMs,\n until,\n sampledActiveMs: Math.min(windowMs, sampledMs),\n },\n policy: 'sampled-200ms',\n coverage: 'component-init',\n components: { total: scopes, withActivity: agg.size },\n rows,\n other: {\n components: scopes - rows.length,\n nodes: t.state + t.derived + t.effect - rowNodes,\n },\n truncated: agg.size > topK,\n capabilities: { valueInspection: false, signalHistory: false, writeCause: false },\n // Seed coverage: changes of pending nodes are not observable yet.\n baseline: this._baselineInfo(),\n }\n },\n\n // Request { requestId?, epoch?, topK?, windowMs? } (same correlation as\n // the graph).\n sendReactiveSummary(request) {\n const req = request ?? {}\n if (this._otherEpoch(req)) return\n const summary = this.getReactiveSummary(req)\n if (req.requestId !== undefined) summary.requestId = req.requestId\n this._send('svelte-devtools:reactive-summary', summary)\n },\n\n // --- State timeline ---\n\n // Current value of a $state node: the signal value, or for tag_proxy\n // nodes (non-reassigned object/array state) the live proxy itself.\n // Returns a sentinel when the value can't be read.\n _readStateValue(nodeId, signal) {\n if (signal._isProxy) {\n const proxy = this._reactiveProxies.get(nodeId)?.deref()\n return proxy === undefined ? __NO_VALUE : proxy\n }\n const v = signal.v\n // Svelte's UNINITIALIZED marker is a symbol; functions aren't state data.\n return typeof v === 'symbol' || typeof v === 'function' ? __NO_VALUE : v\n },\n\n // Runs every 200 ms in the user's app, so it must stay cheap regardless of\n // how much state the app holds.\n // 1. Hint pass, time-sliced: at most HINT_NODES $state nodes per tick,\n // continuing from a cursor carried across ticks, so a full sweep over\n // n nodes takes ceil(n / HINT_NODES) ticks. Per node O(1):\n // primitives are compared directly and recorded at once; objects\n // whose reference or Svelte write version (wv) changed are added to\n // _pollDirty, which persists across ticks until serialized.\n // 2. Serialization work is limited to BUDGET_MS per tick (dirty nodes\n // carry over, nothing is dropped).\n // 3. In-place deep mutations (proxies don't bump an outer wv) are found by\n // time-based re-checks: each object is re-verified no earlier than\n // nextCheckAt = now + max(RECHECK_MS, 50 x its serialization cost),\n // paid from a DEEP_MS-per-tick credit, so the amortized cost is bounded\n // however many large states the app holds.\n // 4. Values serializing above MAX_SNAPSHOT_CHARS are kept as length+hash\n // (not the string) and appear in the timeline as a summary.\n // Writes between two visits of a node are observed as one change (the\n // timeline is a sample, policy 'sampled-200ms'; not counted as dropped).\n _pollStateValues(baseline) {\n const HINT_NODES = 4096\n const SWEEP_NODES = 2048\n const BUDGET_MS = 2\n const DEEP_MS = 0.5\n const now = performance.now()\n if (!baseline) {\n // nodes of destroyed {#each} items / effect runs leave the counts\n this._sweepNodes(SWEEP_NODES)\n this._deepCredit = Math.min(10 * DEEP_MS, this._deepCredit + DEEP_MS)\n // this tick samples 200 ms of wall time (window.sampledActiveMs)\n const bucket = this._bucket()\n bucket.sampledMs = Math.min(1000, bucket.sampledMs + 200)\n }\n const ids = this._pollIds\n const due = []\n const limit = Math.min(HINT_NODES, ids.length)\n for (let visited = 0; visited < limit && ids.length > 0; visited++) {\n if (this._pollCursor >= ids.length) {\n this._pollCursor = 0\n }\n const nodeId = ids[this._pollCursor]\n const entry = this._reactiveNodes.get(nodeId)\n if (entry?.meta.type !== 'state') {\n // re-tracked as another type: drop from the poll list (slot reused)\n this._pollRemove(nodeId)\n continue\n }\n if (!this._scopeLive(entry.meta.componentId)) {\n this._forgetNode(nodeId) // swaps the last id into this slot\n continue\n }\n this._pollCursor++\n const signal = entry.signal.deref()\n const value = signal ? this._readStateValue(nodeId, signal) : __NO_VALUE\n if (value === __NO_VALUE) {\n // nothing readable (collected, uninitialized, function): not pending\n this._unseeded.delete(nodeId)\n continue\n }\n if (value === null || typeof value !== 'object') {\n const had = this._stateSnapshots.has(nodeId)\n const prev = this._stateSnapshots.get(nodeId)\n if (had && Object.is(prev, value)) continue\n // Forget the object key so object -> primitive -> same object again\n // is still recorded as a change.\n this._stateSnapshotStrs.delete(nodeId)\n this._pollDirty.delete(nodeId)\n if (!had) {\n // first observation: seed only\n this._stateSnapshots.set(nodeId, value)\n this._unseeded.delete(nodeId)\n continue\n }\n this._recordChange(\n nodeId,\n entry,\n prev,\n value,\n typeof value === 'string' ? 2 * value.length : 64,\n )\n continue\n }\n let meta = this._pollMeta.get(nodeId)\n if (!meta) {\n meta = { ref: undefined, wv: undefined, nextCheckAt: 0 }\n this._pollMeta.set(nodeId, meta)\n }\n if (meta.ref !== value || meta.wv !== signal.wv) this._pollDirty.add(nodeId)\n else if (now >= meta.nextCheckAt) due.push(nodeId)\n }\n const start = performance.now()\n for (const nodeId of this._pollDirty) {\n if (performance.now() - start > BUDGET_MS) return\n this._pollDirty.delete(nodeId)\n this._serializeNode(nodeId, false)\n }\n for (const nodeId of due) {\n if (this._deepCredit <= 0 || performance.now() - start > BUDGET_MS) return\n this._serializeNode(nodeId, true)\n }\n },\n\n // Activation (late consumer): nodes registered while inactive have no\n // seed yet, so a write before their first visit could not be seen as a\n // change. The first slice is seeded at activation instead of 200 ms later:\n // ONE normal pass (<= HINT_NODES nodes, the per-tick serialization budget;\n // the rest follow on the usual ticks). Seeds record nothing; readiness is\n // disclosed in the summary as baseline { complete, pendingNodes }.\n _pollBaseline() {\n this._baselining = true\n try {\n this._pollStateValues(true)\n } catch {\n /* never break activation */\n } finally {\n this._baselining = false\n }\n },\n\n _serializeNode(nodeId, deep) {\n const MAX_SNAPSHOT_CHARS = 32768\n const RECHECK_MS = 1000\n const entry = this._reactiveNodes.get(nodeId)\n const meta = this._pollMeta.get(nodeId)\n if (!entry || !meta) return\n const signal = entry.signal.deref()\n if (!signal) return\n const value = this._readStateValue(nodeId, signal)\n if (value === __NO_VALUE || value === null || typeof value !== 'object') return\n try {\n const t0 = performance.now()\n const str = JSON.stringify(value)\n const cost = performance.now() - t0\n if (deep) this._deepCredit -= cost\n meta.ref = value\n meta.wv = signal.wv\n meta.nextCheckAt = t0 + Math.max(RECHECK_MS, 50 * cost)\n // Small values keep the string (exact compare); large ones only a\n // length+hash so a 5 MB array doesn't pin 5 MB per node.\n // (toJSON may return undefined: no JSON at all)\n const tooLarge = str !== undefined && str.length > MAX_SNAPSHOT_CHARS\n const key = str === undefined ? '' : tooLarge ? str.length + ':' + __hash(str) : str\n if (this._stateSnapshotStrs.get(nodeId) === key) return\n this._stateSnapshotStrs.set(nodeId, key)\n let snapshot = null\n let size = 64\n if (tooLarge) {\n snapshot = '(object: ' + str.length + ' chars, too large to snapshot)'\n } else if (str !== undefined) {\n snapshot = JSON.parse(str)\n size = str.length\n }\n if (!this._stateSnapshots.has(nodeId)) {\n // first observation: seed only (no entry, no counters)\n this._stateSnapshots.set(nodeId, snapshot)\n this._lastSnapshotSize.set(nodeId, size)\n this._unseeded.delete(nodeId)\n return\n }\n if (tooLarge) this._valueTooLarge++\n const prev = this._stateSnapshots.get(nodeId)\n this._recordChange(\n nodeId,\n entry,\n prev,\n snapshot,\n size + (this._lastSnapshotSize.get(nodeId) ?? 0),\n )\n this._lastSnapshotSize.set(nodeId, size)\n } catch {\n // non-serializable (cycles, BigInt): never observable, so not pending\n this._unseeded.delete(nodeId)\n }\n },\n\n _recordChange(nodeId, entry, oldValue, newValue, approxBytes) {\n const change = {\n id: nodeId,\n name: entry.meta.name,\n componentFile: entry.meta.componentFile,\n oldValue,\n newValue,\n timestamp: Date.now(),\n }\n // 0 (an empty string) or no estimate: assume a small value.\n const bytes = (approxBytes > 0 ? approxBytes : 64) + 192\n // seq stays runtime-internal: the server assigns its own seq.\n this._entryInfo.set(change, { seq: ++this._timelineSeq, bytes })\n this._stateTimeline.push(change)\n this._timelineBytes += bytes\n // sampled change count: independent of the ring\n this._activityRow(entry.meta.componentId).changes++\n this._stateSnapshots.set(nodeId, newValue)\n // The ring (_trimTimeline) is applied in bulk, not with one splice per\n // change (a poll tick can record thousands): before every read (each\n // push — with a hot channel and an active consumer, at least every 200\n // changes — the full snapshot, getStateTimeline() and clear), and here\n // once more than __TIMELINE_TRIM_AT entries are held or the byte budget\n // is exceeded, which bounds memory when nothing reads or pushes.\n if (\n this._stateTimeline.length > __TIMELINE_TRIM_AT ||\n this._timelineBytes > __TIMELINE_BYTES\n ) {\n this._trimTimeline()\n }\n this._scheduleTimelineUpdate()\n },\n\n // Ring: at most 500 entries and __TIMELINE_BYTES (the newest entry is\n // always kept). Removed entries that were never pushed are disclosed\n // as dropped; pushed ones are already on the server.\n _trimTimeline() {\n const all = this._stateTimeline\n let cut = 0\n let bytesLeft = this._timelineBytes\n while (cut < all.length - 1 && (all.length - cut > 500 || bytesLeft > __TIMELINE_BYTES)) {\n const info = this._entryInfo.get(all[cut])\n const reason = all.length - cut > 500 ? 'runtime-count' : 'runtime-bytes'\n if (info.seq > this._pushedSeq) this._timelineDropped[reason]++\n bytesLeft -= info.bytes\n cut++\n }\n if (cut > 0) {\n all.splice(0, cut)\n this._timelineBytes = bytesLeft\n }\n },\n\n // Push: a throttle, not a debounce — a pending timer is never\n // re-armed, so unsent entries leave within 300 ms of the first one even\n // under continuous change — plus an immediate flush once 200 entries\n // (one message) are unsent, since one poll tick can record thousands.\n _scheduleTimelineUpdate() {\n if (!this._active || this._baselining) return\n if (this._timelineSeq - this._pushedSeq >= 200) {\n this._flushTimeline()\n return\n }\n if (this._timelineDebounceTimer) return\n this._timelineDebounceTimer = setTimeout(() => {\n this._timelineDebounceTimer = null\n this._flushTimeline()\n }, 300)\n },\n\n _flushTimeline() {\n if (this._timelineDebounceTimer) {\n clearTimeout(this._timelineDebounceTimer)\n this._timelineDebounceTimer = null\n }\n if (!import.meta.hot) return\n for (const msg of this._timelineDeltas()) {\n import.meta.hot.send('svelte-devtools:state-timeline', msg)\n }\n },\n\n // Disclosure counters since the previous push, attached to (and reset\n // by) the next message: dropped [{ reason, count }] and valueTooLarge.\n _takeTimelineDisclosure(msg) {\n msg.baseline = this._baselineInfo()\n this._sentPendingNodes = msg.baseline.pendingNodes\n const dropped = []\n for (const reason of ['runtime-count', 'runtime-bytes']) {\n const count = this._timelineDropped[reason]\n if (count > 0) dropped.push({ reason, count })\n this._timelineDropped[reason] = 0\n }\n if (dropped.length > 0) msg.dropped = dropped\n if (this._valueTooLarge > 0) msg.valueTooLarge = this._valueTooLarge\n this._valueTooLarge = 0\n return msg\n },\n\n // Seed coverage, on every state-timeline message and the\n // summary: pendingNodes = polled $state nodes without a first sample;\n // their writes are not observable yet.\n _baselineInfo() {\n return { complete: this._unseeded.size === 0, pendingNodes: this._unseeded.size }\n },\n\n _hasTimelineDisclosure() {\n return (\n this._sentPendingNodes !== this._unseeded.size ||\n this._timelineDropped['runtime-count'] > 0 ||\n this._timelineDropped['runtime-bytes'] > 0 ||\n this._valueTooLarge > 0\n )\n },\n\n // Delta push: only entries recorded\n // since the previous push, ≤ 200 per message, tagged with a per-page-load\n // epoch; reset after clearStateTimeline(). A message with no changes is\n // still sent when there is something to disclose (all unsent dropped).\n _timelineDeltas() {\n this._trimTimeline()\n const all = this._stateTimeline\n let start = all.length\n while (start > 0 && this._entryInfo.get(all[start - 1]).seq > this._pushedSeq) start--\n const pending = all.slice(start)\n const msgs = []\n const first = this._timelineReset || this._hasTimelineDisclosure()\n // A first message goes out even with no pending changes (disclosure only).\n const end = first ? Math.max(pending.length, 1) : pending.length\n for (let i = 0; i < end; i += 200) {\n const msg = { epoch: this._epoch, changes: pending.slice(i, i + 200) }\n if (i === 0 && this._timelineReset) msg.reset = true\n if (i === 0) this._takeTimelineDisclosure(msg)\n else msg.baseline = this._baselineInfo()\n msgs.push(msg)\n }\n this._timelineReset = false\n this._pushedSeq = this._timelineSeq\n return msgs\n },\n\n // Full buffer (reset: true) — reply to request-state-timeline and the\n // activation snapshot. Newest entries first up to __TIMELINE_BYTES, the\n // server's own buffer budget, so nothing is sent that it would drop.\n _timelineFull() {\n this._trimTimeline()\n const all = this._stateTimeline\n let start = all.length\n let bytes = 0\n while (start > 0) {\n const size = this._entryInfo.get(all[start - 1]).bytes\n if (bytes + size > __TIMELINE_BYTES && start < all.length) break\n bytes += size\n start--\n }\n this._timelineReset = false\n this._pushedSeq = this._timelineSeq\n return this._takeTimelineDisclosure({\n epoch: this._epoch,\n changes: all.slice(start),\n reset: true,\n })\n },\n\n getStateTimeline() {\n this._trimTimeline()\n return this._stateTimeline\n },\n\n clearStateTimeline() {\n // Ring first: unsent entries past the cap are disclosed as dropped,\n // exactly as if they had been removed when recorded.\n this._trimTimeline()\n this._stateTimeline = []\n this._timelineBytes = 0\n this._pushedSeq = this._timelineSeq\n this._timelineReset = true\n this._scheduleTimelineUpdate()\n },\n\n _send(event, data) {\n if (import.meta.hot) import.meta.hot.send(event, data)\n },\n\n // --- FPS monitoring ---\n // Uses requestAnimationFrame to measure frame rate with minimal overhead.\n // Only stores timestamps - no allocations per frame beyond a single array push.\n _fpsFrameTimes: [],\n\n _fpsLoop(gen) {\n if (gen !== this._fpsGen) return\n this._fpsFrameTimes.push(performance.now())\n requestAnimationFrame(() => this._fpsLoop(gen))\n },\n\n _isVisible() {\n if (typeof document === 'undefined') return true\n return document.visibilityState !== 'hidden'\n },\n\n _setSubscription(data) {\n const wasActive = this._active\n this._active = !!data?.active\n this._componentDeltas = !!data?.componentDeltas\n if (!this._active) {\n this._pendingAdded.clear()\n this._pendingRemoved.clear()\n }\n // resync: the server holds no full base for this epoch, or we reconnected to a possibly restarted server.\n const resync = this._resync || !!data?.resync\n this._resync = false\n if (this._active && !wasActive) this._pollBaseline()\n if (this._active && (!wasActive || resync)) {\n // Collector state may be stale or empty (first activation, resync, or a\n // reconnect to a possibly restarted server): resend everything once, in\n // the order components -> profiles -> timeline(reset: true); the\n // reset push marks the activation snapshot complete.\n this._sendUpdate(true)\n this._sendProfileUpdate()\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:state-timeline', this._timelineFull())\n }\n }\n this._syncSampling()\n },\n\n // Sampling (state poll + FPS) runs only while active AND the app tab is\n // visible.\n _syncSampling() {\n const want = this._active && this._isVisible()\n if (want && !this._sampling) {\n this._fpsFrameTimes = []\n const gen = ++this._fpsGen\n this._sampling = {\n poll: setInterval(() => {\n this._pollStateValues()\n // seed progress changed: push it even without changes (B-2)\n if (this._sentPendingNodes !== this._unseeded.size) this._scheduleTimelineUpdate()\n }, 200),\n fps: setInterval(() => {\n this._sampleFps()\n }, 500),\n }\n requestAnimationFrame(() => this._fpsLoop(gen))\n } else if (!want && this._sampling) {\n clearInterval(this._sampling.poll)\n clearInterval(this._sampling.fps)\n this._sampling = null\n this._fpsGen++\n this._fpsFrameTimes = []\n }\n },\n\n _sampleFps() {\n const now = performance.now()\n // Remove frame timestamps older than 1 second\n const cutoff = now - 1000\n let i = 0\n while (i < this._fpsFrameTimes.length && this._fpsFrameTimes[i] < cutoff) i++\n if (i > 0) this._fpsFrameTimes.splice(0, i)\n const fps = this._fpsFrameTimes.length\n this._send('svelte-devtools:fps', { timestamp: Date.now(), fps })\n },\n }\n\n window.__SVELTE_DEVTOOLS__ = __SVELTE_DT\n\n // State polling and FPS sampling start on the server's subscription\n // message and pause while the app tab is hidden.\n if (typeof document !== 'undefined' && typeof document.addEventListener === 'function') {\n document.addEventListener('visibilitychange', () => __SVELTE_DT._syncSampling())\n }\n\n // Runtime errors\n window.addEventListener('error', event => {\n __SVELTE_DT._send('svelte-devtools:runtime-error', {\n message: event.message,\n file: event.filename,\n line: event.lineno,\n column: event.colno,\n stack: event.error?.stack ?? '',\n timestamp: Date.now(),\n })\n })\n window.addEventListener('unhandledrejection', event => {\n const reason = event.reason\n const message = reason?.message\n const stack = reason?.stack\n __SVELTE_DT._send('svelte-devtools:runtime-error', {\n // No (or an empty / non-string) message: the stringified reason.\n message: typeof message === 'string' && message !== '' ? message : __describe(reason),\n stack: typeof stack === 'string' ? stack : '',\n timestamp: Date.now(),\n })\n })\n\n // Pull requests from the server are answered regardless of the\n // subscription state.\n if (import.meta.hot) {\n import.meta.hot.on('svelte-devtools:subscription', data => {\n __SVELTE_DT._setSubscription(data)\n })\n import.meta.hot.on('vite:ws:connect', () => {\n // The server may have restarted with an empty collector: the reply to\n // runtime-ready is treated as a fresh activation (full snapshot).\n __SVELTE_DT._resync = true\n import.meta.hot.send('svelte-devtools:runtime-ready', {})\n })\n import.meta.hot.send('svelte-devtools:runtime-ready', {})\n import.meta.hot.on('svelte-devtools:request-reactive-graph', data => {\n __SVELTE_DT.sendReactiveGraph(data)\n })\n import.meta.hot.on('svelte-devtools:request-reactive-summary', data => {\n __SVELTE_DT.sendReactiveSummary(data)\n })\n import.meta.hot.on('svelte-devtools:request-state-timeline', () => {\n import.meta.hot.send('svelte-devtools:state-timeline', __SVELTE_DT._timelineFull())\n })\n import.meta.hot.on('svelte-devtools:clear-state-timeline', () => {\n __SVELTE_DT.clearStateTimeline()\n })\n }\n}\n", nt = "import * as __svelte_original from 'svelte/internal/client'\nexport * from 'svelte/internal/client'\n\nfunction __dt() {\n return typeof window === 'undefined' ? null : window.__SVELTE_DEVTOOLS__\n}\n\n// Component ID stack (parallel to runtime._stack but local to wrapper)\nconst __idStack = []\nfunction __currentId() {\n return __idStack.length > 0 ? __idStack.at(-1) : null\n}\n\n// Tracks the most recently created signal for type determination in tag()\nconst __pendingSignal = { ref: null, type: null }\n\n// Component context -> devtools id. A component created later\n// by a block update ({#each}/{#if} after mount) runs outside its parent's\n// push..pop, where the runtime's init stack is empty (the wrapper stack\n// below covers the wrapped block helpers; this covers the rest). Svelte (5.56.8,\n// internal/client) exports active_effect; every effect records the\n// component context it was created in (effect.ctx) and runs with that\n// context restored. The block effect that creates the child belongs to the\n// parent's template, so active_effect.ctx at push time IS the parent's\n// context. Each context is mapped to its id once the component mounted\n// (inside its own deferred effect, where active_effect.ctx is the\n// component's own context). The map lives on the runtime (dt._idByContext)\n// so the reactive graph can name the component of any effect it reaches.\n// Weak map: no leak, no Svelte state touched.\nfunction __parentFromContext() {\n const dt = __dt()\n const effect = __svelte_original.active_effect\n const ctx = effect ? effect.ctx : null\n return dt && ctx && dt._idByContext ? dt._idByContext.get(ctx) : undefined\n}\n\n// Owner of a signal/effect created right now: the component whose init (or\n// wrapped block callback) is running, else — outside init, e.g. an effect\n// created while another effect runs — the component of the active effect.\nfunction __owner() {\n const cid = __currentId()\n if (cid !== null) return cid\n const fromContext = __parentFromContext()\n return fromContext === undefined ? null : fromContext\n}\n\n// --- Component Lifecycle ---\n//\n// Observer must not break the observed: every devtools side-effect below is\n// wrapped in try/catch so a bug or an out-of-shape runtime cannot tear down\n// the user's app. The original Svelte function is always called, and its\n// return value always returned, regardless of devtools failures.\n\nexport function push() {\n // Parent hint, read before this component's own id exists:\n // 1. the wrapper stack: the component whose init is running (children\n // rendered directly by a template, where active_effect still belongs to\n // an outer block), or the block owner re-pushed by __wrapBlockFn for a\n // later {#each}/{#if}/{#key} update (see Block Attribution below);\n // 2. else the context-derived owner, for re-creation paths the wrapper\n // does not wrap (snippet, svelte:element, ...).\n let parentHint = null\n try {\n parentHint = __currentId()\n } catch {}\n if (parentHint === null) {\n try {\n parentHint = __parentFromContext()\n } catch {}\n }\n const result = __svelte_original.push.apply(null, arguments)\n try {\n const dt = __dt()\n if (dt) {\n const file = dt._pendingFile ?? 'Unknown'\n dt._pendingFile = null\n dt._pendingParent = parentHint\n const id = dt.register(file)\n __idStack.push(id)\n dt.startInit(id)\n try {\n __svelte_original.user_effect(() => {\n try {\n const own = __svelte_original.active_effect\n if (own?.ctx) dt._idByContext.set(own.ctx, id)\n if (own) dt.setComponentEffect(id, own)\n } catch {}\n return () => {\n try {\n dt.unmount(id)\n } catch {}\n }\n })\n } catch {}\n }\n } catch {}\n return result\n}\n\nexport function pop() {\n // Capture devtools errors but ALWAYS forward to the original pop so the\n // Svelte component stack stays balanced.\n try {\n const dt = __dt()\n if (dt && __idStack.length > 0) {\n const id = __idStack.pop()\n try {\n dt.endInit(id)\n } catch {}\n try {\n dt.registered(id)\n } catch {}\n }\n } catch {}\n return __svelte_original.pop.apply(null, arguments)\n}\n\n// --- Signal Creation (type markers) ---\n\n// The created signal/proxy is remembered with its type for the tag() call\n// the compiler (dev) emits right after it.\nfunction __marking(original, type) {\n return function () {\n const signal = original.apply(null, arguments)\n __pendingSignal.ref = signal\n __pendingSignal.type = type\n return signal\n }\n}\n\nexport const state = __marking(__svelte_original.state, 'state')\nexport const derived = __marking(__svelte_original.derived, 'derived')\nexport const proxy = __marking(__svelte_original.proxy, 'proxy')\n\n// --- Signal Tagging (Svelte dev mode) ---\n\nexport function tag(signal, name) {\n const result = __svelte_original.tag.apply(null, arguments)\n try {\n const dt = __dt()\n const cid = __owner()\n const type = __pendingSignal.ref === signal ? __pendingSignal.type : 'state'\n if (dt && cid !== null) {\n const owner = __svelte_original.active_effect\n if (type === 'derived') {\n dt.trackDerived(signal, name, cid, owner)\n } else {\n dt.trackState(signal, name, cid, owner)\n }\n } else if (dt?._moduleFile) {\n // created while a .svelte.js/.ts module body runs (shared state)\n dt.trackModuleSignal(type === 'derived' ? 'derived' : 'state', signal, name)\n }\n __pendingSignal.ref = null\n __pendingSignal.type = null\n } catch {}\n return result\n}\n\nexport function tag_proxy(value, name) {\n const result = __svelte_original.tag_proxy.apply(null, arguments)\n try {\n const dt = __dt()\n const cid = __owner()\n if (dt && cid !== null) {\n dt.trackProxy(value, name, cid, __svelte_original.active_effect)\n } else if (dt?._moduleFile) {\n dt.trackModuleSignal('proxy', value, name)\n }\n __pendingSignal.ref = null\n __pendingSignal.type = null\n } catch {}\n return result\n}\n\n// --- Effect Tracking ---\n//\n// A top-level $effect in a component is deferred by Svelte until mount:\n// user_effect() returns undefined and the effect object is created later,\n// in pop(). So the node is registered now (named per component) and bound\n// to the real effect object on its first run, where active_effect IS the\n// effect; the Svelte runtime then keeps effect.deps current, which is what\n// getReactiveGraph() reads to build edges. The wrapped callback forwards\n// this, arguments and the return value (teardown) unchanged.\n\nfunction __trackUserEffect(original, kind, args) {\n let cid = null\n let dt = null\n let fn = null\n try {\n dt = __dt()\n fn = args[0]\n if (dt && typeof fn === 'function') cid = __owner()\n } catch {}\n if (cid === null) return original.apply(null, args)\n let nodeId = null\n let bound = false\n const wrapped = Array.prototype.slice.call(args)\n wrapped[0] = function () {\n if (!bound) {\n bound = true\n try {\n dt.bindEffect(nodeId, __svelte_original.active_effect)\n } catch {}\n }\n return fn.apply(this, arguments)\n }\n try {\n nodeId = dt.trackUserEffect(kind, cid, __svelte_original.active_effect)\n } catch {}\n const result = original.apply(null, wrapped)\n if (result && !bound) {\n bound = true\n try {\n dt.bindEffect(nodeId, result)\n } catch {}\n }\n return result\n}\n\nexport function user_effect() {\n return __trackUserEffect(__svelte_original.user_effect, 'effect', arguments)\n}\n\nexport function user_pre_effect() {\n return __trackUserEffect(__svelte_original.user_pre_effect, 'effect_pre', arguments)\n}\n\n// --- Render Profiling ---\n//\n// Svelte 5 has no virtual DOM: the compiler wraps every dynamic part of a\n// template in a template_effect (deferred_template_effect for <svelte:head>\n// <title>). A re-run of such an effect IS the component updating the DOM, so\n// these two functions are the measurement points for renders / render time.\n//\n// The first run of an effect is the mount-time paint, already covered by\n// initTime, so it is skipped (initialRun). One state change re-runs several\n// effects of the same component, so durations are pooled per microtask and\n// recorded once per flush: recordRender() +1, recordRenderTime() the sum.\n\nconst __pendingRenderDurations = new Map()\nlet __renderFlushScheduled = false\n\nfunction __flushRenderDurations() {\n __renderFlushScheduled = false\n const dt = __dt()\n if (dt) {\n for (const [cid, duration] of __pendingRenderDurations) {\n try {\n dt.recordRender(cid)\n } catch {}\n try {\n dt.recordRenderTime(cid, duration)\n } catch {}\n }\n }\n __pendingRenderDurations.clear()\n}\n\nfunction __recordRenderDuration(cid, duration) {\n __pendingRenderDurations.set(cid, (__pendingRenderDurations.get(cid) ?? 0) + duration)\n if (!__renderFlushScheduled) {\n __renderFlushScheduled = true\n queueMicrotask(__flushRenderDurations)\n }\n}\n\n// Returns a (possibly new) args array whose first element times each re-run\n// of the effect closure. The owning component is whatever id is on top of\n// __idStack at effect-creation time. User exceptions propagate untouched;\n// only the args are built inside try so the original is called exactly once.\nfunction __wrapTemplateEffect(args) {\n const cid = __owner()\n const fn = args[0]\n if (cid === null || typeof fn !== 'function') return args\n const wrapped = Array.prototype.slice.call(args)\n let initialRun = true\n wrapped[0] = function () {\n if (initialRun) {\n initialRun = false\n return fn.apply(this, arguments)\n }\n const start = performance.now()\n try {\n return fn.apply(this, arguments)\n } finally {\n try {\n __recordRenderDuration(cid, performance.now() - start)\n } catch {}\n }\n }\n return wrapped\n}\n\n// `original` called with the arguments rewritten by `wrapArgs`, or with the\n// original arguments when rewriting fails.\nfunction __withArgs(original, wrapArgs) {\n return function () {\n let args = arguments\n try {\n args = wrapArgs(arguments)\n } catch {}\n return original.apply(null, args)\n }\n}\n\nexport const template_effect = __withArgs(__svelte_original.template_effect, __wrapTemplateEffect)\nexport const deferred_template_effect = __withArgs(\n __svelte_original.deferred_template_effect,\n __wrapTemplateEffect,\n)\n\n// --- Block Attribution ---\n//\n// Svelte creates render effects synchronously at creation time. At mount this\n// happens during the component function (between push/pop), so __idStack has\n// the owner. But effects for {#each} items added later or re-created {#if}\n// branches are created during a batch flush, when the stack is empty — they\n// would never be attributed. Block helpers themselves ARE always called\n// during their owner's init (or inside an outer block's callback), so the\n// owner id is on the stack at block-creation time. __wrapBlock captures it\n// and re-pushes it around every function argument the block invokes later,\n// so effects created inside land on the innermost owner. Child components\n// push their own id on top, keeping nested attribution correct.\n\n// A component whose init throws (caught by <svelte:boundary>, or by the\n// block's caller) never reaches pop(): its id would stay on both stacks and\n// every later signal/child would be attributed to it. On the way out — normal\n// or thrown — the stack is cut back to its depth on entry, and ids left\n// above it are dropped as aborted inits (registered, never mounted).\nfunction __wrapBlockFn(fn, cid) {\n return function () {\n let depth = -1\n try {\n depth = __idStack.length\n __idStack.push(cid)\n } catch {}\n try {\n return fn.apply(this, arguments)\n } finally {\n if (depth !== -1) {\n try {\n if (__idStack.length > depth + 1) {\n const dt = __dt()\n const aborted = __idStack.slice(depth + 1)\n for (let i = aborted.length - 1; i >= 0; i--) {\n try {\n if (dt) dt.abortInit(aborted[i])\n } catch {}\n }\n }\n __idStack.length = depth\n } catch {}\n }\n }\n }\n}\n\nfunction __wrapBlock(args) {\n const cid = __owner()\n if (cid === null) return args\n const wrapped = Array.prototype.slice.call(args)\n for (let i = 0; i < wrapped.length; i++) {\n if (typeof wrapped[i] === 'function') wrapped[i] = __wrapBlockFn(wrapped[i], cid)\n }\n return wrapped\n}\n\nexport const each = __withArgs(__svelte_original.each, __wrapBlock)\nexport const key = __withArgs(__svelte_original.key, __wrapBlock)\nexport const component = __withArgs(__svelte_original.component, __wrapBlock)\nexport const boundary = __withArgs(__svelte_original.boundary, __wrapBlock)\n// 'if' and 'await' are reserved words: exported via aliases.\nconst __if_block = __withArgs(__svelte_original.if, __wrapBlock)\nconst __await_block = __withArgs(__svelte_original.await, __wrapBlock)\n\nexport { __if_block as if, __await_block as await }\n", rt = "virtual:svelte-devtools-runtime", it = "\0virtual:svelte-devtools-runtime", at = "\0svelte-devtools:wrapped-client", ot = nt, st = tt, ct = "$.push($$props";
|
|
980
|
+
function lt(e) {
|
|
981
|
+
let t = e.indexOf(ct);
|
|
982
|
+
if (t === -1) return -1;
|
|
983
|
+
if (!e.includes(ct, t + 14)) {
|
|
984
|
+
let n = e[t + 14];
|
|
985
|
+
return ut(e, t) && (n === "," || n === ")") ? t : -1;
|
|
986
|
+
}
|
|
987
|
+
return dt(e);
|
|
988
|
+
}
|
|
989
|
+
function ut(e, t) {
|
|
990
|
+
let n = t - 1;
|
|
991
|
+
for (; n >= 0 && (e[n] === " " || e[n] === " ");) n--;
|
|
992
|
+
return n === -1 || e[n] === "\n";
|
|
993
|
+
}
|
|
994
|
+
function dt(e) {
|
|
995
|
+
let { program: t, errors: n } = a("component.js", e);
|
|
996
|
+
if (n.length > 0) return -1;
|
|
997
|
+
let r = -1;
|
|
998
|
+
return new i({ ExpressionStatement(e) {
|
|
999
|
+
pt(e.expression) && (r === -1 || e.start < r) && (r = e.start);
|
|
1000
|
+
} }).visit(t), r;
|
|
1001
|
+
}
|
|
1002
|
+
function ft(e, t) {
|
|
1003
|
+
return e?.type === "Identifier" && e.name === t;
|
|
1004
|
+
}
|
|
1005
|
+
function pt(e) {
|
|
1006
|
+
return e.type === "CallExpression" && e.callee.type === "MemberExpression" && !e.callee.computed && ft(e.callee.object, "$") && ft(e.callee.property, "push") && ft(e.arguments[0], "$$props");
|
|
1007
|
+
}
|
|
1008
|
+
function mt(e, t) {
|
|
1009
|
+
let n = lt(e);
|
|
1010
|
+
if (n === -1) return null;
|
|
1011
|
+
let r = `if (typeof window !== 'undefined' && window.__SVELTE_DEVTOOLS__) { window.__SVELTE_DEVTOOLS__._pendingFile = ${JSON.stringify(t)}; } `;
|
|
1012
|
+
return `import '${rt}';` + e.slice(0, n) + r + e.slice(n);
|
|
867
1013
|
}
|
|
868
|
-
var
|
|
869
|
-
|
|
1014
|
+
var ht = [
|
|
1015
|
+
"js",
|
|
1016
|
+
"ts",
|
|
1017
|
+
"mjs",
|
|
1018
|
+
"mts",
|
|
1019
|
+
"cjs",
|
|
1020
|
+
"cts"
|
|
1021
|
+
].map((e) => `.svelte.${e}`);
|
|
1022
|
+
function gt(e) {
|
|
1023
|
+
return ht.some((t) => e.endsWith(t));
|
|
1024
|
+
}
|
|
1025
|
+
function _t(e, t) {
|
|
870
1026
|
if (e.includes("svelte/internal/server")) return null;
|
|
871
1027
|
let n = JSON.stringify(t), r = "(typeof window !== 'undefined' && window.__SVELTE_DEVTOOLS__)";
|
|
872
|
-
return `import '${
|
|
1028
|
+
return `import '${rt}';if (${r}) { window.__SVELTE_DEVTOOLS__._enterModule(${n}); }` + e + `\n;if (${r}) { window.__SVELTE_DEVTOOLS__._leaveModule(); }\n`;
|
|
1029
|
+
}
|
|
1030
|
+
//#endregion
|
|
1031
|
+
//#region src/server/payload.ts
|
|
1032
|
+
function P(e) {
|
|
1033
|
+
return typeof e == "object" && e && !Array.isArray(e) ? e : void 0;
|
|
1034
|
+
}
|
|
1035
|
+
function F(e, t, n, r) {
|
|
1036
|
+
return typeof e != "number" || !Number.isFinite(e) ? r : Math.min(n, Math.max(t, Math.trunc(e)));
|
|
1037
|
+
}
|
|
1038
|
+
function I(e) {
|
|
1039
|
+
return F(e, 0, 2 ** 53 - 1, 0);
|
|
1040
|
+
}
|
|
1041
|
+
function vt(e) {
|
|
1042
|
+
return typeof e == "number" && Number.isFinite(e) ? e : null;
|
|
1043
|
+
}
|
|
1044
|
+
function L(e) {
|
|
1045
|
+
return Array.isArray(e) ? e : [];
|
|
1046
|
+
}
|
|
1047
|
+
var R = "(legacy)", yt = Date.now() * 1e3, z = () => ++yt, bt = [
|
|
1048
|
+
"runtime-count",
|
|
1049
|
+
"runtime-bytes",
|
|
1050
|
+
"server-count",
|
|
1051
|
+
"server-bytes"
|
|
1052
|
+
];
|
|
1053
|
+
function xt(e) {
|
|
1054
|
+
let t = e;
|
|
1055
|
+
return !!t && typeof t.complete == "boolean" && Number.isInteger(t.pendingNodes) && t.pendingNodes >= 0;
|
|
1056
|
+
}
|
|
1057
|
+
var St = class {
|
|
1058
|
+
stored = [];
|
|
1059
|
+
entriesCache;
|
|
1060
|
+
bytes = 0;
|
|
1061
|
+
seq = z();
|
|
1062
|
+
resetAt = this.seq;
|
|
1063
|
+
trimmedAt = this.seq;
|
|
1064
|
+
drops = /* @__PURE__ */ new Map();
|
|
1065
|
+
tooLarge = /* @__PURE__ */ new Map();
|
|
1066
|
+
baselines = /* @__PURE__ */ new Map();
|
|
1067
|
+
onChange;
|
|
1068
|
+
constructor(e) {
|
|
1069
|
+
this.onChange = e;
|
|
1070
|
+
}
|
|
1071
|
+
get entries() {
|
|
1072
|
+
return this.entriesCache ??= this.stored.map((e) => e.entry);
|
|
1073
|
+
}
|
|
1074
|
+
ingest(e) {
|
|
1075
|
+
let t = L(e?.changes).slice(-500);
|
|
1076
|
+
if (typeof e?.epoch != "string") {
|
|
1077
|
+
this.appendLegacy(t);
|
|
1078
|
+
return;
|
|
1079
|
+
}
|
|
1080
|
+
let n = e.epoch;
|
|
1081
|
+
if (this.countRuntimeLosses(n, e.dropped, e.valueTooLarge), e.reset === !0 && this.dropEpoch(n), this.append(t, n), xt(e.baseline)) {
|
|
1082
|
+
let { complete: t, pendingNodes: r } = e.baseline;
|
|
1083
|
+
this.baselines.set(n, {
|
|
1084
|
+
complete: t,
|
|
1085
|
+
pendingNodes: r
|
|
1086
|
+
});
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
appendLegacy(e) {
|
|
1090
|
+
let t = this.stored.findLast((e) => e.epoch === R)?.entry, n = t ? e.findLastIndex((e) => e.timestamp === t.timestamp && e.id === t.id) : -1;
|
|
1091
|
+
n === -1 && this.dropEpoch(R), this.append(e.slice(n + 1), R);
|
|
1092
|
+
}
|
|
1093
|
+
delta(e) {
|
|
1094
|
+
let t = this.seq;
|
|
1095
|
+
if (e === void 0 || e < this.resetAt || e < this.trimmedAt || e > t) return {
|
|
1096
|
+
cursor: t,
|
|
1097
|
+
reset: !0,
|
|
1098
|
+
changes: this.entries
|
|
1099
|
+
};
|
|
1100
|
+
let n = this.stored.length;
|
|
1101
|
+
for (; n > 0 && this.stored[n - 1].entry.seq > e;) n--;
|
|
1102
|
+
return {
|
|
1103
|
+
cursor: t,
|
|
1104
|
+
reset: !1,
|
|
1105
|
+
changes: this.stored.slice(n).map((e) => e.entry)
|
|
1106
|
+
};
|
|
1107
|
+
}
|
|
1108
|
+
dropEpoch(e) {
|
|
1109
|
+
this.stored.some((t) => t.epoch === e) && (this.stored = this.stored.filter((t) => t.epoch !== e), this.bytes = this.stored.reduce((e, t) => e + t.size, 0), this.markReset());
|
|
1110
|
+
}
|
|
1111
|
+
forget(e) {
|
|
1112
|
+
this.dropEpoch(e), this.drops.delete(e), this.tooLarge.delete(e), this.baselines.delete(e);
|
|
1113
|
+
}
|
|
1114
|
+
clear() {
|
|
1115
|
+
this.stored = [], this.bytes = 0, this.drops.clear(), this.tooLarge.clear(), this.markReset();
|
|
1116
|
+
}
|
|
1117
|
+
captureInfo(e) {
|
|
1118
|
+
let t = {
|
|
1119
|
+
"runtime-count": 0,
|
|
1120
|
+
"runtime-bytes": 0,
|
|
1121
|
+
"server-count": 0,
|
|
1122
|
+
"server-bytes": 0
|
|
1123
|
+
};
|
|
1124
|
+
for (let e of this.drops.values()) for (let n of bt) t[n] += e[n];
|
|
1125
|
+
let n = bt.filter((e) => t[e] > 0).map((e) => ({
|
|
1126
|
+
reason: e,
|
|
1127
|
+
count: t[e]
|
|
1128
|
+
})), r = 0;
|
|
1129
|
+
for (let e of this.tooLarge.values()) r += e;
|
|
1130
|
+
let i = e === void 0 ? void 0 : this.baselines.get(e);
|
|
1131
|
+
return {
|
|
1132
|
+
captured: this.stored.length,
|
|
1133
|
+
total: null,
|
|
1134
|
+
truncated: n.length > 0,
|
|
1135
|
+
policy: "sampled-200ms",
|
|
1136
|
+
...n.length > 0 && { dropped: n },
|
|
1137
|
+
...r > 0 && { valueTooLarge: r },
|
|
1138
|
+
...i && { baseline: i }
|
|
1139
|
+
};
|
|
1140
|
+
}
|
|
1141
|
+
markReset() {
|
|
1142
|
+
this.resetAt = this.seq = z(), this.entriesCache = void 0, this.onChange();
|
|
1143
|
+
}
|
|
1144
|
+
countRuntimeLosses(e, t, n) {
|
|
1145
|
+
if (Array.isArray(t)) for (let n of t) {
|
|
1146
|
+
if (n?.reason !== "runtime-count" && n?.reason !== "runtime-bytes") continue;
|
|
1147
|
+
let t = I(n.count);
|
|
1148
|
+
t > 0 && this.addDrop(e, n.reason, t);
|
|
1149
|
+
}
|
|
1150
|
+
let r = I(n);
|
|
1151
|
+
r > 0 && this.tooLarge.set(e, (this.tooLarge.get(e) ?? 0) + r);
|
|
1152
|
+
}
|
|
1153
|
+
addDrop(e, t, n) {
|
|
1154
|
+
let r = this.drops.get(e);
|
|
1155
|
+
r || (r = {
|
|
1156
|
+
"runtime-count": 0,
|
|
1157
|
+
"runtime-bytes": 0,
|
|
1158
|
+
"server-count": 0,
|
|
1159
|
+
"server-bytes": 0
|
|
1160
|
+
}, this.drops.set(e, r)), r[t] += n;
|
|
1161
|
+
}
|
|
1162
|
+
append(e, t) {
|
|
1163
|
+
if (e.length === 0) return;
|
|
1164
|
+
for (let n of e) {
|
|
1165
|
+
let e;
|
|
1166
|
+
try {
|
|
1167
|
+
e = JSON.stringify(n).length;
|
|
1168
|
+
} catch {
|
|
1169
|
+
continue;
|
|
1170
|
+
}
|
|
1171
|
+
this.stored.push({
|
|
1172
|
+
entry: {
|
|
1173
|
+
...n,
|
|
1174
|
+
seq: this.seq = z()
|
|
1175
|
+
},
|
|
1176
|
+
size: e,
|
|
1177
|
+
epoch: t
|
|
1178
|
+
}), this.bytes += e;
|
|
1179
|
+
}
|
|
1180
|
+
let n = Math.max(0, this.stored.length - 500);
|
|
1181
|
+
for (let e = 0; e < n; e++) this.bytes -= this.stored[e].size, this.addDrop(this.stored[e].epoch, "server-count", 1);
|
|
1182
|
+
for (; this.bytes > 4194304 && n < this.stored.length - 1;) this.addDrop(this.stored[n].epoch, "server-bytes", 1), this.bytes -= this.stored[n++].size;
|
|
1183
|
+
n > 0 && (this.trimmedAt = this.stored[n - 1].entry.seq, this.stored = this.stored.slice(n)), this.entriesCache = void 0, this.onChange();
|
|
1184
|
+
}
|
|
1185
|
+
}, B = {
|
|
1186
|
+
nodes: 5e3,
|
|
1187
|
+
edges: 2e4
|
|
1188
|
+
}, V = {
|
|
1189
|
+
topK: 50,
|
|
1190
|
+
maxTopK: 200,
|
|
1191
|
+
windowMs: 1e4,
|
|
1192
|
+
minWindowMs: 1e3,
|
|
1193
|
+
maxWindowMs: 6e4
|
|
1194
|
+
};
|
|
1195
|
+
function H(e, t, n) {
|
|
1196
|
+
return {
|
|
1197
|
+
nodes: [],
|
|
1198
|
+
edges: [],
|
|
1199
|
+
scope: e,
|
|
1200
|
+
epoch: t,
|
|
1201
|
+
total: null,
|
|
1202
|
+
truncated: !1,
|
|
1203
|
+
edgesOmitted: 0,
|
|
1204
|
+
computedAt: null,
|
|
1205
|
+
policy: e === null ? "global-head" : "scoped",
|
|
1206
|
+
stale: !0,
|
|
1207
|
+
staleReason: n
|
|
1208
|
+
};
|
|
1209
|
+
}
|
|
1210
|
+
function Ct(e, t, n) {
|
|
1211
|
+
return {
|
|
1212
|
+
epoch: e,
|
|
1213
|
+
window: {
|
|
1214
|
+
ms: t,
|
|
1215
|
+
since: 0,
|
|
1216
|
+
until: 0,
|
|
1217
|
+
sampledActiveMs: 0
|
|
1218
|
+
},
|
|
1219
|
+
policy: "sampled-200ms",
|
|
1220
|
+
coverage: "component-init",
|
|
1221
|
+
components: {
|
|
1222
|
+
total: null,
|
|
1223
|
+
withActivity: 0
|
|
1224
|
+
},
|
|
1225
|
+
rows: [],
|
|
1226
|
+
other: null,
|
|
1227
|
+
truncated: !1,
|
|
1228
|
+
capabilities: {
|
|
1229
|
+
valueInspection: !1,
|
|
1230
|
+
signalHistory: !1,
|
|
1231
|
+
writeCause: !1
|
|
1232
|
+
},
|
|
1233
|
+
stale: !0,
|
|
1234
|
+
staleReason: n
|
|
1235
|
+
};
|
|
1236
|
+
}
|
|
1237
|
+
function U(e, t, n) {
|
|
1238
|
+
let r = typeof e?.requestId != "string", i = L(e?.nodes), a = L(e?.edges), o = e?.policy === "scoped" || e?.policy === "global-head" ? e.policy : t === null ? "global-head" : "scoped", s = null, c = P(e?.total);
|
|
1239
|
+
if (!r && typeof c?.nodes == "number" && (s = {
|
|
1240
|
+
nodes: c.nodes,
|
|
1241
|
+
nodesKind: "registered",
|
|
1242
|
+
edges: typeof c.edges == "number" ? c.edges : null
|
|
1243
|
+
}), r && t !== null) {
|
|
1244
|
+
let e = new Set(i.filter((e) => e?.componentId === t).map((e) => e.id)), n = new Set(e);
|
|
1245
|
+
for (let t of a) e.has(t?.from) && n.add(t.to), e.has(t?.to) && n.add(t.from);
|
|
1246
|
+
i = i.filter((e) => n.has(e?.id)), o = "server-filter";
|
|
1247
|
+
} else r && (s = {
|
|
1248
|
+
nodes: i.length,
|
|
1249
|
+
nodesKind: "sent",
|
|
1250
|
+
edges: a.length
|
|
1251
|
+
});
|
|
1252
|
+
let l = e?.truncated === !0;
|
|
1253
|
+
i.length > B.nodes && (i = i.slice(0, B.nodes), l = !0);
|
|
1254
|
+
let u = new Set(i.map((e) => e?.id)), d = I(e?.edgesOmitted), f = [];
|
|
1255
|
+
for (let e of a) !u.has(e?.from) || !u.has(e?.to) ? o !== "server-filter" && d++ : f.length < B.edges ? f.push(e) : (d++, l = !0);
|
|
1256
|
+
return {
|
|
1257
|
+
nodes: i,
|
|
1258
|
+
edges: f,
|
|
1259
|
+
scope: t,
|
|
1260
|
+
epoch: typeof e?.epoch == "string" ? e.epoch : n,
|
|
1261
|
+
total: s,
|
|
1262
|
+
truncated: l,
|
|
1263
|
+
edgesOmitted: d,
|
|
1264
|
+
computedAt: vt(e?.computedAt),
|
|
1265
|
+
policy: o
|
|
1266
|
+
};
|
|
1267
|
+
}
|
|
1268
|
+
function wt(e, t) {
|
|
1269
|
+
let n = L(e?.rows).slice(0, V.maxTopK).map((e) => {
|
|
1270
|
+
let t = P(e), n = P(t?.nodes), r = {
|
|
1271
|
+
componentId: I(t?.componentId),
|
|
1272
|
+
file: typeof t?.file == "string" ? t.file : "",
|
|
1273
|
+
nodes: {
|
|
1274
|
+
state: I(n?.state),
|
|
1275
|
+
derived: I(n?.derived),
|
|
1276
|
+
effect: I(n?.effect)
|
|
1277
|
+
},
|
|
1278
|
+
changes: I(t?.changes),
|
|
1279
|
+
renders: I(t?.renders),
|
|
1280
|
+
renderMs: typeof t?.renderMs == "number" && t.renderMs >= 0 ? t.renderMs : 0
|
|
1281
|
+
};
|
|
1282
|
+
return t?.kind === "module" && (r.kind = "module"), r;
|
|
1283
|
+
}), r = P(e?.window), i = P(e?.components), a = P(e?.other), o = P(e?.capabilities);
|
|
1284
|
+
return {
|
|
1285
|
+
epoch: typeof e?.epoch == "string" ? e.epoch : t,
|
|
1286
|
+
window: {
|
|
1287
|
+
ms: I(r?.ms),
|
|
1288
|
+
since: I(r?.since),
|
|
1289
|
+
until: I(r?.until),
|
|
1290
|
+
sampledActiveMs: I(r?.sampledActiveMs)
|
|
1291
|
+
},
|
|
1292
|
+
policy: "sampled-200ms",
|
|
1293
|
+
coverage: "component-init",
|
|
1294
|
+
components: {
|
|
1295
|
+
total: typeof i?.total == "number" ? i.total : null,
|
|
1296
|
+
withActivity: I(i?.withActivity)
|
|
1297
|
+
},
|
|
1298
|
+
rows: n,
|
|
1299
|
+
other: typeof a?.components == "number" && typeof a.nodes == "number" ? {
|
|
1300
|
+
components: a.components,
|
|
1301
|
+
nodes: a.nodes
|
|
1302
|
+
} : null,
|
|
1303
|
+
truncated: e?.truncated === !0,
|
|
1304
|
+
capabilities: {
|
|
1305
|
+
valueInspection: o?.valueInspection === !0,
|
|
1306
|
+
signalHistory: o?.signalHistory === !0,
|
|
1307
|
+
writeCause: o?.writeCause === !0
|
|
1308
|
+
},
|
|
1309
|
+
...xt(e?.baseline) && { baseline: { ...e.baseline } }
|
|
1310
|
+
};
|
|
873
1311
|
}
|
|
874
1312
|
//#endregion
|
|
875
|
-
//#region src/server/
|
|
876
|
-
var
|
|
1313
|
+
//#region src/server/ring.ts
|
|
1314
|
+
var W = class {
|
|
1315
|
+
items = [];
|
|
1316
|
+
received = 0;
|
|
1317
|
+
max;
|
|
1318
|
+
constructor(e) {
|
|
1319
|
+
this.max = e;
|
|
1320
|
+
}
|
|
1321
|
+
push(e) {
|
|
1322
|
+
this.received++, this.items.push(e), this.items.length > this.max && (this.items = this.items.slice(-this.max));
|
|
1323
|
+
}
|
|
1324
|
+
clear() {
|
|
1325
|
+
this.items = [], this.received = 0;
|
|
1326
|
+
}
|
|
1327
|
+
get info() {
|
|
1328
|
+
let e = this.items.length;
|
|
1329
|
+
return {
|
|
1330
|
+
captured: e,
|
|
1331
|
+
total: this.received,
|
|
1332
|
+
truncated: this.received > e,
|
|
1333
|
+
policy: "tail"
|
|
1334
|
+
};
|
|
1335
|
+
}
|
|
1336
|
+
}, G = {
|
|
877
1337
|
liveComponents: 5e4,
|
|
878
1338
|
renderProfiles: 5e3,
|
|
879
1339
|
stateTimeline: 500,
|
|
880
|
-
reactiveNodes:
|
|
881
|
-
reactiveEdges:
|
|
1340
|
+
reactiveNodes: B.nodes,
|
|
1341
|
+
reactiveEdges: B.edges,
|
|
882
1342
|
fpsSamples: 1200,
|
|
883
1343
|
runtimeErrors: 200,
|
|
884
1344
|
loadProfiles: 200,
|
|
885
1345
|
compilerWarnings: 500
|
|
886
|
-
},
|
|
1346
|
+
}, Tt = 1e3, Et = 15e3, Dt = 32, K = {
|
|
887
1347
|
components: "svelte-devtools:components",
|
|
888
1348
|
profiles: "svelte-devtools:profiles",
|
|
889
1349
|
stateTimeline: "svelte-devtools:state-timeline",
|
|
@@ -897,128 +1357,63 @@ var N = {
|
|
|
897
1357
|
clearStateTimeline: "svelte-devtools:clear-state-timeline",
|
|
898
1358
|
runtimeReady: "svelte-devtools:runtime-ready",
|
|
899
1359
|
subscription: "svelte-devtools:subscription"
|
|
900
|
-
},
|
|
901
|
-
topK: 50,
|
|
902
|
-
maxTopK: 200,
|
|
903
|
-
windowMs: 1e4,
|
|
904
|
-
minWindowMs: 1e3,
|
|
905
|
-
maxWindowMs: 6e4
|
|
906
|
-
}, Qe = [
|
|
907
|
-
"runtime-count",
|
|
908
|
-
"runtime-bytes",
|
|
909
|
-
"server-count",
|
|
910
|
-
"server-bytes"
|
|
911
|
-
];
|
|
912
|
-
function R(e) {
|
|
913
|
-
let t = e;
|
|
914
|
-
return !!t && typeof t.complete == "boolean" && Number.isInteger(t.pendingNodes) && t.pendingNodes >= 0;
|
|
915
|
-
}
|
|
916
|
-
function z(e, t, n, r) {
|
|
917
|
-
return typeof e != "number" || !Number.isFinite(e) ? r : Math.min(n, Math.max(t, Math.trunc(e)));
|
|
918
|
-
}
|
|
919
|
-
function B(e) {
|
|
920
|
-
return z(e, 0, 2 ** 53 - 1, 0);
|
|
921
|
-
}
|
|
922
|
-
function V(e) {
|
|
923
|
-
return typeof e == "object" && e && !Array.isArray(e) ? e : void 0;
|
|
924
|
-
}
|
|
925
|
-
function $e(e) {
|
|
926
|
-
let t = V(e);
|
|
927
|
-
return typeof t?.timestamp == "number" && typeof t.fps == "number";
|
|
928
|
-
}
|
|
929
|
-
function et(e) {
|
|
930
|
-
return typeof V(e)?.message == "string";
|
|
931
|
-
}
|
|
932
|
-
function H(e, t) {
|
|
933
|
-
return {
|
|
934
|
-
captured: e,
|
|
935
|
-
total: t,
|
|
936
|
-
truncated: t > e,
|
|
937
|
-
policy: "tail"
|
|
938
|
-
};
|
|
939
|
-
}
|
|
940
|
-
var tt = 15e3;
|
|
941
|
-
function nt(e, t) {
|
|
942
|
-
let n = Array.isArray(e) ? e : [];
|
|
943
|
-
return n.length > t ? n.slice(-t) : n;
|
|
944
|
-
}
|
|
945
|
-
function U(e, t) {
|
|
946
|
-
let n = Array.isArray(e) ? e : [];
|
|
947
|
-
return n.length > t ? n.slice(0, t) : n;
|
|
948
|
-
}
|
|
949
|
-
var rt = class {
|
|
1360
|
+
}, Ot = (e) => typeof e?.epoch == "string" ? e.epoch : R, kt = class {
|
|
950
1361
|
epochs = /* @__PURE__ */ new Map();
|
|
951
1362
|
servedEpoch;
|
|
952
1363
|
liveCache;
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
runtimeErrors = [];
|
|
960
|
-
fpsSamples = [];
|
|
1364
|
+
resyncRequested = /* @__PURE__ */ new Set();
|
|
1365
|
+
fps = new W(G.fpsSamples);
|
|
1366
|
+
errors = new W(G.runtimeErrors);
|
|
1367
|
+
loads = new W(G.loadProfiles);
|
|
1368
|
+
warnings = new W(G.compilerWarnings);
|
|
1369
|
+
timeline = new St(() => this.bump("stateTimeline"));
|
|
961
1370
|
versions = {
|
|
962
|
-
components:
|
|
963
|
-
renderProfiles:
|
|
964
|
-
loadProfiles:
|
|
965
|
-
stateTimeline:
|
|
966
|
-
reactiveGraph:
|
|
967
|
-
errors:
|
|
968
|
-
fps:
|
|
1371
|
+
components: z(),
|
|
1372
|
+
renderProfiles: z(),
|
|
1373
|
+
loadProfiles: z(),
|
|
1374
|
+
stateTimeline: z(),
|
|
1375
|
+
reactiveGraph: z(),
|
|
1376
|
+
errors: z(),
|
|
1377
|
+
fps: z()
|
|
969
1378
|
};
|
|
970
|
-
bump(...e) {
|
|
971
|
-
for (let t of e) this.versions[t] = P();
|
|
972
|
-
}
|
|
973
|
-
timeline = [];
|
|
974
|
-
timelineSizes = [];
|
|
975
|
-
timelineEpochs = [];
|
|
976
|
-
timelineBytes = 0;
|
|
977
|
-
timelineSeq = P();
|
|
978
|
-
timelineResetAt = this.timelineSeq;
|
|
979
|
-
timelineTrimmedAt = this.timelineSeq;
|
|
980
|
-
lastPull = { stateTimeline: 0 };
|
|
981
|
-
inflight = {};
|
|
982
1379
|
pulls = /* @__PURE__ */ new Map();
|
|
983
1380
|
pullCache = /* @__PURE__ */ new Map();
|
|
984
1381
|
pullInflight = /* @__PURE__ */ new Map();
|
|
985
1382
|
requestSeq = 0;
|
|
986
1383
|
lastGraph;
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
received = {
|
|
991
|
-
fps: 0,
|
|
992
|
-
runtimeErrors: 0,
|
|
993
|
-
loadProfiles: 0,
|
|
994
|
-
compilerWarnings: 0
|
|
995
|
-
};
|
|
1384
|
+
lastTimelinePull = 0;
|
|
1385
|
+
timelineInflight;
|
|
1386
|
+
timelineResolvers = [];
|
|
996
1387
|
hot;
|
|
997
1388
|
detachHot;
|
|
998
1389
|
leases = /* @__PURE__ */ new Map();
|
|
999
1390
|
snapshotWaiters = [];
|
|
1000
1391
|
active = !1;
|
|
1001
1392
|
sweepTimer;
|
|
1002
|
-
stateTimelineResolvers = [];
|
|
1003
1393
|
hooks;
|
|
1004
1394
|
constructor(e = {}) {
|
|
1005
1395
|
this.hooks = e;
|
|
1006
1396
|
}
|
|
1397
|
+
bump(...e) {
|
|
1398
|
+
for (let t of e) this.versions[t] = z();
|
|
1399
|
+
}
|
|
1007
1400
|
attach(e) {
|
|
1008
1401
|
this.detach(), this.hot = e;
|
|
1009
1402
|
let t = [
|
|
1010
|
-
[
|
|
1011
|
-
[
|
|
1012
|
-
[
|
|
1013
|
-
[
|
|
1014
|
-
[
|
|
1015
|
-
|
|
1403
|
+
[K.runtimeReady, (e, t) => t?.send(K.subscription, this.subscription)],
|
|
1404
|
+
[K.components, (e, t) => this.ingestComponents(P(e), t)],
|
|
1405
|
+
[K.profiles, (e) => this.ingestProfiles(P(e))],
|
|
1406
|
+
[K.stateTimeline, (e) => this.ingestStateTimeline(P(e))],
|
|
1407
|
+
[K.fps, (e) => {
|
|
1408
|
+
let t = P(e);
|
|
1409
|
+
typeof t?.timestamp == "number" && typeof t.fps == "number" && this.ingestFps(t);
|
|
1016
1410
|
}],
|
|
1017
|
-
[
|
|
1018
|
-
|
|
1411
|
+
[K.runtimeError, (e) => {
|
|
1412
|
+
let t = P(e);
|
|
1413
|
+
typeof t?.message == "string" && this.ingestRuntimeError(t);
|
|
1019
1414
|
}],
|
|
1020
|
-
[
|
|
1021
|
-
[
|
|
1415
|
+
[K.reactiveGraph, (e) => this.ingestReactiveGraph(P(e))],
|
|
1416
|
+
[K.reactiveSummary, (e) => this.ingestReactiveSummary(P(e))]
|
|
1022
1417
|
];
|
|
1023
1418
|
for (let [n, r] of t) e.on(n, r);
|
|
1024
1419
|
this.detachHot = () => {
|
|
@@ -1026,7 +1421,9 @@ var rt = class {
|
|
|
1026
1421
|
};
|
|
1027
1422
|
}
|
|
1028
1423
|
detach() {
|
|
1029
|
-
clearTimeout(this.sweepTimer), this.sweepTimer = void 0, this.detachHot?.(), this.detachHot = void 0, this.hot = void 0
|
|
1424
|
+
clearTimeout(this.sweepTimer), this.sweepTimer = void 0, this.detachHot?.(), this.detachHot = void 0, this.hot = void 0;
|
|
1425
|
+
for (let e of this.pulls.keys()) this.settle(e, "no-runtime");
|
|
1426
|
+
this.flushStateTimeline();
|
|
1030
1427
|
}
|
|
1031
1428
|
get subscription() {
|
|
1032
1429
|
return {
|
|
@@ -1034,7 +1431,21 @@ var rt = class {
|
|
|
1034
1431
|
componentDeltas: !0
|
|
1035
1432
|
};
|
|
1036
1433
|
}
|
|
1037
|
-
|
|
1434
|
+
get fpsSamples() {
|
|
1435
|
+
return this.fps.items;
|
|
1436
|
+
}
|
|
1437
|
+
get runtimeErrors() {
|
|
1438
|
+
return this.errors.items;
|
|
1439
|
+
}
|
|
1440
|
+
get loadProfiles() {
|
|
1441
|
+
return this.loads.items;
|
|
1442
|
+
}
|
|
1443
|
+
get compilerWarnings() {
|
|
1444
|
+
return this.warnings.items;
|
|
1445
|
+
}
|
|
1446
|
+
get stateTimeline() {
|
|
1447
|
+
return this.timeline.entries;
|
|
1448
|
+
}
|
|
1038
1449
|
get liveComponents() {
|
|
1039
1450
|
if (!this.liveCache) {
|
|
1040
1451
|
let e = this.servedState();
|
|
@@ -1063,22 +1474,19 @@ var rt = class {
|
|
|
1063
1474
|
};
|
|
1064
1475
|
}
|
|
1065
1476
|
servedState() {
|
|
1066
|
-
|
|
1067
|
-
let e;
|
|
1068
|
-
for (let t of this.epochs.values()) e = t;
|
|
1069
|
-
return e;
|
|
1477
|
+
return this.servedEpoch === void 0 ? [...this.epochs.values()].at(-1) : this.epochs.get(this.servedEpoch);
|
|
1070
1478
|
}
|
|
1071
1479
|
touchEpoch(e) {
|
|
1072
|
-
let t = this.epochs.get(e)
|
|
1073
|
-
for (t ? this.epochs.delete(e) : t = {
|
|
1480
|
+
let t = this.epochs.get(e) ?? {
|
|
1074
1481
|
components: /* @__PURE__ */ new Map(),
|
|
1075
1482
|
overflow: /* @__PURE__ */ new Set(),
|
|
1076
1483
|
hasBase: !1,
|
|
1077
1484
|
profiles: [],
|
|
1078
1485
|
profilesTotal: null
|
|
1079
|
-
}
|
|
1486
|
+
};
|
|
1487
|
+
for (this.epochs.delete(e), this.epochs.set(e, t); this.epochs.size > 4;) {
|
|
1080
1488
|
let e = this.epochs.keys().next().value;
|
|
1081
|
-
this.epochs.delete(e), this.resyncRequested.delete(e), this.
|
|
1489
|
+
this.epochs.delete(e), this.resyncRequested.delete(e), this.timeline.forget(e), this.servedEpoch === e && this.serve(this.newestBasedEpoch());
|
|
1082
1490
|
}
|
|
1083
1491
|
return t.hasBase && this.serve(e), t;
|
|
1084
1492
|
}
|
|
@@ -1090,10 +1498,13 @@ var rt = class {
|
|
|
1090
1498
|
serve(e) {
|
|
1091
1499
|
this.servedEpoch !== e && (this.servedEpoch !== void 0 && this.bump("components", "renderProfiles"), this.servedEpoch = e, this.liveCache = void 0);
|
|
1092
1500
|
}
|
|
1093
|
-
lease(e, t =
|
|
1501
|
+
lease(e, t = Et) {
|
|
1094
1502
|
let n = this.active;
|
|
1095
1503
|
return this.leases.set(e, Date.now() + t), this.updateSubscription(), !n && this.active;
|
|
1096
1504
|
}
|
|
1505
|
+
release(e) {
|
|
1506
|
+
this.leases.delete(e) && this.updateSubscription();
|
|
1507
|
+
}
|
|
1097
1508
|
waitForSnapshot(e) {
|
|
1098
1509
|
return new Promise((t) => {
|
|
1099
1510
|
let n = () => {
|
|
@@ -1104,549 +1515,295 @@ var rt = class {
|
|
|
1104
1515
|
this.snapshotWaiters.push(n);
|
|
1105
1516
|
});
|
|
1106
1517
|
}
|
|
1107
|
-
release(e) {
|
|
1108
|
-
this.leases.delete(e) && this.updateSubscription();
|
|
1109
|
-
}
|
|
1110
1518
|
updateSubscription() {
|
|
1111
1519
|
let e = Date.now(), t = Infinity;
|
|
1112
1520
|
for (let [n, r] of this.leases) r <= e ? this.leases.delete(n) : t = Math.min(t, r);
|
|
1113
1521
|
let n = this.leases.size > 0;
|
|
1114
|
-
n !== this.active && (this.active = n, this.hot?.send(
|
|
1522
|
+
n !== this.active && (this.active = n, this.hot?.send(K.subscription, this.subscription)), clearTimeout(this.sweepTimer), this.sweepTimer = void 0, t !== Infinity && (this.sweepTimer = setTimeout(() => this.updateSubscription(), t - e + 1), this.sweepTimer.unref?.());
|
|
1115
1523
|
}
|
|
1116
1524
|
ingestComponents(e, t) {
|
|
1117
|
-
let n =
|
|
1525
|
+
let n = Ot(e), r = !Array.isArray(e?.components) && (Array.isArray(e?.added) || Array.isArray(e?.removed));
|
|
1118
1526
|
if (r && !this.epochs.get(n)?.hasBase) {
|
|
1119
|
-
this.resyncRequested.has(n) || (this.resyncRequested.add(n), t?.send(
|
|
1527
|
+
this.resyncRequested.has(n) || (this.resyncRequested.add(n), t?.send(K.subscription, {
|
|
1120
1528
|
...this.subscription,
|
|
1121
1529
|
resync: !0
|
|
1122
1530
|
}));
|
|
1123
1531
|
return;
|
|
1124
1532
|
}
|
|
1125
1533
|
let i = this.touchEpoch(n);
|
|
1126
|
-
if (r
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
i.components.set(t, e);
|
|
1534
|
+
if (r) for (let t of L(e?.removed)) i.components.delete(t) || i.overflow.delete(t);
|
|
1535
|
+
else this.resyncRequested.delete(n), i.hasBase = !0, this.serve(n), i.components = /* @__PURE__ */ new Map(), i.overflow = /* @__PURE__ */ new Set();
|
|
1536
|
+
for (let t of L(r ? e?.added : e?.components)) if (typeof t?.id == "number") {
|
|
1537
|
+
if (i.components.has(t.id)) {
|
|
1538
|
+
i.components.set(t.id, t);
|
|
1132
1539
|
continue;
|
|
1133
1540
|
}
|
|
1134
|
-
|
|
1135
|
-
(n == null || i.components.has(n)) && i.components.size < N.liveComponents ? (i.overflow.delete(t), i.components.set(t, e)) : i.overflow.add(t);
|
|
1541
|
+
(t.parentId === null || t.parentId === void 0 || i.components.has(t.parentId)) && i.components.size < G.liveComponents ? (i.overflow.delete(t.id), i.components.set(t.id, t)) : i.overflow.add(t.id);
|
|
1136
1542
|
}
|
|
1137
1543
|
this.liveCache = void 0, this.bump("components");
|
|
1138
1544
|
}
|
|
1139
1545
|
ingestProfiles(e) {
|
|
1140
|
-
let t =
|
|
1141
|
-
|
|
1546
|
+
let t = this.touchEpoch(Ot(e));
|
|
1547
|
+
t.profiles = L(e?.profiles).slice(-G.renderProfiles), t.profilesTotal = vt(e?.total), this.bump("renderProfiles");
|
|
1548
|
+
}
|
|
1549
|
+
ingestStateTimeline(e) {
|
|
1550
|
+
if (typeof e?.epoch == "string" && this.touchEpoch(e.epoch), this.timeline.ingest(e), this.lastTimelinePull = Date.now(), this.flushStateTimeline(), e?.reset === !0) for (let e of this.snapshotWaiters.slice()) e();
|
|
1551
|
+
}
|
|
1552
|
+
ingestFps(e) {
|
|
1553
|
+
this.fps.push(e), this.bump("fps"), this.hooks.onFpsSample?.(e);
|
|
1554
|
+
}
|
|
1555
|
+
ingestRuntimeError(e) {
|
|
1556
|
+
this.errors.push(e), this.bump("errors");
|
|
1557
|
+
}
|
|
1558
|
+
recordLoadProfile(e) {
|
|
1559
|
+
this.loads.push(e), this.bump("loadProfiles"), this.hooks.onLoadProfile?.(e);
|
|
1560
|
+
}
|
|
1561
|
+
recordCompilerWarning(e) {
|
|
1562
|
+
this.warnings.items.some((t) => t.file === e.file && t.line === e.line && t.column === e.column && t.code === e.code && t.message === e.message) || (this.warnings.push(e), this.bump("errors"));
|
|
1563
|
+
}
|
|
1564
|
+
clearLoadProfiles() {
|
|
1565
|
+
this.loads.clear(), this.bump("loadProfiles");
|
|
1566
|
+
}
|
|
1567
|
+
clearErrors() {
|
|
1568
|
+
this.warnings.clear(), this.errors.clear(), this.bump("errors");
|
|
1569
|
+
}
|
|
1570
|
+
clearFps() {
|
|
1571
|
+
this.fps.clear(), this.bump("fps");
|
|
1572
|
+
}
|
|
1573
|
+
clearStateTimeline() {
|
|
1574
|
+
this.timeline.clear(), this.hot?.send(K.clearStateTimeline, {});
|
|
1575
|
+
}
|
|
1576
|
+
getStateTimelineDelta(e) {
|
|
1577
|
+
return this.timeline.delta(e);
|
|
1142
1578
|
}
|
|
1143
1579
|
getCaptureInfo() {
|
|
1144
|
-
let e = this.servedState(), t = this.servedEpoch, n = {
|
|
1145
|
-
"runtime-count": 0,
|
|
1146
|
-
"runtime-bytes": 0,
|
|
1147
|
-
"server-count": 0,
|
|
1148
|
-
"server-bytes": 0
|
|
1149
|
-
};
|
|
1150
|
-
for (let e of this.timelineDrops.values()) for (let t of Qe) n[t] += e[t];
|
|
1151
|
-
let r = Qe.filter((e) => n[e] > 0).map((e) => ({
|
|
1152
|
-
reason: e,
|
|
1153
|
-
count: n[e]
|
|
1154
|
-
})), i = 0;
|
|
1155
|
-
for (let e of this.timelineTooLarge.values()) i += e;
|
|
1156
|
-
let a = e?.profiles.length ?? 0, o = e?.profilesTotal ?? null, s = this.lastGraph, c = {
|
|
1580
|
+
let e = this.servedState(), t = this.servedEpoch, n = t !== void 0 && { epoch: t }, r = e?.profiles.length ?? 0, i = e?.profilesTotal ?? null, a = {
|
|
1157
1581
|
liveComponents: {
|
|
1158
1582
|
captured: e?.components.size ?? 0,
|
|
1159
1583
|
total: this.liveComponentsTotal,
|
|
1160
1584
|
truncated: (e?.overflow.size ?? 0) > 0,
|
|
1161
1585
|
policy: "roots-first",
|
|
1162
|
-
...
|
|
1586
|
+
...n
|
|
1163
1587
|
},
|
|
1164
1588
|
renderProfiles: {
|
|
1165
|
-
captured:
|
|
1166
|
-
total:
|
|
1167
|
-
truncated:
|
|
1589
|
+
captured: r,
|
|
1590
|
+
total: i,
|
|
1591
|
+
truncated: i !== null && i > r,
|
|
1168
1592
|
policy: "newest-mounted",
|
|
1169
|
-
...
|
|
1170
|
-
},
|
|
1171
|
-
stateTimeline: {
|
|
1172
|
-
captured: this.timeline.length,
|
|
1173
|
-
total: null,
|
|
1174
|
-
truncated: r.length > 0,
|
|
1175
|
-
policy: "sampled-200ms",
|
|
1176
|
-
...r.length > 0 && { dropped: r },
|
|
1177
|
-
...i > 0 && { valueTooLarge: i },
|
|
1178
|
-
...t !== void 0 && this.timelineBaseline.has(t) && { baseline: this.timelineBaseline.get(t) }
|
|
1593
|
+
...n
|
|
1179
1594
|
},
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1595
|
+
stateTimeline: this.timeline.captureInfo(t),
|
|
1596
|
+
fpsSamples: this.fps.info,
|
|
1597
|
+
runtimeErrors: this.errors.info,
|
|
1598
|
+
loadProfiles: this.loads.info,
|
|
1599
|
+
compilerWarnings: this.warnings.info
|
|
1600
|
+
}, o = this.lastGraph;
|
|
1601
|
+
if (o) {
|
|
1186
1602
|
let e = {
|
|
1187
|
-
truncated:
|
|
1188
|
-
policy:
|
|
1189
|
-
...
|
|
1603
|
+
truncated: o.truncated,
|
|
1604
|
+
policy: o.policy,
|
|
1605
|
+
...o.epoch !== null && { epoch: o.epoch }
|
|
1190
1606
|
};
|
|
1191
|
-
|
|
1192
|
-
captured:
|
|
1193
|
-
total:
|
|
1607
|
+
a.reactiveNodes = {
|
|
1608
|
+
captured: o.nodes.length,
|
|
1609
|
+
total: o.total?.nodes ?? null,
|
|
1194
1610
|
...e
|
|
1195
|
-
},
|
|
1196
|
-
captured:
|
|
1197
|
-
total:
|
|
1611
|
+
}, a.reactiveEdges = {
|
|
1612
|
+
captured: o.edges.length,
|
|
1613
|
+
total: o.total?.edges ?? null,
|
|
1198
1614
|
...e
|
|
1199
|
-
};
|
|
1200
|
-
}
|
|
1201
|
-
return
|
|
1202
|
-
}
|
|
1203
|
-
get stateTimeline() {
|
|
1204
|
-
return this.timeline;
|
|
1205
|
-
}
|
|
1206
|
-
ingestStateTimeline(e) {
|
|
1207
|
-
let t = nt(e?.changes, N.stateTimeline);
|
|
1208
|
-
if (typeof e?.epoch == "string") this.touchEpoch(e.epoch), this.countRuntimeLosses(e.epoch, e.dropped, e.valueTooLarge), e.reset === !0 && this.dropEpoch(e.epoch), this.appendTimeline(t, e.epoch), R(e.baseline) && this.timelineBaseline.set(e.epoch, {
|
|
1209
|
-
complete: e.baseline.complete,
|
|
1210
|
-
pendingNodes: e.baseline.pendingNodes
|
|
1211
|
-
});
|
|
1212
|
-
else {
|
|
1213
|
-
let e;
|
|
1214
|
-
for (let t = this.timeline.length - 1; t >= 0 && !e; t--) this.timelineEpochs[t] === F && (e = this.timeline[t]);
|
|
1215
|
-
let n = -1;
|
|
1216
|
-
if (e) for (let r = t.length - 1; r >= 0; r--) {
|
|
1217
|
-
let i = t[r];
|
|
1218
|
-
if (i.timestamp === e.timestamp && i.id === e.id) {
|
|
1219
|
-
n = r + 1;
|
|
1220
|
-
break;
|
|
1221
|
-
}
|
|
1222
|
-
}
|
|
1223
|
-
n === -1 && (this.dropEpoch(F), n = 0), this.appendTimeline(t.slice(n), F);
|
|
1224
|
-
}
|
|
1225
|
-
this.lastPull.stateTimeline = Date.now(), this.flushStateTimeline(), e?.reset === !0 && this.resolveSnapshotWaiters();
|
|
1226
|
-
}
|
|
1227
|
-
countRuntimeLosses(e, t, n) {
|
|
1228
|
-
if (Array.isArray(t)) for (let n of t) {
|
|
1229
|
-
if (n?.reason !== "runtime-count" && n?.reason !== "runtime-bytes") continue;
|
|
1230
|
-
let t = z(n.count, 0, 2 ** 53 - 1, 0);
|
|
1231
|
-
t > 0 && this.addDrop(e, n.reason, t);
|
|
1232
|
-
}
|
|
1233
|
-
let r = z(n, 0, 2 ** 53 - 1, 0);
|
|
1234
|
-
r > 0 && this.timelineTooLarge.set(e, (this.timelineTooLarge.get(e) ?? 0) + r);
|
|
1235
|
-
}
|
|
1236
|
-
addDrop(e, t, n) {
|
|
1237
|
-
let r = this.timelineDrops.get(e);
|
|
1238
|
-
r || (r = {
|
|
1239
|
-
"runtime-count": 0,
|
|
1240
|
-
"runtime-bytes": 0,
|
|
1241
|
-
"server-count": 0,
|
|
1242
|
-
"server-bytes": 0
|
|
1243
|
-
}, this.timelineDrops.set(e, r)), r[t] += n;
|
|
1244
|
-
}
|
|
1245
|
-
getStateTimelineDelta(e) {
|
|
1246
|
-
let t = this.timelineSeq;
|
|
1247
|
-
if (e === void 0 || e < this.timelineResetAt || e < this.timelineTrimmedAt || e > t) return {
|
|
1248
|
-
cursor: t,
|
|
1249
|
-
reset: !0,
|
|
1250
|
-
changes: this.timeline
|
|
1251
|
-
};
|
|
1252
|
-
let n = this.timeline.length;
|
|
1253
|
-
for (; n > 0 && this.timeline[n - 1].seq > e;) n--;
|
|
1254
|
-
return {
|
|
1255
|
-
cursor: t,
|
|
1256
|
-
reset: !1,
|
|
1257
|
-
changes: this.timeline.slice(n)
|
|
1258
|
-
};
|
|
1259
|
-
}
|
|
1260
|
-
markTimelineReset() {
|
|
1261
|
-
this.timelineResetAt = this.timelineSeq = P(), this.bump("stateTimeline");
|
|
1262
|
-
}
|
|
1263
|
-
dropEpoch(e) {
|
|
1264
|
-
if (!this.timelineEpochs.includes(e)) return;
|
|
1265
|
-
let t = this.timelineEpochs.map((t) => t !== e);
|
|
1266
|
-
this.timeline = this.timeline.filter((e, n) => t[n]), this.timelineSizes = this.timelineSizes.filter((e, n) => t[n]), this.timelineEpochs = this.timelineEpochs.filter((e, n) => t[n]), this.timelineBytes = this.timelineSizes.reduce((e, t) => e + t, 0), this.markTimelineReset();
|
|
1267
|
-
}
|
|
1268
|
-
appendTimeline(e, t) {
|
|
1269
|
-
if (e.length === 0) return;
|
|
1270
|
-
for (let n of e) {
|
|
1271
|
-
let e = 0;
|
|
1272
|
-
try {
|
|
1273
|
-
e = JSON.stringify(n).length;
|
|
1274
|
-
} catch {
|
|
1275
|
-
continue;
|
|
1276
|
-
}
|
|
1277
|
-
this.timeline.push({
|
|
1278
|
-
...n,
|
|
1279
|
-
seq: this.timelineSeq = P()
|
|
1280
|
-
}), this.timelineSizes.push(e), this.timelineEpochs.push(t), this.timelineBytes += e;
|
|
1281
|
-
}
|
|
1282
|
-
let n = Math.max(0, this.timeline.length - N.stateTimeline), r = this.timelineBytes;
|
|
1283
|
-
for (let e = 0; e < n; e++) r -= this.timelineSizes[e], this.addDrop(this.timelineEpochs[e], "server-count", 1);
|
|
1284
|
-
for (; r > 4194304 && n < this.timeline.length - 1;) this.addDrop(this.timelineEpochs[n], "server-bytes", 1), r -= this.timelineSizes[n++];
|
|
1285
|
-
n > 0 && (this.timelineTrimmedAt = this.timeline[n - 1].seq, this.timeline = this.timeline.slice(n), this.timelineSizes = this.timelineSizes.slice(n), this.timelineEpochs = this.timelineEpochs.slice(n)), this.timelineBytes = r, this.bump("stateTimeline");
|
|
1286
|
-
}
|
|
1287
|
-
resolveSnapshotWaiters() {
|
|
1288
|
-
for (let e of this.snapshotWaiters.slice()) e();
|
|
1289
|
-
}
|
|
1290
|
-
ingestReactiveGraph(e) {
|
|
1291
|
-
let t = typeof e?.requestId == "string" ? e.requestId : void 0;
|
|
1292
|
-
if (t === void 0) {
|
|
1293
|
-
let t = !1;
|
|
1294
|
-
for (let [n, r] of this.pulls) r.kind === "graph" && (t = !0, this.settle(n, this.normalizeGraph(e, r.scope, r.epoch)));
|
|
1295
|
-
t || this.storeGraph(this.normalizeGraph(e, null, this.servedEpoch ?? null));
|
|
1296
|
-
} else {
|
|
1297
|
-
let n = this.pulls.get(t);
|
|
1298
|
-
if (n?.kind !== "graph" || n.epoch !== null && typeof e?.epoch == "string" && e.epoch !== n.epoch) return;
|
|
1299
|
-
this.settle(t, this.normalizeGraph(e, n.scope, n.epoch));
|
|
1300
|
-
}
|
|
1301
|
-
this.bump("reactiveGraph");
|
|
1302
|
-
}
|
|
1303
|
-
normalizeGraph(e, t, n) {
|
|
1304
|
-
let r = typeof e?.requestId != "string", i = U(e?.nodes, Infinity), a = U(e?.edges, Infinity), o = e?.policy === "scoped" || e?.policy === "global-head" ? e.policy : t === null ? "global-head" : "scoped", s = null, c = V(e?.total);
|
|
1305
|
-
if (!r && typeof c?.nodes == "number" && (s = {
|
|
1306
|
-
nodes: c.nodes,
|
|
1307
|
-
nodesKind: "registered",
|
|
1308
|
-
edges: typeof c.edges == "number" ? c.edges : null
|
|
1309
|
-
}), r && t !== null) {
|
|
1310
|
-
let e = new Set(i.filter((e) => e?.componentId === t).map((e) => e.id)), n = new Set(e);
|
|
1311
|
-
for (let t of a) e.has(t?.from) && n.add(t.to), e.has(t?.to) && n.add(t.from);
|
|
1312
|
-
i = i.filter((e) => n.has(e?.id)), o = "server-filter";
|
|
1313
|
-
} else r && (s = {
|
|
1314
|
-
nodes: i.length,
|
|
1315
|
-
nodesKind: "sent",
|
|
1316
|
-
edges: a.length
|
|
1317
|
-
});
|
|
1318
|
-
let l = e?.truncated === !0;
|
|
1319
|
-
i.length > N.reactiveNodes && (i = i.slice(0, N.reactiveNodes), l = !0);
|
|
1320
|
-
let u = new Set(i.map((e) => e?.id)), d = z(e?.edgesOmitted, 0, 2 ** 53 - 1, 0), f = [];
|
|
1321
|
-
for (let e of a) !u.has(e?.from) || !u.has(e?.to) ? o !== "server-filter" && d++ : f.length < N.reactiveEdges ? f.push(e) : (d++, l = !0);
|
|
1322
|
-
return {
|
|
1323
|
-
nodes: i,
|
|
1324
|
-
edges: f,
|
|
1325
|
-
scope: t,
|
|
1326
|
-
epoch: typeof e?.epoch == "string" ? e.epoch : n,
|
|
1327
|
-
total: s,
|
|
1328
|
-
truncated: l,
|
|
1329
|
-
edgesOmitted: d,
|
|
1330
|
-
computedAt: typeof e?.computedAt == "number" && Number.isFinite(e.computedAt) ? e.computedAt : null,
|
|
1331
|
-
policy: o
|
|
1332
|
-
};
|
|
1333
|
-
}
|
|
1334
|
-
storeGraph(e) {
|
|
1335
|
-
this.lastGraph = e, e.scope === null && (this.reactiveGraph = {
|
|
1336
|
-
nodes: e.nodes,
|
|
1337
|
-
edges: e.edges
|
|
1338
|
-
});
|
|
1339
|
-
}
|
|
1340
|
-
ingestReactiveSummary(e) {
|
|
1341
|
-
let t = typeof e?.requestId == "string" ? e.requestId : void 0, n = t === void 0 ? void 0 : this.pulls.get(t);
|
|
1342
|
-
n?.kind === "summary" && (n.epoch === null || typeof e?.epoch != "string" || e.epoch === n.epoch) && this.settle(t, this.normalizeSummary(e, n.epoch));
|
|
1343
|
-
}
|
|
1344
|
-
normalizeSummary(e, t) {
|
|
1345
|
-
let n = U(e?.rows, L.maxTopK).map((e) => {
|
|
1346
|
-
let t = V(e), n = V(t?.nodes), r = {
|
|
1347
|
-
componentId: B(t?.componentId),
|
|
1348
|
-
file: typeof t?.file == "string" ? t.file : "",
|
|
1349
|
-
nodes: {
|
|
1350
|
-
state: B(n?.state),
|
|
1351
|
-
derived: B(n?.derived),
|
|
1352
|
-
effect: B(n?.effect)
|
|
1353
|
-
},
|
|
1354
|
-
changes: B(t?.changes),
|
|
1355
|
-
renders: B(t?.renders),
|
|
1356
|
-
renderMs: typeof t?.renderMs == "number" && t.renderMs >= 0 ? t.renderMs : 0
|
|
1357
|
-
};
|
|
1358
|
-
return t?.kind === "module" && (r.kind = "module"), r;
|
|
1359
|
-
}), r = V(e?.window), i = V(e?.components), a = V(e?.other), o = V(e?.capabilities);
|
|
1360
|
-
return {
|
|
1361
|
-
epoch: typeof e?.epoch == "string" ? e.epoch : t,
|
|
1362
|
-
window: {
|
|
1363
|
-
ms: B(r?.ms),
|
|
1364
|
-
since: B(r?.since),
|
|
1365
|
-
until: B(r?.until),
|
|
1366
|
-
sampledActiveMs: B(r?.sampledActiveMs)
|
|
1367
|
-
},
|
|
1368
|
-
policy: "sampled-200ms",
|
|
1369
|
-
coverage: "component-init",
|
|
1370
|
-
components: {
|
|
1371
|
-
total: typeof i?.total == "number" ? i.total : null,
|
|
1372
|
-
withActivity: B(i?.withActivity)
|
|
1373
|
-
},
|
|
1374
|
-
rows: n,
|
|
1375
|
-
other: typeof a?.components == "number" && typeof a.nodes == "number" ? {
|
|
1376
|
-
components: a.components,
|
|
1377
|
-
nodes: a.nodes
|
|
1378
|
-
} : null,
|
|
1379
|
-
truncated: e?.truncated === !0,
|
|
1380
|
-
capabilities: {
|
|
1381
|
-
valueInspection: o?.valueInspection === !0,
|
|
1382
|
-
signalHistory: o?.signalHistory === !0,
|
|
1383
|
-
writeCause: o?.writeCause === !0
|
|
1384
|
-
},
|
|
1385
|
-
...R(e?.baseline) && { baseline: { ...e.baseline } }
|
|
1386
|
-
};
|
|
1387
|
-
}
|
|
1388
|
-
ingestFps(e) {
|
|
1389
|
-
this.received.fps++, this.fpsSamples.push(e), this.fpsSamples.length > N.fpsSamples && (this.fpsSamples = this.fpsSamples.slice(-N.fpsSamples)), this.bump("fps"), this.hooks.onFpsSample?.(e);
|
|
1390
|
-
}
|
|
1391
|
-
ingestRuntimeError(e) {
|
|
1392
|
-
this.received.runtimeErrors++, this.runtimeErrors.push(e), this.runtimeErrors.length > N.runtimeErrors && (this.runtimeErrors = this.runtimeErrors.slice(-N.runtimeErrors)), this.bump("errors");
|
|
1393
|
-
}
|
|
1394
|
-
recordLoadProfile(e) {
|
|
1395
|
-
this.received.loadProfiles++, this.loadProfiles.push(e), this.loadProfiles.length > N.loadProfiles && (this.loadProfiles = this.loadProfiles.slice(-N.loadProfiles)), this.bump("loadProfiles"), this.hooks.onLoadProfile?.(e);
|
|
1396
|
-
}
|
|
1397
|
-
recordCompilerWarning(e) {
|
|
1398
|
-
this.received.compilerWarnings++, this.compilerWarnings.push(e), this.compilerWarnings.length > N.compilerWarnings && (this.compilerWarnings = this.compilerWarnings.slice(-N.compilerWarnings)), this.bump("errors");
|
|
1399
|
-
}
|
|
1400
|
-
clearLoadProfiles() {
|
|
1401
|
-
this.loadProfiles = [], this.received.loadProfiles = 0, this.bump("loadProfiles");
|
|
1615
|
+
};
|
|
1616
|
+
}
|
|
1617
|
+
return a;
|
|
1402
1618
|
}
|
|
1403
|
-
|
|
1404
|
-
|
|
1619
|
+
ingestReactiveGraph(e) {
|
|
1620
|
+
let t = typeof e?.requestId == "string" ? e.requestId : void 0;
|
|
1621
|
+
if (t === void 0) {
|
|
1622
|
+
let t = !1;
|
|
1623
|
+
for (let [n, r] of this.pulls) r.kind === "graph" && (t = !0, this.settle(n, U(e, r.scope, r.epoch)));
|
|
1624
|
+
t || (this.lastGraph = U(e, null, this.servedEpoch ?? null));
|
|
1625
|
+
} else {
|
|
1626
|
+
let n = this.matchingPull(t, "graph", e);
|
|
1627
|
+
if (!n) return;
|
|
1628
|
+
this.settle(t, U(e, n.scope, n.epoch));
|
|
1629
|
+
}
|
|
1630
|
+
this.bump("reactiveGraph");
|
|
1405
1631
|
}
|
|
1406
|
-
|
|
1407
|
-
|
|
1632
|
+
ingestReactiveSummary(e) {
|
|
1633
|
+
let t = typeof e?.requestId == "string" ? e.requestId : void 0, n = t === void 0 ? void 0 : this.matchingPull(t, "summary", e);
|
|
1634
|
+
n && this.settle(t, wt(e, n.epoch));
|
|
1408
1635
|
}
|
|
1409
|
-
|
|
1410
|
-
|
|
1636
|
+
matchingPull(e, t, n) {
|
|
1637
|
+
let r = this.pulls.get(e);
|
|
1638
|
+
if (r?.kind === t && (r.epoch === null || typeof n?.epoch != "string" || n.epoch === r.epoch)) return r;
|
|
1411
1639
|
}
|
|
1412
1640
|
requestReactiveGraph(e = {}) {
|
|
1413
|
-
let t =
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
});
|
|
1427
|
-
if (t !== null && typeof e.epoch == "string" && e.epoch !== i) return Promise.resolve({
|
|
1428
|
-
nodes: [],
|
|
1429
|
-
edges: [],
|
|
1430
|
-
scope: t,
|
|
1431
|
-
epoch: i,
|
|
1432
|
-
total: null,
|
|
1433
|
-
truncated: !1,
|
|
1434
|
-
edgesOmitted: 0,
|
|
1435
|
-
computedAt: null,
|
|
1436
|
-
policy: "scoped",
|
|
1437
|
-
stale: !0,
|
|
1438
|
-
staleReason: "epoch-changed"
|
|
1641
|
+
let t = e.componentId, n = typeof t == "number" && Number.isInteger(t) && t >= 0 ? t : null, r = F(e.maxNodes, 1, G.reactiveNodes, G.reactiveNodes), i = F(e.maxEdges, 1, G.reactiveEdges, G.reactiveEdges), a = this.servedEpoch ?? null;
|
|
1642
|
+
return n !== null && a === null ? Promise.resolve(H(n, a, "no-runtime")) : n !== null && typeof e.epoch == "string" && e.epoch !== a ? Promise.resolve(H(n, a, "epoch-changed")) : this.keyedPull({
|
|
1643
|
+
kind: "graph",
|
|
1644
|
+
key: `graph|${a ?? ""}|${n ?? "*"}|${r}|${i}`,
|
|
1645
|
+
epoch: a,
|
|
1646
|
+
scope: n,
|
|
1647
|
+
event: K.requestReactiveGraph,
|
|
1648
|
+
payload: {
|
|
1649
|
+
...n !== null && { componentId: n },
|
|
1650
|
+
maxNodes: r,
|
|
1651
|
+
maxEdges: i
|
|
1652
|
+
},
|
|
1653
|
+
empty: (e) => H(n, a, e)
|
|
1439
1654
|
});
|
|
1440
|
-
let a = `graph|${i ?? ""}|${t ?? "*"}|${n}|${r}`;
|
|
1441
|
-
return this.keyedPull("graph", a, i, t, I.requestReactiveGraph, {
|
|
1442
|
-
...t !== null && { componentId: t },
|
|
1443
|
-
maxNodes: n,
|
|
1444
|
-
maxEdges: r
|
|
1445
|
-
}, (e) => ({
|
|
1446
|
-
nodes: [],
|
|
1447
|
-
edges: [],
|
|
1448
|
-
scope: t,
|
|
1449
|
-
epoch: i,
|
|
1450
|
-
total: null,
|
|
1451
|
-
truncated: !1,
|
|
1452
|
-
edgesOmitted: 0,
|
|
1453
|
-
computedAt: null,
|
|
1454
|
-
policy: t === null ? "global-head" : "scoped",
|
|
1455
|
-
stale: !0,
|
|
1456
|
-
staleReason: e
|
|
1457
|
-
}));
|
|
1458
1655
|
}
|
|
1459
1656
|
requestReactiveSummary(e = {}) {
|
|
1460
|
-
let t =
|
|
1461
|
-
return this.keyedPull(
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
sampledActiveMs: 0
|
|
1471
|
-
},
|
|
1472
|
-
policy: "sampled-200ms",
|
|
1473
|
-
coverage: "component-init",
|
|
1474
|
-
components: {
|
|
1475
|
-
total: null,
|
|
1476
|
-
withActivity: 0
|
|
1477
|
-
},
|
|
1478
|
-
rows: [],
|
|
1479
|
-
other: null,
|
|
1480
|
-
truncated: !1,
|
|
1481
|
-
capabilities: {
|
|
1482
|
-
valueInspection: !1,
|
|
1483
|
-
signalHistory: !1,
|
|
1484
|
-
writeCause: !1
|
|
1657
|
+
let { topK: t, maxTopK: n, windowMs: r } = V, i = F(e.topK, 1, n, t), a = F(e.windowMs, V.minWindowMs, V.maxWindowMs, r), o = this.servedEpoch ?? null;
|
|
1658
|
+
return this.keyedPull({
|
|
1659
|
+
kind: "summary",
|
|
1660
|
+
key: `summary|${o ?? ""}|${i}|${a}`,
|
|
1661
|
+
epoch: o,
|
|
1662
|
+
scope: null,
|
|
1663
|
+
event: K.requestReactiveSummary,
|
|
1664
|
+
payload: {
|
|
1665
|
+
topK: i,
|
|
1666
|
+
windowMs: a
|
|
1485
1667
|
},
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
}));
|
|
1668
|
+
empty: (e) => Ct(o, a, e)
|
|
1669
|
+
});
|
|
1489
1670
|
}
|
|
1490
|
-
keyedPull(e
|
|
1491
|
-
let
|
|
1492
|
-
let
|
|
1493
|
-
return
|
|
1494
|
-
...
|
|
1671
|
+
keyedPull(e) {
|
|
1672
|
+
let { key: t, epoch: n } = e, r = (n) => {
|
|
1673
|
+
let r = this.pullCache.get(t);
|
|
1674
|
+
return r ? {
|
|
1675
|
+
...r.value,
|
|
1495
1676
|
stale: !0,
|
|
1496
|
-
staleReason:
|
|
1497
|
-
} :
|
|
1498
|
-
},
|
|
1499
|
-
if (!
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
this.pulls.set(d, {
|
|
1508
|
-
kind: e,
|
|
1677
|
+
staleReason: n
|
|
1678
|
+
} : e.empty(n);
|
|
1679
|
+
}, i = this.hot;
|
|
1680
|
+
if (!i) return Promise.resolve(r("no-runtime"));
|
|
1681
|
+
let a = this.pullCache.get(t);
|
|
1682
|
+
if (a && Date.now() - a.at < 1e3) return Promise.resolve(a.value);
|
|
1683
|
+
let o = this.pullInflight.get(t);
|
|
1684
|
+
if (o) return o;
|
|
1685
|
+
let s = `r${++this.requestSeq}`, c = new Promise((a) => {
|
|
1686
|
+
this.pulls.set(s, {
|
|
1687
|
+
kind: e.kind,
|
|
1509
1688
|
key: t,
|
|
1510
1689
|
epoch: n,
|
|
1511
|
-
scope:
|
|
1512
|
-
resolve:
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1690
|
+
scope: e.scope,
|
|
1691
|
+
resolve: a,
|
|
1692
|
+
fallback: r,
|
|
1693
|
+
timer: setTimeout(() => this.settle(s, "timeout"), Tt)
|
|
1694
|
+
}), i.send(e.event, {
|
|
1695
|
+
requestId: s,
|
|
1516
1696
|
...n !== null && { epoch: n },
|
|
1517
|
-
...
|
|
1697
|
+
...e.payload
|
|
1518
1698
|
});
|
|
1519
1699
|
}).finally(() => {
|
|
1520
|
-
this.pullInflight.get(t) ===
|
|
1700
|
+
this.pullInflight.get(t) === c && this.pullInflight.delete(t);
|
|
1521
1701
|
});
|
|
1522
|
-
return this.pullInflight.set(t,
|
|
1702
|
+
return this.pullInflight.set(t, c), c;
|
|
1523
1703
|
}
|
|
1524
1704
|
settle(e, t) {
|
|
1525
1705
|
let n = this.pulls.get(e);
|
|
1526
1706
|
if (n) {
|
|
1527
|
-
|
|
1707
|
+
if (this.pulls.delete(e), clearTimeout(n.timer), typeof t == "string") {
|
|
1708
|
+
n.resolve(n.fallback(t));
|
|
1709
|
+
return;
|
|
1710
|
+
}
|
|
1711
|
+
for (this.pullCache.delete(n.key), this.pullCache.set(n.key, {
|
|
1528
1712
|
value: t,
|
|
1529
1713
|
at: Date.now()
|
|
1530
|
-
}); this.pullCache.size >
|
|
1531
|
-
n.kind === "graph" && this.
|
|
1532
|
-
}
|
|
1533
|
-
}
|
|
1534
|
-
flushPulls(e) {
|
|
1535
|
-
for (let [t, n] of this.pulls) {
|
|
1536
|
-
this.pulls.delete(t), clearTimeout(n.timer);
|
|
1537
|
-
let r = this.pullCache.get(n.key);
|
|
1538
|
-
r ? n.resolve({
|
|
1539
|
-
...r.value,
|
|
1540
|
-
stale: !0,
|
|
1541
|
-
staleReason: e
|
|
1542
|
-
}) : n.kind === "graph" ? n.resolve({
|
|
1543
|
-
nodes: [],
|
|
1544
|
-
edges: [],
|
|
1545
|
-
scope: n.scope,
|
|
1546
|
-
epoch: n.epoch,
|
|
1547
|
-
total: null,
|
|
1548
|
-
truncated: !1,
|
|
1549
|
-
edgesOmitted: 0,
|
|
1550
|
-
computedAt: null,
|
|
1551
|
-
policy: n.scope === null ? "global-head" : "scoped",
|
|
1552
|
-
stale: !0,
|
|
1553
|
-
staleReason: e
|
|
1554
|
-
}) : n.resolve({
|
|
1555
|
-
epoch: n.epoch,
|
|
1556
|
-
window: {
|
|
1557
|
-
ms: 0,
|
|
1558
|
-
since: 0,
|
|
1559
|
-
until: 0,
|
|
1560
|
-
sampledActiveMs: 0
|
|
1561
|
-
},
|
|
1562
|
-
policy: "sampled-200ms",
|
|
1563
|
-
coverage: "component-init",
|
|
1564
|
-
components: {
|
|
1565
|
-
total: null,
|
|
1566
|
-
withActivity: 0
|
|
1567
|
-
},
|
|
1568
|
-
rows: [],
|
|
1569
|
-
other: null,
|
|
1570
|
-
truncated: !1,
|
|
1571
|
-
capabilities: {
|
|
1572
|
-
valueInspection: !1,
|
|
1573
|
-
signalHistory: !1,
|
|
1574
|
-
writeCause: !1
|
|
1575
|
-
},
|
|
1576
|
-
stale: !0,
|
|
1577
|
-
staleReason: e
|
|
1578
|
-
});
|
|
1714
|
+
}); this.pullCache.size > Dt;) this.pullCache.delete(this.pullCache.keys().next().value);
|
|
1715
|
+
n.kind === "graph" && (this.lastGraph = t), n.resolve(t);
|
|
1579
1716
|
}
|
|
1580
1717
|
}
|
|
1581
1718
|
requestStateTimeline() {
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
let t = n.indexOf(i);
|
|
1593
|
-
t !== -1 && n.splice(t, 1), e(r());
|
|
1594
|
-
}, Ye);
|
|
1595
|
-
n.push(i), a.send(t, {});
|
|
1719
|
+
let e = this.hot;
|
|
1720
|
+
if (!e || Date.now() - this.lastTimelinePull < 1e3) return Promise.resolve(this.stateTimeline);
|
|
1721
|
+
if (this.timelineInflight) return this.timelineInflight;
|
|
1722
|
+
let t = new Promise((t) => {
|
|
1723
|
+
let n = (e) => {
|
|
1724
|
+
clearTimeout(r), t(e);
|
|
1725
|
+
}, r = setTimeout(() => {
|
|
1726
|
+
this.timelineResolvers = this.timelineResolvers.filter((e) => e !== n), t(this.stateTimeline);
|
|
1727
|
+
}, Tt);
|
|
1728
|
+
this.timelineResolvers.push(n), e.send(K.requestStateTimeline, {});
|
|
1596
1729
|
}).finally(() => {
|
|
1597
|
-
this.
|
|
1730
|
+
this.timelineInflight === t && (this.timelineInflight = void 0);
|
|
1598
1731
|
});
|
|
1599
|
-
return this.
|
|
1732
|
+
return this.timelineInflight = t, t;
|
|
1600
1733
|
}
|
|
1601
1734
|
flushStateTimeline() {
|
|
1602
|
-
let e = this.
|
|
1603
|
-
this.
|
|
1735
|
+
let e = this.timelineResolvers;
|
|
1736
|
+
this.timelineResolvers = [];
|
|
1604
1737
|
for (let t of e) t(this.stateTimeline);
|
|
1605
1738
|
}
|
|
1606
1739
|
};
|
|
1607
1740
|
//#endregion
|
|
1741
|
+
//#region src/server/compiler-warnings.ts
|
|
1742
|
+
function At(e) {
|
|
1743
|
+
for (let t of e) {
|
|
1744
|
+
if (!t.name.startsWith("vite-plugin-svelte")) continue;
|
|
1745
|
+
let e = t.api?.options;
|
|
1746
|
+
if (typeof e == "object" && e) return e;
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
function jt(e, n) {
|
|
1750
|
+
let r = At(e);
|
|
1751
|
+
if (!r) return;
|
|
1752
|
+
let i = r.onwarn;
|
|
1753
|
+
r.onwarn = (e, r) => {
|
|
1754
|
+
e.filename?.includes("node_modules") || n({
|
|
1755
|
+
code: e.code,
|
|
1756
|
+
message: e.message,
|
|
1757
|
+
file: e.filename ? t.resolve(e.filename) : "",
|
|
1758
|
+
line: e.start?.line,
|
|
1759
|
+
column: e.start?.column
|
|
1760
|
+
}), i ? i(e, r) : r(e);
|
|
1761
|
+
};
|
|
1762
|
+
}
|
|
1763
|
+
//#endregion
|
|
1608
1764
|
//#region src/server/security.ts
|
|
1609
|
-
function
|
|
1610
|
-
let t;
|
|
1765
|
+
function Mt(e) {
|
|
1766
|
+
let t = Nt(e);
|
|
1767
|
+
if (t.protocol !== "http:" && t.protocol !== "https:") throw Error(`Blocked URL scheme: ${t.protocol}`);
|
|
1768
|
+
let n = Ft(t);
|
|
1769
|
+
if (p.isIP(n)) {
|
|
1770
|
+
if (Rt(n)) throw Error(`Blocked: private IP address ${n}`);
|
|
1771
|
+
} else if (It(n)) throw Error(`Blocked: internal hostname ${n}`);
|
|
1772
|
+
return t;
|
|
1773
|
+
}
|
|
1774
|
+
function Nt(e) {
|
|
1611
1775
|
try {
|
|
1612
|
-
|
|
1776
|
+
return new URL(e);
|
|
1613
1777
|
} catch {
|
|
1614
1778
|
throw Error(`Invalid URL: ${e}`);
|
|
1615
1779
|
}
|
|
1616
|
-
if (t.protocol !== "http:" && t.protocol !== "https:") throw Error(`Blocked URL scheme: ${t.protocol}`);
|
|
1617
|
-
let n = at(t);
|
|
1618
|
-
if (f.isIP(n)) {
|
|
1619
|
-
if (lt(n)) throw Error(`Blocked: private IP address ${n}`);
|
|
1620
|
-
} else if (ot(n)) throw Error(`Blocked: internal hostname ${n}`);
|
|
1621
|
-
return t;
|
|
1622
1780
|
}
|
|
1623
|
-
function
|
|
1624
|
-
return e.
|
|
1781
|
+
function Pt(e) {
|
|
1782
|
+
return e.startsWith("[") && e.endsWith("]") ? e.slice(1, -1) : e;
|
|
1783
|
+
}
|
|
1784
|
+
function Ft(e) {
|
|
1785
|
+
let t = Pt(e.hostname).toLowerCase();
|
|
1786
|
+
return t.endsWith(".") ? t.slice(0, -1) : t;
|
|
1625
1787
|
}
|
|
1626
|
-
function
|
|
1788
|
+
function It(e) {
|
|
1627
1789
|
return e === "localhost" || e.endsWith(".localhost") || e.endsWith(".local") || e.endsWith(".internal");
|
|
1628
1790
|
}
|
|
1629
|
-
async function
|
|
1630
|
-
let n;
|
|
1631
|
-
try {
|
|
1632
|
-
n = new URL(e);
|
|
1633
|
-
} catch {
|
|
1634
|
-
throw Error(`Invalid URL: ${e}`);
|
|
1635
|
-
}
|
|
1791
|
+
async function Lt(e, t = {}) {
|
|
1792
|
+
let n = Nt(e);
|
|
1636
1793
|
if (t.allowedOrigins?.includes(n.origin)) return n;
|
|
1637
|
-
|
|
1638
|
-
let r =
|
|
1639
|
-
if (
|
|
1794
|
+
Mt(e);
|
|
1795
|
+
let r = Ft(n);
|
|
1796
|
+
if (p.isIP(r)) return n;
|
|
1640
1797
|
let i;
|
|
1641
1798
|
try {
|
|
1642
|
-
i = await
|
|
1799
|
+
i = await f.lookup(r, { all: !0 });
|
|
1643
1800
|
} catch {
|
|
1644
1801
|
throw Error(`Blocked: ${r} does not resolve`);
|
|
1645
1802
|
}
|
|
1646
|
-
for (let { address: e } of i) if (
|
|
1803
|
+
for (let { address: e } of i) if (Rt(e)) throw Error(`Blocked: ${r} resolves to private address`);
|
|
1647
1804
|
return n;
|
|
1648
1805
|
}
|
|
1649
|
-
var
|
|
1806
|
+
var q = new p.BlockList();
|
|
1650
1807
|
for (let [e, t] of [
|
|
1651
1808
|
["0.0.0.0", 8],
|
|
1652
1809
|
["10.0.0.0", 8],
|
|
@@ -1662,52 +1819,33 @@ for (let [e, t] of [
|
|
|
1662
1819
|
["203.0.113.0", 24],
|
|
1663
1820
|
["224.0.0.0", 4],
|
|
1664
1821
|
["240.0.0.0", 4]
|
|
1665
|
-
])
|
|
1666
|
-
|
|
1822
|
+
]) {
|
|
1823
|
+
q.addSubnet(e, t, "ipv4");
|
|
1824
|
+
for (let n of [
|
|
1825
|
+
"::ffff:",
|
|
1826
|
+
"::",
|
|
1827
|
+
"64:ff9b::"
|
|
1828
|
+
]) q.addSubnet(n + e, 96 + t, "ipv6");
|
|
1829
|
+
let [n, r, i, a] = e.split(".").map(Number), o = `2002:${(n << 8 | r).toString(16)}:${(i << 8 | a).toString(16)}::`;
|
|
1830
|
+
q.addSubnet(o, 16 + t, "ipv6");
|
|
1831
|
+
}
|
|
1667
1832
|
for (let [e, t] of [
|
|
1668
|
-
["::", 128],
|
|
1669
|
-
["::1", 128],
|
|
1670
|
-
["::", 96],
|
|
1671
1833
|
["100::", 64],
|
|
1672
1834
|
["2001:db8::", 32],
|
|
1673
1835
|
["fc00::", 7],
|
|
1674
1836
|
["fe80::", 10],
|
|
1675
1837
|
["fec0::", 10],
|
|
1676
1838
|
["ff00::", 8]
|
|
1677
|
-
])
|
|
1678
|
-
function
|
|
1679
|
-
let t = e
|
|
1680
|
-
|
|
1681
|
-
if (n !== 6) return !0;
|
|
1682
|
-
let r = ft(ut(t));
|
|
1683
|
-
return r === null ? ct.check(t, "ipv6") : W.check(r, "ipv4");
|
|
1684
|
-
}
|
|
1685
|
-
function ut(e) {
|
|
1686
|
-
let t = e, n = /(\d+\.\d+\.\d+\.\d+)$/.exec(t);
|
|
1687
|
-
if (n) {
|
|
1688
|
-
let [e, r, i, a] = n[1].split(".").map(Number);
|
|
1689
|
-
t = `${t.slice(0, n.index)}${(e << 8 | r).toString(16)}:${(i << 8 | a).toString(16)}`;
|
|
1690
|
-
}
|
|
1691
|
-
let [r, i] = t.split("::");
|
|
1692
|
-
if (i === void 0) return G(r);
|
|
1693
|
-
let a = G(r), o = G(i);
|
|
1694
|
-
return [
|
|
1695
|
-
...a,
|
|
1696
|
-
...Array.from({ length: 8 - a.length - o.length }, () => 0),
|
|
1697
|
-
...o
|
|
1698
|
-
];
|
|
1699
|
-
}
|
|
1700
|
-
function G(e) {
|
|
1701
|
-
return e === "" ? [] : e.split(":").map((e) => Number.parseInt(e, 16));
|
|
1839
|
+
]) q.addSubnet(e, t, "ipv6");
|
|
1840
|
+
function Rt(e) {
|
|
1841
|
+
let t = Pt(e).toLowerCase(), n = p.isIP(t);
|
|
1842
|
+
return n === 0 || q.check(t, n === 4 ? "ipv4" : "ipv6");
|
|
1702
1843
|
}
|
|
1703
|
-
function
|
|
1704
|
-
|
|
1705
|
-
}
|
|
1706
|
-
function ft(e) {
|
|
1707
|
-
let [t, n, r, i, a, o, s, c] = e;
|
|
1708
|
-
return t === 0 && n === 0 && r === 0 && i === 0 && a === 0 && (o === 65535 || o === 0) && (s !== 0 || o === 65535) || t === 100 && n === 65435 && r === 0 && i === 0 && a === 0 && o === 0 ? dt(s, c) : t === 8194 ? dt(n, r) : null;
|
|
1844
|
+
function zt(e, n) {
|
|
1845
|
+
let r = t.relative(e, n);
|
|
1846
|
+
return r !== "" && r !== ".." && !r.startsWith(`..${t.sep}`) && !t.isAbsolute(r);
|
|
1709
1847
|
}
|
|
1710
|
-
function
|
|
1848
|
+
function Bt(e, n) {
|
|
1711
1849
|
if (typeof n != "string" || n.length === 0) throw Error("Invalid file path");
|
|
1712
1850
|
let i = r.realpathSync(e), a = t.isAbsolute(n) ? n : t.resolve(e, n), o;
|
|
1713
1851
|
try {
|
|
@@ -1715,13 +1853,13 @@ function K(e, n) {
|
|
|
1715
1853
|
} catch {
|
|
1716
1854
|
throw Error("File not found");
|
|
1717
1855
|
}
|
|
1718
|
-
if (o !== i && !
|
|
1856
|
+
if (o !== i && !zt(i, o)) throw Error("Forbidden: path outside project root");
|
|
1719
1857
|
return o;
|
|
1720
1858
|
}
|
|
1721
1859
|
//#endregion
|
|
1722
1860
|
//#region src/analyzers/http.ts
|
|
1723
|
-
var
|
|
1724
|
-
async function
|
|
1861
|
+
var Vt = 3e4;
|
|
1862
|
+
async function Ht(e, t, n, r = Vt) {
|
|
1725
1863
|
let i = new AbortController(), a, o = new Promise((e, t) => {
|
|
1726
1864
|
a = setTimeout(() => {
|
|
1727
1865
|
let e = /* @__PURE__ */ Error(`Timed out after ${r}ms`);
|
|
@@ -1741,7 +1879,7 @@ async function mt(e, t, n, r = pt) {
|
|
|
1741
1879
|
}
|
|
1742
1880
|
//#endregion
|
|
1743
1881
|
//#region src/analyzers/api.ts
|
|
1744
|
-
var
|
|
1882
|
+
var Ut = [
|
|
1745
1883
|
"GET",
|
|
1746
1884
|
"POST",
|
|
1747
1885
|
"PUT",
|
|
@@ -1750,8 +1888,8 @@ var ht = [
|
|
|
1750
1888
|
"HEAD",
|
|
1751
1889
|
"OPTIONS"
|
|
1752
1890
|
];
|
|
1753
|
-
function
|
|
1754
|
-
let { program: n, errors: r } =
|
|
1891
|
+
function Wt(e, t) {
|
|
1892
|
+
let { program: n, errors: r } = a(t, e);
|
|
1755
1893
|
if (r.length > 0) return null;
|
|
1756
1894
|
let i = /* @__PURE__ */ new Set();
|
|
1757
1895
|
for (let e of n.body) {
|
|
@@ -1766,16 +1904,16 @@ function gt(e, t) {
|
|
|
1766
1904
|
}
|
|
1767
1905
|
return i;
|
|
1768
1906
|
}
|
|
1769
|
-
function
|
|
1907
|
+
function Gt(e) {
|
|
1770
1908
|
let t = [];
|
|
1771
1909
|
for (let n of e) {
|
|
1772
1910
|
let e = n.files.find((e) => e.type === "endpoint");
|
|
1773
1911
|
if (!e) continue;
|
|
1774
1912
|
let i = null;
|
|
1775
1913
|
try {
|
|
1776
|
-
i =
|
|
1914
|
+
i = Wt(r.readFileSync(e.path, "utf-8"), e.path);
|
|
1777
1915
|
} catch {}
|
|
1778
|
-
let a = i?.has("fallback") ? [...
|
|
1916
|
+
let a = i?.has("fallback") ? [...Ut] : Ut.filter((e) => i?.has(e));
|
|
1779
1917
|
t.push({
|
|
1780
1918
|
route: n.id,
|
|
1781
1919
|
path: n.path,
|
|
@@ -1785,21 +1923,21 @@ function _t(e) {
|
|
|
1785
1923
|
}
|
|
1786
1924
|
return t;
|
|
1787
1925
|
}
|
|
1788
|
-
function
|
|
1926
|
+
function Kt(e) {
|
|
1789
1927
|
if (!e.trim()) return {};
|
|
1790
1928
|
let t = JSON.parse(e);
|
|
1791
1929
|
if (typeof t != "object" || !t || Array.isArray(t) || !Object.values(t).every((e) => typeof e == "string")) throw TypeError("Headers must be a JSON object of string values");
|
|
1792
1930
|
return t;
|
|
1793
1931
|
}
|
|
1794
|
-
async function
|
|
1932
|
+
async function qt(e, t = {}, n) {
|
|
1795
1933
|
let r = performance.now(), i = () => Math.round((performance.now() - r) * 100) / 100;
|
|
1796
1934
|
try {
|
|
1797
|
-
await
|
|
1935
|
+
await Lt(e.url, t);
|
|
1798
1936
|
let r = {
|
|
1799
1937
|
method: e.method,
|
|
1800
|
-
headers:
|
|
1938
|
+
headers: Kt(e.headers)
|
|
1801
1939
|
};
|
|
1802
|
-
return e.body && e.method !== "GET" && e.method !== "HEAD" && (r.body = e.body), await
|
|
1940
|
+
return e.body && e.method !== "GET" && e.method !== "HEAD" && (r.body = e.body), await Ht(e.url, r, async (e) => {
|
|
1803
1941
|
let t = await e.text(), n = {};
|
|
1804
1942
|
return e.headers.forEach((e, t) => {
|
|
1805
1943
|
n[t] = e;
|
|
@@ -1823,7 +1961,7 @@ async function yt(e, t = {}, n) {
|
|
|
1823
1961
|
}
|
|
1824
1962
|
//#endregion
|
|
1825
1963
|
//#region src/analyzers/assets.ts
|
|
1826
|
-
var
|
|
1964
|
+
var Jt = {
|
|
1827
1965
|
".png": "image/png",
|
|
1828
1966
|
".jpg": "image/jpeg",
|
|
1829
1967
|
".jpeg": "image/jpeg",
|
|
@@ -1850,17 +1988,17 @@ var bt = {
|
|
|
1850
1988
|
".js": "text/javascript",
|
|
1851
1989
|
".html": "text/html"
|
|
1852
1990
|
};
|
|
1853
|
-
function
|
|
1991
|
+
function Yt(e, t = "/") {
|
|
1854
1992
|
if (!r.existsSync(e)) return [];
|
|
1855
1993
|
let n = [];
|
|
1856
|
-
return
|
|
1994
|
+
return Xt(e, e, t.endsWith("/") ? t : `${t}/`, n), n.toSorted((e, t) => e.relativePath.localeCompare(t.relativePath));
|
|
1857
1995
|
}
|
|
1858
|
-
function
|
|
1996
|
+
function Xt(e, n, i, a) {
|
|
1859
1997
|
let o = r.readdirSync(e, { withFileTypes: !0 });
|
|
1860
1998
|
for (let s of o) {
|
|
1861
1999
|
let o = t.join(e, s.name);
|
|
1862
2000
|
if (s.isDirectory()) {
|
|
1863
|
-
|
|
2001
|
+
Xt(o, n, i, a);
|
|
1864
2002
|
continue;
|
|
1865
2003
|
}
|
|
1866
2004
|
if (s.name.startsWith(".")) continue;
|
|
@@ -1878,19 +2016,19 @@ function St(e, n, i, a) {
|
|
|
1878
2016
|
relativePath: u,
|
|
1879
2017
|
url: i + u.split(t.sep).map(encodeURIComponent).join("/"),
|
|
1880
2018
|
size: c.size,
|
|
1881
|
-
type:
|
|
2019
|
+
type: Jt[l] ?? "application/octet-stream",
|
|
1882
2020
|
mtime: c.mtimeMs
|
|
1883
2021
|
});
|
|
1884
2022
|
}
|
|
1885
2023
|
}
|
|
1886
2024
|
//#endregion
|
|
1887
2025
|
//#region src/analyzers/build.ts
|
|
1888
|
-
var
|
|
2026
|
+
var Zt = /* @__PURE__ */ new Set([
|
|
1889
2027
|
".js",
|
|
1890
2028
|
".css",
|
|
1891
2029
|
".html"
|
|
1892
2030
|
]);
|
|
1893
|
-
function
|
|
2031
|
+
function Qt(e) {
|
|
1894
2032
|
let n = [], i = /* @__PURE__ */ new Set(), a = [
|
|
1895
2033
|
t.resolve(e, ".svelte-kit/output"),
|
|
1896
2034
|
t.resolve(e, "build/client"),
|
|
@@ -1908,7 +2046,7 @@ function wt(e) {
|
|
|
1908
2046
|
o(s);
|
|
1909
2047
|
continue;
|
|
1910
2048
|
}
|
|
1911
|
-
if (!
|
|
2049
|
+
if (!Zt.has(t.extname(c.name).toLowerCase())) continue;
|
|
1912
2050
|
let l, u;
|
|
1913
2051
|
try {
|
|
1914
2052
|
l = r.realpathSync(s), u = r.statSync(l);
|
|
@@ -1933,33 +2071,31 @@ function wt(e) {
|
|
|
1933
2071
|
}
|
|
1934
2072
|
//#endregion
|
|
1935
2073
|
//#region src/analyzers/module-graph.ts
|
|
1936
|
-
function
|
|
2074
|
+
function $t(e) {
|
|
1937
2075
|
let n = t.extname(e).toLowerCase();
|
|
1938
2076
|
return n === ".svelte" ? "svelte" : n === ".ts" ? "ts" : n === ".js" ? "js" : n === ".css" ? "css" : "other";
|
|
1939
2077
|
}
|
|
1940
|
-
function
|
|
1941
|
-
let r = t.relative(e, n);
|
|
1942
|
-
return r !== "" && r !== ".." && !r.startsWith(`..${t.sep}`) && !t.isAbsolute(r);
|
|
1943
|
-
}
|
|
1944
|
-
function Dt(e, n) {
|
|
2078
|
+
function en(e, n) {
|
|
1945
2079
|
let i = [], a = /* @__PURE__ */ new Map();
|
|
1946
2080
|
for (let o of n) {
|
|
1947
|
-
if (!o.file || o.file
|
|
1948
|
-
let n;
|
|
2081
|
+
if (!o.file || a.has(o.file) || !zt(e, o.file)) continue;
|
|
2082
|
+
let n = t.relative(e, o.file);
|
|
2083
|
+
if (n.split(t.sep).includes("node_modules")) continue;
|
|
2084
|
+
let s;
|
|
1949
2085
|
try {
|
|
1950
|
-
|
|
2086
|
+
s = r.statSync(o.file).size;
|
|
1951
2087
|
} catch {}
|
|
1952
|
-
let
|
|
1953
|
-
id:
|
|
2088
|
+
let c = {
|
|
2089
|
+
id: n,
|
|
1954
2090
|
file: o.file,
|
|
1955
|
-
type:
|
|
2091
|
+
type: $t(o.file),
|
|
1956
2092
|
importedBy: [],
|
|
1957
2093
|
imports: [],
|
|
1958
|
-
size:
|
|
2094
|
+
size: s
|
|
1959
2095
|
};
|
|
1960
|
-
a.set(o.file,
|
|
2096
|
+
a.set(o.file, c), i.push(c);
|
|
1961
2097
|
}
|
|
1962
|
-
let o = /* @__PURE__ */ new Map()
|
|
2098
|
+
let o = /* @__PURE__ */ new Map();
|
|
1963
2099
|
for (let e of n) {
|
|
1964
2100
|
let t = e.file ? a.get(e.file) : void 0;
|
|
1965
2101
|
if (!t) continue;
|
|
@@ -1967,27 +2103,24 @@ function Dt(e, n) {
|
|
|
1967
2103
|
n || o.set(t, n = /* @__PURE__ */ new Set());
|
|
1968
2104
|
for (let r of e.importedModules) {
|
|
1969
2105
|
let e = r.file ? a.get(r.file) : void 0;
|
|
1970
|
-
|
|
1971
|
-
n.has(e.id) || (n.add(e.id), t.imports.push(e.id));
|
|
1972
|
-
let i = s.get(e);
|
|
1973
|
-
i || s.set(e, i = /* @__PURE__ */ new Set()), i.has(t.id) || (i.add(t.id), e.importedBy.push(t.id));
|
|
2106
|
+
e && e !== t && !n.has(e) && (n.add(e), t.imports.push(e.id), e.importedBy.push(t.id));
|
|
1974
2107
|
}
|
|
1975
2108
|
}
|
|
1976
|
-
let
|
|
1977
|
-
for (let e of
|
|
1978
|
-
let
|
|
2109
|
+
let s = new Map(i.map((e) => [e.id, e])), c = tn(i, s), l = /* @__PURE__ */ new Map();
|
|
2110
|
+
for (let e of c.values()) l.set(e, (l.get(e) ?? 0) + 1);
|
|
2111
|
+
let u = (e) => l.get(c.get(e)) > 1, d = [], f = /* @__PURE__ */ new Set();
|
|
1979
2112
|
for (let e of i) {
|
|
1980
|
-
if (!
|
|
1981
|
-
let t =
|
|
1982
|
-
for (let e of t)
|
|
1983
|
-
|
|
2113
|
+
if (!u(e.id) || (e.isCyclic = !0, f.has(e.id))) continue;
|
|
2114
|
+
let t = nn(e.id, s, c);
|
|
2115
|
+
for (let e of t) f.add(e);
|
|
2116
|
+
d.push(t);
|
|
1984
2117
|
}
|
|
1985
2118
|
return {
|
|
1986
2119
|
modules: i,
|
|
1987
|
-
cycles:
|
|
2120
|
+
cycles: d
|
|
1988
2121
|
};
|
|
1989
2122
|
}
|
|
1990
|
-
function
|
|
2123
|
+
function tn(e, t) {
|
|
1991
2124
|
let n = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map(), i = [], a = /* @__PURE__ */ new Set(), o = /* @__PURE__ */ new Map(), s = 0, c = 0, l = (e) => {
|
|
1992
2125
|
n.set(e, s), r.set(e, s), s++, i.push(e), a.add(e);
|
|
1993
2126
|
};
|
|
@@ -2021,7 +2154,7 @@ function Ot(e, t) {
|
|
|
2021
2154
|
}
|
|
2022
2155
|
return o;
|
|
2023
2156
|
}
|
|
2024
|
-
function
|
|
2157
|
+
function nn(e, t, n) {
|
|
2025
2158
|
let r = n.get(e), i = /* @__PURE__ */ new Map(), a = [e];
|
|
2026
2159
|
for (let o = 0; o < a.length; o++) {
|
|
2027
2160
|
let s = a[o];
|
|
@@ -2038,59 +2171,198 @@ function kt(e, t, n) {
|
|
|
2038
2171
|
return [e, e];
|
|
2039
2172
|
}
|
|
2040
2173
|
//#endregion
|
|
2041
|
-
//#region src/analyzers/
|
|
2042
|
-
var
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2174
|
+
//#region src/analyzers/html.ts
|
|
2175
|
+
var J = /* @__PURE__ */ new Set([
|
|
2176
|
+
" ",
|
|
2177
|
+
" ",
|
|
2178
|
+
"\n",
|
|
2179
|
+
"\f",
|
|
2180
|
+
"\r"
|
|
2181
|
+
]), rn = /* @__PURE__ */ new Set([
|
|
2182
|
+
"script",
|
|
2183
|
+
"style",
|
|
2184
|
+
"title",
|
|
2185
|
+
"textarea",
|
|
2186
|
+
"xmp",
|
|
2187
|
+
"iframe",
|
|
2188
|
+
"noembed",
|
|
2189
|
+
"noframes"
|
|
2190
|
+
]), an = (e) => e !== void 0 && (e >= "a" && e <= "z" || e >= "A" && e <= "Z");
|
|
2191
|
+
function* on(e) {
|
|
2192
|
+
let t = 0;
|
|
2193
|
+
for (; (t = e.indexOf("<", t)) !== -1;) {
|
|
2194
|
+
if (e.startsWith("<!--", t)) {
|
|
2195
|
+
let n = e.indexOf("-->", t + 4);
|
|
2196
|
+
if (n === -1) return;
|
|
2197
|
+
t = n + 3;
|
|
2198
|
+
continue;
|
|
2199
|
+
}
|
|
2200
|
+
let n = e[t + 1] === "/", r = t + (n ? 2 : 1);
|
|
2201
|
+
if (!an(e[r])) {
|
|
2202
|
+
if (e[t + 1] === "!" || e[t + 1] === "?" || n) {
|
|
2203
|
+
let n = e.indexOf(">", t);
|
|
2204
|
+
if (n === -1) return;
|
|
2205
|
+
t = n + 1;
|
|
2206
|
+
} else t++;
|
|
2207
|
+
continue;
|
|
2208
|
+
}
|
|
2209
|
+
let i = r;
|
|
2210
|
+
for (; i < e.length && !J.has(e[i]) && e[i] !== "/" && e[i] !== ">";) i++;
|
|
2211
|
+
let a = {
|
|
2212
|
+
name: e.slice(r, i).toLowerCase(),
|
|
2213
|
+
closing: n,
|
|
2214
|
+
selfClosing: !1,
|
|
2215
|
+
attrs: /* @__PURE__ */ new Map()
|
|
2216
|
+
};
|
|
2217
|
+
if (i = sn(e, i, a), i === -1) return;
|
|
2218
|
+
if (!n && !a.selfClosing && rn.has(a.name)) {
|
|
2219
|
+
let n = ln(e, a.name, i);
|
|
2220
|
+
if (a.text = e.slice(i, n === -1 ? e.length : n), yield a, n === -1) return;
|
|
2221
|
+
t = n;
|
|
2222
|
+
continue;
|
|
2223
|
+
}
|
|
2224
|
+
yield a, t = i;
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2227
|
+
function sn(e, t, n) {
|
|
2228
|
+
let r = t;
|
|
2229
|
+
for (;;) {
|
|
2230
|
+
for (; J.has(e[r]) || e[r] === "/";) n.selfClosing = e[r] === "/", r++;
|
|
2231
|
+
if (r >= e.length) return -1;
|
|
2232
|
+
if (e[r] === ">") return r + 1;
|
|
2233
|
+
n.selfClosing = !1;
|
|
2234
|
+
let t = r;
|
|
2235
|
+
for (r++; r < e.length && !J.has(e[r]) && e[r] !== "/" && e[r] !== ">" && e[r] !== "=";) r++;
|
|
2236
|
+
let i = e.slice(t, r).toLowerCase(), a = "", o = cn(e, r);
|
|
2237
|
+
if (e[o] === "=") {
|
|
2238
|
+
o = cn(e, o + 1);
|
|
2239
|
+
let t = e[o];
|
|
2240
|
+
if (t === "\"" || t === "'") {
|
|
2241
|
+
let n = e.indexOf(t, o + 1);
|
|
2242
|
+
if (n === -1) return -1;
|
|
2243
|
+
a = e.slice(o + 1, n), r = n + 1;
|
|
2244
|
+
} else {
|
|
2245
|
+
for (r = o; r < e.length && !J.has(e[r]) && e[r] !== ">";) r++;
|
|
2246
|
+
a = e.slice(o, r);
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2249
|
+
n.attrs.has(i) || n.attrs.set(i, a);
|
|
2250
|
+
}
|
|
2056
2251
|
}
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2252
|
+
function cn(e, t) {
|
|
2253
|
+
let n = t;
|
|
2254
|
+
for (; J.has(e[n]);) n++;
|
|
2255
|
+
return n;
|
|
2256
|
+
}
|
|
2257
|
+
function ln(e, t, n) {
|
|
2258
|
+
for (let r = e.indexOf("</", n); r !== -1; r = e.indexOf("</", r + 2)) {
|
|
2259
|
+
let n = e[r + 2 + t.length];
|
|
2260
|
+
if (e.slice(r + 2, r + 2 + t.length).toLowerCase() === t && (n === void 0 || n === ">" || n === "/" || J.has(n))) return r;
|
|
2261
|
+
}
|
|
2262
|
+
return -1;
|
|
2263
|
+
}
|
|
2264
|
+
var un = /* @__PURE__ */ new Map([
|
|
2265
|
+
["amp", "&"],
|
|
2266
|
+
["lt", "<"],
|
|
2267
|
+
["gt", ">"],
|
|
2268
|
+
["quot", "\""],
|
|
2269
|
+
["apos", "'"],
|
|
2270
|
+
["nbsp", "\xA0"]
|
|
2271
|
+
]);
|
|
2272
|
+
function dn(e) {
|
|
2273
|
+
let t = "", n = 0, r = e.indexOf("&");
|
|
2274
|
+
for (; r !== -1;) {
|
|
2275
|
+
let i = e.indexOf(";", r + 1);
|
|
2276
|
+
if (i === -1) break;
|
|
2277
|
+
let a = fn(e.slice(r + 1, i));
|
|
2278
|
+
a !== void 0 && (t += e.slice(n, r) + a, n = i + 1), r = e.indexOf("&", a === void 0 ? r + 1 : n);
|
|
2279
|
+
}
|
|
2280
|
+
return t + e.slice(n);
|
|
2281
|
+
}
|
|
2282
|
+
function fn(e) {
|
|
2283
|
+
if (!e.startsWith("#")) return un.get(e.toLowerCase());
|
|
2284
|
+
let t = e[1] === "x" || e[1] === "X", n = e.slice(t ? 2 : 1);
|
|
2285
|
+
if (!C(n, t ? ge : "0123456789")) return;
|
|
2286
|
+
let r = t ? Number.parseInt(n, 16) : Number(n);
|
|
2287
|
+
return r > 0 && r <= 1114111 ? String.fromCodePoint(r) : void 0;
|
|
2288
|
+
}
|
|
2289
|
+
function pn(e) {
|
|
2290
|
+
let t = "", n = !1;
|
|
2291
|
+
for (let r of e) {
|
|
2292
|
+
if (J.has(r)) {
|
|
2293
|
+
n = t !== "";
|
|
2294
|
+
continue;
|
|
2065
2295
|
}
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2296
|
+
n && (t += " "), n = !1, t += r;
|
|
2297
|
+
}
|
|
2298
|
+
return t;
|
|
2299
|
+
}
|
|
2300
|
+
//#endregion
|
|
2301
|
+
//#region src/analyzers/og.ts
|
|
2302
|
+
function mn(e) {
|
|
2303
|
+
let t = [];
|
|
2304
|
+
for (let n of on(e)) {
|
|
2305
|
+
if (n.name !== "meta" || n.closing) continue;
|
|
2306
|
+
let e = n.attrs.get("property") ?? n.attrs.get("name"), r = n.attrs.get("content");
|
|
2307
|
+
e && r !== void 0 && t.push({
|
|
2308
|
+
property: dn(e),
|
|
2309
|
+
content: dn(r)
|
|
2070
2310
|
});
|
|
2071
2311
|
}
|
|
2072
2312
|
return t;
|
|
2073
2313
|
}
|
|
2074
|
-
function
|
|
2075
|
-
|
|
2314
|
+
function hn(e) {
|
|
2315
|
+
let t = 0;
|
|
2316
|
+
for (let n of on(e)) if (n.name === "svg" && !n.selfClosing && (t += n.closing ? -1 : 1), n.name === "title" && n.text !== void 0 && t <= 0) return pn(dn(n.text));
|
|
2317
|
+
}
|
|
2318
|
+
function gn(e) {
|
|
2319
|
+
if (!e) return;
|
|
2320
|
+
let t = e.toLowerCase();
|
|
2321
|
+
for (let n = t.indexOf("charset"); n !== -1; n = t.indexOf("charset", n + 1)) {
|
|
2322
|
+
let t = n + 7;
|
|
2323
|
+
for (; J.has(e[t]);) t++;
|
|
2324
|
+
if (e[t] !== "=") continue;
|
|
2325
|
+
for (t++; J.has(e[t]);) t++;
|
|
2326
|
+
let r, i = e[t];
|
|
2327
|
+
if (i === "\"" || i === "'") {
|
|
2328
|
+
let n = e.indexOf(i, t + 1);
|
|
2329
|
+
if (n === -1) return;
|
|
2330
|
+
r = e.slice(t + 1, n).trim();
|
|
2331
|
+
} else {
|
|
2332
|
+
let n = t;
|
|
2333
|
+
for (; n < e.length && !J.has(e[n]) && e[n] !== ";";) n++;
|
|
2334
|
+
r = e.slice(t, n);
|
|
2335
|
+
}
|
|
2336
|
+
return r === "" ? void 0 : r;
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
function _n(e) {
|
|
2340
|
+
for (let t of on(e)) {
|
|
2341
|
+
if (t.name !== "meta" || t.closing) continue;
|
|
2342
|
+
let e = t.attrs.get("charset")?.trim();
|
|
2343
|
+
if (e) return e;
|
|
2344
|
+
if (t.attrs.get("http-equiv")?.toLowerCase() !== "content-type") continue;
|
|
2345
|
+
let n = gn(t.attrs.get("content"));
|
|
2346
|
+
if (n !== void 0) return n;
|
|
2347
|
+
}
|
|
2076
2348
|
}
|
|
2077
|
-
function
|
|
2078
|
-
let n = new TextDecoder("latin1").decode(e.subarray(0, 1024)), r =
|
|
2349
|
+
function vn(e, t) {
|
|
2350
|
+
let n = new TextDecoder("latin1").decode(e.subarray(0, 1024)), r = gn(t) ?? _n(n) ?? "utf-8", i;
|
|
2079
2351
|
try {
|
|
2080
|
-
|
|
2352
|
+
i = new TextDecoder(r);
|
|
2081
2353
|
} catch {
|
|
2082
|
-
|
|
2354
|
+
i = new TextDecoder("utf-8");
|
|
2083
2355
|
}
|
|
2084
|
-
return
|
|
2356
|
+
return i.decode(e);
|
|
2085
2357
|
}
|
|
2086
|
-
function
|
|
2358
|
+
function yn(e, t) {
|
|
2087
2359
|
try {
|
|
2088
2360
|
return new URL(e, t).href;
|
|
2089
2361
|
} catch {
|
|
2090
2362
|
return e;
|
|
2091
2363
|
}
|
|
2092
2364
|
}
|
|
2093
|
-
async function
|
|
2365
|
+
async function bn(e, t = {}, n) {
|
|
2094
2366
|
let r = {
|
|
2095
2367
|
url: e,
|
|
2096
2368
|
title: "",
|
|
@@ -2100,24 +2372,20 @@ async function Lt(e, t = {}, n) {
|
|
|
2100
2372
|
issues: []
|
|
2101
2373
|
};
|
|
2102
2374
|
try {
|
|
2103
|
-
await
|
|
2104
|
-
let i = await
|
|
2375
|
+
await Lt(e, t);
|
|
2376
|
+
let i = await Ht(e, {}, async (e) => ({
|
|
2105
2377
|
status: e.status,
|
|
2106
2378
|
location: e.headers.get("location"),
|
|
2107
|
-
html: e.status >= 300 && e.status < 400 ? "" :
|
|
2379
|
+
html: e.status >= 300 && e.status < 400 ? "" : vn(new Uint8Array(await e.arrayBuffer()), e.headers.get("content-type"))
|
|
2108
2380
|
}), n);
|
|
2109
2381
|
if (i.status >= 300 && i.status < 400) return r.issues.push(`Redirects to ${i.location ?? "(no location)"} (not followed)`), r;
|
|
2110
2382
|
i.status >= 400 && r.issues.push(`Responded with HTTP ${i.status}`);
|
|
2111
2383
|
let a = i.html;
|
|
2112
|
-
r.tags =
|
|
2384
|
+
r.tags = mn(a);
|
|
2113
2385
|
let o = (e) => r.tags.find((t) => t.property === e)?.content;
|
|
2114
2386
|
r.title = o("og:title") ?? "", r.description = o("og:description") ?? "";
|
|
2115
2387
|
let s = o("og:image");
|
|
2116
|
-
|
|
2117
|
-
let e = /<title\b[^>]*>([\s\S]*?)<\/title>/i.exec(a);
|
|
2118
|
-
e && (r.title = q(e[1]).replaceAll(/\s+/g, " ").trim());
|
|
2119
|
-
}
|
|
2120
|
-
r.description ||= o("description") ?? "", r.title || r.issues.push("Missing og:title or <title>"), r.description || r.issues.push("Missing og:description or meta description"), r.image || r.issues.push("Missing og:image"), r.tags.some((e) => e.property === "og:url") || r.issues.push("Missing og:url"), r.tags.some((e) => e.property === "og:type") || r.issues.push("Missing og:type");
|
|
2388
|
+
r.image = s ? yn(s, e) : "", r.title ||= hn(a) ?? "", r.description ||= o("description") ?? "", r.title || r.issues.push("Missing og:title or <title>"), r.description || r.issues.push("Missing og:description or meta description"), r.image || r.issues.push("Missing og:image"), r.tags.some((e) => e.property === "og:url") || r.issues.push("Missing og:url"), r.tags.some((e) => e.property === "og:type") || r.issues.push("Missing og:type");
|
|
2121
2389
|
} catch (e) {
|
|
2122
2390
|
r.issues.push(`Failed to fetch: ${String(e)}`);
|
|
2123
2391
|
}
|
|
@@ -2125,201 +2393,194 @@ async function Lt(e, t = {}, n) {
|
|
|
2125
2393
|
}
|
|
2126
2394
|
//#endregion
|
|
2127
2395
|
//#region src/analyzers/source.ts
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
if (!
|
|
2132
|
-
|
|
2133
|
-
|
|
2396
|
+
var xn;
|
|
2397
|
+
function Sn(e, t, n) {
|
|
2398
|
+
let r = n === "effect", i = r ? "$effect" : t.slice(t.lastIndexOf(".") + 1);
|
|
2399
|
+
if (!i || !e.includes(i)) return 0;
|
|
2400
|
+
xn?.source !== e && (xn = {
|
|
2401
|
+
source: e,
|
|
2402
|
+
index: Tn(e)
|
|
2403
|
+
});
|
|
2404
|
+
let { declared: a, effects: o, allEffects: s } = xn.index, c = r ? Cn(o, t) ?? s[0] : a.get(t);
|
|
2405
|
+
return c === void 0 ? 0 : wn(e, c);
|
|
2406
|
+
}
|
|
2407
|
+
function Cn(e, t) {
|
|
2408
|
+
let n = t.lastIndexOf("_"), r = Number(t.slice(n + 1));
|
|
2409
|
+
if (!(!Number.isInteger(r) || r < 1)) return e.get(t.slice(0, n))?.[r - 1];
|
|
2410
|
+
}
|
|
2411
|
+
function wn(e, t) {
|
|
2412
|
+
let n = 1;
|
|
2413
|
+
for (let r = e.indexOf("\n"); r !== -1 && r < t; r = e.indexOf("\n", r + 1)) n++;
|
|
2414
|
+
return n;
|
|
2415
|
+
}
|
|
2416
|
+
function Tn(e) {
|
|
2417
|
+
let t = {
|
|
2418
|
+
declared: /* @__PURE__ */ new Map(),
|
|
2419
|
+
effects: /* @__PURE__ */ new Map([["effect", []], ["effect_pre", []]]),
|
|
2420
|
+
allEffects: []
|
|
2421
|
+
}, n = (e, n) => {
|
|
2422
|
+
t.declared.has(e) || t.declared.set(e, n);
|
|
2423
|
+
};
|
|
2424
|
+
for (let { offset: r, result: i } of ee(e)) _(i.program, (e, i) => {
|
|
2425
|
+
if (e.type === "VariableDeclarator") Y(e.id, (e) => n(e.name, r + e.start));
|
|
2426
|
+
else if (e.type === "PropertyDefinition" && i !== void 0 && !e.computed) {
|
|
2427
|
+
let t = e.key, a = t.type === "PrivateIdentifier" ? `#${t.name}` : t.name;
|
|
2428
|
+
typeof a == "string" && n(`${i}.${a}`, r + e.start);
|
|
2429
|
+
} else {
|
|
2430
|
+
let n = En(e);
|
|
2431
|
+
n && (t.effects.get(n).push(r + e.start), t.allEffects.push(r + e.start));
|
|
2432
|
+
}
|
|
2433
|
+
});
|
|
2434
|
+
return t;
|
|
2435
|
+
}
|
|
2436
|
+
function En(e) {
|
|
2437
|
+
if (e.type !== "CallExpression") return;
|
|
2438
|
+
let t = e.callee;
|
|
2439
|
+
if (Dn(t, "$effect")) return "effect";
|
|
2440
|
+
if (t.type === "MemberExpression" && !t.computed && Dn(t.object, "$effect") && Dn(t.property, "pre")) return "effect_pre";
|
|
2441
|
+
}
|
|
2442
|
+
function Y(e, t) {
|
|
2443
|
+
if (e) switch (e.type) {
|
|
2444
|
+
case "Identifier":
|
|
2445
|
+
t(e);
|
|
2446
|
+
break;
|
|
2447
|
+
case "ObjectPattern":
|
|
2448
|
+
for (let n of e.properties) Y(n.type === "RestElement" ? n.argument : n.value, t);
|
|
2449
|
+
break;
|
|
2450
|
+
case "ArrayPattern":
|
|
2451
|
+
for (let n of e.elements) Y(n, t);
|
|
2452
|
+
break;
|
|
2453
|
+
case "AssignmentPattern":
|
|
2454
|
+
Y(e.left, t);
|
|
2455
|
+
break;
|
|
2456
|
+
case "RestElement": Y(e.argument, t);
|
|
2457
|
+
}
|
|
2458
|
+
}
|
|
2459
|
+
function Dn(e, t) {
|
|
2460
|
+
return e.type === "Identifier" && e.name === t;
|
|
2134
2461
|
}
|
|
2135
2462
|
//#endregion
|
|
2136
2463
|
//#region src/server/devframe.ts
|
|
2137
|
-
var
|
|
2138
|
-
function
|
|
2139
|
-
|
|
2464
|
+
var On = "svelte-devtools", X = "/.svelte-devtools/", kn = l(import.meta.url), An = kn.resolve("vite-devtools-svelte/package.json"), Z = kn(An), jn = t.join(t.dirname(An), "dist/client"), Mn = c.string().min(1).max(4096);
|
|
2465
|
+
function Nn(e, t, n) {
|
|
2466
|
+
return d({
|
|
2467
|
+
name: t,
|
|
2468
|
+
type: e,
|
|
2469
|
+
jsonSerializable: !0,
|
|
2470
|
+
handler: n
|
|
2471
|
+
});
|
|
2472
|
+
}
|
|
2473
|
+
var Q = (e, t) => Nn("query", e, t), $ = (e, t) => Nn("action", e, t);
|
|
2474
|
+
function Pn(e) {
|
|
2475
|
+
let { collector: t } = e, n = () => b(e.root()), i = () => ve(n().routesDir);
|
|
2140
2476
|
return [
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
handler: () => xt(n().staticDir, e.publicBase())
|
|
2158
|
-
}),
|
|
2159
|
-
l({
|
|
2160
|
-
name: "get-component-relations",
|
|
2161
|
-
type: "query",
|
|
2162
|
-
jsonSerializable: !0,
|
|
2163
|
-
handler: () => g(e.root())
|
|
2164
|
-
}),
|
|
2165
|
-
l({
|
|
2166
|
-
name: "get-svelte-files",
|
|
2167
|
-
type: "query",
|
|
2168
|
-
jsonSerializable: !0,
|
|
2169
|
-
handler: () => g(e.root()).map((e) => ({
|
|
2170
|
-
file: e.file,
|
|
2171
|
-
name: e.name
|
|
2172
|
-
}))
|
|
2173
|
-
}),
|
|
2174
|
-
l({
|
|
2175
|
-
name: "get-live-components",
|
|
2176
|
-
type: "query",
|
|
2177
|
-
jsonSerializable: !0,
|
|
2178
|
-
handler: () => t.liveComponents
|
|
2179
|
-
}),
|
|
2180
|
-
l({
|
|
2181
|
-
name: "get-live-components-meta",
|
|
2182
|
-
type: "query",
|
|
2183
|
-
jsonSerializable: !0,
|
|
2184
|
-
handler: () => ({
|
|
2185
|
-
total: t.liveComponentsTotal,
|
|
2186
|
-
kept: t.liveComponents.length,
|
|
2187
|
-
truncated: t.liveComponentsTotal > t.liveComponents.length,
|
|
2188
|
-
...t.epochInfo
|
|
2189
|
-
})
|
|
2190
|
-
}),
|
|
2191
|
-
l({
|
|
2477
|
+
Q("get-project", n),
|
|
2478
|
+
Q("get-routes", i),
|
|
2479
|
+
Q("get-assets", () => Yt(n().staticDir, e.publicBase())),
|
|
2480
|
+
Q("get-component-relations", () => v(e.root())),
|
|
2481
|
+
Q("get-svelte-files", () => v(e.root()).map((e) => ({
|
|
2482
|
+
file: e.file,
|
|
2483
|
+
name: e.name
|
|
2484
|
+
}))),
|
|
2485
|
+
Q("get-live-components", () => t.liveComponents),
|
|
2486
|
+
Q("get-live-components-meta", () => ({
|
|
2487
|
+
total: t.liveComponentsTotal,
|
|
2488
|
+
kept: t.liveComponents.length,
|
|
2489
|
+
truncated: t.liveComponentsTotal > t.liveComponents.length,
|
|
2490
|
+
...t.epochInfo
|
|
2491
|
+
})),
|
|
2492
|
+
d({
|
|
2192
2493
|
name: "set-active",
|
|
2193
2494
|
type: "action",
|
|
2194
2495
|
jsonSerializable: !0,
|
|
2195
|
-
args: [
|
|
2196
|
-
client:
|
|
2197
|
-
active:
|
|
2496
|
+
args: [c.object({
|
|
2497
|
+
client: c.string().min(1).max(64),
|
|
2498
|
+
active: c.boolean()
|
|
2198
2499
|
})],
|
|
2199
|
-
returns:
|
|
2500
|
+
returns: c.void(),
|
|
2200
2501
|
handler: ({ client: e, active: n }) => {
|
|
2201
2502
|
n ? t.lease(`ui:${e}`) : t.release(`ui:${e}`);
|
|
2202
2503
|
}
|
|
2203
2504
|
}),
|
|
2204
|
-
|
|
2505
|
+
d({
|
|
2205
2506
|
name: "open-in-editor",
|
|
2206
2507
|
type: "action",
|
|
2207
2508
|
jsonSerializable: !0,
|
|
2208
|
-
args: [
|
|
2209
|
-
file:
|
|
2210
|
-
line:
|
|
2509
|
+
args: [c.object({
|
|
2510
|
+
file: Mn,
|
|
2511
|
+
line: c.number().int().nonnegative().optional()
|
|
2211
2512
|
})],
|
|
2212
|
-
returns:
|
|
2513
|
+
returns: c.void(),
|
|
2213
2514
|
handler: ({ file: t, line: n }) => {
|
|
2214
|
-
let r =
|
|
2515
|
+
let r = Bt(e.root(), t);
|
|
2215
2516
|
e.openInEditor(n ? `${r}:${n}` : r);
|
|
2216
2517
|
}
|
|
2217
2518
|
}),
|
|
2218
|
-
|
|
2519
|
+
d({
|
|
2219
2520
|
name: "open-reactive-in-editor",
|
|
2220
2521
|
type: "action",
|
|
2221
2522
|
jsonSerializable: !0,
|
|
2222
|
-
args: [
|
|
2223
|
-
file:
|
|
2224
|
-
name:
|
|
2225
|
-
type:
|
|
2523
|
+
args: [c.object({
|
|
2524
|
+
file: Mn,
|
|
2525
|
+
name: c.string().max(256),
|
|
2526
|
+
type: c.string().max(32)
|
|
2226
2527
|
})],
|
|
2227
|
-
returns:
|
|
2528
|
+
returns: c.void(),
|
|
2228
2529
|
handler: ({ file: t, name: n, type: i }) => {
|
|
2229
|
-
let a =
|
|
2530
|
+
let a = Bt(e.root(), t), o = 0;
|
|
2230
2531
|
try {
|
|
2231
|
-
o =
|
|
2532
|
+
o = Sn(r.readFileSync(a, "utf-8"), n, i);
|
|
2232
2533
|
} catch {}
|
|
2233
2534
|
e.openInEditor(o > 0 ? `${a}:${o}` : a);
|
|
2234
2535
|
}
|
|
2235
2536
|
}),
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
type: "query",
|
|
2239
|
-
jsonSerializable: !0,
|
|
2240
|
-
handler: () => t.renderProfiles
|
|
2241
|
-
}),
|
|
2242
|
-
l({
|
|
2537
|
+
Q("get-render-profiles", () => t.renderProfiles),
|
|
2538
|
+
d({
|
|
2243
2539
|
name: "get-reactive-graph",
|
|
2244
2540
|
type: "query",
|
|
2245
2541
|
jsonSerializable: !0,
|
|
2246
|
-
args: [
|
|
2247
|
-
componentId:
|
|
2248
|
-
epoch:
|
|
2249
|
-
maxNodes:
|
|
2250
|
-
maxEdges:
|
|
2542
|
+
args: [c.object({
|
|
2543
|
+
componentId: c.number().int().nonnegative().optional(),
|
|
2544
|
+
epoch: c.string().max(200).optional(),
|
|
2545
|
+
maxNodes: c.number().int().positive().optional(),
|
|
2546
|
+
maxEdges: c.number().int().positive().optional()
|
|
2251
2547
|
}).optional()],
|
|
2252
|
-
returns:
|
|
2548
|
+
returns: c.custom(),
|
|
2253
2549
|
handler: (e) => t.requestReactiveGraph(e ?? {})
|
|
2254
2550
|
}),
|
|
2255
|
-
|
|
2551
|
+
d({
|
|
2256
2552
|
name: "get-reactive-summary",
|
|
2257
2553
|
type: "query",
|
|
2258
2554
|
jsonSerializable: !0,
|
|
2259
|
-
args: [
|
|
2260
|
-
topK:
|
|
2261
|
-
windowMs:
|
|
2555
|
+
args: [c.object({
|
|
2556
|
+
topK: c.number().int().positive().optional(),
|
|
2557
|
+
windowMs: c.number().int().positive().optional()
|
|
2262
2558
|
}).optional()],
|
|
2263
|
-
returns:
|
|
2559
|
+
returns: c.custom(),
|
|
2264
2560
|
handler: (e) => t.requestReactiveSummary(e ?? {})
|
|
2265
2561
|
}),
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
}),
|
|
2272
|
-
l({
|
|
2273
|
-
name: "get-load-profiles",
|
|
2274
|
-
type: "query",
|
|
2275
|
-
jsonSerializable: !0,
|
|
2276
|
-
handler: () => t.loadProfiles
|
|
2277
|
-
}),
|
|
2278
|
-
l({
|
|
2279
|
-
name: "clear-load-profiles",
|
|
2280
|
-
type: "action",
|
|
2281
|
-
jsonSerializable: !0,
|
|
2282
|
-
handler: () => t.clearLoadProfiles()
|
|
2283
|
-
}),
|
|
2284
|
-
l({
|
|
2285
|
-
name: "get-state-timeline",
|
|
2286
|
-
type: "query",
|
|
2287
|
-
jsonSerializable: !0,
|
|
2288
|
-
handler: () => t.requestStateTimeline()
|
|
2289
|
-
}),
|
|
2290
|
-
l({
|
|
2562
|
+
Q("get-capture-info", () => t.getCaptureInfo()),
|
|
2563
|
+
Q("get-load-profiles", () => t.loadProfiles),
|
|
2564
|
+
$("clear-load-profiles", () => t.clearLoadProfiles()),
|
|
2565
|
+
Q("get-state-timeline", () => t.requestStateTimeline()),
|
|
2566
|
+
d({
|
|
2291
2567
|
name: "get-state-timeline-delta",
|
|
2292
2568
|
type: "query",
|
|
2293
2569
|
jsonSerializable: !0,
|
|
2294
|
-
args: [
|
|
2295
|
-
returns:
|
|
2570
|
+
args: [c.object({ since: c.number().int().nonnegative().optional() })],
|
|
2571
|
+
returns: c.custom(),
|
|
2296
2572
|
handler: ({ since: e }) => t.getStateTimelineDelta(e)
|
|
2297
2573
|
}),
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
handler: () => ({ ...t.versions })
|
|
2303
|
-
}),
|
|
2304
|
-
l({
|
|
2305
|
-
name: "clear-state-timeline",
|
|
2306
|
-
type: "action",
|
|
2307
|
-
jsonSerializable: !0,
|
|
2308
|
-
handler: () => t.clearStateTimeline()
|
|
2309
|
-
}),
|
|
2310
|
-
l({
|
|
2311
|
-
name: "get-api-endpoints",
|
|
2312
|
-
type: "query",
|
|
2313
|
-
jsonSerializable: !0,
|
|
2314
|
-
handler: () => _t(i())
|
|
2315
|
-
}),
|
|
2316
|
-
l({
|
|
2574
|
+
Q("get-versions", () => ({ ...t.versions })),
|
|
2575
|
+
$("clear-state-timeline", () => t.clearStateTimeline()),
|
|
2576
|
+
Q("get-api-endpoints", () => Gt(i())),
|
|
2577
|
+
d({
|
|
2317
2578
|
name: "send-api-request",
|
|
2318
2579
|
type: "action",
|
|
2319
2580
|
jsonSerializable: !0,
|
|
2320
|
-
args: [
|
|
2321
|
-
url:
|
|
2322
|
-
method:
|
|
2581
|
+
args: [c.object({
|
|
2582
|
+
url: c.string().max(8192),
|
|
2583
|
+
method: c.enum([
|
|
2323
2584
|
"GET",
|
|
2324
2585
|
"POST",
|
|
2325
2586
|
"PUT",
|
|
@@ -2328,127 +2589,94 @@ function Ht(e) {
|
|
|
2328
2589
|
"HEAD",
|
|
2329
2590
|
"OPTIONS"
|
|
2330
2591
|
]),
|
|
2331
|
-
headers:
|
|
2332
|
-
body:
|
|
2592
|
+
headers: c.string().max(65536),
|
|
2593
|
+
body: c.string().max(1e6)
|
|
2333
2594
|
})],
|
|
2334
|
-
returns:
|
|
2335
|
-
handler: (t) =>
|
|
2336
|
-
}),
|
|
2337
|
-
l({
|
|
2338
|
-
name: "get-compiler-warnings",
|
|
2339
|
-
type: "query",
|
|
2340
|
-
jsonSerializable: !0,
|
|
2341
|
-
handler: () => t.compilerWarnings
|
|
2342
|
-
}),
|
|
2343
|
-
l({
|
|
2344
|
-
name: "get-runtime-errors",
|
|
2345
|
-
type: "query",
|
|
2346
|
-
jsonSerializable: !0,
|
|
2347
|
-
handler: () => t.runtimeErrors
|
|
2348
|
-
}),
|
|
2349
|
-
l({
|
|
2350
|
-
name: "clear-errors",
|
|
2351
|
-
type: "action",
|
|
2352
|
-
jsonSerializable: !0,
|
|
2353
|
-
handler: () => t.clearErrors()
|
|
2595
|
+
returns: c.custom(),
|
|
2596
|
+
handler: (t) => qt(t, { allowedOrigins: e.serverOrigins() })
|
|
2354
2597
|
}),
|
|
2355
|
-
|
|
2598
|
+
Q("get-compiler-warnings", () => t.compilerWarnings),
|
|
2599
|
+
Q("get-runtime-errors", () => t.runtimeErrors),
|
|
2600
|
+
$("clear-errors", () => t.clearErrors()),
|
|
2601
|
+
d({
|
|
2356
2602
|
name: "inspect-file",
|
|
2357
2603
|
type: "query",
|
|
2358
2604
|
jsonSerializable: !0,
|
|
2359
|
-
args: [
|
|
2360
|
-
returns:
|
|
2361
|
-
handler:
|
|
2362
|
-
let n = {
|
|
2363
|
-
source: "",
|
|
2364
|
-
compiled: "",
|
|
2365
|
-
file: t
|
|
2366
|
-
}, i, a;
|
|
2367
|
-
try {
|
|
2368
|
-
i = K(e.root(), t), a = r.readFileSync(i, "utf-8");
|
|
2369
|
-
} catch {
|
|
2370
|
-
return n;
|
|
2371
|
-
}
|
|
2372
|
-
if (!e.transformRequest) return {
|
|
2373
|
-
...n,
|
|
2374
|
-
source: a
|
|
2375
|
-
};
|
|
2376
|
-
try {
|
|
2377
|
-
let n = await e.transformRequest(i), r = Wt(n?.map);
|
|
2378
|
-
return {
|
|
2379
|
-
source: a,
|
|
2380
|
-
compiled: n?.code ?? "",
|
|
2381
|
-
file: t,
|
|
2382
|
-
mappings: r?.mappings,
|
|
2383
|
-
sources: r?.sources
|
|
2384
|
-
};
|
|
2385
|
-
} catch {
|
|
2386
|
-
return {
|
|
2387
|
-
source: a,
|
|
2388
|
-
compiled: "// Transform failed",
|
|
2389
|
-
file: t
|
|
2390
|
-
};
|
|
2391
|
-
}
|
|
2392
|
-
}
|
|
2393
|
-
}),
|
|
2394
|
-
l({
|
|
2395
|
-
name: "get-module-graph",
|
|
2396
|
-
type: "query",
|
|
2397
|
-
jsonSerializable: !0,
|
|
2398
|
-
handler: () => Dt(e.root(), e.modules())
|
|
2605
|
+
args: [c.object({ file: Mn })],
|
|
2606
|
+
returns: c.custom(),
|
|
2607
|
+
handler: ({ file: t }) => Fn(e, t)
|
|
2399
2608
|
}),
|
|
2400
|
-
|
|
2609
|
+
Q("get-module-graph", () => en(e.root(), e.modules())),
|
|
2610
|
+
d({
|
|
2401
2611
|
name: "get-og-preview",
|
|
2402
2612
|
type: "action",
|
|
2403
2613
|
jsonSerializable: !0,
|
|
2404
|
-
args: [
|
|
2405
|
-
returns:
|
|
2406
|
-
handler: ({ url: t }) =>
|
|
2407
|
-
}),
|
|
2408
|
-
l({
|
|
2409
|
-
name: "get-build-analysis",
|
|
2410
|
-
type: "query",
|
|
2411
|
-
jsonSerializable: !0,
|
|
2412
|
-
handler: () => wt(e.root())
|
|
2614
|
+
args: [c.object({ url: c.string().max(8192) })],
|
|
2615
|
+
returns: c.custom(),
|
|
2616
|
+
handler: ({ url: t }) => bn(t, { allowedOrigins: e.serverOrigins() })
|
|
2413
2617
|
}),
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
jsonSerializable: !0,
|
|
2418
|
-
handler: () => t.fpsSamples
|
|
2419
|
-
}),
|
|
2420
|
-
l({
|
|
2421
|
-
name: "clear-fps",
|
|
2422
|
-
type: "action",
|
|
2423
|
-
jsonSerializable: !0,
|
|
2424
|
-
handler: () => t.clearFps()
|
|
2425
|
-
})
|
|
2618
|
+
Q("get-build-analysis", () => Qt(e.root())),
|
|
2619
|
+
Q("get-fps", () => t.fpsSamples),
|
|
2620
|
+
$("clear-fps", () => t.clearFps())
|
|
2426
2621
|
];
|
|
2427
2622
|
}
|
|
2428
|
-
function
|
|
2429
|
-
|
|
2430
|
-
|
|
2623
|
+
async function Fn(e, t) {
|
|
2624
|
+
let n, i;
|
|
2625
|
+
try {
|
|
2626
|
+
n = Bt(e.root(), t), i = r.readFileSync(n, "utf-8");
|
|
2627
|
+
} catch {
|
|
2628
|
+
return {
|
|
2629
|
+
source: "",
|
|
2630
|
+
compiled: "",
|
|
2631
|
+
file: t
|
|
2632
|
+
};
|
|
2633
|
+
}
|
|
2634
|
+
if (!e.transformRequest) return {
|
|
2635
|
+
source: i,
|
|
2636
|
+
compiled: "",
|
|
2637
|
+
file: t
|
|
2638
|
+
};
|
|
2639
|
+
try {
|
|
2640
|
+
let r = await e.transformRequest(n), a = Ln(r?.map);
|
|
2641
|
+
return {
|
|
2642
|
+
source: i,
|
|
2643
|
+
compiled: r?.code ?? "",
|
|
2644
|
+
file: t,
|
|
2645
|
+
mappings: a?.mappings,
|
|
2646
|
+
sources: a?.sources
|
|
2647
|
+
};
|
|
2648
|
+
} catch {
|
|
2649
|
+
return {
|
|
2650
|
+
source: i,
|
|
2651
|
+
compiled: "// Transform failed",
|
|
2652
|
+
file: t
|
|
2653
|
+
};
|
|
2654
|
+
}
|
|
2655
|
+
}
|
|
2656
|
+
function In(e) {
|
|
2657
|
+
return u({
|
|
2658
|
+
id: On,
|
|
2431
2659
|
name: "Svelte",
|
|
2432
|
-
version:
|
|
2433
|
-
packageName:
|
|
2660
|
+
version: Z.version,
|
|
2661
|
+
packageName: Z.name,
|
|
2434
2662
|
importMetaUrl: import.meta.url,
|
|
2435
|
-
homepage:
|
|
2436
|
-
description:
|
|
2663
|
+
homepage: Z.homepage,
|
|
2664
|
+
description: Z.description,
|
|
2437
2665
|
icon: "simple-icons:svelte",
|
|
2438
|
-
basePath:
|
|
2666
|
+
basePath: X,
|
|
2439
2667
|
capabilities: {
|
|
2440
2668
|
dev: !0,
|
|
2441
2669
|
build: !1
|
|
2442
2670
|
},
|
|
2443
2671
|
dock: { category: "framework" },
|
|
2444
|
-
clientAssets:
|
|
2672
|
+
clientAssets: jn,
|
|
2445
2673
|
setup(t) {
|
|
2446
|
-
let n = t.scope(
|
|
2447
|
-
for (let t of
|
|
2674
|
+
let n = t.scope(On);
|
|
2675
|
+
for (let t of Pn(e)) n.rpc.register(t);
|
|
2448
2676
|
}
|
|
2449
2677
|
});
|
|
2450
2678
|
}
|
|
2451
|
-
function
|
|
2679
|
+
function Ln(e) {
|
|
2452
2680
|
if (typeof e != "string") return e ?? void 0;
|
|
2453
2681
|
let t = JSON.parse(e);
|
|
2454
2682
|
if (typeof t != "object" || !t) return;
|
|
@@ -2459,19 +2687,70 @@ function Wt(e) {
|
|
|
2459
2687
|
};
|
|
2460
2688
|
}
|
|
2461
2689
|
//#endregion
|
|
2690
|
+
//#region src/server/load-profile.ts
|
|
2691
|
+
var Rn = "__svelte_devtools_record_load", zn = {
|
|
2692
|
+
"+page.server.ts": "server",
|
|
2693
|
+
"+page.server.js": "server",
|
|
2694
|
+
"+layout.server.ts": "server",
|
|
2695
|
+
"+layout.server.js": "server",
|
|
2696
|
+
"+page.ts": "universal",
|
|
2697
|
+
"+page.js": "universal",
|
|
2698
|
+
"+layout.ts": "universal",
|
|
2699
|
+
"+layout.js": "universal"
|
|
2700
|
+
};
|
|
2701
|
+
function Bn(e, n) {
|
|
2702
|
+
let r = e.slice(0, e.lastIndexOf("/")), i = t.posix.join(n, "src/routes");
|
|
2703
|
+
if (r === i || r.startsWith(`${i}/`)) return r.slice(i.length) || "/";
|
|
2704
|
+
let a = r.split("/"), o = a.indexOf("routes");
|
|
2705
|
+
return o === -1 ? "/" : `/${a.slice(o + 1).join("/")}`;
|
|
2706
|
+
}
|
|
2707
|
+
function Vn(e, t, n) {
|
|
2708
|
+
let r = zn[t.slice(t.lastIndexOf("/") + 1)];
|
|
2709
|
+
if (!r || t.includes("node_modules") || !e.includes("load")) return null;
|
|
2710
|
+
let { module: i, errors: o } = a(t, e);
|
|
2711
|
+
if (o.length > 0) return null;
|
|
2712
|
+
let s = i.staticExports.find((e) => e.entries.some((e) => e.exportName.name === "load")), c = s?.entries.find((e) => e.exportName.name === "load");
|
|
2713
|
+
if (!s || c?.localName.name !== "load" || c.end !== s.end) return null;
|
|
2714
|
+
let l = s.entries.map((e) => e.localName.name).filter((e) => e !== "load");
|
|
2715
|
+
return e.slice(0, s.start) + e.slice(c.start) + Hn(l, Bn(t, n), t, r);
|
|
2716
|
+
}
|
|
2717
|
+
function Hn(e, t, n, r) {
|
|
2718
|
+
let i = [
|
|
2719
|
+
t,
|
|
2720
|
+
n,
|
|
2721
|
+
r
|
|
2722
|
+
].map((e) => JSON.stringify(e)).join(", ");
|
|
2723
|
+
return `${e.length > 0 ? `\nexport { ${e.join(", ")} };` : ""}
|
|
2724
|
+
const __profiled_load = async (event) => {
|
|
2725
|
+
const __start = performance.now();
|
|
2726
|
+
const __result = await load(event);
|
|
2727
|
+
try {
|
|
2728
|
+
const __duration = performance.now() - __start;
|
|
2729
|
+
let __dataSize = 0;
|
|
2730
|
+
try { __dataSize = JSON.stringify(__result || {}).length; } catch {}
|
|
2731
|
+
if (typeof globalThis.${Rn} === 'function') {
|
|
2732
|
+
globalThis.${Rn}(${i}, __duration, __dataSize);
|
|
2733
|
+
}
|
|
2734
|
+
} catch {}
|
|
2735
|
+
return __result;
|
|
2736
|
+
};
|
|
2737
|
+
export { __profiled_load as load };
|
|
2738
|
+
`;
|
|
2739
|
+
}
|
|
2740
|
+
//#endregion
|
|
2462
2741
|
//#region src/server/mount.ts
|
|
2463
|
-
var
|
|
2742
|
+
var Un = /* @__PURE__ */ new Set(["0.0.0.0", "::"]), Wn = /* @__PURE__ */ new Set([
|
|
2464
2743
|
"127.0.0.1",
|
|
2465
2744
|
"::1",
|
|
2466
2745
|
"localhost"
|
|
2467
2746
|
]);
|
|
2468
|
-
function
|
|
2469
|
-
return e.includes(":") ? `[${e}]` : e;
|
|
2747
|
+
function Gn(e) {
|
|
2748
|
+
return Wn.has(e) || Un.has(e) ? "localhost" : e.includes(":") ? `[${e}]` : e;
|
|
2470
2749
|
}
|
|
2471
|
-
function
|
|
2472
|
-
return
|
|
2750
|
+
function Kn(e, t) {
|
|
2751
|
+
return Wn.has(e.address) ? [] : (Un.has(e.address) ? Object.values(m.networkInterfaces()).flat().filter((e) => e && !e.internal).map((e) => e.address) : [e.address]).map((n) => `${t}://${Gn(n)}:${e.port}`);
|
|
2473
2752
|
}
|
|
2474
|
-
function
|
|
2753
|
+
function qn(e, t, { auth: n = !0 } = {}) {
|
|
2475
2754
|
let r, i = !1, a = e.httpServer;
|
|
2476
2755
|
if (e.middlewares.use((e, t, n) => {
|
|
2477
2756
|
if (r) return r.nodeMiddleware(e, t, n);
|
|
@@ -2481,8 +2760,8 @@ function Yt(e, t, { auth: n = !0 } = {}) {
|
|
|
2481
2760
|
}
|
|
2482
2761
|
n();
|
|
2483
2762
|
}), !a) {
|
|
2484
|
-
let e =
|
|
2485
|
-
base:
|
|
2763
|
+
let e = h(t, {
|
|
2764
|
+
base: X,
|
|
2486
2765
|
ws: !1,
|
|
2487
2766
|
sse: !0,
|
|
2488
2767
|
mcp: !1,
|
|
@@ -2496,34 +2775,34 @@ function Yt(e, t, { auth: n = !0 } = {}) {
|
|
|
2496
2775
|
let o = a.address();
|
|
2497
2776
|
if (i || !o || typeof o == "string") return;
|
|
2498
2777
|
let s = e.config.server.https ? "https" : "http", c = `${s}://localhost:${o.port}`;
|
|
2499
|
-
r =
|
|
2500
|
-
base:
|
|
2778
|
+
r = h(t, {
|
|
2779
|
+
base: X,
|
|
2501
2780
|
server: a,
|
|
2502
2781
|
mcp: !1,
|
|
2503
2782
|
auth: n,
|
|
2504
|
-
origin: `${c}${
|
|
2505
|
-
allowedOrigins:
|
|
2506
|
-
}), e.config.logger.info(` ➜ Svelte DevTools: ${c}${
|
|
2783
|
+
origin: `${c}${X}`,
|
|
2784
|
+
allowedOrigins: Kn(o, s)
|
|
2785
|
+
}), e.config.logger.info(` ➜ Svelte DevTools: ${c}${X}`);
|
|
2507
2786
|
}), a.once("close", () => {
|
|
2508
2787
|
i = !0;
|
|
2509
2788
|
let e = r;
|
|
2510
2789
|
r = void 0, e?.close().catch(() => {});
|
|
2511
2790
|
});
|
|
2512
2791
|
}
|
|
2513
|
-
var
|
|
2514
|
-
function
|
|
2515
|
-
if (!e.includes("templates: {") || !e.includes(
|
|
2516
|
-
let t = e.indexOf(
|
|
2517
|
-
return a === -1 ? null : e.slice(0, a) +
|
|
2792
|
+
var Jn = [".svelte-kit/generated/server/internal.js", ".svelte-kit/generated/dev/server.js"], Yn = "templates: {", Xn = `${g}embedded.js`, Zn = `<script type=\\"module\\" src=\\"${Xn}\\"><\/script>`, Qn = "</body>";
|
|
2793
|
+
function $n(e) {
|
|
2794
|
+
if (!e.includes("templates: {") || !e.includes(Qn) || e.includes(Xn)) return null;
|
|
2795
|
+
let t = e.indexOf(Yn), n = e.indexOf("app:", t), r = n === -1 ? -1 : e.indexOf("\n", n), i = n === -1 ? -1 : e.lastIndexOf(Qn, r === -1 ? e.length : r), a = i > n ? i : e.indexOf(Qn, t);
|
|
2796
|
+
return a === -1 ? null : e.slice(0, a) + Zn + e.slice(a);
|
|
2518
2797
|
}
|
|
2519
|
-
function
|
|
2798
|
+
function er(e) {
|
|
2520
2799
|
return {
|
|
2521
2800
|
name: "vite-devtools-svelte:sveltekit-template-injector",
|
|
2522
2801
|
enforce: "post",
|
|
2523
2802
|
apply: (e, t) => t.command === "serve" && !t.isSsrBuild,
|
|
2524
2803
|
transform(t, n) {
|
|
2525
|
-
if (!
|
|
2526
|
-
let r =
|
|
2804
|
+
if (!Jn.some((e) => n.endsWith(e)) || !e()) return null;
|
|
2805
|
+
let r = $n(t);
|
|
2527
2806
|
return r === null ? null : {
|
|
2528
2807
|
code: r,
|
|
2529
2808
|
map: null
|
|
@@ -2533,13 +2812,8 @@ function tn(e) {
|
|
|
2533
2812
|
}
|
|
2534
2813
|
//#endregion
|
|
2535
2814
|
//#region src/plugin.ts
|
|
2536
|
-
var
|
|
2537
|
-
function
|
|
2538
|
-
if (typeof t != "string") return !1;
|
|
2539
|
-
let r = Buffer.from(t), i = Buffer.from(n);
|
|
2540
|
-
return r.length === i.length && e.timingSafeEqual(r, i);
|
|
2541
|
-
}
|
|
2542
|
-
function on(e) {
|
|
2815
|
+
var tr = "vite:devtools", nr = 0;
|
|
2816
|
+
function rr(e) {
|
|
2543
2817
|
let t = [];
|
|
2544
2818
|
for (let n of Object.values(e.environments ?? {})) {
|
|
2545
2819
|
let e = n.moduleGraph;
|
|
@@ -2551,11 +2825,11 @@ function on(e) {
|
|
|
2551
2825
|
}
|
|
2552
2826
|
return t;
|
|
2553
2827
|
}
|
|
2554
|
-
function
|
|
2555
|
-
let { componentTracking: i = !0, clientAuth:
|
|
2828
|
+
function ir(r = {}) {
|
|
2829
|
+
let { componentTracking: i = !0, clientAuth: a = !0 } = r, o, s, c, l = !1, u = () => o?.command === "serve", d = e.randomUUID(), f = null;
|
|
2556
2830
|
function p() {
|
|
2557
|
-
return f ??= new
|
|
2558
|
-
persistDir: t.join(
|
|
2831
|
+
return f ??= new qe({
|
|
2832
|
+
persistDir: t.join(c, "node_modules", ".vite-devtools-svelte", "sessions"),
|
|
2559
2833
|
getters: {
|
|
2560
2834
|
getRenderProfiles: () => m.renderProfiles,
|
|
2561
2835
|
getLoadProfiles: () => m.loadProfiles,
|
|
@@ -2563,21 +2837,21 @@ function sn(r = {}) {
|
|
|
2563
2837
|
}
|
|
2564
2838
|
}), f;
|
|
2565
2839
|
}
|
|
2566
|
-
let m = new
|
|
2840
|
+
let m = new kt({
|
|
2567
2841
|
onFpsSample: (e) => p().recordFpsSample(e),
|
|
2568
2842
|
onLoadProfile: (e) => p().recordLoadProfile(e)
|
|
2569
|
-
}), h =
|
|
2843
|
+
}), h = In({
|
|
2570
2844
|
collector: m,
|
|
2571
|
-
root: () =>
|
|
2572
|
-
publicBase: () =>
|
|
2573
|
-
modules: () =>
|
|
2574
|
-
transformRequest: (e) =>
|
|
2845
|
+
root: () => c,
|
|
2846
|
+
publicBase: () => o?.base ?? "/",
|
|
2847
|
+
modules: () => s ? rr(s) : [],
|
|
2848
|
+
transformRequest: (e) => s ? s.transformRequest(e) : Promise.resolve(null),
|
|
2575
2849
|
serverOrigins: () => {
|
|
2576
|
-
let e =
|
|
2850
|
+
let e = s?.resolvedUrls;
|
|
2577
2851
|
return e ? [...e.local, ...e.network].map((e) => new URL(e).origin) : [];
|
|
2578
2852
|
},
|
|
2579
2853
|
openInEditor: (e) => n(e)
|
|
2580
|
-
}),
|
|
2854
|
+
}), g = [];
|
|
2581
2855
|
return [
|
|
2582
2856
|
{
|
|
2583
2857
|
name: "vite-devtools-svelte",
|
|
@@ -2585,89 +2859,64 @@ function sn(r = {}) {
|
|
|
2585
2859
|
apply: "serve",
|
|
2586
2860
|
api: { getDevtoolsToken: () => d },
|
|
2587
2861
|
configResolved(e) {
|
|
2588
|
-
|
|
2862
|
+
o = e, c = o.root, l = o.plugins.some((e) => e.name === tr);
|
|
2589
2863
|
},
|
|
2590
2864
|
configureServer(e) {
|
|
2591
|
-
|
|
2592
|
-
let t = ++
|
|
2865
|
+
s = e;
|
|
2866
|
+
let t = ++nr;
|
|
2593
2867
|
if (m.attach(e.hot), e.httpServer?.once("close", () => {
|
|
2594
|
-
|
|
2595
|
-
}), !
|
|
2596
|
-
let n =
|
|
2597
|
-
n &&
|
|
2868
|
+
s === e && (m.detach(), s = void 0);
|
|
2869
|
+
}), !l) {
|
|
2870
|
+
let n = qn(e, h, { auth: a });
|
|
2871
|
+
n && g.push({
|
|
2598
2872
|
generation: t,
|
|
2599
2873
|
dispose: n
|
|
2600
2874
|
});
|
|
2601
2875
|
}
|
|
2602
|
-
let n = () => Re({
|
|
2603
|
-
getProject: () => y(l),
|
|
2604
|
-
getRoutes: () => de(y(l).routesDir),
|
|
2605
|
-
getLiveComponents: () => m.liveComponents,
|
|
2606
|
-
getLiveSnapshot: () => m.liveSnapshot,
|
|
2607
|
-
getComponentRelations: () => g(l),
|
|
2608
|
-
getRenderProfiles: () => m.renderProfiles,
|
|
2609
|
-
getReactiveGraph: () => m.requestReactiveGraph(),
|
|
2610
|
-
getLoadProfiles: () => m.loadProfiles,
|
|
2611
|
-
getFpsSamples: () => m.fpsSamples,
|
|
2612
|
-
sessions: p(),
|
|
2613
|
-
getReactiveSummary: (e) => m.requestReactiveSummary(e),
|
|
2614
|
-
getReactiveScope: (e) => m.requestReactiveGraph(e),
|
|
2615
|
-
getStateTimelineDelta: (e) => m.getStateTimelineDelta(e),
|
|
2616
|
-
getCaptureInfo: () => m.getCaptureInfo()
|
|
2617
|
-
});
|
|
2618
2876
|
e.httpServer?.once("listening", () => {
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
}
|
|
2642
|
-
|
|
2643
|
-
} finally {
|
|
2644
|
-
await o.close().catch(() => {}), await i.close().catch(() => {});
|
|
2645
|
-
}
|
|
2646
|
-
};
|
|
2647
|
-
e.middlewares.use("/__svelte-devtools/mcp", (t, n) => {
|
|
2648
|
-
r(t, n).catch((t) => {
|
|
2649
|
-
e.config.logger.error(`[svelte-devtools] MCP handler error: ${String(t)}`), n.headersSent || (n.statusCode = 500, n.setHeader("Content-Type", "application/json"), n.end(JSON.stringify({ error: String(t) })));
|
|
2650
|
-
});
|
|
2651
|
-
});
|
|
2877
|
+
let t = e.httpServer?.address();
|
|
2878
|
+
if (!t || typeof t == "string") return;
|
|
2879
|
+
let n = `${e.config.server?.https ? "https" : "http"}://${Gn(t.address)}:${t.port}${Te}`, { logger: r } = e.config;
|
|
2880
|
+
r.info(""), r.info(" svelte-devtools MCP ready — register with Claude Code:"), r.info(` claude mcp add --transport http svelte ${n} --header x-svelte-devtools-token:${d}`), r.info("");
|
|
2881
|
+
}), e.middlewares.use(Te, Oe({
|
|
2882
|
+
token: d,
|
|
2883
|
+
collector: m,
|
|
2884
|
+
logger: e.config.logger,
|
|
2885
|
+
createServer: () => et({
|
|
2886
|
+
getProject: () => b(c),
|
|
2887
|
+
getRoutes: () => ve(b(c).routesDir),
|
|
2888
|
+
getLiveSnapshot: () => m.liveSnapshot,
|
|
2889
|
+
getComponentRelations: () => v(c),
|
|
2890
|
+
getRenderProfiles: () => m.renderProfiles,
|
|
2891
|
+
getReactiveGraph: () => m.requestReactiveGraph(),
|
|
2892
|
+
getLoadProfiles: () => m.loadProfiles,
|
|
2893
|
+
getFpsSamples: () => m.fpsSamples,
|
|
2894
|
+
sessions: p(),
|
|
2895
|
+
getReactiveSummary: (e) => m.requestReactiveSummary(e),
|
|
2896
|
+
getReactiveScope: (e) => m.requestReactiveGraph(e),
|
|
2897
|
+
getStateTimelineDelta: (e) => m.getStateTimelineDelta(e),
|
|
2898
|
+
getCaptureInfo: () => m.getCaptureInfo()
|
|
2899
|
+
})
|
|
2900
|
+
}));
|
|
2652
2901
|
},
|
|
2653
2902
|
async closeServer({ reason: e }) {
|
|
2654
|
-
let t =
|
|
2655
|
-
for (let e of t)
|
|
2903
|
+
let t = g.filter((t) => e === "close" || t.generation < nr);
|
|
2904
|
+
for (let e of t) g.splice(g.indexOf(e), 1);
|
|
2656
2905
|
await Promise.all(t.map((e) => e.dispose()));
|
|
2657
2906
|
},
|
|
2658
2907
|
resolveId(e, t) {
|
|
2659
|
-
return
|
|
2908
|
+
return u() ? e === "virtual:svelte-devtools-runtime" ? it : i && e === "svelte/internal/client" && t && !t.includes("node_modules") && !t.startsWith("\0") ? at : null : null;
|
|
2660
2909
|
},
|
|
2661
2910
|
load(e) {
|
|
2662
|
-
return
|
|
2911
|
+
return u() ? e === "\0virtual:svelte-devtools-runtime" ? st : e === "\0svelte-devtools:wrapped-client" ? ot : null : null;
|
|
2663
2912
|
},
|
|
2664
2913
|
transformIndexHtml: {
|
|
2665
2914
|
order: "pre",
|
|
2666
2915
|
handler() {
|
|
2667
|
-
return
|
|
2916
|
+
return u() ? [{
|
|
2668
2917
|
tag: "script",
|
|
2669
2918
|
attrs: { type: "module" },
|
|
2670
|
-
children: `import '${
|
|
2919
|
+
children: `import '${rt}'`,
|
|
2671
2920
|
injectTo: "head-prepend"
|
|
2672
2921
|
}] : [];
|
|
2673
2922
|
}
|
|
@@ -2679,7 +2928,7 @@ function sn(r = {}) {
|
|
|
2679
2928
|
},
|
|
2680
2929
|
async setup(e) {
|
|
2681
2930
|
let { createPluginFromDevframe: t } = await import("@vitejs/devtools-kit/node");
|
|
2682
|
-
await t(h, { base:
|
|
2931
|
+
await t(h, { base: X }).devtools?.setup?.(e);
|
|
2683
2932
|
}
|
|
2684
2933
|
}
|
|
2685
2934
|
},
|
|
@@ -2688,8 +2937,8 @@ function sn(r = {}) {
|
|
|
2688
2937
|
enforce: "post",
|
|
2689
2938
|
apply: "serve",
|
|
2690
2939
|
transform(e, t, n) {
|
|
2691
|
-
if (!i || t.includes("node_modules") ||
|
|
2692
|
-
let [r = t] = t.split("?"), a = r.endsWith(".svelte") ?
|
|
2940
|
+
if (!i || !u() || t.includes("node_modules") || n?.ssr) return null;
|
|
2941
|
+
let [r = t] = t.split("?"), a = r.endsWith(".svelte") ? mt(e, r) : gt(r) ? _t(e, r) : null;
|
|
2693
2942
|
return a === null ? null : {
|
|
2694
2943
|
code: a,
|
|
2695
2944
|
map: null
|
|
@@ -2700,47 +2949,24 @@ function sn(r = {}) {
|
|
|
2700
2949
|
name: "vite-devtools-svelte:load-profile",
|
|
2701
2950
|
enforce: "post",
|
|
2702
2951
|
apply: "serve",
|
|
2703
|
-
transform(e, t) {
|
|
2704
|
-
if (s?.command !== "serve") return null;
|
|
2705
|
-
let n = /\+page\.server\.[tj]s$/.test(t) || /\+layout\.server\.[tj]s$/.test(t), r = /\+(page|layout)\.[tj]s$/.test(t) && !t.includes(".server.");
|
|
2706
|
-
if (!n && !r || t.includes("node_modules") || !e.includes("export") || !e.includes("load")) return null;
|
|
2707
|
-
let i = n ? "server" : "universal", a = (t.match(/routes(.*)\/\+/)?.[1] ?? "") || "/", o = JSON.stringify(a), c = JSON.stringify(t), l = JSON.stringify(i), u = e.replace(/export\s+(const|let|var)\s+load\s*=\s*/, "$1 __original_load = ");
|
|
2708
|
-
if (u === e && (u = e.replace(/export\s+(async\s+)?function\s+load\s*\(/, "const __original_load = $1function __load_impl(")), u === e) return null;
|
|
2709
|
-
let d = `
|
|
2710
|
-
export const load = async (event) => {
|
|
2711
|
-
const __start = performance.now();
|
|
2712
|
-
const __result = await __original_load(event);
|
|
2713
|
-
try {
|
|
2714
|
-
const __duration = performance.now() - __start;
|
|
2715
|
-
let __dataSize = 0;
|
|
2716
|
-
try { __dataSize = JSON.stringify(__result || {}).length; } catch {}
|
|
2717
|
-
if (typeof globalThis.__svelte_devtools_record_load === 'function') {
|
|
2718
|
-
globalThis.__svelte_devtools_record_load(${o}, ${c}, ${l}, __duration, __dataSize);
|
|
2719
|
-
}
|
|
2720
|
-
} catch {}
|
|
2721
|
-
return __result;
|
|
2722
|
-
};
|
|
2723
|
-
`;
|
|
2724
|
-
return {
|
|
2725
|
-
code: u + d,
|
|
2726
|
-
map: null
|
|
2727
|
-
};
|
|
2728
|
-
}
|
|
2729
|
-
},
|
|
2730
|
-
{
|
|
2731
|
-
name: "vite-devtools-svelte:load-profile-server",
|
|
2732
|
-
apply: "serve",
|
|
2733
2952
|
configureServer() {
|
|
2734
|
-
globalThis
|
|
2735
|
-
|
|
2953
|
+
globalThis[Rn] = (e, t, n, r, i) => {
|
|
2954
|
+
m.recordLoadProfile({
|
|
2736
2955
|
route: e,
|
|
2737
2956
|
file: t,
|
|
2738
2957
|
type: n,
|
|
2739
2958
|
duration: Math.round(r * 100) / 100,
|
|
2740
2959
|
dataSize: i,
|
|
2741
2960
|
timestamp: Date.now()
|
|
2742
|
-
};
|
|
2743
|
-
|
|
2961
|
+
});
|
|
2962
|
+
};
|
|
2963
|
+
},
|
|
2964
|
+
transform(e, t) {
|
|
2965
|
+
if (!u()) return null;
|
|
2966
|
+
let n = Vn(e, t, c);
|
|
2967
|
+
return n === null ? null : {
|
|
2968
|
+
code: n,
|
|
2969
|
+
map: null
|
|
2744
2970
|
};
|
|
2745
2971
|
}
|
|
2746
2972
|
},
|
|
@@ -2749,29 +2975,13 @@ export const load = async (event) => {
|
|
|
2749
2975
|
enforce: "post",
|
|
2750
2976
|
apply: "serve",
|
|
2751
2977
|
configResolved(e) {
|
|
2752
|
-
|
|
2753
|
-
if (t[$] = (e) => {
|
|
2754
|
-
let t = e.replaceAll(/\u001B\[[0-9;]*m/g, "").trim();
|
|
2755
|
-
if (!t.includes(".svelte") || s?.command !== "serve") return;
|
|
2756
|
-
let n = t.match(/(?:^|\s)((?:\/|\.\/|\w:)[^\s:]+\.svelte)(?::(\d+):(\d+))?/), r = t.match(/\(([a-z0-9_-]+)\)/);
|
|
2757
|
-
m.recordCompilerWarning({
|
|
2758
|
-
code: r?.[1] ?? "unknown",
|
|
2759
|
-
message: t,
|
|
2760
|
-
file: n?.[1] ?? "",
|
|
2761
|
-
line: n?.[2] ? Number(n[2]) : void 0,
|
|
2762
|
-
column: n?.[3] ? Number(n[3]) : void 0
|
|
2763
|
-
});
|
|
2764
|
-
}, n) return;
|
|
2765
|
-
let r = t.warn.bind(t);
|
|
2766
|
-
t.warn = (e, n) => {
|
|
2767
|
-
t[$]?.(e), r(e, n);
|
|
2768
|
-
};
|
|
2978
|
+
e.command === "serve" && jt(e.plugins, (e) => m.recordCompilerWarning(e));
|
|
2769
2979
|
}
|
|
2770
2980
|
},
|
|
2771
|
-
|
|
2981
|
+
er(() => l)
|
|
2772
2982
|
];
|
|
2773
2983
|
}
|
|
2774
2984
|
//#endregion
|
|
2775
|
-
export {
|
|
2985
|
+
export { ir as svelteDevtools };
|
|
2776
2986
|
|
|
2777
2987
|
//# sourceMappingURL=index.mjs.map
|