Merge pull request #11158 from electron/execute-errors
fix: Pass on errors thrown in `executeJavaScript`
This commit is contained in:
commit
5eb00e45aa
4 changed files with 53 additions and 1 deletions
|
@ -112,6 +112,16 @@ const webFrameMethods = [
|
||||||
]
|
]
|
||||||
const webFrameMethodsWithResult = []
|
const webFrameMethodsWithResult = []
|
||||||
|
|
||||||
|
const errorConstructors = {
|
||||||
|
Error,
|
||||||
|
EvalError,
|
||||||
|
RangeError,
|
||||||
|
ReferenceError,
|
||||||
|
SyntaxError,
|
||||||
|
TypeError,
|
||||||
|
URIError
|
||||||
|
}
|
||||||
|
|
||||||
const asyncWebFrameMethods = function (requestId, method, callback, ...args) {
|
const asyncWebFrameMethods = function (requestId, method, callback, ...args) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.send('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', requestId, method, args)
|
this.send('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', requestId, method, args)
|
||||||
|
@ -119,9 +129,16 @@ const asyncWebFrameMethods = function (requestId, method, callback, ...args) {
|
||||||
if (error == null) {
|
if (error == null) {
|
||||||
if (typeof callback === 'function') callback(result)
|
if (typeof callback === 'function') callback(result)
|
||||||
resolve(result)
|
resolve(result)
|
||||||
|
} else {
|
||||||
|
if (error.__ELECTRON_SERIALIZED_ERROR__ && errorConstructors[error.name]) {
|
||||||
|
const rehydratedError = new errorConstructors[error.name](error.message)
|
||||||
|
rehydratedError.stack = error.stack
|
||||||
|
|
||||||
|
reject(rehydratedError)
|
||||||
} else {
|
} else {
|
||||||
reject(error)
|
reject(error)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,17 @@ electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', (ev
|
||||||
event.sender.send(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, null, resolvedResult)
|
event.sender.send(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, null, resolvedResult)
|
||||||
})
|
})
|
||||||
.catch((resolvedError) => {
|
.catch((resolvedError) => {
|
||||||
|
if (resolvedError instanceof Error) {
|
||||||
|
// Errors get lost, because: JSON.stringify(new Error('Message')) === {}
|
||||||
|
// Take the serializable properties and construct a generic object
|
||||||
|
resolvedError = {
|
||||||
|
message: resolvedError.message,
|
||||||
|
stack: resolvedError.stack,
|
||||||
|
name: resolvedError.name,
|
||||||
|
__ELECTRON_SERIALIZED_ERROR__: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
event.sender.send(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, resolvedError)
|
event.sender.send(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, resolvedError)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -2514,6 +2514,15 @@ describe('BrowserWindow module', () => {
|
||||||
const code = `(() => "${expected}")()`
|
const code = `(() => "${expected}")()`
|
||||||
const asyncCode = `(() => new Promise(r => setTimeout(() => r("${expected}"), 500)))()`
|
const asyncCode = `(() => new Promise(r => setTimeout(() => r("${expected}"), 500)))()`
|
||||||
const badAsyncCode = `(() => new Promise((r, e) => setTimeout(() => e("${expectedErrorMsg}"), 500)))()`
|
const badAsyncCode = `(() => new Promise((r, e) => setTimeout(() => e("${expectedErrorMsg}"), 500)))()`
|
||||||
|
const errorTypes = new Set([
|
||||||
|
Error,
|
||||||
|
ReferenceError,
|
||||||
|
EvalError,
|
||||||
|
RangeError,
|
||||||
|
SyntaxError,
|
||||||
|
TypeError,
|
||||||
|
URIError
|
||||||
|
])
|
||||||
|
|
||||||
it('doesnt throw when no calback is provided', () => {
|
it('doesnt throw when no calback is provided', () => {
|
||||||
const result = ipcRenderer.sendSync('executeJavaScript', code, false)
|
const result = ipcRenderer.sendSync('executeJavaScript', code, false)
|
||||||
|
@ -2561,6 +2570,17 @@ describe('BrowserWindow module', () => {
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
it('rejects the returned promise with an error if an Error.prototype is thrown', async () => {
|
||||||
|
for (const error in errorTypes) {
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
ipcRenderer.send('executeJavaScript', `Promise.reject(new ${error.name}("Wamp-wamp")`, true)
|
||||||
|
ipcRenderer.once('executeJavaScript-promise-error-name', (event, name) => {
|
||||||
|
assert.equal(name, error.name)
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
it('works after page load and during subframe load', (done) => {
|
it('works after page load and during subframe load', (done) => {
|
||||||
w.webContents.once('did-finish-load', () => {
|
w.webContents.once('did-finish-load', () => {
|
||||||
// initiate a sub-frame load, then try and execute script during it
|
// initiate a sub-frame load, then try and execute script during it
|
||||||
|
|
|
@ -217,6 +217,10 @@ app.on('ready', function () {
|
||||||
window.webContents.send('executeJavaScript-promise-response', result)
|
window.webContents.send('executeJavaScript-promise-response', result)
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
window.webContents.send('executeJavaScript-promise-error', error)
|
window.webContents.send('executeJavaScript-promise-error', error)
|
||||||
|
|
||||||
|
if (error && error.name) {
|
||||||
|
window.webContents.send('executeJavaScript-promise-error-name', error.name)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!hasCallback) {
|
if (!hasCallback) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue