fix: Invalidate weak ptrs before window Javascript object is destroyed (#14532)
* fix: Invalidate weak ptrs before window Javascript object is destroyed * chore: add regression test for #14513 This test is similar to the original gist at https://gist.github.com/bpasero/a02a645e11f4946dcca1331d0299149d -- the key is to open multiple windows and add an `app.on('browser-window-focus') listener that accesses window.id. * fix: last commit didn't test the right thing. The test needs to run in the main process to reproduce the conditions reported in #14513
This commit is contained in:
parent
4b5cb7c548
commit
e860748d6b
3 changed files with 30 additions and 0 deletions
|
@ -142,6 +142,11 @@ void TopLevelWindow::WillCloseWindow(bool* prevent_default) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TopLevelWindow::OnWindowClosed() {
|
void TopLevelWindow::OnWindowClosed() {
|
||||||
|
// Invalidate weak ptrs before the Javascript object is destroyed,
|
||||||
|
// there might be some delayed emit events which shouldn't be
|
||||||
|
// triggered after this.
|
||||||
|
weak_factory_.InvalidateWeakPtrs();
|
||||||
|
|
||||||
RemoveFromWeakMap();
|
RemoveFromWeakMap();
|
||||||
window_->RemoveObserver(this);
|
window_->RemoveObserver(this);
|
||||||
|
|
||||||
|
|
|
@ -221,6 +221,11 @@ describe('BrowserWindow module', () => {
|
||||||
contents.getProcessId()
|
contents.getProcessId()
|
||||||
}, /Object has been destroyed/)
|
}, /Object has been destroyed/)
|
||||||
})
|
})
|
||||||
|
it('should not crash when destroying windows with pending events', (done) => {
|
||||||
|
const responseEvent = 'destroy-test-completed'
|
||||||
|
ipcRenderer.on(responseEvent, () => done())
|
||||||
|
ipcRenderer.send('test-browserwindow-destroy', { responseEvent })
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('BrowserWindow.loadURL(url)', () => {
|
describe('BrowserWindow.loadURL(url)', () => {
|
||||||
|
|
|
@ -381,6 +381,26 @@ ipcMain.on('test-webcontents-navigation-observer', (event, options) => {
|
||||||
contents.loadURL(options.url)
|
contents.loadURL(options.url)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ipcMain.on('test-browserwindow-destroy', (event, testOptions) => {
|
||||||
|
let focusListener = (event, win) => win.id
|
||||||
|
app.on('browser-window-focus', focusListener)
|
||||||
|
const windowCount = 3
|
||||||
|
const windowOptions = {
|
||||||
|
show: false,
|
||||||
|
width: 400,
|
||||||
|
height: 400,
|
||||||
|
webPreferences: {
|
||||||
|
backgroundThrottling: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const windows = Array.from(Array(windowCount)).map(x => new BrowserWindow(windowOptions))
|
||||||
|
windows.forEach(win => win.show())
|
||||||
|
windows.forEach(win => win.focus())
|
||||||
|
windows.forEach(win => win.destroy())
|
||||||
|
app.removeListener('browser-window-focus', focusListener)
|
||||||
|
event.sender.send(testOptions.responseEvent)
|
||||||
|
})
|
||||||
|
|
||||||
// Suspend listeners until the next event and then restore them
|
// Suspend listeners until the next event and then restore them
|
||||||
const suspendListeners = (emitter, eventName, callback) => {
|
const suspendListeners = (emitter, eventName, callback) => {
|
||||||
const listeners = emitter.listeners(eventName)
|
const listeners = emitter.listeners(eventName)
|
||||||
|
|
Loading…
Reference in a new issue