diff --git a/packages/wxt/src/utils/__tests__/content-script-context.test.ts b/packages/wxt/src/utils/__tests__/content-script-context.test.ts index f7a5ffc8..ca7bdcac 100644 --- a/packages/wxt/src/utils/__tests__/content-script-context.test.ts +++ b/packages/wxt/src/utils/__tests__/content-script-context.test.ts @@ -32,6 +32,25 @@ describe('Content Script Context', () => { expect(isValid).toBe(false); }); + it('should not throw when browser.runtime is undefined (extension context fully invalidated)', () => { + const ctx = new ContentScriptContext('test'); + const onInvalidated = vi.fn(); + + ctx.onInvalidated(onInvalidated); + // Simulate complete extension context invalidation where browser.runtime becomes undefined + const originalRuntime = fakeBrowser.runtime; + // @ts-ignore + fakeBrowser.runtime = undefined; + + // Should not throw, and should mark as invalid + expect(() => ctx.isInvalid).not.toThrow(); + expect(ctx.isInvalid).toBe(true); + expect(onInvalidated).toBeCalled(); + + // Restore for other tests + fakeBrowser.runtime = originalRuntime; + }); + it('should invalidate the current content script when a new context is created', async () => { const name = 'test'; const onInvalidated = vi.fn(); diff --git a/packages/wxt/src/utils/content-script-context.ts b/packages/wxt/src/utils/content-script-context.ts index fdcbe857..7fa84da0 100644 --- a/packages/wxt/src/utils/content-script-context.ts +++ b/packages/wxt/src/utils/content-script-context.ts @@ -71,7 +71,7 @@ export class ContentScriptContext implements AbortController { } get isInvalid(): boolean { - if (browser.runtime.id == null) { + if (browser.runtime?.id == null) { this.notifyInvalidated(); // Sets `signal.aborted` to true } return this.signal.aborted;