// In Shoal the viewer runs in a frame with scripts only (no same origin), where touching localStorage or // sessionStorage throws. The upstream UI reads both (onboarding, the identity reveal, sound settings), some of it // without a try, so the page gets in-memory stand-ins before any of it loads. for (const name of ['localStorage', 'sessionStorage'] as const) { try { void window[name].length; } catch { const data = new Map(); const memory: Storage = { get length() { return data.size; }, clear: () => data.clear(), getItem: (k) => data.get(k) ?? null, key: (i) => [...data.keys()][i] ?? null, removeItem: (k) => void data.delete(k), setItem: (k, v) => void data.set(k, String(v)), }; try { Object.defineProperty(window, name, { value: memory, configurable: true }); } catch { // nothing more to do: the upstream code that guards its storage keeps working } } }