assafvayner HF Staff commited on
Commit
9e075cf
·
0 Parent(s):
Files changed (11) hide show
  1. .gitignore +1 -0
  2. README.md +97 -0
  3. index.html +16 -0
  4. package-lock.json +899 -0
  5. package.json +15 -0
  6. public/sample.txt +0 -0
  7. sample.txt +0 -0
  8. src/App.svelte +257 -0
  9. src/app.css +192 -0
  10. src/main.js +8 -0
  11. vite.config.js +6 -0
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ node_modules/
README.md ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 🔍 Backtrace Viewer
2
+
3
+ A modern web application for viewing and analyzing backtrace files from sampling profilers, built with Svelte.
4
+
5
+ ## Features
6
+
7
+ - **📁 File Upload**: Load your own backtrace files or use the included sample
8
+ - **🔍 Thread Filtering**: Filter threads by name using exact prefix matching
9
+ - **👀 Toggle Views**: Expand/collapse individual threads to focus on what matters
10
+ - **📊 Collapsible Backtraces**: Click on any backtrace line to collapse/expand sections
11
+ - **📱 Responsive Design**: Works great on desktop and mobile devices
12
+ - **⚡ Fast Performance**: Built with Svelte for optimal performance
13
+
14
+ ## Getting Started
15
+
16
+ ### Prerequisites
17
+
18
+ - Node.js (version 14 or higher)
19
+ - npm or yarn
20
+
21
+ ### Installation
22
+
23
+ 1. Clone or navigate to the project directory:
24
+
25
+ ```bash
26
+ cd backtrace-viewer
27
+ ```
28
+
29
+ 2. Install dependencies:
30
+
31
+ ```bash
32
+ npm install
33
+ ```
34
+
35
+ 3. Start the development server:
36
+
37
+ ```bash
38
+ npm run dev
39
+ ```
40
+
41
+ 4. Open your browser to `http://localhost:5173`
42
+
43
+ ### Building for Production
44
+
45
+ ```bash
46
+ npm run build
47
+ ```
48
+
49
+ The built files will be in the `dist/` directory.
50
+
51
+ ## Usage
52
+
53
+ ### Loading Files
54
+
55
+ - The app will automatically load `sample.txt` when you open it
56
+ - Click "📁 Load Backtrace File" to upload your own backtrace files
57
+ - Supported format: Text files from sampling profilers (like macOS `sample` command)
58
+
59
+ ### Filtering Threads
60
+
61
+ - Use the filter input to find threads by name
62
+ - Only shows threads whose names start with your filter text (case-insensitive)
63
+ - Thread names are extracted from the part after the `:` in thread headers
64
+
65
+ ### Viewing Backtraces
66
+
67
+ - Click on any thread header to expand/collapse its backtrace
68
+ - Click on individual backtrace lines to collapse/expand sections
69
+ - Indentation shows the call hierarchy
70
+ - Sample counts and function names are highlighted for easy reading
71
+
72
+ ### File Format Support
73
+
74
+ The viewer supports backtrace files with this format:
75
+
76
+ ```
77
+ 6963 Thread_10032126: hf-xet-0
78
+ + 6963 thread_start (in libsystem_pthread.dylib) + 8 [0x19e40ab80]
79
+ + 6963 _pthread_start (in libsystem_pthread.dylib) + 136 [0x19e40fc0c]
80
+ + 6963 pythread_wrapper (in Python) + 48 [0x104da7cd0]
81
+ ...
82
+ ```
83
+
84
+ Where:
85
+
86
+ - Thread headers: `{count} Thread_{id}: {name}`
87
+ - Thread names: Optional part after `:`
88
+ - Backtrace lines: Indented with `+`, `!`, `:`, `|` characters
89
+ - Sample counts, function names, and addresses are automatically highlighted
90
+
91
+ ## Contributing
92
+
93
+ Feel free to open issues or submit pull requests to improve the viewer!
94
+
95
+ ## License
96
+
97
+ MIT License
index.html ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
7
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
+ <title>Backtrace Viewer</title>
9
+ </head>
10
+
11
+ <body>
12
+ <div id="app"></div>
13
+ <script type="module" src="/src/main.js"></script>
14
+ </body>
15
+
16
+ </html>
package-lock.json ADDED
@@ -0,0 +1,899 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "backtrace-viewer",
3
+ "version": "1.0.0",
4
+ "lockfileVersion": 3,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "backtrace-viewer",
9
+ "version": "1.0.0",
10
+ "devDependencies": {
11
+ "@sveltejs/vite-plugin-svelte": "^2.4.2",
12
+ "svelte": "^4.0.5",
13
+ "vite": "^4.4.5"
14
+ }
15
+ },
16
+ "node_modules/@ampproject/remapping": {
17
+ "version": "2.3.0",
18
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
19
+ "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
20
+ "dev": true,
21
+ "license": "Apache-2.0",
22
+ "dependencies": {
23
+ "@jridgewell/gen-mapping": "^0.3.5",
24
+ "@jridgewell/trace-mapping": "^0.3.24"
25
+ },
26
+ "engines": {
27
+ "node": ">=6.0.0"
28
+ }
29
+ },
30
+ "node_modules/@esbuild/android-arm": {
31
+ "version": "0.18.20",
32
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
33
+ "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==",
34
+ "cpu": [
35
+ "arm"
36
+ ],
37
+ "dev": true,
38
+ "license": "MIT",
39
+ "optional": true,
40
+ "os": [
41
+ "android"
42
+ ],
43
+ "engines": {
44
+ "node": ">=12"
45
+ }
46
+ },
47
+ "node_modules/@esbuild/android-arm64": {
48
+ "version": "0.18.20",
49
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz",
50
+ "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==",
51
+ "cpu": [
52
+ "arm64"
53
+ ],
54
+ "dev": true,
55
+ "license": "MIT",
56
+ "optional": true,
57
+ "os": [
58
+ "android"
59
+ ],
60
+ "engines": {
61
+ "node": ">=12"
62
+ }
63
+ },
64
+ "node_modules/@esbuild/android-x64": {
65
+ "version": "0.18.20",
66
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz",
67
+ "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==",
68
+ "cpu": [
69
+ "x64"
70
+ ],
71
+ "dev": true,
72
+ "license": "MIT",
73
+ "optional": true,
74
+ "os": [
75
+ "android"
76
+ ],
77
+ "engines": {
78
+ "node": ">=12"
79
+ }
80
+ },
81
+ "node_modules/@esbuild/darwin-arm64": {
82
+ "version": "0.18.20",
83
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz",
84
+ "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==",
85
+ "cpu": [
86
+ "arm64"
87
+ ],
88
+ "dev": true,
89
+ "license": "MIT",
90
+ "optional": true,
91
+ "os": [
92
+ "darwin"
93
+ ],
94
+ "engines": {
95
+ "node": ">=12"
96
+ }
97
+ },
98
+ "node_modules/@esbuild/darwin-x64": {
99
+ "version": "0.18.20",
100
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz",
101
+ "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==",
102
+ "cpu": [
103
+ "x64"
104
+ ],
105
+ "dev": true,
106
+ "license": "MIT",
107
+ "optional": true,
108
+ "os": [
109
+ "darwin"
110
+ ],
111
+ "engines": {
112
+ "node": ">=12"
113
+ }
114
+ },
115
+ "node_modules/@esbuild/freebsd-arm64": {
116
+ "version": "0.18.20",
117
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz",
118
+ "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==",
119
+ "cpu": [
120
+ "arm64"
121
+ ],
122
+ "dev": true,
123
+ "license": "MIT",
124
+ "optional": true,
125
+ "os": [
126
+ "freebsd"
127
+ ],
128
+ "engines": {
129
+ "node": ">=12"
130
+ }
131
+ },
132
+ "node_modules/@esbuild/freebsd-x64": {
133
+ "version": "0.18.20",
134
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz",
135
+ "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==",
136
+ "cpu": [
137
+ "x64"
138
+ ],
139
+ "dev": true,
140
+ "license": "MIT",
141
+ "optional": true,
142
+ "os": [
143
+ "freebsd"
144
+ ],
145
+ "engines": {
146
+ "node": ">=12"
147
+ }
148
+ },
149
+ "node_modules/@esbuild/linux-arm": {
150
+ "version": "0.18.20",
151
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz",
152
+ "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==",
153
+ "cpu": [
154
+ "arm"
155
+ ],
156
+ "dev": true,
157
+ "license": "MIT",
158
+ "optional": true,
159
+ "os": [
160
+ "linux"
161
+ ],
162
+ "engines": {
163
+ "node": ">=12"
164
+ }
165
+ },
166
+ "node_modules/@esbuild/linux-arm64": {
167
+ "version": "0.18.20",
168
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz",
169
+ "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==",
170
+ "cpu": [
171
+ "arm64"
172
+ ],
173
+ "dev": true,
174
+ "license": "MIT",
175
+ "optional": true,
176
+ "os": [
177
+ "linux"
178
+ ],
179
+ "engines": {
180
+ "node": ">=12"
181
+ }
182
+ },
183
+ "node_modules/@esbuild/linux-ia32": {
184
+ "version": "0.18.20",
185
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz",
186
+ "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==",
187
+ "cpu": [
188
+ "ia32"
189
+ ],
190
+ "dev": true,
191
+ "license": "MIT",
192
+ "optional": true,
193
+ "os": [
194
+ "linux"
195
+ ],
196
+ "engines": {
197
+ "node": ">=12"
198
+ }
199
+ },
200
+ "node_modules/@esbuild/linux-loong64": {
201
+ "version": "0.18.20",
202
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz",
203
+ "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==",
204
+ "cpu": [
205
+ "loong64"
206
+ ],
207
+ "dev": true,
208
+ "license": "MIT",
209
+ "optional": true,
210
+ "os": [
211
+ "linux"
212
+ ],
213
+ "engines": {
214
+ "node": ">=12"
215
+ }
216
+ },
217
+ "node_modules/@esbuild/linux-mips64el": {
218
+ "version": "0.18.20",
219
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz",
220
+ "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==",
221
+ "cpu": [
222
+ "mips64el"
223
+ ],
224
+ "dev": true,
225
+ "license": "MIT",
226
+ "optional": true,
227
+ "os": [
228
+ "linux"
229
+ ],
230
+ "engines": {
231
+ "node": ">=12"
232
+ }
233
+ },
234
+ "node_modules/@esbuild/linux-ppc64": {
235
+ "version": "0.18.20",
236
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz",
237
+ "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==",
238
+ "cpu": [
239
+ "ppc64"
240
+ ],
241
+ "dev": true,
242
+ "license": "MIT",
243
+ "optional": true,
244
+ "os": [
245
+ "linux"
246
+ ],
247
+ "engines": {
248
+ "node": ">=12"
249
+ }
250
+ },
251
+ "node_modules/@esbuild/linux-riscv64": {
252
+ "version": "0.18.20",
253
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz",
254
+ "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==",
255
+ "cpu": [
256
+ "riscv64"
257
+ ],
258
+ "dev": true,
259
+ "license": "MIT",
260
+ "optional": true,
261
+ "os": [
262
+ "linux"
263
+ ],
264
+ "engines": {
265
+ "node": ">=12"
266
+ }
267
+ },
268
+ "node_modules/@esbuild/linux-s390x": {
269
+ "version": "0.18.20",
270
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz",
271
+ "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==",
272
+ "cpu": [
273
+ "s390x"
274
+ ],
275
+ "dev": true,
276
+ "license": "MIT",
277
+ "optional": true,
278
+ "os": [
279
+ "linux"
280
+ ],
281
+ "engines": {
282
+ "node": ">=12"
283
+ }
284
+ },
285
+ "node_modules/@esbuild/linux-x64": {
286
+ "version": "0.18.20",
287
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz",
288
+ "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==",
289
+ "cpu": [
290
+ "x64"
291
+ ],
292
+ "dev": true,
293
+ "license": "MIT",
294
+ "optional": true,
295
+ "os": [
296
+ "linux"
297
+ ],
298
+ "engines": {
299
+ "node": ">=12"
300
+ }
301
+ },
302
+ "node_modules/@esbuild/netbsd-x64": {
303
+ "version": "0.18.20",
304
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz",
305
+ "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==",
306
+ "cpu": [
307
+ "x64"
308
+ ],
309
+ "dev": true,
310
+ "license": "MIT",
311
+ "optional": true,
312
+ "os": [
313
+ "netbsd"
314
+ ],
315
+ "engines": {
316
+ "node": ">=12"
317
+ }
318
+ },
319
+ "node_modules/@esbuild/openbsd-x64": {
320
+ "version": "0.18.20",
321
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz",
322
+ "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==",
323
+ "cpu": [
324
+ "x64"
325
+ ],
326
+ "dev": true,
327
+ "license": "MIT",
328
+ "optional": true,
329
+ "os": [
330
+ "openbsd"
331
+ ],
332
+ "engines": {
333
+ "node": ">=12"
334
+ }
335
+ },
336
+ "node_modules/@esbuild/sunos-x64": {
337
+ "version": "0.18.20",
338
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz",
339
+ "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==",
340
+ "cpu": [
341
+ "x64"
342
+ ],
343
+ "dev": true,
344
+ "license": "MIT",
345
+ "optional": true,
346
+ "os": [
347
+ "sunos"
348
+ ],
349
+ "engines": {
350
+ "node": ">=12"
351
+ }
352
+ },
353
+ "node_modules/@esbuild/win32-arm64": {
354
+ "version": "0.18.20",
355
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz",
356
+ "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==",
357
+ "cpu": [
358
+ "arm64"
359
+ ],
360
+ "dev": true,
361
+ "license": "MIT",
362
+ "optional": true,
363
+ "os": [
364
+ "win32"
365
+ ],
366
+ "engines": {
367
+ "node": ">=12"
368
+ }
369
+ },
370
+ "node_modules/@esbuild/win32-ia32": {
371
+ "version": "0.18.20",
372
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz",
373
+ "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==",
374
+ "cpu": [
375
+ "ia32"
376
+ ],
377
+ "dev": true,
378
+ "license": "MIT",
379
+ "optional": true,
380
+ "os": [
381
+ "win32"
382
+ ],
383
+ "engines": {
384
+ "node": ">=12"
385
+ }
386
+ },
387
+ "node_modules/@esbuild/win32-x64": {
388
+ "version": "0.18.20",
389
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz",
390
+ "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==",
391
+ "cpu": [
392
+ "x64"
393
+ ],
394
+ "dev": true,
395
+ "license": "MIT",
396
+ "optional": true,
397
+ "os": [
398
+ "win32"
399
+ ],
400
+ "engines": {
401
+ "node": ">=12"
402
+ }
403
+ },
404
+ "node_modules/@jridgewell/gen-mapping": {
405
+ "version": "0.3.13",
406
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
407
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
408
+ "dev": true,
409
+ "license": "MIT",
410
+ "dependencies": {
411
+ "@jridgewell/sourcemap-codec": "^1.5.0",
412
+ "@jridgewell/trace-mapping": "^0.3.24"
413
+ }
414
+ },
415
+ "node_modules/@jridgewell/resolve-uri": {
416
+ "version": "3.1.2",
417
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
418
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
419
+ "dev": true,
420
+ "license": "MIT",
421
+ "engines": {
422
+ "node": ">=6.0.0"
423
+ }
424
+ },
425
+ "node_modules/@jridgewell/sourcemap-codec": {
426
+ "version": "1.5.5",
427
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
428
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
429
+ "dev": true,
430
+ "license": "MIT"
431
+ },
432
+ "node_modules/@jridgewell/trace-mapping": {
433
+ "version": "0.3.30",
434
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz",
435
+ "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==",
436
+ "dev": true,
437
+ "license": "MIT",
438
+ "dependencies": {
439
+ "@jridgewell/resolve-uri": "^3.1.0",
440
+ "@jridgewell/sourcemap-codec": "^1.4.14"
441
+ }
442
+ },
443
+ "node_modules/@sveltejs/vite-plugin-svelte": {
444
+ "version": "2.5.3",
445
+ "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-2.5.3.tgz",
446
+ "integrity": "sha512-erhNtXxE5/6xGZz/M9eXsmI7Pxa6MS7jyTy06zN3Ck++ldrppOnOlJwHHTsMC7DHDQdgUp4NAc4cDNQ9eGdB/w==",
447
+ "dev": true,
448
+ "license": "MIT",
449
+ "dependencies": {
450
+ "@sveltejs/vite-plugin-svelte-inspector": "^1.0.4",
451
+ "debug": "^4.3.4",
452
+ "deepmerge": "^4.3.1",
453
+ "kleur": "^4.1.5",
454
+ "magic-string": "^0.30.3",
455
+ "svelte-hmr": "^0.15.3",
456
+ "vitefu": "^0.2.4"
457
+ },
458
+ "engines": {
459
+ "node": "^14.18.0 || >= 16"
460
+ },
461
+ "peerDependencies": {
462
+ "svelte": "^3.54.0 || ^4.0.0 || ^5.0.0-next.0",
463
+ "vite": "^4.0.0"
464
+ }
465
+ },
466
+ "node_modules/@sveltejs/vite-plugin-svelte-inspector": {
467
+ "version": "1.0.4",
468
+ "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-1.0.4.tgz",
469
+ "integrity": "sha512-zjiuZ3yydBtwpF3bj0kQNV0YXe+iKE545QGZVTaylW3eAzFr+pJ/cwK8lZEaRp4JtaJXhD5DyWAV4AxLh6DgaQ==",
470
+ "dev": true,
471
+ "license": "MIT",
472
+ "dependencies": {
473
+ "debug": "^4.3.4"
474
+ },
475
+ "engines": {
476
+ "node": "^14.18.0 || >= 16"
477
+ },
478
+ "peerDependencies": {
479
+ "@sveltejs/vite-plugin-svelte": "^2.2.0",
480
+ "svelte": "^3.54.0 || ^4.0.0",
481
+ "vite": "^4.0.0"
482
+ }
483
+ },
484
+ "node_modules/@types/estree": {
485
+ "version": "1.0.8",
486
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
487
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
488
+ "dev": true,
489
+ "license": "MIT"
490
+ },
491
+ "node_modules/acorn": {
492
+ "version": "8.15.0",
493
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
494
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
495
+ "dev": true,
496
+ "license": "MIT",
497
+ "bin": {
498
+ "acorn": "bin/acorn"
499
+ },
500
+ "engines": {
501
+ "node": ">=0.4.0"
502
+ }
503
+ },
504
+ "node_modules/aria-query": {
505
+ "version": "5.3.2",
506
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
507
+ "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==",
508
+ "dev": true,
509
+ "license": "Apache-2.0",
510
+ "engines": {
511
+ "node": ">= 0.4"
512
+ }
513
+ },
514
+ "node_modules/axobject-query": {
515
+ "version": "4.1.0",
516
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
517
+ "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
518
+ "dev": true,
519
+ "license": "Apache-2.0",
520
+ "engines": {
521
+ "node": ">= 0.4"
522
+ }
523
+ },
524
+ "node_modules/code-red": {
525
+ "version": "1.0.4",
526
+ "resolved": "https://registry.npmjs.org/code-red/-/code-red-1.0.4.tgz",
527
+ "integrity": "sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==",
528
+ "dev": true,
529
+ "license": "MIT",
530
+ "dependencies": {
531
+ "@jridgewell/sourcemap-codec": "^1.4.15",
532
+ "@types/estree": "^1.0.1",
533
+ "acorn": "^8.10.0",
534
+ "estree-walker": "^3.0.3",
535
+ "periscopic": "^3.1.0"
536
+ }
537
+ },
538
+ "node_modules/css-tree": {
539
+ "version": "2.3.1",
540
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz",
541
+ "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==",
542
+ "dev": true,
543
+ "license": "MIT",
544
+ "dependencies": {
545
+ "mdn-data": "2.0.30",
546
+ "source-map-js": "^1.0.1"
547
+ },
548
+ "engines": {
549
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
550
+ }
551
+ },
552
+ "node_modules/debug": {
553
+ "version": "4.4.1",
554
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
555
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
556
+ "dev": true,
557
+ "license": "MIT",
558
+ "dependencies": {
559
+ "ms": "^2.1.3"
560
+ },
561
+ "engines": {
562
+ "node": ">=6.0"
563
+ },
564
+ "peerDependenciesMeta": {
565
+ "supports-color": {
566
+ "optional": true
567
+ }
568
+ }
569
+ },
570
+ "node_modules/deepmerge": {
571
+ "version": "4.3.1",
572
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
573
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
574
+ "dev": true,
575
+ "license": "MIT",
576
+ "engines": {
577
+ "node": ">=0.10.0"
578
+ }
579
+ },
580
+ "node_modules/esbuild": {
581
+ "version": "0.18.20",
582
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
583
+ "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==",
584
+ "dev": true,
585
+ "hasInstallScript": true,
586
+ "license": "MIT",
587
+ "bin": {
588
+ "esbuild": "bin/esbuild"
589
+ },
590
+ "engines": {
591
+ "node": ">=12"
592
+ },
593
+ "optionalDependencies": {
594
+ "@esbuild/android-arm": "0.18.20",
595
+ "@esbuild/android-arm64": "0.18.20",
596
+ "@esbuild/android-x64": "0.18.20",
597
+ "@esbuild/darwin-arm64": "0.18.20",
598
+ "@esbuild/darwin-x64": "0.18.20",
599
+ "@esbuild/freebsd-arm64": "0.18.20",
600
+ "@esbuild/freebsd-x64": "0.18.20",
601
+ "@esbuild/linux-arm": "0.18.20",
602
+ "@esbuild/linux-arm64": "0.18.20",
603
+ "@esbuild/linux-ia32": "0.18.20",
604
+ "@esbuild/linux-loong64": "0.18.20",
605
+ "@esbuild/linux-mips64el": "0.18.20",
606
+ "@esbuild/linux-ppc64": "0.18.20",
607
+ "@esbuild/linux-riscv64": "0.18.20",
608
+ "@esbuild/linux-s390x": "0.18.20",
609
+ "@esbuild/linux-x64": "0.18.20",
610
+ "@esbuild/netbsd-x64": "0.18.20",
611
+ "@esbuild/openbsd-x64": "0.18.20",
612
+ "@esbuild/sunos-x64": "0.18.20",
613
+ "@esbuild/win32-arm64": "0.18.20",
614
+ "@esbuild/win32-ia32": "0.18.20",
615
+ "@esbuild/win32-x64": "0.18.20"
616
+ }
617
+ },
618
+ "node_modules/estree-walker": {
619
+ "version": "3.0.3",
620
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
621
+ "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
622
+ "dev": true,
623
+ "license": "MIT",
624
+ "dependencies": {
625
+ "@types/estree": "^1.0.0"
626
+ }
627
+ },
628
+ "node_modules/fsevents": {
629
+ "version": "2.3.3",
630
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
631
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
632
+ "dev": true,
633
+ "hasInstallScript": true,
634
+ "license": "MIT",
635
+ "optional": true,
636
+ "os": [
637
+ "darwin"
638
+ ],
639
+ "engines": {
640
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
641
+ }
642
+ },
643
+ "node_modules/is-reference": {
644
+ "version": "3.0.3",
645
+ "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz",
646
+ "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==",
647
+ "dev": true,
648
+ "license": "MIT",
649
+ "dependencies": {
650
+ "@types/estree": "^1.0.6"
651
+ }
652
+ },
653
+ "node_modules/kleur": {
654
+ "version": "4.1.5",
655
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
656
+ "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
657
+ "dev": true,
658
+ "license": "MIT",
659
+ "engines": {
660
+ "node": ">=6"
661
+ }
662
+ },
663
+ "node_modules/locate-character": {
664
+ "version": "3.0.0",
665
+ "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
666
+ "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==",
667
+ "dev": true,
668
+ "license": "MIT"
669
+ },
670
+ "node_modules/magic-string": {
671
+ "version": "0.30.17",
672
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
673
+ "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
674
+ "dev": true,
675
+ "license": "MIT",
676
+ "dependencies": {
677
+ "@jridgewell/sourcemap-codec": "^1.5.0"
678
+ }
679
+ },
680
+ "node_modules/mdn-data": {
681
+ "version": "2.0.30",
682
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
683
+ "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==",
684
+ "dev": true,
685
+ "license": "CC0-1.0"
686
+ },
687
+ "node_modules/ms": {
688
+ "version": "2.1.3",
689
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
690
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
691
+ "dev": true,
692
+ "license": "MIT"
693
+ },
694
+ "node_modules/nanoid": {
695
+ "version": "3.3.11",
696
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
697
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
698
+ "dev": true,
699
+ "funding": [
700
+ {
701
+ "type": "github",
702
+ "url": "https://github.com/sponsors/ai"
703
+ }
704
+ ],
705
+ "license": "MIT",
706
+ "bin": {
707
+ "nanoid": "bin/nanoid.cjs"
708
+ },
709
+ "engines": {
710
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
711
+ }
712
+ },
713
+ "node_modules/periscopic": {
714
+ "version": "3.1.0",
715
+ "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz",
716
+ "integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==",
717
+ "dev": true,
718
+ "license": "MIT",
719
+ "dependencies": {
720
+ "@types/estree": "^1.0.0",
721
+ "estree-walker": "^3.0.0",
722
+ "is-reference": "^3.0.0"
723
+ }
724
+ },
725
+ "node_modules/picocolors": {
726
+ "version": "1.1.1",
727
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
728
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
729
+ "dev": true,
730
+ "license": "ISC"
731
+ },
732
+ "node_modules/postcss": {
733
+ "version": "8.5.6",
734
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
735
+ "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
736
+ "dev": true,
737
+ "funding": [
738
+ {
739
+ "type": "opencollective",
740
+ "url": "https://opencollective.com/postcss/"
741
+ },
742
+ {
743
+ "type": "tidelift",
744
+ "url": "https://tidelift.com/funding/github/npm/postcss"
745
+ },
746
+ {
747
+ "type": "github",
748
+ "url": "https://github.com/sponsors/ai"
749
+ }
750
+ ],
751
+ "license": "MIT",
752
+ "dependencies": {
753
+ "nanoid": "^3.3.11",
754
+ "picocolors": "^1.1.1",
755
+ "source-map-js": "^1.2.1"
756
+ },
757
+ "engines": {
758
+ "node": "^10 || ^12 || >=14"
759
+ }
760
+ },
761
+ "node_modules/rollup": {
762
+ "version": "3.29.5",
763
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz",
764
+ "integrity": "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==",
765
+ "dev": true,
766
+ "license": "MIT",
767
+ "bin": {
768
+ "rollup": "dist/bin/rollup"
769
+ },
770
+ "engines": {
771
+ "node": ">=14.18.0",
772
+ "npm": ">=8.0.0"
773
+ },
774
+ "optionalDependencies": {
775
+ "fsevents": "~2.3.2"
776
+ }
777
+ },
778
+ "node_modules/source-map-js": {
779
+ "version": "1.2.1",
780
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
781
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
782
+ "dev": true,
783
+ "license": "BSD-3-Clause",
784
+ "engines": {
785
+ "node": ">=0.10.0"
786
+ }
787
+ },
788
+ "node_modules/svelte": {
789
+ "version": "4.2.20",
790
+ "resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.20.tgz",
791
+ "integrity": "sha512-eeEgGc2DtiUil5ANdtd8vPwt9AgaMdnuUFnPft9F5oMvU/FHu5IHFic+p1dR/UOB7XU2mX2yHW+NcTch4DCh5Q==",
792
+ "dev": true,
793
+ "license": "MIT",
794
+ "dependencies": {
795
+ "@ampproject/remapping": "^2.2.1",
796
+ "@jridgewell/sourcemap-codec": "^1.4.15",
797
+ "@jridgewell/trace-mapping": "^0.3.18",
798
+ "@types/estree": "^1.0.1",
799
+ "acorn": "^8.9.0",
800
+ "aria-query": "^5.3.0",
801
+ "axobject-query": "^4.0.0",
802
+ "code-red": "^1.0.3",
803
+ "css-tree": "^2.3.1",
804
+ "estree-walker": "^3.0.3",
805
+ "is-reference": "^3.0.1",
806
+ "locate-character": "^3.0.0",
807
+ "magic-string": "^0.30.4",
808
+ "periscopic": "^3.1.0"
809
+ },
810
+ "engines": {
811
+ "node": ">=16"
812
+ }
813
+ },
814
+ "node_modules/svelte-hmr": {
815
+ "version": "0.15.3",
816
+ "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.15.3.tgz",
817
+ "integrity": "sha512-41snaPswvSf8TJUhlkoJBekRrABDXDMdpNpT2tfHIv4JuhgvHqLMhEPGtaQn0BmbNSTkuz2Ed20DF2eHw0SmBQ==",
818
+ "dev": true,
819
+ "license": "ISC",
820
+ "engines": {
821
+ "node": "^12.20 || ^14.13.1 || >= 16"
822
+ },
823
+ "peerDependencies": {
824
+ "svelte": "^3.19.0 || ^4.0.0"
825
+ }
826
+ },
827
+ "node_modules/vite": {
828
+ "version": "4.5.14",
829
+ "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.14.tgz",
830
+ "integrity": "sha512-+v57oAaoYNnO3hIu5Z/tJRZjq5aHM2zDve9YZ8HngVHbhk66RStobhb1sqPMIPEleV6cNKYK4eGrAbE9Ulbl2g==",
831
+ "dev": true,
832
+ "license": "MIT",
833
+ "dependencies": {
834
+ "esbuild": "^0.18.10",
835
+ "postcss": "^8.4.27",
836
+ "rollup": "^3.27.1"
837
+ },
838
+ "bin": {
839
+ "vite": "bin/vite.js"
840
+ },
841
+ "engines": {
842
+ "node": "^14.18.0 || >=16.0.0"
843
+ },
844
+ "funding": {
845
+ "url": "https://github.com/vitejs/vite?sponsor=1"
846
+ },
847
+ "optionalDependencies": {
848
+ "fsevents": "~2.3.2"
849
+ },
850
+ "peerDependencies": {
851
+ "@types/node": ">= 14",
852
+ "less": "*",
853
+ "lightningcss": "^1.21.0",
854
+ "sass": "*",
855
+ "stylus": "*",
856
+ "sugarss": "*",
857
+ "terser": "^5.4.0"
858
+ },
859
+ "peerDependenciesMeta": {
860
+ "@types/node": {
861
+ "optional": true
862
+ },
863
+ "less": {
864
+ "optional": true
865
+ },
866
+ "lightningcss": {
867
+ "optional": true
868
+ },
869
+ "sass": {
870
+ "optional": true
871
+ },
872
+ "stylus": {
873
+ "optional": true
874
+ },
875
+ "sugarss": {
876
+ "optional": true
877
+ },
878
+ "terser": {
879
+ "optional": true
880
+ }
881
+ }
882
+ },
883
+ "node_modules/vitefu": {
884
+ "version": "0.2.5",
885
+ "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-0.2.5.tgz",
886
+ "integrity": "sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==",
887
+ "dev": true,
888
+ "license": "MIT",
889
+ "peerDependencies": {
890
+ "vite": "^3.0.0 || ^4.0.0 || ^5.0.0"
891
+ },
892
+ "peerDependenciesMeta": {
893
+ "vite": {
894
+ "optional": true
895
+ }
896
+ }
897
+ }
898
+ }
899
+ }
package.json ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "backtrace-viewer",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "scripts": {
6
+ "dev": "vite",
7
+ "build": "vite build",
8
+ "preview": "vite preview"
9
+ },
10
+ "devDependencies": {
11
+ "@sveltejs/vite-plugin-svelte": "^2.4.2",
12
+ "svelte": "^4.0.5",
13
+ "vite": "^4.4.5"
14
+ }
15
+ }
public/sample.txt ADDED
The diff for this file is too large to render. See raw diff
 
sample.txt ADDED
The diff for this file is too large to render. See raw diff
 
src/App.svelte ADDED
@@ -0,0 +1,257 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script>
2
+ import { onMount } from "svelte";
3
+
4
+ let fileInput;
5
+ let backtraceData = "";
6
+ let threads = [];
7
+ let filteredThreads = [];
8
+ let filterText = "";
9
+ let visibleThreads = new Set();
10
+
11
+ // Parse the backtrace file format
12
+ function parseBacktraceFile(content) {
13
+ const lines = content.split("\n");
14
+ const parsedThreads = [];
15
+ let currentThread = null;
16
+ let currentBacktrace = [];
17
+
18
+ for (let i = 0; i < lines.length; i++) {
19
+ const line = lines[i];
20
+
21
+ // Simpler approach: look for lines containing "Thread_" with numbers at the start
22
+ if (line.includes("Thread_") && /^\s*\d+\s+Thread_\d+/.test(line)) {
23
+ // Save previous thread if exists
24
+ if (currentThread) {
25
+ currentThread.backtrace = currentBacktrace;
26
+ currentThread.collapsibleBacktrace =
27
+ createCollapsibleBacktrace(currentBacktrace);
28
+ parsedThreads.push(currentThread);
29
+ }
30
+
31
+ // Extract sample count and thread ID
32
+ const sampleMatch = line.match(/^\s*(\d+)\s+(Thread_\d+)/);
33
+ const sampleCount = sampleMatch[1];
34
+ const threadId = sampleMatch[2];
35
+
36
+ // Extract thread name (everything after the first colon, before parentheses)
37
+ let threadName = "";
38
+ const colonIndex = line.indexOf(":");
39
+ if (colonIndex !== -1) {
40
+ const afterColon = line.substring(colonIndex + 1);
41
+ const parenIndex = afterColon.indexOf("(");
42
+ threadName = (
43
+ parenIndex !== -1 ? afterColon.substring(0, parenIndex) : afterColon
44
+ ).trim();
45
+ }
46
+
47
+ currentThread = {
48
+ id: threadId,
49
+ name: threadName,
50
+ fullName: threadName || threadId,
51
+ sampleCount: parseInt(sampleCount),
52
+ rawHeader: line.trim(),
53
+ backtrace: [],
54
+ expanded: false,
55
+ collapsibleBacktrace: null, // Will be created after backtrace is complete
56
+ };
57
+ currentBacktrace = [];
58
+ } else if (currentThread && line.trim()) {
59
+ // This is part of the backtrace
60
+ currentBacktrace.push(line);
61
+ }
62
+ // Skip empty lines
63
+ }
64
+
65
+ // Don't forget the last thread
66
+ if (currentThread) {
67
+ currentThread.backtrace = currentBacktrace;
68
+ currentThread.collapsibleBacktrace =
69
+ createCollapsibleBacktrace(currentBacktrace);
70
+ parsedThreads.push(currentThread);
71
+ }
72
+
73
+ return parsedThreads;
74
+ }
75
+
76
+ // Toggle thread visibility
77
+ function toggleThread(threadId) {
78
+ console.log("🔄 Toggling thread:", threadId);
79
+ // Create a new array with updated thread to trigger Svelte reactivity
80
+ threads = threads.map((thread) => {
81
+ if (thread.id === threadId) {
82
+ const newThread = { ...thread, expanded: !thread.expanded };
83
+ console.log(
84
+ "📊 Thread expanded:",
85
+ newThread.expanded,
86
+ "backtrace lines:",
87
+ newThread.backtrace.length
88
+ );
89
+ return newThread;
90
+ }
91
+ return thread;
92
+ });
93
+ }
94
+
95
+ // Handle file upload
96
+ function handleFileUpload(event) {
97
+ const file = event.target.files[0];
98
+ if (file) {
99
+ const reader = new FileReader();
100
+ reader.onload = (e) => {
101
+ backtraceData = e.target.result;
102
+ threads = parseBacktraceFile(backtraceData);
103
+ };
104
+ reader.readAsText(file);
105
+ }
106
+ }
107
+
108
+ // Load sample file on mount
109
+ onMount(async () => {
110
+ try {
111
+ const response = await fetch("/sample.txt");
112
+ if (response.ok) {
113
+ backtraceData = await response.text();
114
+ threads = parseBacktraceFile(backtraceData);
115
+ console.log("✅ Loaded", threads.length, "threads successfully");
116
+ }
117
+ } catch (error) {
118
+ console.error("Could not load sample.txt:", error);
119
+ }
120
+ });
121
+
122
+ // Parse individual backtrace lines for better display
123
+ function parseBacktraceLine(line) {
124
+ // Extract indentation
125
+ const indentMatch = line.match(/^(\s*[\+\!\:\|]*\s*)/);
126
+ const indent = indentMatch ? indentMatch[1] : "";
127
+ const content = line.substring(indent.length);
128
+
129
+ // Try to extract sample count, function name, and address
130
+ const parts = {
131
+ indent,
132
+ content,
133
+ original: line,
134
+ };
135
+
136
+ // Extract sample count if at beginning
137
+ const sampleMatch = content.match(/^(\d+)\s+(.+)/);
138
+ if (sampleMatch) {
139
+ parts.sampleCount = sampleMatch[1];
140
+ parts.content = sampleMatch[2];
141
+ }
142
+
143
+ return parts;
144
+ }
145
+
146
+ // Create collapsible backtrace structure
147
+ function createCollapsibleBacktrace(backtrace) {
148
+ return backtrace.map((line, index) => ({
149
+ id: index,
150
+ line,
151
+ parsed: parseBacktraceLine(line),
152
+ collapsed: false,
153
+ }));
154
+ }
155
+
156
+ // Toggle backtrace line collapse
157
+ function toggleBacktraceLine(threadId, lineIndex) {
158
+ threads = threads.map((thread) => {
159
+ if (thread.id === threadId && thread.collapsibleBacktrace) {
160
+ const updatedBacktrace = [...thread.collapsibleBacktrace];
161
+ updatedBacktrace[lineIndex] = {
162
+ ...updatedBacktrace[lineIndex],
163
+ collapsed: !updatedBacktrace[lineIndex].collapsed,
164
+ };
165
+ return { ...thread, collapsibleBacktrace: updatedBacktrace };
166
+ }
167
+ return thread;
168
+ });
169
+ }
170
+
171
+ // Reactive updates - run filter when threads OR filterText changes
172
+ $: filteredThreads = threads.filter(
173
+ (thread) =>
174
+ !filterText.trim() ||
175
+ thread.fullName.toLowerCase().startsWith(filterText.toLowerCase())
176
+ );
177
+ </script>
178
+
179
+ <div class="header">
180
+ <h1>🔍 Backtrace Viewer</h1>
181
+ <div class="controls">
182
+ <label for="fileInput" class="file-label"> 📁 Load Backtrace File </label>
183
+ <input
184
+ type="file"
185
+ id="fileInput"
186
+ class="file-input"
187
+ accept=".txt"
188
+ on:change={handleFileUpload}
189
+ bind:this={fileInput}
190
+ />
191
+
192
+ <input
193
+ type="text"
194
+ class="filter-input"
195
+ placeholder="Filter threads by name prefix..."
196
+ bind:value={filterText}
197
+ />
198
+
199
+ <div class="stats">
200
+ {filteredThreads.length} / {threads.length} threads
201
+ </div>
202
+ </div>
203
+ </div>
204
+
205
+ {#if threads.length === 0}
206
+ <div class="no-threads">
207
+ <p>No backtrace data loaded. Upload a file to get started.</p>
208
+ </div>
209
+ {:else}
210
+ {#each filteredThreads as thread (thread.id)}
211
+ <div class="thread-container">
212
+ <div
213
+ class="thread-header"
214
+ on:click={() => toggleThread(thread.id)}
215
+ on:keydown={(e) => e.key === "Enter" && toggleThread(thread.id)}
216
+ role="button"
217
+ tabindex="0"
218
+ >
219
+ <div class="thread-title">
220
+ <strong>{thread.sampleCount}</strong>
221
+ {thread.id}
222
+ {#if thread.name}
223
+ : <span style="color: #3498db;">{thread.name}</span>
224
+ {/if}
225
+ </div>
226
+ <div class="toggle-indicator" class:expanded={thread.expanded}>▶</div>
227
+ </div>
228
+
229
+ {#if thread.expanded}
230
+ <div class="thread-content">
231
+ <div class="backtrace">
232
+ {#each thread.collapsibleBacktrace as backtraceLine (backtraceLine.id)}
233
+ <div
234
+ class="backtrace-line"
235
+ class:collapsed={backtraceLine.collapsed}
236
+ on:click={() =>
237
+ toggleBacktraceLine(thread.id, backtraceLine.id)}
238
+ on:keydown={(e) =>
239
+ e.key === "Enter" &&
240
+ toggleBacktraceLine(thread.id, backtraceLine.id)}
241
+ role="button"
242
+ tabindex="0"
243
+ >
244
+ <span class="indent">{backtraceLine.parsed.indent}</span
245
+ >{#if backtraceLine.parsed.sampleCount}<span
246
+ class="sample-count"
247
+ >{backtraceLine.parsed.sampleCount}</span
248
+ >
249
+ {/if}<span class="content">{backtraceLine.parsed.content}</span>
250
+ </div>
251
+ {/each}
252
+ </div>
253
+ </div>
254
+ {/if}
255
+ </div>
256
+ {/each}
257
+ {/if}
src/app.css ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ * {
2
+ margin: 0;
3
+ padding: 0;
4
+ box-sizing: border-box;
5
+ }
6
+
7
+ body {
8
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
9
+ background-color: #f8f9fa;
10
+ color: #333;
11
+ line-height: 1.4;
12
+ }
13
+
14
+ #app {
15
+ max-width: 1400px;
16
+ margin: 0 auto;
17
+ padding: 2rem;
18
+ }
19
+
20
+ .header {
21
+ background: white;
22
+ padding: 1.5rem;
23
+ border-radius: 8px;
24
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
25
+ margin-bottom: 2rem;
26
+ }
27
+
28
+ .header h1 {
29
+ color: #2c3e50;
30
+ margin-bottom: 1rem;
31
+ }
32
+
33
+ .controls {
34
+ display: flex;
35
+ gap: 1rem;
36
+ align-items: center;
37
+ flex-wrap: wrap;
38
+ }
39
+
40
+ .file-input {
41
+ display: none;
42
+ }
43
+
44
+ .file-label {
45
+ background: #3498db;
46
+ color: white;
47
+ padding: 0.5rem 1rem;
48
+ border-radius: 4px;
49
+ cursor: pointer;
50
+ transition: background-color 0.2s;
51
+ }
52
+
53
+ .file-label:hover {
54
+ background: #2980b9;
55
+ }
56
+
57
+ .filter-input {
58
+ padding: 0.5rem;
59
+ border: 1px solid #ddd;
60
+ border-radius: 4px;
61
+ font-size: 14px;
62
+ }
63
+
64
+ .filter-input:focus {
65
+ outline: none;
66
+ border-color: #3498db;
67
+ }
68
+
69
+ .stats {
70
+ color: #666;
71
+ font-size: 14px;
72
+ }
73
+
74
+ .thread-container {
75
+ background: white;
76
+ border-radius: 8px;
77
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
78
+ margin-bottom: 1rem;
79
+ overflow: hidden;
80
+ }
81
+
82
+ .thread-header {
83
+ padding: 1rem;
84
+ background: #34495e;
85
+ color: white;
86
+ cursor: pointer;
87
+ user-select: none;
88
+ display: flex;
89
+ justify-content: space-between;
90
+ align-items: center;
91
+ }
92
+
93
+ .thread-header:hover {
94
+ background: #2c3e50;
95
+ }
96
+
97
+ .thread-title {
98
+ font-family: "Monaco", "Menlo", "Ubuntu Mono", monospace;
99
+ font-size: 14px;
100
+ }
101
+
102
+ .toggle-indicator {
103
+ transition: transform 0.2s;
104
+ }
105
+
106
+ .toggle-indicator.expanded {
107
+ transform: rotate(90deg);
108
+ }
109
+
110
+ .thread-content {
111
+ padding: 1rem;
112
+ background: #f8f9fa;
113
+ border-top: 1px solid #e9ecef;
114
+ }
115
+
116
+ .backtrace {
117
+ font-family: "Monaco", "Menlo", "Ubuntu Mono", monospace;
118
+ font-size: 12px;
119
+ line-height: 1.3;
120
+ white-space: pre;
121
+ overflow-x: auto;
122
+ background: white;
123
+ padding: 1rem;
124
+ border-radius: 4px;
125
+ border: 1px solid #e9ecef;
126
+ }
127
+
128
+ .backtrace-line {
129
+ margin: 2px 0;
130
+ cursor: pointer;
131
+ padding: 1px 0;
132
+ }
133
+
134
+ .backtrace-line:hover {
135
+ background-color: #f0f8ff;
136
+ }
137
+
138
+ .backtrace-line.collapsed {
139
+ color: #666;
140
+ }
141
+
142
+ .backtrace-line.collapsed .content {
143
+ display: none;
144
+ }
145
+
146
+ .backtrace-line .indent {
147
+ display: inline-block;
148
+ }
149
+
150
+ .backtrace-line .sample-count {
151
+ color: #e67e22;
152
+ font-weight: bold;
153
+ }
154
+
155
+ .backtrace-line .function-name {
156
+ color: #2c3e50;
157
+ }
158
+
159
+ .backtrace-line .address {
160
+ color: #7f8c8d;
161
+ }
162
+
163
+ .no-threads {
164
+ text-align: center;
165
+ padding: 3rem;
166
+ color: #666;
167
+ }
168
+
169
+ .loading {
170
+ text-align: center;
171
+ padding: 2rem;
172
+ color: #666;
173
+ }
174
+
175
+ @media (max-width: 768px) {
176
+ #app {
177
+ padding: 1rem;
178
+ }
179
+
180
+ .controls {
181
+ flex-direction: column;
182
+ align-items: stretch;
183
+ }
184
+
185
+ .thread-header {
186
+ padding: 0.75rem;
187
+ }
188
+
189
+ .backtrace {
190
+ font-size: 11px;
191
+ }
192
+ }
src/main.js ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ import "./app.css";
2
+ import App from "./App.svelte";
3
+
4
+ const app = new App({
5
+ target: document.getElementById("app"),
6
+ });
7
+
8
+ export default app;
vite.config.js ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ import { defineConfig } from "vite";
2
+ import { svelte } from "@sveltejs/vite-plugin-svelte";
3
+
4
+ export default defineConfig({
5
+ plugins: [svelte()],
6
+ });