Skip to content

Commit 51ff1b4

Browse files
pbi-qfsnornagonKiliandsanders11
authored
fix: senderId removed in Electron 28 (#171)
* Accepting ipc events without senderId Since the property has been removed with Electron 28 * Access senderId on cast event object to be compatible with Electron 28, where "senderId" is removed from IpcRendererEvent * fix type error * Implement interface for missing senderId check * replace process.mainModule with a while loop to get the topmost parent * disable test using removed APIs * split the codepaths for electron 28 and electron < 28 * prefix comment for skipped test with TODO * chore: formatting --------- Co-authored-by: Jeremy Rose <[email protected]> Co-authored-by: Kilian Valkhof <[email protected]> Co-authored-by: David Sanders <[email protected]>
1 parent 642040d commit 51ff1b4

File tree

4 files changed

+34
-7
lines changed

4 files changed

+34
-7
lines changed

.circleci/config.yml

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ workflows:
4848
- 25
4949
- 26
5050
- 27
51+
- 28
5152
- cfa/release:
5253
requires:
5354
- test-electron

src/main/server.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,17 @@ export function initialize() {
385385
if (customEvent.defaultPrevented) {
386386
throw new Error(`Blocked remote.require('${moduleName}')`)
387387
} else {
388-
customEvent.returnValue = process.mainModule!.require(moduleName)
388+
// electron < 28
389+
if (process.mainModule) {
390+
customEvent.returnValue = process.mainModule!.require(moduleName)
391+
} else {
392+
// electron >= 28
393+
let mainModule = module;
394+
while (mainModule.parent) {
395+
mainModule = mainModule.parent;
396+
}
397+
customEvent.returnValue = mainModule.require(moduleName)
398+
}
389399
}
390400
}
391401

src/renderer/remote.ts

+15-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { CallbacksRegistry } from './callbacks-registry'
22
import { isPromise, isSerializableObject, serialize, deserialize } from '../common/type-utils'
33
import { MetaTypeFromRenderer, ObjectMember, ObjProtoDescriptor, MetaType } from '../common/types'
4-
import { BrowserWindow, WebContents, ipcRenderer } from 'electron'
4+
import { BrowserWindow, WebContents, ipcRenderer, IpcRendererEvent } from 'electron'
55
import { browserModuleNames } from '../common/module-names'
66
import { getElectronBinding } from '../common/get-electron-binding'
77
import { IPC_MESSAGES } from '../common/ipc-messages';
@@ -309,11 +309,22 @@ function metaToError (meta: { type: 'error', value: any, members: ObjectMember[]
309309
return obj
310310
}
311311

312+
// Backwards compatibility interface for Electron < v28
313+
interface IpcRendererEventWithSenderId extends IpcRendererEvent {
314+
senderId: number
315+
}
316+
317+
function hasSenderId(input: any): input is IpcRendererEventWithSenderId {
318+
return typeof input.senderId === "number"
319+
}
320+
312321
function handleMessage (channel: string, handler: Function) {
313322
ipcRenderer.on(channel, (event, passedContextId, id, ...args) => {
314-
if (event.senderId !== 0) {
315-
console.error(`Message ${channel} sent by unexpected WebContents (${event.senderId})`);
316-
return;
323+
if (hasSenderId(event)) {
324+
if (event.senderId !== 0 && event.senderId !== undefined) {
325+
console.error(`Message ${channel} sent by unexpected WebContents (${event.senderId})`);
326+
return;
327+
}
317328
}
318329

319330
if (passedContextId === contextId) {

test/all.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,12 @@ describe('remote module', () => {
498498
expect(a.getConstructorName(new (class {})())).to.equal('')
499499
})
500500

501-
it('should search module from the user app', async () => {
501+
/* TODO: Electron 28 removed process.mainModule, so we need to find an alternative way to test that the remotely
502+
required module in the renderer uses the same main module as the main process. In src/main/server.ts:388 we do so
503+
by looping over the module parents until getting the top most one and using their require, but that require
504+
doesn't send along the module paths, so we can't use it here. */
505+
506+
it.skip('should search module from the user app', async () => {
502507
expectPathsEqual(
503508
path.normalize(await remotely(() => require('./renderer').process.mainModule!.filename)),
504509
path.resolve(__dirname, 'index.js')
@@ -887,7 +892,7 @@ describe('remote module', () => {
887892
} catch (e) {
888893
done(e)
889894
} finally {
890-
process.off('unhandledRejection', onUnhandledRejection)
895+
process.off('unhandledRejection' as any, onUnhandledRejection)
891896
}
892897
})
893898
})

0 commit comments

Comments
 (0)