Skip to content

Commit b4e4a8d

Browse files
committed
add triggering unhandled promise rejection events, fixes #205
1 parent 330b6cf commit b4e4a8d

File tree

5 files changed

+53
-10
lines changed

5 files changed

+53
-10
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
- `.forEach` method to iterable DOM collections ([#329](https://github.com/zloirock/core-js/issues/329))
1111
- `Symbol#description` ([stage 1 proposal](https://tc39.github.io/proposal-Symbol-description/))
1212
- `String#replaceAll` ([stage 1 proposal](https://github.com/psmarshall/string-replace-all-proposal))
13+
- Triggering unhandled `Promise` rejection events (instead of only global handlers) [#205](https://github.com/zloirock/core-js/issues/205)
1314
- Removed obsolete features:
1415
- `Error.isError` (withdrawn)
1516
- `System.global` (replaced by `global`)

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,9 @@ setTimeout(() => promise.catch(() => {}), 1e3);
801801
```
802802
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):
803803
```js
804+
window.addEventListener('unhandledrejection', e => console.log('unhandled', e.reason, e.promise));
805+
window.addEventListener('rejectionhandled', e => console.log('handled', e.reason, e.promise));
806+
// or
804807
window.onunhandledrejection = e => console.log('unhandled', e.reason, e.promise);
805808
window.onrejectionhandled = e => console.log('handled', e.reason, e.promise);
806809

modules/es.promise.js

+19-8
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@ var hostReportErrors = require('./_host-report-errors');
1818
var PROMISE = 'Promise';
1919
var TypeError = global.TypeError;
2020
var process = global.process;
21+
var document = global.document;
2122
var $Promise = global[PROMISE];
2223
var isNode = classof(process) == 'process';
2324
var empty = function () { /* empty */ };
2425
var Internal, newGenericPromiseCapability, OwnPromiseCapability, Wrapper;
2526
var newPromiseCapability = newGenericPromiseCapability = newPromiseCapabilityModule.f;
27+
var DISPATCH_EVENT = !!(document && document.createEvent && global.dispatchEvent);
28+
var UNHANDLED_REJECTION = 'unhandledrejection';
29+
var REJECTION_HANDLED = 'rejectionhandled';
2630

2731
var USE_NATIVE = !!function () {
2832
try {
@@ -83,18 +87,28 @@ var notify = function (promise, isReject) {
8387
if (isReject && !promise._h) onUnhandled(promise);
8488
});
8589
};
90+
var dispatchEvent = function (name, promise, reason) {
91+
var event, handler;
92+
if (DISPATCH_EVENT) {
93+
event = document.createEvent('Event');
94+
event.promise = promise;
95+
event.reason = reason;
96+
event.initEvent(name, false, true);
97+
global.dispatchEvent(event);
98+
} else event = { promise: promise, reason: reason };
99+
if (handler = global['on' + name]) handler(event);
100+
else if (name === UNHANDLED_REJECTION) hostReportErrors('Unhandled promise rejection', reason);
101+
};
86102
var onUnhandled = function (promise) {
87103
task.call(global, function () {
88104
var value = promise._v;
89105
var unhandled = isUnhandled(promise);
90-
var result, handler;
106+
var result;
91107
if (unhandled) {
92108
result = perform(function () {
93109
if (isNode) {
94110
process.emit('unhandledRejection', value, promise);
95-
} else if (handler = global.onunhandledrejection) {
96-
handler({ promise: promise, reason: value });
97-
} else hostReportErrors('Unhandled promise rejection', value);
111+
} else dispatchEvent(UNHANDLED_REJECTION, promise, value);
98112
});
99113
// Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should
100114
promise._h = isNode || isUnhandled(promise) ? 2 : 1;
@@ -107,12 +121,9 @@ var isUnhandled = function (promise) {
107121
};
108122
var onHandleUnhandled = function (promise) {
109123
task.call(global, function () {
110-
var handler;
111124
if (isNode) {
112125
process.emit('rejectionHandled', promise);
113-
} else if (handler = global.onrejectionhandled) {
114-
handler({ promise: promise, reason: promise._v });
115-
}
126+
} else dispatchEvent(REJECTION_HANDLED, promise, promise._v);
116127
});
117128
};
118129
var $reject = function (value) {

tests/library/es.promise.js

+15-1
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,21 @@ QUnit.test('Unhandled rejection tracking', assert => {
390390
process.on('unhandledRejection', onunhandledrejection);
391391
process.on('rejectionHandled', onrejectionhandled);
392392
} else {
393-
assert.expect(4);
393+
if (GLOBAL.addEventListener) {
394+
assert.expect(8);
395+
function onunhandledrejection(it) {
396+
assert.same(it.promise, $promise, 'addEventListener(unhandledrejection), promise');
397+
assert.same(it.reason, 42, 'addEventListener(unhandledrejection), reason');
398+
GLOBAL.removeEventListener('unhandledrejection', onunhandledrejection);
399+
}
400+
GLOBAL.addEventListener('rejectionhandled', onunhandledrejection);
401+
function onrejectionhandled(it) {
402+
assert.same(it.promise, $promise, 'addEventListener(rejectionhandled), promise');
403+
assert.same(it.reason, 42, 'addEventListener(rejectionhandled), reason');
404+
GLOBAL.removeEventListener('rejectionhandled', onrejectionhandled);
405+
}
406+
GLOBAL.addEventListener('rejectionhandled', onrejectionhandled);
407+
} else assert.expect(4);
394408
GLOBAL.onunhandledrejection = function (it) {
395409
assert.same(it.promise, $promise, 'onunhandledrejection, promise');
396410
assert.same(it.reason, 42, 'onunhandledrejection, reason');

tests/tests/es.promise.js

+15-1
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,21 @@ QUnit.test('Unhandled rejection tracking', assert => {
414414
process.on('unhandledRejection', onunhandledrejection);
415415
process.on('rejectionHandled', onrejectionhandled);
416416
} else {
417-
assert.expect(4);
417+
if (GLOBAL.addEventListener) {
418+
assert.expect(8);
419+
function onunhandledrejection(it) {
420+
assert.same(it.promise, $promise, 'addEventListener(unhandledrejection), promise');
421+
assert.same(it.reason, 42, 'addEventListener(unhandledrejection), reason');
422+
GLOBAL.removeEventListener('unhandledrejection', onunhandledrejection);
423+
}
424+
GLOBAL.addEventListener('rejectionhandled', onunhandledrejection);
425+
function onrejectionhandled(it) {
426+
assert.same(it.promise, $promise, 'addEventListener(rejectionhandled), promise');
427+
assert.same(it.reason, 42, 'addEventListener(rejectionhandled), reason');
428+
GLOBAL.removeEventListener('rejectionhandled', onrejectionhandled);
429+
}
430+
GLOBAL.addEventListener('rejectionhandled', onrejectionhandled);
431+
} else assert.expect(4);
418432
GLOBAL.onunhandledrejection = function (it) {
419433
assert.same(it.promise, $promise, 'onunhandledrejection, promise');
420434
assert.same(it.reason, 42, 'onunhandledrejection, reason');

0 commit comments

Comments
 (0)