Add default error handler to remote promises (#6151)
* Add failing spec for unhandled main process exception * Remove unused return * Use let/const instead of var * Add spec for unhandled rejection in renderer process * Prevent unhandled rejection defaul * Use once instead of on * Add default fulfilled/rejection handler to promise
This commit is contained in:
parent
74321dce74
commit
8a9f2261d0
3 changed files with 43 additions and 10 deletions
|
@ -54,7 +54,7 @@ let getObjectPrototype = function (object) {
|
||||||
// Convert a real value into meta data.
|
// Convert a real value into meta data.
|
||||||
let valueToMeta = function (sender, value, optimizeSimpleObject = false) {
|
let valueToMeta = function (sender, value, optimizeSimpleObject = false) {
|
||||||
// Determine the type of value.
|
// Determine the type of value.
|
||||||
let meta = { type: typeof value }
|
const meta = { type: typeof value }
|
||||||
if (meta.type === 'object') {
|
if (meta.type === 'object') {
|
||||||
// Recognize certain types of objects.
|
// Recognize certain types of objects.
|
||||||
if (value === null) {
|
if (value === null) {
|
||||||
|
@ -93,6 +93,10 @@ let valueToMeta = function (sender, value, optimizeSimpleObject = false) {
|
||||||
} else if (meta.type === 'buffer') {
|
} else if (meta.type === 'buffer') {
|
||||||
meta.value = Array.prototype.slice.call(value, 0)
|
meta.value = Array.prototype.slice.call(value, 0)
|
||||||
} else if (meta.type === 'promise') {
|
} else if (meta.type === 'promise') {
|
||||||
|
// Add default handler to prevent unhandled rejections in main process
|
||||||
|
// Instead they should appear in the renderer process
|
||||||
|
value.then(function () {}, function () {})
|
||||||
|
|
||||||
meta.then = valueToMeta(sender, function (onFulfilled, onRejected) {
|
meta.then = valueToMeta(sender, function (onFulfilled, onRejected) {
|
||||||
value.then(onFulfilled, onRejected)
|
value.then(onFulfilled, onRejected)
|
||||||
})
|
})
|
||||||
|
@ -114,7 +118,7 @@ let valueToMeta = function (sender, value, optimizeSimpleObject = false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert object to meta by value.
|
// Convert object to meta by value.
|
||||||
var plainObjectToMeta = function (obj) {
|
const plainObjectToMeta = function (obj) {
|
||||||
return Object.getOwnPropertyNames(obj).map(function (name) {
|
return Object.getOwnPropertyNames(obj).map(function (name) {
|
||||||
return {
|
return {
|
||||||
name: name,
|
name: name,
|
||||||
|
@ -124,7 +128,7 @@ var plainObjectToMeta = function (obj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert Error into meta data.
|
// Convert Error into meta data.
|
||||||
var exceptionToMeta = function (error) {
|
const exceptionToMeta = function (error) {
|
||||||
return {
|
return {
|
||||||
type: 'exception',
|
type: 'exception',
|
||||||
message: error.message,
|
message: error.message,
|
||||||
|
@ -133,10 +137,9 @@ var exceptionToMeta = function (error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert array of meta data from renderer into array of real values.
|
// Convert array of meta data from renderer into array of real values.
|
||||||
var unwrapArgs = function (sender, args) {
|
const unwrapArgs = function (sender, args) {
|
||||||
var metaToValue
|
const metaToValue = function (meta) {
|
||||||
metaToValue = function (meta) {
|
let i, len, member, ref, returnValue
|
||||||
var i, len, member, ref, returnValue
|
|
||||||
switch (meta.type) {
|
switch (meta.type) {
|
||||||
case 'value':
|
case 'value':
|
||||||
return meta.value
|
return meta.value
|
||||||
|
@ -200,8 +203,8 @@ var unwrapArgs = function (sender, args) {
|
||||||
|
|
||||||
// Call a function and send reply asynchronously if it's a an asynchronous
|
// Call a function and send reply asynchronously if it's a an asynchronous
|
||||||
// style function and the caller didn't pass a callback.
|
// style function and the caller didn't pass a callback.
|
||||||
var callFunction = function (event, func, caller, args) {
|
const callFunction = function (event, func, caller, args) {
|
||||||
var funcMarkedAsync, funcName, funcPassedCallback, ref, ret
|
let funcMarkedAsync, funcName, funcPassedCallback, ref, ret
|
||||||
funcMarkedAsync = v8Util.getHiddenValue(func, 'asynchronous')
|
funcMarkedAsync = v8Util.getHiddenValue(func, 'asynchronous')
|
||||||
funcPassedCallback = typeof args[args.length - 1] === 'function'
|
funcPassedCallback = typeof args[args.length - 1] === 'function'
|
||||||
try {
|
try {
|
||||||
|
@ -209,7 +212,7 @@ var callFunction = function (event, func, caller, args) {
|
||||||
args.push(function (ret) {
|
args.push(function (ret) {
|
||||||
event.returnValue = valueToMeta(event.sender, ret, true)
|
event.returnValue = valueToMeta(event.sender, ret, true)
|
||||||
})
|
})
|
||||||
return func.apply(caller, args)
|
func.apply(caller, args)
|
||||||
} else {
|
} else {
|
||||||
ret = func.apply(caller, args)
|
ret = func.apply(caller, args)
|
||||||
event.returnValue = valueToMeta(event.sender, ret, true)
|
event.returnValue = valueToMeta(event.sender, ret, true)
|
||||||
|
|
|
@ -126,6 +126,33 @@ describe('ipc module', function () {
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('does not emit unhandled rejection events in the main process', function (done) {
|
||||||
|
remote.process.once('unhandledRejection', function (reason) {
|
||||||
|
done(reason)
|
||||||
|
})
|
||||||
|
|
||||||
|
var promise = remote.require(path.join(fixtures, 'module', 'unhandled-rejection.js'))
|
||||||
|
promise.reject().then(function () {
|
||||||
|
done(new Error('Promise was not rejected'))
|
||||||
|
}).catch(function (error) {
|
||||||
|
assert.equal(error.message, 'rejected')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('emits unhandled rejection events in the renderer process', function (done) {
|
||||||
|
window.addEventListener('unhandledrejection', function (event) {
|
||||||
|
event.preventDefault()
|
||||||
|
assert.equal(event.reason.message, 'rejected')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
var promise = remote.require(path.join(fixtures, 'module', 'unhandled-rejection.js'))
|
||||||
|
promise.reject().then(function () {
|
||||||
|
done(new Error('Promise was not rejected'))
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('remote webContents', function () {
|
describe('remote webContents', function () {
|
||||||
|
|
3
spec/fixtures/module/unhandled-rejection.js
vendored
Normal file
3
spec/fixtures/module/unhandled-rejection.js
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
exports.reject = function () {
|
||||||
|
return Promise.reject(new Error('rejected'))
|
||||||
|
}
|
Loading…
Reference in a new issue