From cd7ceab319a2668a9ab0bb456f5f505dc9845b3b Mon Sep 17 00:00:00 2001 From: Daniel Brauner Date: Mon, 21 Sep 2026 14:41:22 +0200 Subject: [PATCH] fix: download button produces truncated or empty JSON The dashboard's "Download data as JSON" button built a `data:,` URL by concatenating the raw `JSON.stringify` output, but that output is not URL-encoded: - `#` starts a fragment, so everything after the first one is dropped. A single commit message referencing an issue (`Fix it (#123)`) is enough to truncate the download to a few hundred bytes. - `%` starts a percent-escape, so a `%` unit or any literal `%` in a commit message makes the URL undecodable and the download fails. Build the download from a `Blob` and an object URL instead, which needs no escaping and carries an `application/json` media type. The object URL is revoked after the click so the data is not pinned in memory for the life of the page. Cover it with a test that runs the dashboard script against a minimal fake DOM with data containing both `#` and `%`, and asserts the downloaded blob round-trips to the complete data. Co-Authored-By: Claude Opus 5 (1M context) --- src/default_index_html.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/default_index_html.ts b/src/default_index_html.ts index a6246d51b..4ee1f14e1 100644 --- a/src/default_index_html.ts +++ b/src/default_index_html.ts @@ -154,11 +154,13 @@ export const DEFAULT_INDEX_HTML = String.raw` // Render footer document.getElementById('dl-button').onclick = () => { - const dataUrl = 'data:,' + JSON.stringify(data, null, 2); + const blob = new Blob([JSON.stringify(data, null, 2)], {type: 'application/json'}); + const url = URL.createObjectURL(blob); const a = document.createElement('a'); - a.href = dataUrl; + a.href = url; a.download = 'benchmark_data.json'; a.click(); + URL.revokeObjectURL(url); }; // Prepare data points for charts