index.html RawHistoryFolder
1<!doctype html>
2<html lang="en">
3<head>
4 <meta charset="utf-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="dark light">
7 <title>systemviews</title>
8 <link rel="stylesheet" href="./systemviews.css">
9 <script src="./wasm_exec.js"></script>
10 <script>
11 // One terminal-error guard: the loading shell reports its first fatal
12 // failure exactly once. Streaming fallback noise stays console-only.
13 let terminalErrorReported = false;
14 function renderWasmError(prefixText, err) {
15 console.error(prefixText, err);
16 if (terminalErrorReported) return;
17 terminalErrorReported = true;
18 const render = () => {
19 const app = document.getElementById('app');
20 if (!app) return;
21 // innerHTML replacement alone does not clear outer state: drop
22 // the busy flag so assistive tech leaves the loading state.
23 app.removeAttribute('aria-busy');
24 app.setAttribute('data-failed', 'true');
25 app.innerHTML = '';
26 const message = document.createElement('div');
27 message.className = 'sv-error';
28 const prefix = document.createElement('span');
29 prefix.textContent = prefixText;
30 const details = document.createElement('span');
31 details.textContent = err && err.message ? err.message : String(err || 'unsupported browser');
32 message.append(prefix, details);
33 app.append(message);
34 };
35 if (document.readyState === 'loading' && !document.getElementById('app')) {
36 document.addEventListener('DOMContentLoaded', render, { once: true });
37 } else {
38 render();
39 }
40 }
41
42 // Fetch exactly once: retain a clone for byte fallback before streaming
43 // starts, so a streaming failure never issues a second fetch. An
44 // unsuccessful status fails fast without consuming the body.
45 function instantiateWasm(go, wasmURL) {
46 const instantiateFromBytes = (bytes) => WebAssembly.instantiate(bytes, go.importObject);
47
48 if (!WebAssembly.instantiateStreaming) {
49 return fetch(wasmURL)
50 .then((response) => {
51 if (!response.ok) {
52 throw new Error(`HTTP ${response.status} loading ${wasmURL}`);
53 }
54 return response.arrayBuffer();
55 })
56 .then(instantiateFromBytes);
57 }
58 let fallback = null;
59 return fetch(wasmURL)
60 .then((response) => {
61 if (!response.ok) {
62 throw new Error(`HTTP ${response.status} loading ${wasmURL}`);
63 }
64 fallback = response.clone();
65 return WebAssembly.instantiateStreaming(response, go.importObject);
66 })
67 .catch((err) => {
68 if (!fallback) throw err;
69 console.error(`Streaming WebAssembly load failed for ${wasmURL}; falling back to ArrayBuffer instantiation`, err);
70 return fallback.arrayBuffer().then(instantiateFromBytes);
71 });
72 }
73
74 function waitForBridge() {
75 if (window.dumber && typeof window.dumber.postMessage === 'function') return Promise.resolve();
76 if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.dumber) return Promise.resolve();
77 return new Promise((resolve, reject) => {
78 const deadline = Date.now() + 5000;
79 const check = () => {
80 if (window.dumber && typeof window.dumber.postMessage === 'function') return resolve();
81 if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.dumber) return resolve();
82 if (Date.now() >= deadline) return reject(new Error('no bridge transport available'));
83 setTimeout(check, 10);
84 };
85 check();
86 });
87 }
88
89 if (typeof WebAssembly !== 'object') {
90 renderWasmError('WebAssembly is not supported in this browser: ');
91 } else if (typeof Go !== 'function') {
92 renderWasmError('Go WebAssembly runtime failed to load: ');
93 } else {
94 const go = new Go();
95 // Record the runtime exit code: wasm_exec.js routes runtime.wasmExit
96 // through go.exit, whose default only logs. Reporting the actual
97 // status beats the misleading generic suffix on unexpected exits.
98 let goExitCode = null;
99 const goExit = go.exit.bind(go);
100 go.exit = (code) => {
101 goExitCode = code;
102 goExit(code);
103 };
104 waitForBridge()
105 .then(() => instantiateWasm(go, './systemviews.wasm'))
106 // The runtime stays alive: a resolved go.run means main returned
107 // instead of serving, which is itself a terminal failure.
108 .then((result) => go.run(result.instance))
109 .then(
110 () => {
111 // Go renders fatal mount/bind failures itself and marks
112 // data-failed: never overwrite its terminal state here.
113 const app = document.getElementById('app');
114 if (app && app.dataset && app.dataset.failed) return;
115 const code = goExitCode === null ? 'unknown' : String(goExitCode);
116 renderWasmError('systemviews runtime exited: ', new Error(`exit status ${code}`));
117 },
118 (err) => renderWasmError('Failed to load systemviews WebAssembly: ', err),
119 );
120 }
121 </script>
122</head>
123<body>
124 <main id="app" aria-busy="true">Loading systemviews…</main>
125 <noscript>
126 <p>JavaScript is required to run Dumber system views. Enable JavaScript for <code>dumb://history</code>, <code>dumb://favorites</code>, and <code>dumb://config</code>.</p>
127 </noscript>
128</body>
129</html>