Skip to content

Commit

Permalink
add triggering unhandled promise rejection events, fixes #205
Browse files Browse the repository at this point in the history
  • Loading branch information
zloirock committed Dec 24, 2017
1 parent c8d4fe7 commit aec8407
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
- `.forEach` method to iterable DOM collections ([#329](https://github.com/zloirock/core-js/issues/329))
- `Symbol#description` ([stage 1 proposal](https://tc39.github.io/proposal-Symbol-description/))
- `String#replaceAll` ([stage 1 proposal](https://github.com/psmarshall/string-replace-all-proposal))
- Triggering unhandled `Promise` rejection events (instead of only global handlers) [#205](https://github.com/zloirock/core-js/issues/205)
- Removed obsolete features:
- `Error.isError` (withdrawn)
- `System.global` (replaced by `global`)
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,9 @@ setTimeout(() => promise.catch(() => {}), 1e3);
```
In a browser on rejection, by default, you will see notify in the console, or you can add a custom handler and a handler on handling unhandled, [*example*](http://goo.gl/Wozskl):
```js
window.addEventListener('unhandledrejection', e => console.log('unhandled', e.reason, e.promise));
window.addEventListener('rejectionhandled', e => console.log('handled', e.reason, e.promise));
// or
window.onunhandledrejection = e => console.log('unhandled', e.reason, e.promise);
window.onrejectionhandled = e => console.log('handled', e.reason, e.promise);

Expand Down
27 changes: 19 additions & 8 deletions modules/es.promise.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,15 @@ var hostReportErrors = require('./_host-report-errors');
var PROMISE = 'Promise';
var TypeError = global.TypeError;
var process = global.process;
var document = global.document;
var $Promise = global[PROMISE];
var isNode = classof(process) == 'process';
var empty = function () { /* empty */ };
var Internal, newGenericPromiseCapability, OwnPromiseCapability, Wrapper;
var newPromiseCapability = newGenericPromiseCapability = newPromiseCapabilityModule.f;
var DISPATCH_EVENT = !!(document && document.createEvent && global.dispatchEvent);
var UNHANDLED_REJECTION = 'unhandledrejection';
var REJECTION_HANDLED = 'rejectionhandled';

var USE_NATIVE = !!function () {
try {
Expand Down Expand Up @@ -87,18 +91,28 @@ var notify = function (promise, isReject) {
if (isReject && !promise._h) onUnhandled(promise);
});
};
var dispatchEvent = function (name, promise, reason) {
var event, handler;
if (DISPATCH_EVENT) {
event = document.createEvent('Event');
event.promise = promise;
event.reason = reason;
event.initEvent(name, false, true);
global.dispatchEvent(event);
} else event = { promise: promise, reason: reason };
if (handler = global['on' + name]) handler(event);
else if (name === UNHANDLED_REJECTION) hostReportErrors('Unhandled promise rejection', reason);
};
var onUnhandled = function (promise) {
task.call(global, function () {
var value = promise._v;
var unhandled = isUnhandled(promise);
var result, handler;
var result;
if (unhandled) {
result = perform(function () {
if (isNode) {
process.emit('unhandledRejection', value, promise);
} else if (handler = global.onunhandledrejection) {
handler({ promise: promise, reason: value });
} else hostReportErrors('Unhandled promise rejection', value);
} else dispatchEvent(UNHANDLED_REJECTION, promise, value);
});
// Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should
promise._h = isNode || isUnhandled(promise) ? 2 : 1;
Expand All @@ -111,12 +125,9 @@ var isUnhandled = function (promise) {
};
var onHandleUnhandled = function (promise) {
task.call(global, function () {
var handler;
if (isNode) {
process.emit('rejectionHandled', promise);
} else if (handler = global.onrejectionhandled) {
handler({ promise: promise, reason: promise._v });
}
} else dispatchEvent(REJECTION_HANDLED, promise, promise._v);
});
};
var $reject = function (value) {
Expand Down
16 changes: 15 additions & 1 deletion tests/library/es.promise.js
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,21 @@ QUnit.test('Unhandled rejection tracking', assert => {
process.on('unhandledRejection', onunhandledrejection);
process.on('rejectionHandled', onrejectionhandled);
} else {
assert.expect(4);
if (GLOBAL.addEventListener) {
assert.expect(8);
function onunhandledrejection(it) {
assert.same(it.promise, $promise, 'addEventListener(unhandledrejection), promise');
assert.same(it.reason, 42, 'addEventListener(unhandledrejection), reason');
GLOBAL.removeEventListener('unhandledrejection', onunhandledrejection);
}
GLOBAL.addEventListener('rejectionhandled', onunhandledrejection);
function onrejectionhandled(it) {
assert.same(it.promise, $promise, 'addEventListener(rejectionhandled), promise');
assert.same(it.reason, 42, 'addEventListener(rejectionhandled), reason');
GLOBAL.removeEventListener('rejectionhandled', onrejectionhandled);
}
GLOBAL.addEventListener('rejectionhandled', onrejectionhandled);
} else assert.expect(4);
GLOBAL.onunhandledrejection = function (it) {
assert.same(it.promise, $promise, 'onunhandledrejection, promise');
assert.same(it.reason, 42, 'onunhandledrejection, reason');
Expand Down
16 changes: 15 additions & 1 deletion tests/tests/es.promise.js
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,21 @@ QUnit.test('Unhandled rejection tracking', assert => {
process.on('unhandledRejection', onunhandledrejection);
process.on('rejectionHandled', onrejectionhandled);
} else {
assert.expect(4);
if (GLOBAL.addEventListener) {
assert.expect(8);
function onunhandledrejection(it) {
assert.same(it.promise, $promise, 'addEventListener(unhandledrejection), promise');
assert.same(it.reason, 42, 'addEventListener(unhandledrejection), reason');
GLOBAL.removeEventListener('unhandledrejection', onunhandledrejection);
}
GLOBAL.addEventListener('rejectionhandled', onunhandledrejection);
function onrejectionhandled(it) {
assert.same(it.promise, $promise, 'addEventListener(rejectionhandled), promise');
assert.same(it.reason, 42, 'addEventListener(rejectionhandled), reason');
GLOBAL.removeEventListener('rejectionhandled', onrejectionhandled);
}
GLOBAL.addEventListener('rejectionhandled', onrejectionhandled);
} else assert.expect(4);
GLOBAL.onunhandledrejection = function (it) {
assert.same(it.promise, $promise, 'onunhandledrejection, promise');
assert.same(it.reason, 42, 'onunhandledrejection, reason');
Expand Down

0 comments on commit aec8407

Please sign in to comment.