diff --git a/lib/browser/remote/objects-registry.ts b/lib/browser/remote/objects-registry.ts index 97fa39c5ee..0de48c3960 100644 --- a/lib/browser/remote/objects-registry.ts +++ b/lib/browser/remote/objects-registry.ts @@ -127,6 +127,10 @@ class ObjectsRegistry { this.clear(webContents, contextId) } } + // Note that the "render-view-deleted" event may not be emitted on time when + // the renderer process get destroyed because of navigation, we rely on the + // renderer process to send "ELECTRON_BROWSER_CONTEXT_RELEASE" message to + // guard this situation. webContents.on('render-view-deleted' as any, listener) } } diff --git a/lib/browser/remote/server.ts b/lib/browser/remote/server.ts index d1cfab1e80..5dcf3b8848 100644 --- a/lib/browser/remote/server.ts +++ b/lib/browser/remote/server.ts @@ -541,7 +541,6 @@ handleRemoteCommand('ELECTRON_BROWSER_DEREFERENCE', function (event, contextId, handleRemoteCommand('ELECTRON_BROWSER_CONTEXT_RELEASE', (event, contextId) => { objectsRegistry.clear(event.sender, contextId) - return null }) handleRemoteCommand('ELECTRON_BROWSER_GUEST_WEB_CONTENTS', function (event, contextId, guestInstanceId, stack) { diff --git a/lib/renderer/api/remote.js b/lib/renderer/api/remote.js index ebe6e62ecb..53087896d9 100644 --- a/lib/renderer/api/remote.js +++ b/lib/renderer/api/remote.js @@ -19,7 +19,7 @@ const contextId = v8Util.getHiddenValue(global, 'contextId') // to guard that situation. process.on('exit', () => { const command = 'ELECTRON_BROWSER_CONTEXT_RELEASE' - ipcRendererInternal.sendSync(command, contextId) + ipcRendererInternal.send(command, contextId) }) // Convert the arguments object into an array of meta data. diff --git a/spec-main/api-remote-spec.ts b/spec-main/api-remote-spec.ts index 130576811c..13d8e3b9ce 100644 --- a/spec-main/api-remote-spec.ts +++ b/spec-main/api-remote-spec.ts @@ -1,18 +1,21 @@ +import * as path from 'path' import { expect } from 'chai' import { closeWindow } from './window-helpers' import { ifdescribe } from './spec-helpers'; -import { BrowserWindow } from 'electron' +import { ipcMain, BrowserWindow } from 'electron' const features = process.electronBinding('features') ifdescribe(features.isRemoteModuleEnabled())('remote module', () => { + const fixtures = path.join(__dirname, 'fixtures') + let w = null as unknown as BrowserWindow - before(async () => { + beforeEach(async () => { w = new BrowserWindow({show: false, webPreferences: {nodeIntegration: true}}) await w.loadURL('about:blank') }) - after(async () => { + afterEach(async () => { await closeWindow(w) }) @@ -112,4 +115,25 @@ ifdescribe(features.isRemoteModuleEnabled())('remote module', () => { await expect(remotely(`require('electron').remote.getCurrentWebContents()`)).to.eventually.be.rejected(`Blocked remote.getCurrentWebContents()`) }) }) + + describe('remote references', () => { + it('render-view-deleted is sent when page is destroyed', (done) => { + w.webContents.once('render-view-deleted' as any, () => { + done() + }) + w.destroy() + }) + + // The ELECTRON_BROWSER_CONTEXT_RELEASE message relies on this to work. + it('message can be sent on exit when page is being navigated', (done) => { + after(() => { ipcMain.removeAllListeners('SENT_ON_EXIT') }) + ipcMain.once('SENT_ON_EXIT', () => { + done() + }) + w.webContents.once('did-finish-load', () => { + w.webContents.loadURL('about:blank') + }) + w.loadFile(path.join(fixtures, 'api', 'send-on-exit.html')) + }) + }) }) diff --git a/spec-main/fixtures/api/send-on-exit.html b/spec-main/fixtures/api/send-on-exit.html new file mode 100644 index 0000000000..8be9b4b06a --- /dev/null +++ b/spec-main/fixtures/api/send-on-exit.html @@ -0,0 +1,11 @@ + +
+ + +