From e7e1059137771732db8159564ea205ff6daf1a57 Mon Sep 17 00:00:00 2001 From: fregante Date: Sun, 17 Nov 2024 17:08:18 +0700 Subject: [PATCH] `oneEvent` - Return arguments of listener call (#30) --- readme.md | 10 ++++------ source/one-event.md | 13 +++++++++++++ source/one-event.test.ts | 12 +++++++++--- source/one-event.ts | 6 +++--- 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/readme.md b/readme.md index 3d5715e..e4b8c90 100644 --- a/readme.md +++ b/readme.md @@ -17,17 +17,15 @@ Or download the [standalone bundle](https://bundle.fregante.com/?pkg=webext-even This package exports various utilities, just import what you need. -- [onContextInvalidated](./source/on-context-invalidated.md) -- [onExtensionStart](./source/on-extension-start.md) -- [oneEvent](./source/one-event.md) +- [onContextInvalidated](./source/on-context-invalidated.md) - Fires in content scripts when the extension is disabled, updated or reloaded. +- [onExtensionStart](./source/on-extension-start.md) - Fires when the extension starts or is enabled. This is what yuou thought `chrome.runtime.onStartup` was for. +- [oneEvent](./source/one-event.md) - Creates a promise that resolves when an event is received. +- [addListener](./source/add-listener.md) - Like `.addEventListener` but with a `signal` to remove the listener. ## Related - [webext-tools](https://github.com/fregante/webext-tools) - Utility functions for Web Extensions. - [webext-content-scripts](https://github.com/fregante/webext-content-scripts) - Utility functions to inject content scripts in WebExtensions. -- [webext-detect](https://github.com/fregante/webext-detect) - Detects where the current browser extension code is being run. -- [webext-base-css](https://github.com/fregante/webext-base-css) - Extremely minimal stylesheet/setup for Web Extensions’ options pages (also dark mode) -- [webext-options-sync](https://github.com/fregante/webext-options-sync) - Helps you manage and autosave your extension's options. - [More…](https://github.com/fregante/webext-fun) ## License diff --git a/source/one-event.md b/source/one-event.md index c94d518..c8bfcaa 100644 --- a/source/one-event.md +++ b/source/one-event.md @@ -11,6 +11,17 @@ await oneEvent(chrome.tabs.onCreated); console.log('Hurray, a new tab was created') ``` +It will return the arguments of the event: + +```js +import {oneEvent} from 'webext-events'; + +const [message, sender] = await oneEvent(chrome.runtime.onMessage); +console.log('Message received:', message); +console.log('Message sender:', sender); +``` + + It also supports filtering: ```js @@ -42,6 +53,8 @@ if (timeout.aborted) { } ``` +Note that the signal is aborted, the promise is resolved with `undefined` rather than with the event arguments array. + ## Compatibility - Any browser diff --git a/source/one-event.test.ts b/source/one-event.test.ts index 5a6175c..9cf89bf 100644 --- a/source/one-event.test.ts +++ b/source/one-event.test.ts @@ -50,7 +50,7 @@ describe('oneEvent', () => { }); it('it should resolve original event\'s parameters', () => { - void oneEvent(chrome.tabs.onMoved, { + const onMoved = oneEvent(chrome.tabs.onMoved, { filter(tabId, moveInfo) { expectTypeOf(tabId).toEqualTypeOf(); expectTypeOf(moveInfo).toEqualTypeOf(); @@ -58,7 +58,9 @@ describe('oneEvent', () => { }, }); - void oneEvent(chrome.runtime.onMessage, { + expectTypeOf(onMoved).toEqualTypeOf>(); + + const onMessage = oneEvent(chrome.runtime.onMessage, { filter(message, sender, sendResponse) { expectTypeOf(message).toEqualTypeOf(); expectTypeOf(sender).toEqualTypeOf(); @@ -67,11 +69,15 @@ describe('oneEvent', () => { }, }); - void oneEvent(chrome.cookies.onChanged, { + expectTypeOf(onMessage).toEqualTypeOf void] | void>>(); + + const onChanged = oneEvent(chrome.cookies.onChanged, { filter(changeInfo) { expectTypeOf(changeInfo).toEqualTypeOf(); return true; }, }); + + expectTypeOf(onChanged).toEqualTypeOf>(); }); }); diff --git a/source/one-event.ts b/source/one-event.ts index cd2c72f..c0e00cc 100644 --- a/source/one-event.ts +++ b/source/one-event.ts @@ -18,16 +18,16 @@ export async function oneEvent>( filter?: (...parameters: EventParameters) => boolean; signal?: AbortSignal; } = {}, -): Promise { +): Promise | void> { if (signal?.aborted) { return; } - await new Promise(resolve => { + return new Promise | void>(resolve => { // TODO: VoidFunction should not be necessary, it's equivalent to using "any" const listener: VoidFunction = (...parameters: EventParameters) => { if (!filter || filter(...parameters)) { - resolve(); + resolve(parameters); event.removeListener(listener); } };