As the Electron API documentation for ipcRenderer states, "The ipcRenderer module is an EventEmitter".
This "EventEmitter" referenced by Electron is the EventEmitter class of node.js. Electron's ipcRenderer module inherits node's EventEmitter class.
The methods viewable by console.log(ipcRenderer) are Electron's methods. All inherited methods are found in the Prototype object, which is exactly where you will find the on() method.
To see this in action add console.log(ipcRenderer) to a typical, well formed, safe and readable preload.js script.
preload.js (main thread)
// Import the necessary Electron components.
const contextBridge = require('electron').contextBridge;
const ipcRenderer = require('electron').ipcRenderer;
// White-listed channels.
const ipc = {
'render': {
// From render to main.
'send': [],
// From main to render.
'receive': [],
// From render to main and back again.
'sendReceive': []
}
};
// Exposed protected methods in the render process.
contextBridge.exposeInMainWorld(
// Allowed 'ipcRenderer' methods.
'ipcRender', {
// From render to main.
send: (channel, args) => {
let validChannels = ipc.render.send;
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, args);
}
},
// From main to render.
receive: (channel, listener) => {
let validChannels = ipc.render.receive;
if (validChannels.includes(channel)) {
// Show me the prototype (use DevTools in the render thread)
console.log(ipcRenderer);
// Deliberately strip event as it includes `sender`.
ipcRenderer.on(channel, (event, ...args) => listener(...args));
}
},
// From render to main and back again.
invoke: (channel, args) => {
let validChannels = ipc.render.sendReceive;
if (validChannels.includes(channel)) {
return ipcRenderer.invoke(channel, args);
}
}
}
);
Now, open Chrome's DevTools and view the Console tab.
Chrome DevTools - Console Tab Output (render thread)
v EventEmitter
> invoke: async ƒ (e,...t)
> postMessage: ƒ (e,t,n)
> send: ƒ (e,...t)
> sendSync: ƒ (e,...t)
> sendTo: ƒ (e,t,...n)
> sendToHost: ƒ (e,...t)
> _events: {app:versions: ƒ}
_eventsCount: 1
_maxListeners: undefined
Symbol(kCapture): false
v [[Prototype]]: Object
> addListener: ƒ addListener(type, listener)
> emit: ƒ emit(type, ...args)
> eventNames: ƒ eventNames()
> getMaxListeners: ƒ getMaxListeners()
> listenerCount: ƒ listenerCount(type)
> listeners: ƒ listeners(type)
> off: ƒ removeListener(type, listener)
v on: ƒ addListener(type, listener) // <-- Here it is
length: 2
name: "addListener"
> prototype: {constructor: ƒ}
arguments: (...)
caller: (...)
[[FunctionLocation]]: VM14 node:events:486
[[Prototype]]: ƒ ()
[[Scopes]]: Scopes[2]
> once: ƒ once(type, listener)
> prependListener: ƒ prependListener(type, listener)
> prependOnceListener: ƒ prependOnceListener(type, listener)
> rawListeners: ƒ rawListeners(type)
> removeAllListeners: ƒ removeAllListeners(type)
> removeListener: ƒ removeListener(type, listener)
> setMaxListeners: ƒ setMaxListeners(n)
_events: undefined
_eventsCount: 0
_maxListeners: undefined
> constructor: ƒ EventEmitter(opts)
Symbol(kCapture): false
> [[Prototype]]: Object