@ogygia/devtools 0.0.0-stage → 0.11.0
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/LICENSE +21 -0
- package/README.md +25 -2
- package/dist/client.d.ts +3 -0
- package/dist/client.js +24 -0
- package/dist/devtools/BoundaryOverlay.svelte +396 -0
- package/dist/devtools/BoundaryOverlay.svelte.d.ts +19 -0
- package/dist/devtools/Devtools.svelte +663 -0
- package/dist/devtools/Devtools.svelte.d.ts +15 -0
- package/dist/devtools/HubTab.svelte +206 -0
- package/dist/devtools/HubTab.svelte.d.ts +11 -0
- package/dist/devtools/HydrationTab.svelte +237 -0
- package/dist/devtools/HydrationTab.svelte.d.ts +13 -0
- package/dist/devtools/IslandDetail.svelte +615 -0
- package/dist/devtools/IslandDetail.svelte.d.ts +15 -0
- package/dist/devtools/LedgerTab.svelte +287 -0
- package/dist/devtools/LedgerTab.svelte.d.ts +11 -0
- package/dist/devtools/LensTab.svelte +290 -0
- package/dist/devtools/LensTab.svelte.d.ts +19 -0
- package/dist/devtools/NavTab.svelte +229 -0
- package/dist/devtools/NavTab.svelte.d.ts +11 -0
- package/dist/devtools/PageTab.svelte +1122 -0
- package/dist/devtools/PageTab.svelte.d.ts +15 -0
- package/dist/devtools/ProfilerTab.svelte +755 -0
- package/dist/devtools/ProfilerTab.svelte.d.ts +15 -0
- package/dist/devtools/PropsTree.svelte +155 -0
- package/dist/devtools/PropsTree.svelte.d.ts +15 -0
- package/dist/devtools/SessionTab.svelte +796 -0
- package/dist/devtools/SessionTab.svelte.d.ts +11 -0
- package/dist/devtools/TimelineTab.svelte +267 -0
- package/dist/devtools/TimelineTab.svelte.d.ts +11 -0
- package/dist/devtools/WireTab.svelte +149 -0
- package/dist/devtools/WireTab.svelte.d.ts +11 -0
- package/dist/devtools/bytes.d.ts +70 -0
- package/dist/devtools/bytes.js +82 -0
- package/dist/devtools/cache-headers.d.ts +20 -0
- package/dist/devtools/cache-headers.js +81 -0
- package/dist/devtools/highlight.d.ts +7 -0
- package/dist/devtools/highlight.js +83 -0
- package/dist/devtools/hydration.d.ts +48 -0
- package/dist/devtools/hydration.js +93 -0
- package/dist/devtools/index.d.ts +3 -0
- package/dist/devtools/index.js +3 -0
- package/dist/devtools/ledger-dom.d.ts +7 -0
- package/dist/devtools/ledger-dom.js +151 -0
- package/dist/devtools/leftovers.d.ts +77 -0
- package/dist/devtools/leftovers.js +319 -0
- package/dist/devtools/names.d.ts +1 -0
- package/dist/devtools/names.js +34 -0
- package/dist/devtools/page.d.ts +96 -0
- package/dist/devtools/page.js +957 -0
- package/dist/devtools/profile-anchors.d.ts +22 -0
- package/dist/devtools/profile-anchors.js +135 -0
- package/dist/devtools/profile-store.d.ts +175 -0
- package/dist/devtools/profile-store.js +239 -0
- package/dist/devtools/regions.d.ts +77 -0
- package/dist/devtools/regions.js +132 -0
- package/dist/devtools/session.d.ts +31 -0
- package/dist/devtools/session.js +455 -0
- package/dist/devtools/since-load.d.ts +50 -0
- package/dist/devtools/since-load.js +89 -0
- package/dist/devtools/source-lines.d.ts +24 -0
- package/dist/devtools/source-lines.js +106 -0
- package/dist/devtools/styles.d.ts +52 -0
- package/dist/devtools/styles.js +248 -0
- package/dist/devtools/testing-engine.d.ts +83 -0
- package/dist/devtools/testing-engine.js +220 -0
- package/dist/devtools/ui-app.d.ts +5 -0
- package/dist/devtools/ui-app.js +69 -0
- package/dist/devtools/ui.d.ts +50 -0
- package/dist/devtools/ui.js +175 -0
- package/dist/profiler/alloc.d.ts +75 -0
- package/dist/profiler/alloc.js +76 -0
- package/dist/profiler/analyze.d.ts +437 -0
- package/dist/profiler/analyze.js +1941 -0
- package/dist/profiler/app-path.d.ts +7 -0
- package/dist/profiler/app-path.js +26 -0
- package/dist/profiler/async-io.d.ts +58 -0
- package/dist/profiler/async-io.js +187 -0
- package/dist/profiler/beacon-standalone.d.ts +4 -0
- package/dist/profiler/beacon-standalone.js +409 -0
- package/dist/profiler/browser-findings.d.ts +25 -0
- package/dist/profiler/browser-findings.js +260 -0
- package/dist/profiler/byte-strip.d.ts +58 -0
- package/dist/profiler/byte-strip.js +228 -0
- package/dist/profiler/client-files.d.ts +16 -0
- package/dist/profiler/client-files.js +60 -0
- package/dist/profiler/client-windows.d.ts +49 -0
- package/dist/profiler/client-windows.js +95 -0
- package/dist/profiler/client.d.ts +40 -0
- package/dist/profiler/client.js +82 -0
- package/dist/profiler/compare.d.ts +308 -0
- package/dist/profiler/compare.js +733 -0
- package/dist/profiler/compress.d.ts +10 -0
- package/dist/profiler/compress.js +36 -0
- package/dist/profiler/contention.d.ts +60 -0
- package/dist/profiler/contention.js +86 -0
- package/dist/profiler/crypto.d.ts +19 -0
- package/dist/profiler/crypto.js +101 -0
- package/dist/profiler/doc-diff.d.ts +47 -0
- package/dist/profiler/doc-diff.js +214 -0
- package/dist/profiler/dom-diff.d.ts +43 -0
- package/dist/profiler/dom-diff.js +121 -0
- package/dist/profiler/drill.d.ts +89 -0
- package/dist/profiler/drill.js +553 -0
- package/dist/profiler/embedded-maps.d.ts +37 -0
- package/dist/profiler/embedded-maps.js +135 -0
- package/dist/profiler/env.d.ts +6 -0
- package/dist/profiler/env.js +10 -0
- package/dist/profiler/forecast.d.ts +76 -0
- package/dist/profiler/forecast.js +225 -0
- package/dist/profiler/frames.d.ts +11 -0
- package/dist/profiler/frames.js +42 -0
- package/dist/profiler/gc.d.ts +144 -0
- package/dist/profiler/gc.js +271 -0
- package/dist/profiler/hole-slots.d.ts +31 -0
- package/dist/profiler/hole-slots.js +90 -0
- package/dist/profiler/index.d.ts +288 -0
- package/dist/profiler/index.js +4921 -0
- package/dist/profiler/insights.d.ts +96 -0
- package/dist/profiler/insights.js +239 -0
- package/dist/profiler/ledger.d.ts +121 -0
- package/dist/profiler/ledger.js +440 -0
- package/dist/profiler/lineage.d.ts +81 -0
- package/dist/profiler/lineage.js +359 -0
- package/dist/profiler/module-map.d.ts +12 -0
- package/dist/profiler/module-map.js +94 -0
- package/dist/profiler/net.d.ts +169 -0
- package/dist/profiler/net.js +586 -0
- package/dist/profiler/on-demand.d.ts +11 -0
- package/dist/profiler/on-demand.js +15 -0
- package/dist/profiler/own-requests.d.ts +9 -0
- package/dist/profiler/own-requests.js +17 -0
- package/dist/profiler/patterns.d.ts +476 -0
- package/dist/profiler/patterns.js +2203 -0
- package/dist/profiler/profiler-router.d.ts +245 -0
- package/dist/profiler/profiler-router.js +113 -0
- package/dist/profiler/refresh-stub.d.ts +2 -0
- package/dist/profiler/refresh-stub.js +37 -0
- package/dist/profiler/report.d.ts +1404 -0
- package/dist/profiler/report.js +2638 -0
- package/dist/profiler/river.d.ts +65 -0
- package/dist/profiler/river.js +298 -0
- package/dist/profiler/route-files.d.ts +22 -0
- package/dist/profiler/route-files.js +55 -0
- package/dist/profiler/route-imports.d.ts +14 -0
- package/dist/profiler/route-imports.js +83 -0
- package/dist/profiler/saving.d.ts +22 -0
- package/dist/profiler/saving.js +42 -0
- package/dist/profiler/score.d.ts +109 -0
- package/dist/profiler/score.js +261 -0
- package/dist/profiler/session-cookie.d.ts +28 -0
- package/dist/profiler/session-cookie.js +45 -0
- package/dist/profiler/sink.d.ts +81 -0
- package/dist/profiler/sink.js +124 -0
- package/dist/profiler/site-fixes.d.ts +25 -0
- package/dist/profiler/site-fixes.js +62 -0
- package/dist/profiler/source-scan.d.ts +210 -0
- package/dist/profiler/source-scan.js +1724 -0
- package/dist/profiler/span.d.ts +90 -0
- package/dist/profiler/span.js +109 -0
- package/dist/profiler/stacks.d.ts +43 -0
- package/dist/profiler/stacks.js +107 -0
- package/dist/profiler/standalone.d.ts +27 -0
- package/dist/profiler/standalone.js +98 -0
- package/dist/profiler/steps.d.ts +39 -0
- package/dist/profiler/steps.js +74 -0
- package/dist/profiler/storage/index.d.ts +87 -0
- package/dist/profiler/storage/index.js +76 -0
- package/dist/profiler/storage/postgres.d.ts +12 -0
- package/dist/profiler/storage/postgres.js +94 -0
- package/dist/profiler/storage/redis.d.ts +19 -0
- package/dist/profiler/storage/redis.js +148 -0
- package/dist/profiler/storage/sqlite.d.ts +2 -0
- package/dist/profiler/storage/sqlite.js +85 -0
- package/dist/profiler/storage/visits.d.ts +4 -0
- package/dist/profiler/storage/visits.js +6 -0
- package/dist/profiler/stream-tail.d.ts +26 -0
- package/dist/profiler/stream-tail.js +74 -0
- package/dist/profiler/timeline.d.ts +279 -0
- package/dist/profiler/timeline.js +690 -0
- package/dist/profiler/ui/AllocStrip.svelte +146 -0
- package/dist/profiler/ui/AllocStrip.svelte.d.ts +17 -0
- package/dist/profiler/ui/Awaits.svelte +363 -0
- package/dist/profiler/ui/Awaits.svelte.d.ts +16 -0
- package/dist/profiler/ui/ByteStrip.svelte +182 -0
- package/dist/profiler/ui/ByteStrip.svelte.d.ts +18 -0
- package/dist/profiler/ui/Compare.svelte +24 -0
- package/dist/profiler/ui/Compare.svelte.d.ts +16 -0
- package/dist/profiler/ui/CompareBody.svelte +429 -0
- package/dist/profiler/ui/CompareBody.svelte.d.ts +8 -0
- package/dist/profiler/ui/ComponentsTable.svelte +265 -0
- package/dist/profiler/ui/ComponentsTable.svelte.d.ts +20 -0
- package/dist/profiler/ui/Dashboard.svelte +492 -0
- package/dist/profiler/ui/Dashboard.svelte.d.ts +31 -0
- package/dist/profiler/ui/DataRiver.svelte +206 -0
- package/dist/profiler/ui/DataRiver.svelte.d.ts +13 -0
- package/dist/profiler/ui/DomTravel.svelte +207 -0
- package/dist/profiler/ui/DomTravel.svelte.d.ts +9 -0
- package/dist/profiler/ui/DownloadHtml.svelte +52 -0
- package/dist/profiler/ui/DownloadHtml.svelte.d.ts +10 -0
- package/dist/profiler/ui/Drill.svelte +276 -0
- package/dist/profiler/ui/Drill.svelte.d.ts +12 -0
- package/dist/profiler/ui/ExportButton.svelte +59 -0
- package/dist/profiler/ui/ExportButton.svelte.d.ts +8 -0
- package/dist/profiler/ui/Flame.svelte +222 -0
- package/dist/profiler/ui/Flame.svelte.d.ts +12 -0
- package/dist/profiler/ui/FrameDetails.svelte +308 -0
- package/dist/profiler/ui/FrameDetails.svelte.d.ts +16 -0
- package/dist/profiler/ui/FunctionsTable.svelte +156 -0
- package/dist/profiler/ui/FunctionsTable.svelte.d.ts +17 -0
- package/dist/profiler/ui/IslandHeatmap.svelte +151 -0
- package/dist/profiler/ui/IslandHeatmap.svelte.d.ts +16 -0
- package/dist/profiler/ui/IslandsTable.svelte +448 -0
- package/dist/profiler/ui/IslandsTable.svelte.d.ts +16 -0
- package/dist/profiler/ui/KeepLocal.svelte +46 -0
- package/dist/profiler/ui/KeepLocal.svelte.d.ts +8 -0
- package/dist/profiler/ui/Ledger.svelte +196 -0
- package/dist/profiler/ui/Ledger.svelte.d.ts +18 -0
- package/dist/profiler/ui/LocalCompare.svelte +48 -0
- package/dist/profiler/ui/LocalCompare.svelte.d.ts +8 -0
- package/dist/profiler/ui/LocalReports.svelte +68 -0
- package/dist/profiler/ui/LocalReports.svelte.d.ts +7 -0
- package/dist/profiler/ui/Login.svelte +13 -0
- package/dist/profiler/ui/Login.svelte.d.ts +12 -0
- package/dist/profiler/ui/LoginForm.svelte +42 -0
- package/dist/profiler/ui/LoginForm.svelte.d.ts +7 -0
- package/dist/profiler/ui/Message.svelte +10 -0
- package/dist/profiler/ui/Message.svelte.d.ts +12 -0
- package/dist/profiler/ui/OnThisPage.svelte +137 -0
- package/dist/profiler/ui/OnThisPage.svelte.d.ts +3 -0
- package/dist/profiler/ui/OneClock.svelte +297 -0
- package/dist/profiler/ui/OneClock.svelte.d.ts +27 -0
- package/dist/profiler/ui/Panel.svelte +10 -0
- package/dist/profiler/ui/Panel.svelte.d.ts +16 -0
- package/dist/profiler/ui/Paths.svelte +269 -0
- package/dist/profiler/ui/Paths.svelte.d.ts +15 -0
- package/dist/profiler/ui/Patterns.svelte +364 -0
- package/dist/profiler/ui/Patterns.svelte.d.ts +15 -0
- package/dist/profiler/ui/PermalinkGate.svelte +143 -0
- package/dist/profiler/ui/PermalinkGate.svelte.d.ts +10 -0
- package/dist/profiler/ui/RenderSteps.svelte +218 -0
- package/dist/profiler/ui/RenderSteps.svelte.d.ts +13 -0
- package/dist/profiler/ui/Report.svelte +28 -0
- package/dist/profiler/ui/Report.svelte.d.ts +20 -0
- package/dist/profiler/ui/ReportBody.svelte +2592 -0
- package/dist/profiler/ui/ReportBody.svelte.d.ts +21 -0
- package/dist/profiler/ui/Run.svelte +17 -0
- package/dist/profiler/ui/Run.svelte.d.ts +14 -0
- package/dist/profiler/ui/RunView.svelte +146 -0
- package/dist/profiler/ui/RunView.svelte.d.ts +10 -0
- package/dist/profiler/ui/ScoreCard.svelte +197 -0
- package/dist/profiler/ui/ScoreCard.svelte.d.ts +7 -0
- package/dist/profiler/ui/Scrub.svelte +293 -0
- package/dist/profiler/ui/Scrub.svelte.d.ts +18 -0
- package/dist/profiler/ui/SeedExplainer.svelte +193 -0
- package/dist/profiler/ui/SeedExplainer.svelte.d.ts +16 -0
- package/dist/profiler/ui/ShareLink.svelte +148 -0
- package/dist/profiler/ui/ShareLink.svelte.d.ts +8 -0
- package/dist/profiler/ui/Shell.svelte +50 -0
- package/dist/profiler/ui/Shell.svelte.d.ts +27 -0
- package/dist/profiler/ui/Sidebar.svelte +312 -0
- package/dist/profiler/ui/Sidebar.svelte.d.ts +7 -0
- package/dist/profiler/ui/Site.svelte +20 -0
- package/dist/profiler/ui/Site.svelte.d.ts +23 -0
- package/dist/profiler/ui/SiteView.svelte +385 -0
- package/dist/profiler/ui/SiteView.svelte.d.ts +27 -0
- package/dist/profiler/ui/ThemeSwitch.svelte +78 -0
- package/dist/profiler/ui/ThemeSwitch.svelte.d.ts +3 -0
- package/dist/profiler/ui/Timeline.svelte +672 -0
- package/dist/profiler/ui/Timeline.svelte.d.ts +22 -0
- package/dist/profiler/ui/Treemap.svelte +278 -0
- package/dist/profiler/ui/Treemap.svelte.d.ts +20 -0
- package/dist/profiler/ui/Upload.svelte +19 -0
- package/dist/profiler/ui/Upload.svelte.d.ts +10 -0
- package/dist/profiler/ui/UploadForm.svelte +59 -0
- package/dist/profiler/ui/UploadForm.svelte.d.ts +6 -0
- package/dist/profiler/ui/WaitingTable.svelte +55 -0
- package/dist/profiler/ui/WaitingTable.svelte.d.ts +14 -0
- package/dist/profiler/ui/Waterfall.svelte +371 -0
- package/dist/profiler/ui/Waterfall.svelte.d.ts +7 -0
- package/dist/profiler/ui/WhatIf.svelte +87 -0
- package/dist/profiler/ui/WhatIf.svelte.d.ts +18 -0
- package/dist/profiler/ui/fake-progress.svelte.d.ts +15 -0
- package/dist/profiler/ui/fake-progress.svelte.js +38 -0
- package/dist/profiler/ui/format.d.ts +20 -0
- package/dist/profiler/ui/format.js +71 -0
- package/dist/profiler/ui/permalink.d.ts +9 -0
- package/dist/profiler/ui/permalink.js +108 -0
- package/dist/profiler/ui/press.d.ts +5 -0
- package/dist/profiler/ui/press.js +19 -0
- package/dist/profiler/ui/profiler.css +650 -0
- package/dist/profiler/ui/report-data.d.ts +189 -0
- package/dist/profiler/ui/report-data.js +393 -0
- package/dist/profiler/ui/report-request.d.ts +6 -0
- package/dist/profiler/ui/report-request.js +50 -0
- package/dist/profiler/ui/row-anchor.svelte.d.ts +12 -0
- package/dist/profiler/ui/row-anchor.svelte.js +44 -0
- package/dist/profiler/ui/sort.svelte.d.ts +14 -0
- package/dist/profiler/ui/sort.svelte.js +37 -0
- package/dist/profiler/ui/store.d.ts +45 -0
- package/dist/profiler/ui/store.js +92 -0
- package/dist/profiler/visit.d.ts +389 -0
- package/dist/profiler/visit.js +1002 -0
- package/dist/report.d.ts +5 -0
- package/dist/report.js +4 -0
- package/dist/server.d.ts +11 -0
- package/dist/server.js +38 -0
- package/dist/vite.d.ts +12 -0
- package/dist/vite.js +78 -0
- package/package.json +103 -3
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
<!-- (its CSS injected into the dock's shadow root: see Devtools.svelte) -->
|
|
2
|
+
<svelte:options css="injected" />
|
|
3
|
+
|
|
4
|
+
<script>
|
|
5
|
+
/**
|
|
6
|
+
* The Hub tab (hub inspector, internal/notes/devtools.md, Rung 5 · 6): ogygia's identity spine made
|
|
7
|
+
* visible. Every transportable that crosses an island boundary — a wired class, a store, a snippet,
|
|
8
|
+
* a held region, a hoisted fn — is a hub Ref with one id, and the browser MEMOIZES decode by id so
|
|
9
|
+
* N islands holding the same handle REUNITE on ONE live instance. This tab shows that: per id, its
|
|
10
|
+
* kind, how many times it was resolved (= how many carriers picked it up), and how many of those
|
|
11
|
+
* were REUNIONS (a memo hit returning the existing instance vs a first fresh decode). Plus the
|
|
12
|
+
* dispose reaping that runs on navigation. Reads hub.mint / hub.resolve / hub.dispose off the bus.
|
|
13
|
+
*/
|
|
14
|
+
import { snapshot } from '@ogygia/core/events';
|
|
15
|
+
|
|
16
|
+
let { tick = 0 } = $props();
|
|
17
|
+
|
|
18
|
+
// A transportable's registration tag is `<module path>#<ExportName>` — the class/const name is the
|
|
19
|
+
// part after `#`. That's the human label; the id is a mint hash (fall back to it when untagged).
|
|
20
|
+
function short_id(id) {
|
|
21
|
+
return id && id.length > 12 ? id.slice(0, 8) + '…' : id;
|
|
22
|
+
}
|
|
23
|
+
function name_of(m) {
|
|
24
|
+
if (m.tag) return m.tag.split('#').pop() || m.tag;
|
|
25
|
+
return short_id(m.id);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Kind → colour, so wire / store / snippet / region / fn read at a glance.
|
|
29
|
+
const KIND = {
|
|
30
|
+
wire: '#14b8a6',
|
|
31
|
+
store: '#8b5cf6',
|
|
32
|
+
snippet: '#f59e0b',
|
|
33
|
+
region: '#38bdf8',
|
|
34
|
+
fn: '#ec4899'
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const model = $derived.by(() => {
|
|
38
|
+
void tick; // refresh with the panel tick
|
|
39
|
+
const ev = snapshot();
|
|
40
|
+
const byId = new Map();
|
|
41
|
+
const get = (id) => {
|
|
42
|
+
let m = byId.get(id);
|
|
43
|
+
if (!m) byId.set(id, (m = { id, kind: '', tag: '', scope: '', resolves: 0, reunions: 0 }));
|
|
44
|
+
return m;
|
|
45
|
+
};
|
|
46
|
+
for (const e of ev) {
|
|
47
|
+
if (e.name === 'hub.mint') {
|
|
48
|
+
const m = get(e.id);
|
|
49
|
+
m.kind = e.kind;
|
|
50
|
+
if (e.tag) m.tag = e.tag;
|
|
51
|
+
} else if (e.name === 'hub.resolve') {
|
|
52
|
+
const m = get(e.id);
|
|
53
|
+
if (!m.kind) m.kind = e.kind;
|
|
54
|
+
if (e.tag && !m.tag) m.tag = e.tag; // wire tag rides the client decode (mint is server-only)
|
|
55
|
+
m.scope = e.scope;
|
|
56
|
+
m.resolves++;
|
|
57
|
+
if (e.hit) m.reunions++;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Shared instances (reunited at least once) first — they ARE the story — then by carrier count.
|
|
61
|
+
const rows = [...byId.values()].sort(
|
|
62
|
+
(a, b) => b.reunions - a.reunions || b.resolves - a.resolves
|
|
63
|
+
);
|
|
64
|
+
const shared = rows.filter((r) => r.reunions > 0).length;
|
|
65
|
+
const disposes = ev.filter((e) => e.name === 'hub.dispose');
|
|
66
|
+
return { rows, shared, disposes };
|
|
67
|
+
});
|
|
68
|
+
</script>
|
|
69
|
+
|
|
70
|
+
<div class="cap">
|
|
71
|
+
hub inspector <span class="muted">· one live object, shared across islands by identity</span>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
{#if model.rows.length === 0}
|
|
75
|
+
<div class="muted">
|
|
76
|
+
no hub activity on this page. Visit a page with a wired class / store / held region (e.g.
|
|
77
|
+
<b>/transportable</b> or <b>/lab/wire</b>) — then reopen this tab.
|
|
78
|
+
</div>
|
|
79
|
+
{:else}
|
|
80
|
+
{#if model.shared > 0}
|
|
81
|
+
<div class="hero">
|
|
82
|
+
<b>{model.shared}</b> shared live object{model.shared === 1 ? '' : 's'} — each held by several islands
|
|
83
|
+
but decoded ONCE, so every holder reunites on the same instance.
|
|
84
|
+
</div>
|
|
85
|
+
{/if}
|
|
86
|
+
<table>
|
|
87
|
+
<thead>
|
|
88
|
+
<tr><th>object</th><th>kind</th><th>scope</th><th>held by</th><th>reunited</th></tr>
|
|
89
|
+
</thead>
|
|
90
|
+
<tbody>
|
|
91
|
+
{#each model.rows as r (r.id)}
|
|
92
|
+
<tr class:shared={r.reunions > 0}>
|
|
93
|
+
<td title={r.tag || r.id}><span class="nm">{name_of(r)}</span></td>
|
|
94
|
+
<td>
|
|
95
|
+
<span class="dot" style:background={KIND[r.kind] || '#64748b'}></span>{r.kind || '—'}
|
|
96
|
+
</td>
|
|
97
|
+
<td class="muted">{r.scope || '—'}</td>
|
|
98
|
+
<td>{r.resolves}×</td>
|
|
99
|
+
<td>
|
|
100
|
+
{#if r.reunions > 0}
|
|
101
|
+
<span class="badge"
|
|
102
|
+
>1 instance · {r.reunions} reunion{r.reunions === 1 ? '' : 's'}</span
|
|
103
|
+
>
|
|
104
|
+
{:else}<span class="muted">fresh</span>{/if}
|
|
105
|
+
</td>
|
|
106
|
+
</tr>
|
|
107
|
+
{/each}
|
|
108
|
+
</tbody>
|
|
109
|
+
</table>
|
|
110
|
+
<div class="note muted">
|
|
111
|
+
<b>held by</b> = how many carriers (islands) picked this handle up. <b>reunited</b> = a memo hit returning
|
|
112
|
+
the existing live instance instead of decoding a fresh one — the reunification that makes N islands
|
|
113
|
+
share ONE reactive object.
|
|
114
|
+
</div>
|
|
115
|
+
|
|
116
|
+
{#if model.disposes.length}
|
|
117
|
+
<div class="sec">dispose (nav teardown)</div>
|
|
118
|
+
<table>
|
|
119
|
+
<thead><tr><th>scope</th><th>instances</th></tr></thead>
|
|
120
|
+
<tbody>
|
|
121
|
+
{#each model.disposes as d (d.seq)}
|
|
122
|
+
<tr><td>{d.scope}</td><td>{d.count}</td></tr>
|
|
123
|
+
{/each}
|
|
124
|
+
</tbody>
|
|
125
|
+
</table>
|
|
126
|
+
{/if}
|
|
127
|
+
{/if}
|
|
128
|
+
|
|
129
|
+
<style>
|
|
130
|
+
.cap {
|
|
131
|
+
font-size: 12px;
|
|
132
|
+
color: #5eead4;
|
|
133
|
+
margin-bottom: 8px;
|
|
134
|
+
}
|
|
135
|
+
.muted {
|
|
136
|
+
color: #94a3b8;
|
|
137
|
+
}
|
|
138
|
+
.muted b {
|
|
139
|
+
color: #94a3b8;
|
|
140
|
+
}
|
|
141
|
+
.hero {
|
|
142
|
+
margin-bottom: 10px;
|
|
143
|
+
padding: 7px 10px;
|
|
144
|
+
border-radius: 8px;
|
|
145
|
+
background: rgba(20, 184, 166, 0.1);
|
|
146
|
+
border: 1px solid rgba(20, 184, 166, 0.25);
|
|
147
|
+
color: #cbd5e1;
|
|
148
|
+
line-height: 1.5;
|
|
149
|
+
}
|
|
150
|
+
.hero b {
|
|
151
|
+
color: #5eead4;
|
|
152
|
+
font-size: 13px;
|
|
153
|
+
}
|
|
154
|
+
table {
|
|
155
|
+
border-collapse: collapse;
|
|
156
|
+
width: 100%;
|
|
157
|
+
}
|
|
158
|
+
th,
|
|
159
|
+
td {
|
|
160
|
+
text-align: right;
|
|
161
|
+
padding: 3px 8px;
|
|
162
|
+
white-space: nowrap;
|
|
163
|
+
}
|
|
164
|
+
th:first-child,
|
|
165
|
+
td:first-child,
|
|
166
|
+
th:nth-child(2),
|
|
167
|
+
td:nth-child(2) {
|
|
168
|
+
text-align: left;
|
|
169
|
+
}
|
|
170
|
+
thead th {
|
|
171
|
+
color: #94a3b8;
|
|
172
|
+
border-bottom: 1px solid rgba(148, 163, 184, 0.2);
|
|
173
|
+
}
|
|
174
|
+
.nm {
|
|
175
|
+
color: #e2e8f0;
|
|
176
|
+
font-weight: 600;
|
|
177
|
+
}
|
|
178
|
+
.dot {
|
|
179
|
+
display: inline-block;
|
|
180
|
+
width: 8px;
|
|
181
|
+
height: 8px;
|
|
182
|
+
border-radius: 50%;
|
|
183
|
+
margin-right: 6px;
|
|
184
|
+
vertical-align: 0;
|
|
185
|
+
}
|
|
186
|
+
tr.shared td {
|
|
187
|
+
background: rgba(20, 184, 166, 0.08);
|
|
188
|
+
}
|
|
189
|
+
.badge {
|
|
190
|
+
margin-left: 6px;
|
|
191
|
+
padding: 0 6px;
|
|
192
|
+
border-radius: 999px;
|
|
193
|
+
font-size: 10px;
|
|
194
|
+
background: rgba(20, 184, 166, 0.18);
|
|
195
|
+
color: #5eead4;
|
|
196
|
+
}
|
|
197
|
+
.note {
|
|
198
|
+
margin-top: 8px;
|
|
199
|
+
line-height: 1.5;
|
|
200
|
+
}
|
|
201
|
+
.sec {
|
|
202
|
+
margin: 12px 0 4px;
|
|
203
|
+
color: #94a3b8;
|
|
204
|
+
font-weight: 600;
|
|
205
|
+
}
|
|
206
|
+
</style>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export default HubTab;
|
|
2
|
+
type HubTab = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
|
+
};
|
|
6
|
+
declare const HubTab: import("svelte").Component<{
|
|
7
|
+
tick?: number;
|
|
8
|
+
}, {}, "">;
|
|
9
|
+
type $$ComponentProps = {
|
|
10
|
+
tick?: number;
|
|
11
|
+
};
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
<!-- (its CSS injected into the dock's shadow root: see Devtools.svelte) -->
|
|
2
|
+
<svelte:options css="injected" />
|
|
3
|
+
|
|
4
|
+
<script>
|
|
5
|
+
/**
|
|
6
|
+
* The Hydration tab: did every island wake from its server markup, and if not, what differed.
|
|
7
|
+
* Per island: failed (threw), recovered (Svelte threw the server DOM away and rendered again),
|
|
8
|
+
* healed (another script edited it before it woke; the runtime put the server markup back),
|
|
9
|
+
* changed (the browser's first render differs from the server's), clean, or still asleep — with
|
|
10
|
+
* the runtime's own reason, and for a changed one the diff of server markup against the browser's
|
|
11
|
+
* (html-diff.ts). Hover a row: the island lights up. Sources: the bus (failed / recovered /
|
|
12
|
+
* healed events), the beacon's before/after markup, the element's `data-og-recovered` reason.
|
|
13
|
+
*/
|
|
14
|
+
import { hydration_rows, STATUS_RANK as RANK } from './hydration.js';
|
|
15
|
+
import { html_diff } from '@ogygia/core/insights';
|
|
16
|
+
import { highlight, clear_highlight } from './highlight.js';
|
|
17
|
+
import { onMount } from 'svelte';
|
|
18
|
+
|
|
19
|
+
let { tick = 0, selected = $bindable(null) } = $props();
|
|
20
|
+
// a row with a difference to show opens it; any other row opens the island's card (a click that
|
|
21
|
+
// did nothing on 8 of 9 rows is what the press-everything sweep found)
|
|
22
|
+
function press(/** @type {{ el: Element; snap?: unknown; status: string }} */ r) {
|
|
23
|
+
if (r.snap && r.status !== 'clean') open_el = open_el === r.el ? null : r.el;
|
|
24
|
+
else selected = r.el;
|
|
25
|
+
}
|
|
26
|
+
// (by element: two copies of one island with the same props share a fingerprint)
|
|
27
|
+
let open_el = $state(/** @type {Element | null} */ (null));
|
|
28
|
+
|
|
29
|
+
const LABEL = {
|
|
30
|
+
failed: 'failed',
|
|
31
|
+
recovered: 'recovered',
|
|
32
|
+
healed: 'healed',
|
|
33
|
+
changed: 'markup changed',
|
|
34
|
+
asleep: 'asleep',
|
|
35
|
+
clean: 'clean'
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const model = $derived.by(() => {
|
|
39
|
+
void tick;
|
|
40
|
+
const { rows, measured } = hydration_rows();
|
|
41
|
+
const counts = {};
|
|
42
|
+
for (const r of rows) counts[r.status] = (counts[r.status] ?? 0) + 1;
|
|
43
|
+
return { rows, counts, measured };
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const diff = $derived.by(() => {
|
|
47
|
+
const r = model.rows.find((x) => x.el === open_el);
|
|
48
|
+
return r?.snap ? html_diff(r.snap.ssr, r.snap.hydrated) : null;
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
onMount(() => () => clear_highlight());
|
|
52
|
+
</script>
|
|
53
|
+
|
|
54
|
+
<div class="hy" data-og-hydration>
|
|
55
|
+
<div class="cap">
|
|
56
|
+
hydration <span class="muted">· did each island wake from its server markup</span>
|
|
57
|
+
</div>
|
|
58
|
+
<div class="counts">
|
|
59
|
+
{#each Object.keys(RANK) as s (s)}
|
|
60
|
+
{#if model.counts[s]}<span class="badge {s}">{LABEL[s]} {model.counts[s]}</span>{/if}
|
|
61
|
+
{/each}
|
|
62
|
+
</div>
|
|
63
|
+
{#if !model.measured}
|
|
64
|
+
<p class="muted">
|
|
65
|
+
The browser's before/after markup needs a measured page load (in a build: open devtools, then
|
|
66
|
+
reload).
|
|
67
|
+
</p>
|
|
68
|
+
{/if}
|
|
69
|
+
|
|
70
|
+
<table>
|
|
71
|
+
<tbody>
|
|
72
|
+
{#each model.rows as r (r.el)}
|
|
73
|
+
<tr
|
|
74
|
+
class="row {r.status}"
|
|
75
|
+
data-status={r.status}
|
|
76
|
+
onmouseenter={() => highlight([r.el], `${r.name} — ${LABEL[r.status]}`)}
|
|
77
|
+
onmouseleave={() => clear_highlight()}
|
|
78
|
+
onclick={() => press(r)}
|
|
79
|
+
title={r.snap && r.status !== 'clean' ? 'show the difference' : "open the island's card"}
|
|
80
|
+
>
|
|
81
|
+
<td><span class="badge {r.status}">{LABEL[r.status]}</span></td>
|
|
82
|
+
<!-- the name is a button: Tab reaches the row, Enter presses it (the press bubbles to the row) -->
|
|
83
|
+
<td class="nm"
|
|
84
|
+
><button
|
|
85
|
+
class="rowbtn"
|
|
86
|
+
onfocus={() => highlight([r.el], `${r.name} — ${LABEL[r.status]}`)}
|
|
87
|
+
onblur={() => clear_highlight()}>{r.name}</button
|
|
88
|
+
><span class="muted"> {r.wake}</span></td
|
|
89
|
+
>
|
|
90
|
+
<td class="why" title={r.reason}
|
|
91
|
+
>{r.reason}{#if r.snap && r.status !== 'clean'}<span class="muted">
|
|
92
|
+
· click for the difference</span
|
|
93
|
+
>{/if}</td
|
|
94
|
+
>
|
|
95
|
+
</tr>
|
|
96
|
+
{#if open_el === r.el && diff}
|
|
97
|
+
<tr class="diffrow">
|
|
98
|
+
<td colspan="3">
|
|
99
|
+
<p class="muted">
|
|
100
|
+
server markup against the browser's first render: <b class="del">−{diff.removed}</b>
|
|
101
|
+
<b class="add">+{diff.added}</b>
|
|
102
|
+
pieces{diff.partial ? ' (too many changes: only where they start)' : ''}
|
|
103
|
+
</p>
|
|
104
|
+
{#if r.snap?.from !== undefined}<p class="muted" data-og-hyd-window>
|
|
105
|
+
A big island: this is the part around its first change, about {Math.round(
|
|
106
|
+
r.snap.from / 1024
|
|
107
|
+
)} KB into its markup — later changes are not shown.
|
|
108
|
+
</p>{/if}
|
|
109
|
+
{#each diff.hunks as h, i (i)}
|
|
110
|
+
<div class="hunk">
|
|
111
|
+
{#each h.ops as o, k (k)}<span class={o.op}>{o.text}</span>{/each}
|
|
112
|
+
</div>
|
|
113
|
+
{/each}
|
|
114
|
+
{#if !diff.hunks.length}<p class="muted">
|
|
115
|
+
No visible difference (only Svelte's markers moved).
|
|
116
|
+
</p>{/if}
|
|
117
|
+
</td>
|
|
118
|
+
</tr>
|
|
119
|
+
{/if}
|
|
120
|
+
{:else}
|
|
121
|
+
<tr><td class="muted">no islands on this page</td></tr>
|
|
122
|
+
{/each}
|
|
123
|
+
</tbody>
|
|
124
|
+
</table>
|
|
125
|
+
</div>
|
|
126
|
+
|
|
127
|
+
<style>
|
|
128
|
+
.hy {
|
|
129
|
+
display: flex;
|
|
130
|
+
flex-direction: column;
|
|
131
|
+
gap: 8px;
|
|
132
|
+
}
|
|
133
|
+
.cap {
|
|
134
|
+
font-size: 12px;
|
|
135
|
+
color: #5eead4;
|
|
136
|
+
}
|
|
137
|
+
.muted {
|
|
138
|
+
color: #94a3b8;
|
|
139
|
+
}
|
|
140
|
+
.counts {
|
|
141
|
+
display: flex;
|
|
142
|
+
flex-wrap: wrap;
|
|
143
|
+
gap: 5px;
|
|
144
|
+
}
|
|
145
|
+
.badge {
|
|
146
|
+
display: inline-block;
|
|
147
|
+
font-size: 10px;
|
|
148
|
+
padding: 1px 7px;
|
|
149
|
+
border-radius: 999px;
|
|
150
|
+
border: 1px solid rgba(148, 163, 184, 0.3);
|
|
151
|
+
white-space: nowrap;
|
|
152
|
+
}
|
|
153
|
+
.badge.failed,
|
|
154
|
+
.badge.recovered {
|
|
155
|
+
background: rgba(239, 68, 68, 0.18);
|
|
156
|
+
color: #fca5a5;
|
|
157
|
+
border-color: rgba(239, 68, 68, 0.4);
|
|
158
|
+
}
|
|
159
|
+
.badge.healed,
|
|
160
|
+
.badge.changed {
|
|
161
|
+
background: rgba(245, 158, 11, 0.16);
|
|
162
|
+
color: #fcd34d;
|
|
163
|
+
border-color: rgba(245, 158, 11, 0.4);
|
|
164
|
+
}
|
|
165
|
+
.badge.clean {
|
|
166
|
+
color: #86efac;
|
|
167
|
+
border-color: rgba(34, 197, 94, 0.35);
|
|
168
|
+
}
|
|
169
|
+
.badge.asleep {
|
|
170
|
+
color: #94a3b8;
|
|
171
|
+
}
|
|
172
|
+
table {
|
|
173
|
+
border-collapse: collapse;
|
|
174
|
+
width: 100%;
|
|
175
|
+
}
|
|
176
|
+
td {
|
|
177
|
+
padding: 3px 4px;
|
|
178
|
+
border-bottom: 1px solid rgba(148, 163, 184, 0.08);
|
|
179
|
+
vertical-align: top;
|
|
180
|
+
}
|
|
181
|
+
.row {
|
|
182
|
+
cursor: pointer;
|
|
183
|
+
}
|
|
184
|
+
.row:hover td {
|
|
185
|
+
background: rgba(148, 163, 184, 0.08);
|
|
186
|
+
}
|
|
187
|
+
.nm {
|
|
188
|
+
white-space: nowrap;
|
|
189
|
+
}
|
|
190
|
+
/* a button that reads as the name it was */
|
|
191
|
+
.rowbtn {
|
|
192
|
+
all: unset;
|
|
193
|
+
cursor: pointer;
|
|
194
|
+
}
|
|
195
|
+
.rowbtn:focus-visible {
|
|
196
|
+
outline: 2px solid rgba(94, 234, 212, 0.7);
|
|
197
|
+
outline-offset: 2px;
|
|
198
|
+
border-radius: 3px;
|
|
199
|
+
}
|
|
200
|
+
.why {
|
|
201
|
+
color: #cbd5e1;
|
|
202
|
+
max-width: 320px;
|
|
203
|
+
overflow: hidden;
|
|
204
|
+
text-overflow: ellipsis;
|
|
205
|
+
white-space: nowrap;
|
|
206
|
+
}
|
|
207
|
+
.diffrow td {
|
|
208
|
+
background: rgba(15, 23, 42, 0.6);
|
|
209
|
+
}
|
|
210
|
+
.hunk {
|
|
211
|
+
font-size: 10.5px;
|
|
212
|
+
line-height: 1.6;
|
|
213
|
+
padding: 5px 7px;
|
|
214
|
+
margin: 4px 0;
|
|
215
|
+
border-radius: 6px;
|
|
216
|
+
background: rgba(148, 163, 184, 0.06);
|
|
217
|
+
word-break: break-all;
|
|
218
|
+
}
|
|
219
|
+
.hunk .same {
|
|
220
|
+
color: #94a3b8;
|
|
221
|
+
}
|
|
222
|
+
.hunk .del {
|
|
223
|
+
background: rgba(239, 68, 68, 0.22);
|
|
224
|
+
color: #fecaca;
|
|
225
|
+
text-decoration: line-through;
|
|
226
|
+
}
|
|
227
|
+
.hunk .add {
|
|
228
|
+
background: rgba(34, 197, 94, 0.2);
|
|
229
|
+
color: #bbf7d0;
|
|
230
|
+
}
|
|
231
|
+
b.del {
|
|
232
|
+
color: #fca5a5;
|
|
233
|
+
}
|
|
234
|
+
b.add {
|
|
235
|
+
color: #86efac;
|
|
236
|
+
}
|
|
237
|
+
</style>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export default HydrationTab;
|
|
2
|
+
type HydrationTab = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
|
+
};
|
|
6
|
+
declare const HydrationTab: import("svelte").Component<{
|
|
7
|
+
tick?: number;
|
|
8
|
+
selected?: any;
|
|
9
|
+
}, {}, "selected">;
|
|
10
|
+
type $$ComponentProps = {
|
|
11
|
+
tick?: number;
|
|
12
|
+
selected?: any;
|
|
13
|
+
};
|