UNPKG

wxt

Version:

⚡ Next-gen Web Extension Framework

144 lines (143 loc) 5.37 kB
import { WxtLocationChangeEvent } from "./internal/custom-events.mjs"; import { ContentScriptDefinition } from "../types.mjs"; //#region src/utils/content-script-context.d.ts /** * Implements * [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController). * Used to detect and stop content script code when the script is invalidated. * * It also provides several utilities like `ctx.setTimeout` and * `ctx.setInterval` that should be used in content scripts instead of * `window.setTimeout` or `window.setInterval`. * * To create context for testing, you can use the class's constructor: * * ```ts * import { ContentScriptContext } from 'wxt/utils/content-scripts-context'; * * test('storage listener should be removed when context is invalidated', () => { * const ctx = new ContentScriptContext('test'); * const item = storage.defineItem('local:count', { defaultValue: 0 }); * const watcher = vi.fn(); * * const unwatch = item.watch(watcher); * ctx.onInvalidated(unwatch); // Listen for invalidate here * * await item.setValue(1); * expect(watcher).toBeCalledTimes(1); * expect(watcher).toBeCalledWith(1, 0); * * ctx.notifyInvalidated(); // Use this function to invalidate the context * await item.setValue(2); * expect(watcher).toBeCalledTimes(1); * }); * ``` */ declare class ContentScriptContext implements AbortController { private readonly contentScriptName; readonly options?: Omit<ContentScriptDefinition, "main"> | undefined; private static SCRIPT_STARTED_MESSAGE_TYPE; private id; private abortController; private locationWatcher; constructor(contentScriptName: string, options?: Omit<ContentScriptDefinition, "main"> | undefined); get signal(): AbortSignal; abort(reason?: any): void; get isInvalid(): boolean; get isValid(): boolean; /** * Add a listener that is called when the content script's context is * invalidated. * * @example * browser.runtime.onMessage.addListener(cb); * const removeInvalidatedListener = ctx.onInvalidated(() => { * browser.runtime.onMessage.removeListener(cb); * }); * // ... * removeInvalidatedListener(); * * @returns A function to remove the listener. */ onInvalidated(cb: () => void): () => void; /** * Return a promise that never resolves. Useful if you have an async function * that shouldn't run after the context is expired. * * @example * const getValueFromStorage = async () => { * if (ctx.isInvalid) return ctx.block(); * * // ... * }; */ block<T>(): Promise<T>; /** * Wrapper around `window.setInterval` that automatically clears the interval * when invalidated. * * Intervals can be cleared by calling the normal `clearInterval` function. */ setInterval(handler: () => void, timeout?: number): number; /** * Wrapper around `window.setTimeout` that automatically clears the interval * when invalidated. * * Timeouts can be cleared by calling the normal `setTimeout` function. */ setTimeout(handler: () => void, timeout?: number): number; /** * Wrapper around `window.requestAnimationFrame` that automatically cancels * the request when invalidated. * * Callbacks can be canceled by calling the normal `cancelAnimationFrame` * function. */ requestAnimationFrame(callback: FrameRequestCallback): number; /** * Wrapper around `window.requestIdleCallback` that automatically cancels the * request when invalidated. * * Callbacks can be canceled by calling the normal `cancelIdleCallback` * function. */ requestIdleCallback(callback: IdleRequestCallback, options?: IdleRequestOptions): number; /** * Call `target.addEventListener` and remove the event listener when the * context is invalidated. * * Listeners can be canceled by calling the normal `removeEventListener` * function. * * Includes additional events useful for content scripts: * * - `"wxt:locationchange"` - Triggered when HTML5 history mode is used to * change URL. Content scripts are not reloaded when navigating this way, so * this can be used to reset the content script state on URL change, or run * custom code. * * @example * ctx.addEventListener(document, 'visibilitychange', () => { * // ... * }); * ctx.addEventListener(window, 'wxt:locationchange', () => { * // ... * }); */ addEventListener<TType extends keyof WxtWindowEventMap>(target: Window, type: TType, handler: (event: WxtWindowEventMap[TType]) => void, options?: AddEventListenerOptions): void; addEventListener<TType extends keyof DocumentEventMap>(target: Document, type: TType, handler: (event: DocumentEventMap[TType]) => void, options?: AddEventListenerOptions): void; addEventListener<TTarget extends EventTarget>(target: TTarget, ...params: Parameters<TTarget['addEventListener']>): void; /** * @internal * Abort the abort controller and execute all `onInvalidated` listeners. */ notifyInvalidated(): void; stopOldScripts(): void; verifyScriptStartedEvent(event: CustomEvent): boolean; listenForNewerScripts(): void; } interface WxtWindowEventMap extends WindowEventMap { 'wxt:locationchange': WxtLocationChangeEvent; } //#endregion export { ContentScriptContext, WxtWindowEventMap };