Fix missing remote object error when calling remote function created in preload script (3-0-x) (#15445)
* fix: report wrong context error based on contextId * fix: destroyed remote renderer warning is now async
This commit is contained in:
parent
7b0959ed2b
commit
5c853b681c
5 changed files with 52 additions and 20 deletions
|
@ -148,9 +148,10 @@ const throwRPCError = function (message) {
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
|
|
||||||
const removeRemoteListenersAndLogWarning = (sender, meta, callIntoRenderer) => {
|
const removeRemoteListenersAndLogWarning = (sender, callIntoRenderer) => {
|
||||||
|
const location = v8Util.getHiddenValue(callIntoRenderer, 'location')
|
||||||
let message = `Attempting to call a function in a renderer window that has been closed or released.` +
|
let message = `Attempting to call a function in a renderer window that has been closed or released.` +
|
||||||
`\nFunction provided here: ${meta.location}`
|
`\nFunction provided here: ${location}`
|
||||||
|
|
||||||
if (sender instanceof EventEmitter) {
|
if (sender instanceof EventEmitter) {
|
||||||
const remoteEvents = sender.eventNames().filter((eventName) => {
|
const remoteEvents = sender.eventNames().filter((eventName) => {
|
||||||
|
@ -213,14 +214,14 @@ const unwrapArgs = function (sender, contextId, args) {
|
||||||
return rendererFunctions.get(objectId)
|
return rendererFunctions.get(objectId)
|
||||||
}
|
}
|
||||||
|
|
||||||
const webContentsId = sender.getId()
|
const callIntoRenderer = function (...args) {
|
||||||
let callIntoRenderer = function (...args) {
|
if (!sender.isDestroyed()) {
|
||||||
if (!sender.isDestroyed() && webContentsId === sender.getId()) {
|
|
||||||
sender.send('ELECTRON_RENDERER_CALLBACK', contextId, meta.id, valueToMeta(sender, contextId, args))
|
sender.send('ELECTRON_RENDERER_CALLBACK', contextId, meta.id, valueToMeta(sender, contextId, args))
|
||||||
} else {
|
} else {
|
||||||
removeRemoteListenersAndLogWarning(this, meta, callIntoRenderer)
|
removeRemoteListenersAndLogWarning(this, callIntoRenderer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
v8Util.setHiddenValue(callIntoRenderer, 'location', meta.location)
|
||||||
Object.defineProperty(callIntoRenderer, 'length', { value: meta.length })
|
Object.defineProperty(callIntoRenderer, 'length', { value: meta.length })
|
||||||
|
|
||||||
v8Util.setRemoteCallbackFreer(callIntoRenderer, contextId, meta.id, sender)
|
v8Util.setRemoteCallbackFreer(callIntoRenderer, contextId, meta.id, sender)
|
||||||
|
@ -261,6 +262,15 @@ const callFunction = function (event, contextId, func, caller, args) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ipcMain.on('ELECTRON_BROWSER_WRONG_CONTEXT_ERROR', function (event, contextId, passedContextId, id) {
|
||||||
|
const objectId = [passedContextId, id]
|
||||||
|
if (!rendererFunctions.has(objectId)) {
|
||||||
|
// Do nothing if the error has already been reported before.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
removeRemoteListenersAndLogWarning(event.sender, rendererFunctions.get(objectId))
|
||||||
|
})
|
||||||
|
|
||||||
ipcMain.on('ELECTRON_BROWSER_REQUIRE', function (event, contextId, module) {
|
ipcMain.on('ELECTRON_BROWSER_REQUIRE', function (event, contextId, module) {
|
||||||
try {
|
try {
|
||||||
event.returnValue = valueToMeta(event.sender, contextId, process.mainModule.require(module))
|
event.returnValue = valueToMeta(event.sender, contextId, process.mainModule.require(module))
|
||||||
|
|
|
@ -279,6 +279,7 @@ function metaToException (meta) {
|
||||||
ipcRenderer.on('ELECTRON_RENDERER_CALLBACK', (event, passedContextId, id, args) => {
|
ipcRenderer.on('ELECTRON_RENDERER_CALLBACK', (event, passedContextId, id, args) => {
|
||||||
if (passedContextId !== contextId) {
|
if (passedContextId !== contextId) {
|
||||||
// The invoked callback belongs to an old page in this renderer.
|
// The invoked callback belongs to an old page in this renderer.
|
||||||
|
ipcRenderer.send('ELECTRON_BROWSER_WRONG_CONTEXT_ERROR', contextId, passedContextId, id)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
callbacksRegistry.apply(id, metaToValue(args))
|
callbacksRegistry.apply(id, metaToValue(args))
|
||||||
|
@ -288,6 +289,7 @@ ipcRenderer.on('ELECTRON_RENDERER_CALLBACK', (event, passedContextId, id, args)
|
||||||
ipcRenderer.on('ELECTRON_RENDERER_RELEASE_CALLBACK', (event, passedContextId, id) => {
|
ipcRenderer.on('ELECTRON_RENDERER_RELEASE_CALLBACK', (event, passedContextId, id) => {
|
||||||
if (passedContextId !== contextId) {
|
if (passedContextId !== contextId) {
|
||||||
// The freed callback belongs to an old page in this renderer.
|
// The freed callback belongs to an old page in this renderer.
|
||||||
|
ipcRenderer.send('ELECTRON_BROWSER_WRONG_CONTEXT_ERROR', contextId, passedContextId, id)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
callbacksRegistry.remove(id)
|
callbacksRegistry.remove(id)
|
||||||
|
|
|
@ -5,6 +5,7 @@ const path = require('path')
|
||||||
const {closeWindow} = require('./window-helpers')
|
const {closeWindow} = require('./window-helpers')
|
||||||
|
|
||||||
const {remote} = require('electron')
|
const {remote} = require('electron')
|
||||||
|
const {ipcMain, BrowserWindow} = remote
|
||||||
|
|
||||||
const comparePaths = (path1, path2) => {
|
const comparePaths = (path1, path2) => {
|
||||||
if (process.platform === 'win32') {
|
if (process.platform === 'win32') {
|
||||||
|
@ -484,4 +485,23 @@ describe('remote module', () => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('remote function in renderer', () => {
|
||||||
|
afterEach(() => {
|
||||||
|
ipcMain.removeAllListeners('done')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('works when created in preload script', (done) => {
|
||||||
|
ipcMain.once('done', () => w.close())
|
||||||
|
const preload = path.join(fixtures, 'module', 'preload-remote-function.js')
|
||||||
|
w = new BrowserWindow({
|
||||||
|
show: false,
|
||||||
|
webPreferences: {
|
||||||
|
preload: preload
|
||||||
|
}
|
||||||
|
})
|
||||||
|
w.once('closed', () => done())
|
||||||
|
w.loadURL('about:blank')
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
5
spec/fixtures/module/preload-remote-function.js
vendored
Normal file
5
spec/fixtures/module/preload-remote-function.js
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
const { remote, ipcRenderer } = require('electron')
|
||||||
|
remote.getCurrentWindow().rendererFunc = () => {
|
||||||
|
ipcRenderer.send('done')
|
||||||
|
}
|
||||||
|
remote.getCurrentWindow().rendererFunc()
|
|
@ -313,26 +313,21 @@ ipcMain.on('disable-preload-on-next-will-attach-webview', (event, id) => {
|
||||||
|
|
||||||
ipcMain.on('try-emit-web-contents-event', (event, id, eventName) => {
|
ipcMain.on('try-emit-web-contents-event', (event, id, eventName) => {
|
||||||
const consoleWarn = console.warn
|
const consoleWarn = console.warn
|
||||||
let warningMessage = null
|
|
||||||
const contents = webContents.fromId(id)
|
const contents = webContents.fromId(id)
|
||||||
const listenerCountBefore = contents.listenerCount(eventName)
|
const listenerCountBefore = contents.listenerCount(eventName)
|
||||||
|
|
||||||
try {
|
console.warn = (warningMessage) => {
|
||||||
console.warn = (message) => {
|
|
||||||
warningMessage = message
|
|
||||||
}
|
|
||||||
contents.emit(eventName, {sender: contents})
|
|
||||||
} finally {
|
|
||||||
console.warn = consoleWarn
|
console.warn = consoleWarn
|
||||||
|
|
||||||
|
const listenerCountAfter = contents.listenerCount(eventName)
|
||||||
|
event.returnValue = {
|
||||||
|
warningMessage,
|
||||||
|
listenerCountBefore,
|
||||||
|
listenerCountAfter
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const listenerCountAfter = contents.listenerCount(eventName)
|
contents.emit(eventName, {sender: contents})
|
||||||
|
|
||||||
event.returnValue = {
|
|
||||||
warningMessage,
|
|
||||||
listenerCountBefore,
|
|
||||||
listenerCountAfter
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.on('handle-uncaught-exception', (event, message) => {
|
ipcMain.on('handle-uncaught-exception', (event, message) => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue