/** * `localStorage` that cannot throw. * * Reaching `window.localStorage` at all raises `SecurityError` where the * browser is set to block site data, and `setItem` raises `QuotaExceededError` * once the origin's five megabytes are full — which the flow editor's node * clipboard, carrying whole Python sources, can genuinely reach. Either one * thrown from an event handler escapes to `window.onerror`, and with a single * error boundary at the root that blanks the app. * * The pre-paint theme script in `index.html` already guards its own read this * way; this is the same thing for everything that runs after it. */ export const safeStorage = { get(key: string): string | null { try { return localStorage.getItem(key) } catch { return null } }, /** Whether it was actually stored, for the rare caller that wants to know. */ set(key: string, value: string): boolean { try { localStorage.setItem(key, value) return true } catch { return false } }, remove(key: string): void { try { localStorage.removeItem(key) } catch { // Nothing to clean up if it was never reachable. } }, }