handle remote exception (#12694)
* add cause property to exception in callFunction * update exceptionToMeta function * add sender argument * and cause property to return value * update exception convert in metaToValue function * add from and cause properties to the exception error * unit test for remote exception
This commit is contained in:
parent
2579071b98
commit
9c65abd746
4 changed files with 54 additions and 17 deletions
|
@ -131,11 +131,12 @@ const plainObjectToMeta = function (obj) {
|
|||
}
|
||||
|
||||
// Convert Error into meta data.
|
||||
const exceptionToMeta = function (error) {
|
||||
const exceptionToMeta = function (sender, error) {
|
||||
return {
|
||||
type: 'exception',
|
||||
message: error.message,
|
||||
stack: error.stack || error
|
||||
stack: error.stack || error,
|
||||
cause: valueToMeta(sender, error.cause)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,7 +237,7 @@ const unwrapArgs = function (sender, args) {
|
|||
// Call a function and send reply asynchronously if it's a an asynchronous
|
||||
// style function and the caller didn't pass a callback.
|
||||
const callFunction = function (event, func, caller, args) {
|
||||
let funcMarkedAsync, funcName, funcPassedCallback, ref, ret
|
||||
let err, funcMarkedAsync, funcName, funcPassedCallback, ref, ret
|
||||
funcMarkedAsync = v8Util.getHiddenValue(func, 'asynchronous')
|
||||
funcPassedCallback = typeof args[args.length - 1] === 'function'
|
||||
try {
|
||||
|
@ -254,7 +255,9 @@ const callFunction = function (event, func, caller, args) {
|
|||
// them with the function name so it's easier to trace things like
|
||||
// `Error processing argument -1.`
|
||||
funcName = ((ref = func.name) != null) ? ref : 'anonymous'
|
||||
throw new Error(`Could not call remote function '${funcName}'. Check that the function signature is correct. Underlying error: ${error.message}`)
|
||||
err = new Error(`Could not call remote function '${funcName}'. Check that the function signature is correct. Underlying error: ${error.message}`)
|
||||
err.cause = error
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -262,7 +265,7 @@ ipcMain.on('ELECTRON_BROWSER_REQUIRE', function (event, module) {
|
|||
try {
|
||||
event.returnValue = valueToMeta(event.sender, process.mainModule.require(module))
|
||||
} catch (error) {
|
||||
event.returnValue = exceptionToMeta(error)
|
||||
event.returnValue = exceptionToMeta(event.sender, error)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -270,7 +273,7 @@ ipcMain.on('ELECTRON_BROWSER_GET_BUILTIN', function (event, module) {
|
|||
try {
|
||||
event.returnValue = valueToMeta(event.sender, electron[module])
|
||||
} catch (error) {
|
||||
event.returnValue = exceptionToMeta(error)
|
||||
event.returnValue = exceptionToMeta(event.sender, error)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -278,7 +281,7 @@ ipcMain.on('ELECTRON_BROWSER_GLOBAL', function (event, name) {
|
|||
try {
|
||||
event.returnValue = valueToMeta(event.sender, global[name])
|
||||
} catch (error) {
|
||||
event.returnValue = exceptionToMeta(error)
|
||||
event.returnValue = exceptionToMeta(event.sender, error)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -286,7 +289,7 @@ ipcMain.on('ELECTRON_BROWSER_CURRENT_WINDOW', function (event) {
|
|||
try {
|
||||
event.returnValue = valueToMeta(event.sender, event.sender.getOwnerBrowserWindow())
|
||||
} catch (error) {
|
||||
event.returnValue = exceptionToMeta(error)
|
||||
event.returnValue = exceptionToMeta(event.sender, error)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -308,7 +311,7 @@ ipcMain.on('ELECTRON_BROWSER_CONSTRUCTOR', function (event, id, args) {
|
|||
let obj = new (Function.prototype.bind.apply(constructor, [null].concat(args)))()
|
||||
event.returnValue = valueToMeta(event.sender, obj)
|
||||
} catch (error) {
|
||||
event.returnValue = exceptionToMeta(error)
|
||||
event.returnValue = exceptionToMeta(event.sender, error)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -323,7 +326,7 @@ ipcMain.on('ELECTRON_BROWSER_FUNCTION_CALL', function (event, id, args) {
|
|||
|
||||
callFunction(event, func, global, args)
|
||||
} catch (error) {
|
||||
event.returnValue = exceptionToMeta(error)
|
||||
event.returnValue = exceptionToMeta(event.sender, error)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -341,7 +344,7 @@ ipcMain.on('ELECTRON_BROWSER_MEMBER_CONSTRUCTOR', function (event, id, method, a
|
|||
let obj = new (Function.prototype.bind.apply(constructor, [null].concat(args)))()
|
||||
event.returnValue = valueToMeta(event.sender, obj)
|
||||
} catch (error) {
|
||||
event.returnValue = exceptionToMeta(error)
|
||||
event.returnValue = exceptionToMeta(event.sender, error)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -356,7 +359,7 @@ ipcMain.on('ELECTRON_BROWSER_MEMBER_CALL', function (event, id, method, args) {
|
|||
|
||||
callFunction(event, obj[method], obj, args)
|
||||
} catch (error) {
|
||||
event.returnValue = exceptionToMeta(error)
|
||||
event.returnValue = exceptionToMeta(event.sender, error)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -372,7 +375,7 @@ ipcMain.on('ELECTRON_BROWSER_MEMBER_SET', function (event, id, name, args) {
|
|||
obj[name] = args[0]
|
||||
event.returnValue = null
|
||||
} catch (error) {
|
||||
event.returnValue = exceptionToMeta(error)
|
||||
event.returnValue = exceptionToMeta(event.sender, error)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -386,7 +389,7 @@ ipcMain.on('ELECTRON_BROWSER_MEMBER_GET', function (event, id, name) {
|
|||
|
||||
event.returnValue = valueToMeta(event.sender, obj[name])
|
||||
} catch (error) {
|
||||
event.returnValue = exceptionToMeta(error)
|
||||
event.returnValue = exceptionToMeta(event.sender, error)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -404,7 +407,7 @@ ipcMain.on('ELECTRON_BROWSER_GUEST_WEB_CONTENTS', function (event, guestInstance
|
|||
let guestViewManager = require('./guest-view-manager')
|
||||
event.returnValue = valueToMeta(event.sender, guestViewManager.getGuest(guestInstanceId))
|
||||
} catch (error) {
|
||||
event.returnValue = exceptionToMeta(error)
|
||||
event.returnValue = exceptionToMeta(event.sender, error)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -420,7 +423,7 @@ ipcMain.on('ELECTRON_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', function (event, request
|
|||
}
|
||||
guest[method].apply(guest, args)
|
||||
} catch (error) {
|
||||
event.returnValue = exceptionToMeta(error)
|
||||
event.returnValue = exceptionToMeta(event.sender, error)
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -206,7 +206,7 @@ function metaToValue (meta) {
|
|||
promise: () => resolvePromise({then: metaToValue(meta.then)}),
|
||||
error: () => metaToPlainObject(meta),
|
||||
date: () => new Date(meta.value),
|
||||
exception: () => { throw new Error(`${meta.message}\n${meta.stack}`) }
|
||||
exception: () => { throw metaToException(meta) }
|
||||
}
|
||||
|
||||
if (meta.type in types) {
|
||||
|
@ -256,6 +256,15 @@ function metaToPlainObject (meta) {
|
|||
return obj
|
||||
}
|
||||
|
||||
// Construct an exception error from the meta.
|
||||
function metaToException (meta) {
|
||||
const error = new Error(`${meta.message}\n${meta.stack}`)
|
||||
const remoteProcess = exports.process
|
||||
error.from = remoteProcess ? remoteProcess.type : null
|
||||
error.cause = metaToValue(meta.cause)
|
||||
return error
|
||||
}
|
||||
|
||||
// Browser calls a callback in renderer.
|
||||
ipcRenderer.on('ELECTRON_RENDERER_CALLBACK', (event, id, args) => {
|
||||
callbacksRegistry.apply(id, metaToValue(args))
|
||||
|
|
|
@ -370,4 +370,26 @@ describe('remote module', () => {
|
|||
assert.equal(method(), 'method')
|
||||
})
|
||||
})
|
||||
|
||||
describe('remote exception', () => {
|
||||
const throwFunction = remote.require(path.join(fixtures, 'module', 'exception.js'))
|
||||
|
||||
it('throws errors from the main process', () => {
|
||||
assert.throws(() => {
|
||||
throwFunction()
|
||||
})
|
||||
})
|
||||
|
||||
it('throws custom errors from the main process', () => {
|
||||
let err = new Error('error')
|
||||
err.cause = new Error('cause')
|
||||
err.prop = 'error prop'
|
||||
try {
|
||||
throwFunction(err)
|
||||
} catch (error) {
|
||||
assert.ok(error.from)
|
||||
assert.deepEqual(error.cause, err)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
3
spec/fixtures/module/exception.js
vendored
Normal file
3
spec/fixtures/module/exception.js
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
module.exports = function (error) {
|
||||
throw error
|
||||
}
|
Loading…
Reference in a new issue