GitHub Actions commited on
Commit
19031e8
Β·
1 Parent(s): 35043c2

sync from abhijitramesh/webgpu-bench@3d3db948b0

Browse files
Files changed (4) hide show
  1. data/combined.json +3 -3
  2. js/run/controller.js +51 -84
  3. js/run/hub.js +17 -68
  4. run.html +0 -23
data/combined.json CHANGED
@@ -7,7 +7,7 @@
7
  "platform": "darwin",
8
  "arch": "arm",
9
  "totalMemoryGB": 4,
10
- "submittedAt": "2026-04-25T18:48:06.721Z",
11
  "resultCount": 4,
12
  "passCount": 4,
13
  "llamaCppCommit": null,
@@ -27,7 +27,7 @@
27
  "platform": "darwin",
28
  "arch": "arm",
29
  "totalMemoryGB": 8,
30
- "submittedAt": "2026-04-25T18:48:06.720Z",
31
  "resultCount": 2,
32
  "passCount": 2,
33
  "llamaCppCommit": null,
@@ -50,7 +50,7 @@
50
  "browsers": [
51
  "chromium-147"
52
  ],
53
- "generatedAt": "2026-04-25T18:48:06.775Z"
54
  },
55
  "results": [
56
  {
 
7
  "platform": "darwin",
8
  "arch": "arm",
9
  "totalMemoryGB": 4,
10
+ "submittedAt": "2026-04-25T19:42:00.460Z",
11
  "resultCount": 4,
12
  "passCount": 4,
13
  "llamaCppCommit": null,
 
27
  "platform": "darwin",
28
  "arch": "arm",
29
  "totalMemoryGB": 8,
30
+ "submittedAt": "2026-04-25T19:42:00.459Z",
31
  "resultCount": 2,
32
  "passCount": 2,
33
  "llamaCppCommit": null,
 
50
  "browsers": [
51
  "chromium-147"
52
  ],
53
+ "generatedAt": "2026-04-25T19:42:00.502Z"
54
  },
55
  "results": [
56
  {
js/run/controller.js CHANGED
@@ -7,7 +7,6 @@ import { localSource, hostedSource, inventoryOpfs, purgeOpfs } from './source.js
7
  import { getDeviceBudgetMB, variantFits, describeDevice } from './device.js';
8
  import {
9
  resumeHFSession, beginHFSignIn, signOutHF, submitResultsToDataset,
10
- HF_TOKEN_STORAGE_KEY, HF_POPUP_DONE_MESSAGE, isHFPopupCallback,
11
  } from './hub.js';
12
  import { isHubConfigured, HF_DATASET_REPO } from './config.js';
13
 
@@ -241,13 +240,17 @@ function renderHfSection() {
241
 
242
  if (state.hfSession) {
243
  signinBtn.textContent = 'Sign out';
244
- signinBtn.disabled = false;
 
 
245
  submitBtn.hidden = false;
246
  const eligible = submittableResults();
247
- submitBtn.disabled = eligible.length === 0;
248
- submitBtn.title = eligible.length === 0 && state.results.length > 0
249
- ? `Need at least ${MIN_ITERATIONS_FOR_SUBMIT} successful iterations per variant to submit`
250
- : '';
 
 
251
  const who = state.hfSession.userName ? `@${state.hfSession.userName}` : 'signed in';
252
  const hint = eligible.length > 0
253
  ? ` Β· ${eligible.length}/${state.results.length} variants eligible`
@@ -255,7 +258,15 @@ function renderHfSection() {
255
  userEl.textContent = `${who} Β· β†’ ${HF_DATASET_REPO}${hint}`;
256
  } else {
257
  signinBtn.textContent = 'Sign in with Hugging Face';
258
- signinBtn.disabled = false;
 
 
 
 
 
 
 
 
259
  submitBtn.hidden = true;
260
  userEl.textContent = '';
261
  }
@@ -598,6 +609,9 @@ function updateButtons() {
598
  const rn = $('btn-run'); if (rn) rn.disabled = state.running || checked.length === 0;
599
  const ab = $('btn-abort'); if (ab) { ab.disabled = !state.running; ab.hidden = !state.running; }
600
  renderBudgetMeter(checked, cachedChecked);
 
 
 
601
  }
602
 
603
  /* Show selected size as a fill bar against the device's max model size.
@@ -1485,35 +1499,14 @@ function wirePurgeHandler() {
1485
  });
1486
  }
1487
 
1488
- async function refreshHfSessionFromStorage() {
1489
- try {
1490
- state.hfSession = await resumeHFSession();
1491
- } catch {
1492
- state.hfSession = null;
1493
- }
1494
- renderHfSection();
1495
- }
1496
-
1497
- function wireCrossTabHubSync() {
1498
- // Popup writes the token to localStorage and posts a message to opener.
1499
- // We listen to both: postMessage is the fast path; the storage event also
1500
- // fires for any other open tab on the same origin so they all stay in sync.
1501
- window.addEventListener('storage', (e) => {
1502
- if (e.key !== HF_TOKEN_STORAGE_KEY) return;
1503
- refreshHfSessionFromStorage();
1504
- });
1505
- window.addEventListener('message', (e) => {
1506
- if (e.origin !== location.origin) return;
1507
- if (e.data?.type !== HF_POPUP_DONE_MESSAGE) return;
1508
- refreshHfSessionFromStorage();
1509
- });
1510
- }
1511
-
1512
  function wireHubHandlers() {
1513
  const signinBtn = $('btn-signin');
1514
  const submitBtn = $('btn-submit');
1515
  if (signinBtn) {
1516
  signinBtn.addEventListener('click', async () => {
 
 
 
1517
  try {
1518
  if (state.hfSession) {
1519
  signOutHF();
@@ -1521,20 +1514,8 @@ function wireHubHandlers() {
1521
  renderHfSection();
1522
  return;
1523
  }
1524
- // Popup keeps any in-flight benchmark + accumulated results alive on
1525
- // this tab. Fall back to a full-page redirect only if the popup is
1526
- // blocked by the browser.
1527
- try {
1528
- await beginHFSignIn({ popup: true });
1529
- logLine('Opened HF sign-in in a new tab β€” finish there and come back.');
1530
- } catch (err) {
1531
- if (err.code === 'popup-blocked') {
1532
- logLine('Popup blocked β€” falling back to full-page sign-in. Your in-progress run will be lost.');
1533
- await beginHFSignIn({ popup: false });
1534
- } else {
1535
- throw err;
1536
- }
1537
- }
1538
  } catch (err) {
1539
  logLine(`Sign-in failed: ${err.message}`);
1540
  }
@@ -1584,43 +1565,6 @@ function wireRunHandlers() {
1584
 
1585
  export async function mountRunSection() {
1586
  if (state.mounted) return;
1587
-
1588
- // OAuth popup fast-path: when this page is loaded inside the sign-in
1589
- // popup, the URL carries `code`+`state` from HF. We can't rely on
1590
- // `window.opener` alone because HF's OAuth response sets COOP, which
1591
- // severs the opener reference in Chrome/Safari. `isHFPopupCallback()`
1592
- // also checks the localStorage marker the opener writes pre-popup.
1593
- if (typeof window !== 'undefined') {
1594
- const params = new URLSearchParams(location.search);
1595
- if (params.get('code') && params.get('state') && isHFPopupCallback()) {
1596
- document.body.innerHTML = `
1597
- <div style="padding:48px 32px;font-family:system-ui,sans-serif;color:#222;max-width:480px;margin:0 auto;text-align:center">
1598
- <div id="hf-popup-status" style="font-size:15px;line-height:1.5">Completing sign-in…</div>
1599
- <button id="hf-popup-close" type="button" hidden
1600
- style="margin-top:24px;padding:8px 16px;font:inherit;border:1px solid #ccc;border-radius:6px;background:#f6f6f6;cursor:pointer">
1601
- Close this tab
1602
- </button>
1603
- </div>
1604
- `;
1605
- // Restore visibility β€” the inline guard in run.html hid <html> to avoid
1606
- // a bench-skeleton flash; we own the body now and want our message visible.
1607
- document.documentElement.style.visibility = '';
1608
- try { await resumeHFSession(); } catch { /* logged inside */ }
1609
- // resumeHFSession already calls window.close(); if the browser denies
1610
- // it (Firefox is strict; some COOP cases too), surface a clear message
1611
- // and a manual close button. The parent tab already updated via the
1612
- // storage event triggered by the token write.
1613
- const status = document.getElementById('hf-popup-status');
1614
- const closeBtn = document.getElementById('hf-popup-close');
1615
- if (status) status.textContent = 'Signed in. You can close this tab.';
1616
- if (closeBtn) {
1617
- closeBtn.hidden = false;
1618
- closeBtn.addEventListener('click', () => { try { window.close(); } catch {} });
1619
- }
1620
- return;
1621
- }
1622
- }
1623
-
1624
  state.mounted = true;
1625
 
1626
  state.surface = await detectSurface();
@@ -1663,14 +1607,37 @@ export async function mountRunSection() {
1663
  wireAbortHandler();
1664
  wirePurgeHandler();
1665
  wireHubHandlers();
1666
- wireCrossTabHubSync();
1667
  wireOutputHandlers();
 
 
 
 
 
1668
  updateButtons();
1669
  renderOutput();
1670
- hideProgressUntilFirstRow();
1671
  maybeShowCrashBanner();
1672
  }
1673
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1674
  export function teardownRunSection() {
1675
  // Placeholder β€” no explicit teardown today. Future: abort in-flight runs,
1676
  // detach listeners. For now the Run tab just sits idle.
 
7
  import { getDeviceBudgetMB, variantFits, describeDevice } from './device.js';
8
  import {
9
  resumeHFSession, beginHFSignIn, signOutHF, submitResultsToDataset,
 
10
  } from './hub.js';
11
  import { isHubConfigured, HF_DATASET_REPO } from './config.js';
12
 
 
240
 
241
  if (state.hfSession) {
242
  signinBtn.textContent = 'Sign out';
243
+ // Sign-out itself is fine mid-run, but stay consistent with the disabled
244
+ // sign-in state so the row doesn't toggle look mid-run.
245
+ signinBtn.disabled = state.running;
246
  submitBtn.hidden = false;
247
  const eligible = submittableResults();
248
+ submitBtn.disabled = state.running || eligible.length === 0;
249
+ submitBtn.title = state.running
250
+ ? 'Wait for the benchmark to finish before submitting'
251
+ : (eligible.length === 0 && state.results.length > 0
252
+ ? `Need at least ${MIN_ITERATIONS_FOR_SUBMIT} successful iterations per variant to submit`
253
+ : '');
254
  const who = state.hfSession.userName ? `@${state.hfSession.userName}` : 'signed in';
255
  const hint = eligible.length > 0
256
  ? ` Β· ${eligible.length}/${state.results.length} variants eligible`
 
258
  userEl.textContent = `${who} Β· β†’ ${HF_DATASET_REPO}${hint}`;
259
  } else {
260
  signinBtn.textContent = 'Sign in with Hugging Face';
261
+ // Sign-in triggers a full-page redirect, which would kill an in-flight
262
+ // worker. Disable the button while the benchmark is running so the user
263
+ // can't accidentally lose their run; results are saved progressively to
264
+ // localStorage and restored on the next mount, so finishing the run and
265
+ // signing in afterwards still lets them submit.
266
+ signinBtn.disabled = state.running;
267
+ signinBtn.title = state.running
268
+ ? 'Wait for the benchmark to finish before signing in'
269
+ : '';
270
  submitBtn.hidden = true;
271
  userEl.textContent = '';
272
  }
 
609
  const rn = $('btn-run'); if (rn) rn.disabled = state.running || checked.length === 0;
610
  const ab = $('btn-abort'); if (ab) { ab.disabled = !state.running; ab.hidden = !state.running; }
611
  renderBudgetMeter(checked, cachedChecked);
612
+ // Keep the Sign in / Submit buttons in sync with the running flag β€” they
613
+ // depend on it so the user can't kick off a redirect mid-run.
614
+ renderHfSection();
615
  }
616
 
617
  /* Show selected size as a fill bar against the device's max model size.
 
1499
  });
1500
  }
1501
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1502
  function wireHubHandlers() {
1503
  const signinBtn = $('btn-signin');
1504
  const submitBtn = $('btn-submit');
1505
  if (signinBtn) {
1506
  signinBtn.addEventListener('click', async () => {
1507
+ // Sign in / Sign out is disabled while a run is in flight; this guard
1508
+ // catches a stale-event-during-state-change race and keeps results safe.
1509
+ if (state.running) return;
1510
  try {
1511
  if (state.hfSession) {
1512
  signOutHF();
 
1514
  renderHfSection();
1515
  return;
1516
  }
1517
+ await beginHFSignIn();
1518
+ // beginHFSignIn redirects β€” unreachable after.
 
 
 
 
 
 
 
 
 
 
 
 
1519
  } catch (err) {
1520
  logLine(`Sign-in failed: ${err.message}`);
1521
  }
 
1565
 
1566
  export async function mountRunSection() {
1567
  if (state.mounted) return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1568
  state.mounted = true;
1569
 
1570
  state.surface = await detectSurface();
 
1607
  wireAbortHandler();
1608
  wirePurgeHandler();
1609
  wireHubHandlers();
 
1610
  wireOutputHandlers();
1611
+ // Restore the last completed run from localStorage so it survives a page
1612
+ // reload β€” including the OAuth redirect taking the user to HF and back.
1613
+ // Must run before updateButtons/renderOutput/hideProgress so they pick up
1614
+ // the rehydrated state.results.
1615
+ restoreSavedResults();
1616
  updateButtons();
1617
  renderOutput();
1618
+ if (state.results.length === 0) hideProgressUntilFirstRow();
1619
  maybeShowCrashBanner();
1620
  }
1621
 
1622
+ const RESULTS_STORAGE_KEY = 'webgpu-bench:lastRun';
1623
+
1624
+ function restoreSavedResults() {
1625
+ let saved;
1626
+ try {
1627
+ const raw = localStorage.getItem(RESULTS_STORAGE_KEY);
1628
+ if (!raw) return;
1629
+ saved = JSON.parse(raw);
1630
+ } catch { return; }
1631
+ if (!Array.isArray(saved) || saved.length === 0) return;
1632
+
1633
+ state.results = saved;
1634
+ for (const record of saved) {
1635
+ const v = state.variants.find(x => x.repo === record.repo && x.filename === record.filename);
1636
+ if (!v) continue;
1637
+ progressRowFor(v).fillFromRecord(record);
1638
+ }
1639
+ }
1640
+
1641
  export function teardownRunSection() {
1642
  // Placeholder β€” no explicit teardown today. Future: abort in-flight runs,
1643
  // detach listeners. For now the Run tab just sits idle.
js/run/hub.js CHANGED
@@ -4,11 +4,13 @@
4
  // 1. On page load, the run controller calls `resumeHFSession()` to handle
5
  // the OAuth redirect (if the URL has the expected query params) and to
6
  // reuse any previously-stored access token.
7
- // 2. Clicking [Sign in] calls `beginHFSignIn({ popup: true })` which opens
8
- // HF in a new window. After consent, HF redirects the popup back here;
9
- // the popup completes the exchange, persists the token to localStorage,
10
- // pings the opener via postMessage, and closes itself. The original
11
- // tab keeps any in-flight benchmark + accumulated results intact.
 
 
12
  // 3. Clicking [Submit] calls `submitResultsToDataset()` which commits a
13
  // JSON file (one per machine-slug / browser / session) as a PR to the
14
  // leaderboard dataset.
@@ -26,34 +28,9 @@ import {
26
  isHubConfigured,
27
  } from './config.js';
28
 
29
- // localStorage (not sessionStorage) so the popup and the original tab share
30
- // the same token namespace, and a `storage` event fires in the opener when
31
- // the popup completes sign-in.
32
- export const HF_TOKEN_STORAGE_KEY = 'webgpu-bench:hfOauth';
33
- export const HF_POPUP_DONE_MESSAGE = 'webgpu-bench:hf-signed-in';
34
- // Marker written by the opener tab right before window.open(). The popup
35
- // reads it on callback to know it's running inside a popup β€” `window.opener`
36
- // is unreliable because HF's OAuth page sets a COOP header that severs the
37
- // opener relationship in Chrome/Safari. Marker is cleared after callback.
38
- const HF_POPUP_PENDING_KEY = 'webgpu-bench:hfPopupPending';
39
- const HF_POPUP_PENDING_TTL_MS = 10 * 60 * 1000;
40
-
41
- export function isHFPopupCallback() {
42
- if (typeof window === 'undefined') return false;
43
- if (window.opener && window.opener !== window) return true;
44
- try {
45
- const raw = localStorage.getItem(HF_POPUP_PENDING_KEY);
46
- if (!raw) return false;
47
- const data = JSON.parse(raw);
48
- if (!data?.ts || (Date.now() - data.ts) > HF_POPUP_PENDING_TTL_MS) {
49
- localStorage.removeItem(HF_POPUP_PENDING_KEY);
50
- return false;
51
- }
52
- return true;
53
- } catch {
54
- return false;
55
- }
56
- }
57
 
58
  // ──────────────── session ────────────────
59
 
@@ -64,30 +41,18 @@ export async function resumeHFSession() {
64
  try {
65
  const res = await oauthHandleRedirectIfPresent();
66
  if (res) {
67
- const session = {
68
  accessToken: res.accessToken,
69
  expiresAt: res.accessTokenExpiresAt,
70
  userName: res.userInfo?.preferred_username || res.userInfo?.name || null,
71
  avatarUrl: res.userInfo?.picture || null,
72
  hubId: res.userInfo?.sub || null,
73
- };
74
- localStorage.setItem(HF_TOKEN_STORAGE_KEY, JSON.stringify(session));
75
  // Clean up the OAuth query params so a reload doesn't retry.
76
  const url = new URL(location.href);
77
  for (const k of ['code', 'state']) url.searchParams.delete(k);
78
  history.replaceState({}, '', url.toString());
79
- // Popup hand-off: tell the opener tab (if accessible) and close. The
80
- // opener also gets a `storage` event from the localStorage write β€”
81
- // postMessage is the fast path; storage event is the safety net for
82
- // when COOP severs window.opener.
83
- if (isHFPopupCallback()) {
84
- localStorage.removeItem(HF_POPUP_PENDING_KEY);
85
- if (window.opener && window.opener !== window && !window.opener.closed) {
86
- try { window.opener.postMessage({ type: HF_POPUP_DONE_MESSAGE }, location.origin); } catch { /* opener gone */ }
87
- }
88
- try { window.close(); } catch { /* not script-opened */ }
89
- }
90
- return session;
91
  }
92
  } catch (err) {
93
  console.warn('OAuth redirect handling failed:', err.message);
@@ -98,12 +63,12 @@ export async function resumeHFSession() {
98
 
99
  function readStoredSession() {
100
  try {
101
- const raw = localStorage.getItem(HF_TOKEN_STORAGE_KEY);
102
  if (!raw) return null;
103
  const data = JSON.parse(raw);
104
  if (!data.accessToken) return null;
105
  if (data.expiresAt && new Date(data.expiresAt).getTime() < Date.now()) {
106
- localStorage.removeItem(HF_TOKEN_STORAGE_KEY);
107
  return null;
108
  }
109
  return data;
@@ -112,7 +77,7 @@ function readStoredSession() {
112
  }
113
  }
114
 
115
- export async function beginHFSignIn({ popup = false } = {}) {
116
  if (!isHubConfigured()) {
117
  throw new Error('HF hub is not configured. Set HF_DATASET_REPO in run/config.js.');
118
  }
@@ -135,27 +100,11 @@ export async function beginHFSignIn({ popup = false } = {}) {
135
  scopes,
136
  redirectUrl: location.origin + location.pathname,
137
  });
138
- if (popup) {
139
- // Set marker BEFORE window.open so the popup callback can detect popup
140
- // mode even when COOP nullifies window.opener.
141
- try {
142
- localStorage.setItem(HF_POPUP_PENDING_KEY, JSON.stringify({ ts: Date.now() }));
143
- } catch { /* quota / disabled β€” best effort */ }
144
- const win = window.open(url, 'hf-oauth', 'popup=yes,width=520,height=720');
145
- if (!win) {
146
- try { localStorage.removeItem(HF_POPUP_PENDING_KEY); } catch { /* noop */ }
147
- const err = new Error('Popup blocked β€” allow popups for this site, or use full-page sign-in.');
148
- err.code = 'popup-blocked';
149
- throw err;
150
- }
151
- return { popup: win };
152
- }
153
  location.assign(url);
154
- return null;
155
  }
156
 
157
  export function signOutHF() {
158
- localStorage.removeItem(HF_TOKEN_STORAGE_KEY);
159
  }
160
 
161
  export async function fetchWhoAmI(token) {
 
4
  // 1. On page load, the run controller calls `resumeHFSession()` to handle
5
  // the OAuth redirect (if the URL has the expected query params) and to
6
  // reuse any previously-stored access token.
7
+ // 2. Clicking [Sign in] calls `beginHFSignIn()` which redirects the
8
+ // browser to HF; after consent, HF redirects back to the page with
9
+ // the OAuth response encoded in the URL. The next page load calls
10
+ // `resumeHFSession()` again, completes the exchange, and stores the
11
+ // token in localStorage. The Run controller restores any previously
12
+ // saved benchmark results from localStorage so they survive the
13
+ // OAuth round-trip.
14
  // 3. Clicking [Submit] calls `submitResultsToDataset()` which commits a
15
  // JSON file (one per machine-slug / browser / session) as a PR to the
16
  // leaderboard dataset.
 
28
  isHubConfigured,
29
  } from './config.js';
30
 
31
+ // localStorage (not sessionStorage) so the token survives the OAuth redirect
32
+ // (different document load) and is shared across tabs on the same origin.
33
+ const TOKEN_STORAGE_KEY = 'webgpu-bench:hfOauth';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
  // ──────────────── session ────────────────
36
 
 
41
  try {
42
  const res = await oauthHandleRedirectIfPresent();
43
  if (res) {
44
+ localStorage.setItem(TOKEN_STORAGE_KEY, JSON.stringify({
45
  accessToken: res.accessToken,
46
  expiresAt: res.accessTokenExpiresAt,
47
  userName: res.userInfo?.preferred_username || res.userInfo?.name || null,
48
  avatarUrl: res.userInfo?.picture || null,
49
  hubId: res.userInfo?.sub || null,
50
+ }));
 
51
  // Clean up the OAuth query params so a reload doesn't retry.
52
  const url = new URL(location.href);
53
  for (const k of ['code', 'state']) url.searchParams.delete(k);
54
  history.replaceState({}, '', url.toString());
55
+ return readStoredSession();
 
 
 
 
 
 
 
 
 
 
 
56
  }
57
  } catch (err) {
58
  console.warn('OAuth redirect handling failed:', err.message);
 
63
 
64
  function readStoredSession() {
65
  try {
66
+ const raw = localStorage.getItem(TOKEN_STORAGE_KEY);
67
  if (!raw) return null;
68
  const data = JSON.parse(raw);
69
  if (!data.accessToken) return null;
70
  if (data.expiresAt && new Date(data.expiresAt).getTime() < Date.now()) {
71
+ localStorage.removeItem(TOKEN_STORAGE_KEY);
72
  return null;
73
  }
74
  return data;
 
77
  }
78
  }
79
 
80
+ export async function beginHFSignIn() {
81
  if (!isHubConfigured()) {
82
  throw new Error('HF hub is not configured. Set HF_DATASET_REPO in run/config.js.');
83
  }
 
100
  scopes,
101
  redirectUrl: location.origin + location.pathname,
102
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  location.assign(url);
 
104
  }
105
 
106
  export function signOutHF() {
107
+ localStorage.removeItem(TOKEN_STORAGE_KEY);
108
  }
109
 
110
  export async function fetchWhoAmI(token) {
run.html CHANGED
@@ -5,29 +5,6 @@
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <meta name="color-scheme" content="light dark">
7
  <script>(function(){var s=localStorage.getItem('theme');if(!s){s=(window.matchMedia&&matchMedia('(prefers-color-scheme: dark)').matches)?'dark':'light';}document.documentElement.setAttribute('data-theme',s);})();</script>
8
- <script>
9
- // OAuth-popup flash guard: if this load is the HF sign-in popup callback,
10
- // hide the page immediately so the user doesn't see the bench skeleton
11
- // flash before mountRunSection() runs the close path.
12
- (function () {
13
- try {
14
- var p = new URLSearchParams(location.search);
15
- if (!p.get('code') || !p.get('state')) return;
16
- var hasOpener = !!(window.opener && window.opener !== window);
17
- var marker = false;
18
- try {
19
- var raw = localStorage.getItem('webgpu-bench:hfPopupPending');
20
- if (raw) {
21
- var data = JSON.parse(raw);
22
- marker = !!(data && data.ts && (Date.now() - data.ts) < 10 * 60 * 1000);
23
- }
24
- } catch (e) { /* localStorage disabled */ }
25
- if (hasOpener || marker) {
26
- document.documentElement.style.visibility = 'hidden';
27
- }
28
- } catch (e) { /* noop */ }
29
- })();
30
- </script>
31
  <title>Run β€” WebGPU Bench</title>
32
  <link rel="preconnect" href="https://fonts.googleapis.com">
33
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
 
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <meta name="color-scheme" content="light dark">
7
  <script>(function(){var s=localStorage.getItem('theme');if(!s){s=(window.matchMedia&&matchMedia('(prefers-color-scheme: dark)').matches)?'dark':'light';}document.documentElement.setAttribute('data-theme',s);})();</script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  <title>Run β€” WebGPU Bench</title>
9
  <link rel="preconnect" href="https://fonts.googleapis.com">
10
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>