diff --git a/.eslintrc.json b/.eslintrc.json index 4d54b63c..4934137b 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -9,7 +9,32 @@ "@typescript-eslint" ], "rules": { - "@typescript-eslint/naming-convention": "warn", + "@typescript-eslint/naming-convention": [ + "warn", + { + "selector": "default", + "format": ["camelCase"], + "leadingUnderscore": "allow", + "trailingUnderscore": "allow" + }, + { + "selector": "variable", + "format": ["camelCase", "UPPER_CASE"], + "leadingUnderscore": "allow", + "trailingUnderscore": "allow" + }, + { + "selector": "typeLike", + "format": ["PascalCase"] + }, + { + // Keys of a foreign API, quoted because they have to be - the dotted ELK + // layout options have no camelCase spelling to pick. + "selector": ["objectLiteralProperty", "typeProperty"], + "modifiers": ["requiresQuotes"], + "format": null + } + ], "@typescript-eslint/semi": "warn", "curly": "warn", "eqeqeq": "warn", diff --git a/elk-task/current.png b/elk-task/current.png new file mode 100644 index 00000000..9c6d2afa Binary files /dev/null and b/elk-task/current.png differ diff --git a/elk-task/elk-plan.md b/elk-task/elk-plan.md new file mode 100644 index 00000000..eed483a8 --- /dev/null +++ b/elk-task/elk-plan.md @@ -0,0 +1,733 @@ +# ELK-based visualization: plan + +Replace the current CSS-flexbox + linkerline rendering of the programflow visualization +with a real graph model laid out by [elkjs](https://github.com/kieler/elkjs), add +collapsible heap nodes, and make the whole thing themable from CSS. + +`example.elkt` in the repo root is the hand-written target shape (prototype for +). It is a *specification*, +not a runtime artifact: elkjs consumes a JSON graph, not the `.elkt` text notation. + +--- + +## 1. Where we are today + +| Concern | Current implementation | +| --- | --- | +| Model | none — `html-generator.ts` builds two raw HTML strings (`stackHTML`, `heapHTML`) | +| Layout | CSS flex, two floated columns (`.floating-left` = frames 35%, `.floating-right` = objects 65%) | +| Edges | `linkerline`, drawn *after* render by measuring DOM elements found via `id="…Pointer"` / `id="heapEndPointer"` regex-scraped out of the HTML strings | +| Styling | hardcoded colors in `webview.css` (`.box`, `.frame`, `.current-frame`, …) | +| Collapsing | not supported | + +Blast radius is small: `FrontendTraceElem` / `HTMLGenerator` are referenced **only** by +`web/webview.ts` and `web/html-generator.ts`. The extension host +(`frontend/visualization_panel.ts`) only ships `BackendTraceElem`s, so nothing on the +VS Code side changes. + +## 2. Constraints found while checking the code + +- **`heap` is not a `Map`.** `types.ts` declares `heap: Map`, but after + IPC/JSON it is a plain object — today's code works around this with `Object.keys(...)`. + Same for `HeapValue.value` / `.keys` on `dict` and `instance`. Use `Object.entries`. +- **CSP blocks Web Workers.** `web/index.html` has `default-src 'none'` and no + `worker-src`, so `worker-src` falls back to `none`. → Use the synchronous bundled build + `elkjs/lib/elk.bundled.js` (main thread, no worker). Revisit the worker build only if + layout is too slow; that would also need `worker-src blob:;` in the CSP. +- **Bundling, and minification is now mandatory.** `elk.bundled.js` is plain JS and bundles + fine into `webview.js` via esbuild; elkjs ships its own type declarations, so no + `@types/*` package. Measured by the spike (`elk-task/spike/spike.mjs`): + + | | size | + | --- | --- | + | `webview.js` today | 161 KiB | + | elkjs bundled, unminified | 3423 KiB | + | elkjs bundled, minified | 1426 KiB | + + esbuild is currently run **without** `minify`, so bundling elkjs as-is would grow the + webview payload 21×. `scripts/build-web.mjs` must set `minify: true` (at least for + non-watch builds) before elkjs goes in. Even then it is ~1.4 MiB, so if webview startup + suffers, the fallback is a separate `