From 10d967028af2e72382d16b7e2025d243b9e204ae Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Mon, 18 Nov 2024 14:44:30 -0800 Subject: [PATCH] docs: Make ipcRenderer and ipcMain listener API docs consistent (#44651) * docs: Make ipcRenderer and ipcMain listener API docs consistent * test: add some unit tests for ipcRenderer/ipcMain listener behavior * fix: Mark on/off methods as primary and addListener/removeListener as aliases * fix: clear all listeners before running ipcMain removeAllListeners tests --- docs/api/ipc-main.md | 26 ++++++++++++++++++++++---- docs/api/ipc-renderer.md | 12 ++++++------ spec/api-ipc-main-spec.ts | 23 +++++++++++++++++++++++ spec/api-ipc-renderer-spec.ts | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 10 deletions(-) diff --git a/docs/api/ipc-main.md b/docs/api/ipc-main.md index 83dd3628a2..b5b84a2176 100644 --- a/docs/api/ipc-main.md +++ b/docs/api/ipc-main.md @@ -32,7 +32,7 @@ process, see [webContents.send][web-contents-send] for more information. ## Methods -The `ipcMain` module has the following method to listen for events: +The `ipcMain` module has the following methods to listen for events: ### `ipcMain.on(channel, listener)` @@ -44,6 +44,16 @@ The `ipcMain` module has the following method to listen for events: Listens to `channel`, when a new message arrives `listener` would be called with `listener(event, args...)`. +### `ipcMain.off(channel, listener)` + +* `channel` string +* `listener` Function + * `event` [IpcMainEvent][ipc-main-event] + * `...args` any[] + +Removes the specified `listener` from the listener array for the specified +`channel`. + ### `ipcMain.once(channel, listener)` * `channel` string @@ -54,20 +64,28 @@ Listens to `channel`, when a new message arrives `listener` would be called with Adds a one time `listener` function for the event. This `listener` is invoked only the next time a message is sent to `channel`, after which it is removed. +### `ipcMain.addListener(channel, listener)` + +* `channel` string +* `listener` Function + * `event` [IpcMainEvent][ipc-main-event] + * `...args` any[] + +Alias for [`ipcMain.on`](#ipcmainonchannel-listener). + ### `ipcMain.removeListener(channel, listener)` * `channel` string * `listener` Function * `...args` any[] -Removes the specified `listener` from the listener array for the specified -`channel`. +Alias for [`ipcMain.off`](#ipcmainoffchannel-listener). ### `ipcMain.removeAllListeners([channel])` * `channel` string (optional) -Removes listeners of the specified `channel`. +Removes all listeners from the specified `channel`. Removes all listeners from all channels if no channel is specified. ### `ipcMain.handle(channel, listener)` diff --git a/docs/api/ipc-renderer.md b/docs/api/ipc-renderer.md index c33e94fe77..12273e9e1f 100644 --- a/docs/api/ipc-renderer.md +++ b/docs/api/ipc-renderer.md @@ -48,7 +48,8 @@ Listens to `channel`, when a new message arrives `listener` would be called with * `event` [IpcRendererEvent][ipc-renderer-event] * `...args` any[] -Alias for [`ipcRenderer.removeListener`](#ipcrendererremovelistenerchannel-listener). +Removes the specified `listener` from the listener array for the specified +`channel`. ### `ipcRenderer.once(channel, listener)` @@ -76,14 +77,13 @@ Alias for [`ipcRenderer.on`](#ipcrendereronchannel-listener). * `event` [IpcRendererEvent][ipc-renderer-event] * `...args` any[] -Removes the specified `listener` from the listener array for the specified -`channel`. +Alias for [`ipcRenderer.off`](#ipcrendereroffchannel-listener). -### `ipcRenderer.removeAllListeners(channel)` +### `ipcRenderer.removeAllListeners([channel])` -* `channel` string +* `channel` string (optional) -Removes all listeners, or those of the specified `channel`. +Removes all listeners from the specified `channel`. Removes all listeners from all channels if no channel is specified. ### `ipcRenderer.send(channel, ...args)` diff --git a/spec/api-ipc-main-spec.ts b/spec/api-ipc-main-spec.ts index 869591f1d7..7a6340328a 100644 --- a/spec/api-ipc-main-spec.ts +++ b/spec/api-ipc-main-spec.ts @@ -92,4 +92,27 @@ describe('ipc main module', () => { expect(v).to.equal('hello'); }); }); + + describe('ipcMain.removeAllListeners', () => { + beforeEach(() => { ipcMain.removeAllListeners(); }); + beforeEach(() => { ipcMain.removeAllListeners(); }); + + it('removes only the given channel', () => { + ipcMain.on('channel1', () => {}); + ipcMain.on('channel2', () => {}); + + ipcMain.removeAllListeners('channel1'); + + expect(ipcMain.eventNames()).to.deep.equal(['channel2']); + }); + + it('removes all channels if no channel is specified', () => { + ipcMain.on('channel1', () => {}); + ipcMain.on('channel2', () => {}); + + ipcMain.removeAllListeners(); + + expect(ipcMain.eventNames()).to.deep.equal([]); + }); + }); }); diff --git a/spec/api-ipc-renderer-spec.ts b/spec/api-ipc-renderer-spec.ts index 2db75ef3a3..c05be34589 100644 --- a/spec/api-ipc-renderer-spec.ts +++ b/spec/api-ipc-renderer-spec.ts @@ -18,6 +18,7 @@ describe('ipcRenderer module', () => { } }); await w.loadURL('about:blank'); + w.webContents.on('console-message', (event, ...args) => console.error(...args)); }); after(async () => { await closeWindow(w); @@ -144,6 +145,40 @@ describe('ipcRenderer module', () => { }); }); + describe('ipcRenderer.removeAllListeners', () => { + it('removes only the given channel', async () => { + const result = await w.webContents.executeJavaScript(` + (() => { + const { ipcRenderer } = require('electron'); + + ipcRenderer.on('channel1', () => {}); + ipcRenderer.on('channel2', () => {}); + + ipcRenderer.removeAllListeners('channel1'); + + return ipcRenderer.eventNames(); + })() + `); + expect(result).to.deep.equal(['channel2']); + }); + + it('removes all channels if no channel is specified', async () => { + const result = await w.webContents.executeJavaScript(` + (() => { + const { ipcRenderer } = require('electron'); + + ipcRenderer.on('channel1', () => {}); + ipcRenderer.on('channel2', () => {}); + + ipcRenderer.removeAllListeners(); + + return ipcRenderer.eventNames(); + })() + `); + expect(result).to.deep.equal([]); + }); + }); + describe('after context is released', () => { it('throws an exception', async () => { const error = await w.webContents.executeJavaScript(`(${() => {