diff --git a/lib/store/__tests__/page-side.test.ts b/lib/store/__tests__/page-side.test.ts index 531759a33..d1b2758df 100644 --- a/lib/store/__tests__/page-side.test.ts +++ b/lib/store/__tests__/page-side.test.ts @@ -56,6 +56,22 @@ afterEach(() => { configureStore(null); }); +describe('whether the store can run here', () => { + afterEach(() => { + delete (window.navigator as { storage?: unknown }).storage; + delete (window.navigator as { locks?: unknown }).locks; + }); + + it('doesn’t ask the page for what only exists in a worker', () => { + expect(StoreClient.supported()).toBe(false); + Object.defineProperty(window.navigator, 'storage', { configurable: true, value: { getDirectory: async () => ({}) } }); + Object.defineProperty(window.navigator, 'locks', { configurable: true, value: { request: async () => {} } }); + // As on a real page: the class is there, without createSyncAccessHandle on it. + vi.stubGlobal('FileSystemFileHandle', class {}); + expect(StoreClient.supported()).toBe(true); + }); +}); + describe('a tab that starts after the owner', () => { it('asks who owns the store, so its calls don\'t wait for an announcement that never comes', async () => { const owner = new FakeChannel('bulwark-store-rpc'); diff --git a/lib/store/client/store-client.ts b/lib/store/client/store-client.ts index d6b2f8440..90926a40a 100644 --- a/lib/store/client/store-client.ts +++ b/lib/store/client/store-client.ts @@ -68,8 +68,10 @@ export class StoreClient { && typeof navigator !== 'undefined' && Boolean(navigator.locks) && typeof navigator.storage?.getDirectory === 'function' - && typeof FileSystemFileHandle !== 'undefined' - && 'createSyncAccessHandle' in FileSystemFileHandle.prototype; + // createSyncAccessHandle itself only exists inside a dedicated worker, + // so the page can't check for it. A browser without it fails at the + // worker's start, which the page hears as an error event. + && typeof FileSystemFileHandle !== 'undefined'; } start(): void {