Browse Source

fix: send ELECTRON_BROWSER_CONTEXT_RELEASE asynchronously (#20632)

* fix: send ELECTRON_BROWSER_CONTEXT_RELEASE asynchronously

* test: remote references should be able to be cleared for all cases
Milan Burda 5 years ago
parent
commit
ba8f80267c

+ 4 - 0
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)
   }
 }

+ 0 - 1
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) {

+ 1 - 1
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.

+ 27 - 3
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'))
+    })
+  })
 })

+ 11 - 0
spec-main/fixtures/api/send-on-exit.html

@@ -0,0 +1,11 @@
+<html>
+<body>
+<script type="text/javascript" charset="utf-8">
+  const {ipcRenderer} = require('electron')
+
+  process.on('exit', () => {
+    ipcRenderer.send('SENT_ON_EXIT')
+  })
+</script>
+</body>
+</html>