diff --git a/doc/api/errors.md b/doc/api/errors.md
index 1b78f2c3379b20..13cde982839b3e 100644
--- a/doc/api/errors.md
+++ b/doc/api/errors.md
@@ -1251,6 +1251,12 @@ buffer.
Used when a string that contains unescaped characters was received.
+
+### ERR_UNHANDLED_ERROR
+
+Used when an unhandled "error" occurs (for instance, when an `'error'` event
+is emitted by an `EventEmitter` but an `'error'` handler is not registered).
+
### ERR_UNKNOWN_ENCODING
diff --git a/lib/events.js b/lib/events.js
index dce1dc48fa42e8..1414a1429dfe3b 100644
--- a/lib/events.js
+++ b/lib/events.js
@@ -41,6 +41,13 @@ EventEmitter.prototype._maxListeners = undefined;
// added to it. This is a useful default which helps finding memory leaks.
var defaultMaxListeners = 10;
+var errors;
+function lazyErrors() {
+ if (errors === undefined)
+ errors = require('internal/errors');
+ return errors;
+}
+
Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
enumerable: true,
get: function() {
@@ -52,8 +59,10 @@ Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
console;
// check whether the input is a positive number (whose value is zero or
// greater and not a NaN).
- if (typeof arg !== 'number' || arg < 0 || arg !== arg)
- throw new TypeError('"defaultMaxListeners" must be a positive number');
+ if (typeof arg !== 'number' || arg < 0 || arg !== arg) {
+ const errors = lazyErrors();
+ throw new errors.TypeError('ERR_OUT_OF_RANGE', 'defaultMaxListeners');
+ }
defaultMaxListeners = arg;
}
});
@@ -79,8 +88,10 @@ EventEmitter.init = function() {
// Obviously not all Emitters should be limited to 10. This function allows
// that to be increased. Set to zero for unlimited.
EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
- if (typeof n !== 'number' || n < 0 || isNaN(n))
- throw new TypeError('"n" argument must be a positive number');
+ if (typeof n !== 'number' || n < 0 || isNaN(n)) {
+ const errors = lazyErrors();
+ throw new errors.TypeError('ERR_OUT_OF_RANGE', 'n');
+ }
this._maxListeners = n;
return this;
};
@@ -170,8 +181,10 @@ EventEmitter.prototype.emit = function emit(type) {
if (arguments.length > 1)
er = arguments[1];
if (domain) {
- if (!er)
- er = new Error('Unhandled "error" event');
+ if (!er) {
+ const errors = lazyErrors();
+ er = new errors.Error('ERR_UNHANDLED_ERROR');
+ }
if (typeof er === 'object' && er !== null) {
er.domainEmitter = this;
er.domain = domain;
@@ -182,7 +195,8 @@ EventEmitter.prototype.emit = function emit(type) {
throw er; // Unhandled 'error' event
} else {
// At least give some kind of context to the user
- const err = new Error('Unhandled "error" event. (' + er + ')');
+ const errors = lazyErrors();
+ const err = new errors.Error('ERR_UNHANDLED_ERROR', er);
err.context = er;
throw err;
}
@@ -234,8 +248,10 @@ function _addListener(target, type, listener, prepend) {
var events;
var existing;
- if (typeof listener !== 'function')
- throw new TypeError('"listener" argument must be a function');
+ if (typeof listener !== 'function') {
+ const errors = lazyErrors();
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'listener', 'function');
+ }
events = target._events;
if (!events) {
@@ -278,6 +294,7 @@ function _addListener(target, type, listener, prepend) {
m = $getMaxListeners(target);
if (m && m > 0 && existing.length > m) {
existing.warned = true;
+ // No error code for this since it is a Warning
const w = new Error('Possible EventEmitter memory leak detected. ' +
`${existing.length} ${String(type)} listeners ` +
'added. Use emitter.setMaxListeners() to ' +
@@ -337,16 +354,21 @@ function _onceWrap(target, type, listener) {
}
EventEmitter.prototype.once = function once(type, listener) {
- if (typeof listener !== 'function')
- throw new TypeError('"listener" argument must be a function');
+ if (typeof listener !== 'function') {
+ const errors = lazyErrors();
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'listener', 'function');
+ }
this.on(type, _onceWrap(this, type, listener));
return this;
};
EventEmitter.prototype.prependOnceListener =
function prependOnceListener(type, listener) {
- if (typeof listener !== 'function')
- throw new TypeError('"listener" argument must be a function');
+ if (typeof listener !== 'function') {
+ const errors = lazyErrors();
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'listener',
+ 'function');
+ }
this.prependListener(type, _onceWrap(this, type, listener));
return this;
};
@@ -356,8 +378,11 @@ EventEmitter.prototype.removeListener =
function removeListener(type, listener) {
var list, events, position, i, originalListener;
- if (typeof listener !== 'function')
- throw new TypeError('"listener" argument must be a function');
+ if (typeof listener !== 'function') {
+ const errors = lazyErrors();
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'listener',
+ 'function');
+ }
events = this._events;
if (!events)
diff --git a/lib/internal/errors.js b/lib/internal/errors.js
index 9a5551617d3e4b..7c5c8a1f0a5346 100755
--- a/lib/internal/errors.js
+++ b/lib/internal/errors.js
@@ -327,6 +327,12 @@ E('ERR_TRANSFORM_WITH_LENGTH_0',
'Calling transform done when writableState.length != 0');
E('ERR_UNESCAPED_CHARACTERS',
(name) => `${name} contains unescaped characters`);
+E('ERR_UNHANDLED_ERROR',
+ (err) => {
+ const msg = 'Unhandled error.';
+ if (err === undefined) return msg;
+ return `${msg} (${err})`;
+ });
E('ERR_UNKNOWN_ENCODING', 'Unknown encoding: %s');
E('ERR_UNKNOWN_FILE_EXTENSION', 'Unknown file extension: %s');
E('ERR_UNKNOWN_MODULE_FORMAT', 'Unknown module format: %s');
diff --git a/test/parallel/test-event-emitter-add-listeners.js b/test/parallel/test-event-emitter-add-listeners.js
index d6177a78806e49..2a02a94940fa5d 100644
--- a/test/parallel/test-event-emitter-add-listeners.js
+++ b/test/parallel/test-event-emitter-add-listeners.js
@@ -86,8 +86,11 @@ const EventEmitter = require('events');
}
// Verify that the listener must be a function
-assert.throws(() => {
+common.expectsError(() => {
const ee = new EventEmitter();
-
ee.on('foo', null);
-}, /^TypeError: "listener" argument must be a function$/);
+}, {
+ code: 'ERR_INVALID_ARG_TYPE',
+ type: TypeError,
+ message: 'The "listener" argument must be of type function'
+});
diff --git a/test/parallel/test-event-emitter-errors.js b/test/parallel/test-event-emitter-errors.js
index d52d3b4f4e74ef..ef2bbee93f8bfd 100644
--- a/test/parallel/test-event-emitter-errors.js
+++ b/test/parallel/test-event-emitter-errors.js
@@ -1,14 +1,23 @@
'use strict';
-require('../common');
+const common = require('../common');
const EventEmitter = require('events');
-const assert = require('assert');
const EE = new EventEmitter();
-assert.throws(() => {
- EE.emit('error', 'Accepts a string');
-}, /^Error: Unhandled "error" event\. \(Accepts a string\)$/);
+common.expectsError(
+ () => EE.emit('error', 'Accepts a string'),
+ {
+ code: 'ERR_UNHANDLED_ERROR',
+ type: Error,
+ message: 'Unhandled error. (Accepts a string)'
+ }
+);
-assert.throws(() => {
- EE.emit('error', { message: 'Error!' });
-}, /^Error: Unhandled "error" event\. \(\[object Object\]\)$/);
+common.expectsError(
+ () => EE.emit('error', { message: 'Error!' }),
+ {
+ code: 'ERR_UNHANDLED_ERROR',
+ type: Error,
+ message: 'Unhandled error. ([object Object])'
+ }
+);
diff --git a/test/parallel/test-event-emitter-max-listeners.js b/test/parallel/test-event-emitter-max-listeners.js
index cf8c072271db35..319e0dffd6494d 100644
--- a/test/parallel/test-event-emitter-max-listeners.js
+++ b/test/parallel/test-event-emitter-max-listeners.js
@@ -21,7 +21,6 @@
'use strict';
const common = require('../common');
-const assert = require('assert');
const events = require('events');
const e = new events.EventEmitter();
@@ -31,12 +30,25 @@ e.on('maxListeners', common.mustCall());
e.setMaxListeners(42);
const throwsObjs = [NaN, -1, 'and even this'];
-const maxError = /^TypeError: "n" argument must be a positive number$/;
-const defError = /^TypeError: "defaultMaxListeners" must be a positive number$/;
for (const obj of throwsObjs) {
- assert.throws(() => e.setMaxListeners(obj), maxError);
- assert.throws(() => events.defaultMaxListeners = obj, defError);
+ common.expectsError(
+ () => e.setMaxListeners(obj),
+ {
+ code: 'ERR_OUT_OF_RANGE',
+ type: TypeError,
+ message: 'The "n" argument is out of range'
+ }
+ );
+
+ common.expectsError(
+ () => events.defaultMaxListeners = obj,
+ {
+ code: 'ERR_OUT_OF_RANGE',
+ type: TypeError,
+ message: 'The "defaultMaxListeners" argument is out of range'
+ }
+ );
}
e.emit('maxListeners');
diff --git a/test/parallel/test-event-emitter-once.js b/test/parallel/test-event-emitter-once.js
index dd4f5133a198d9..35ebf72968a19a 100644
--- a/test/parallel/test-event-emitter-once.js
+++ b/test/parallel/test-event-emitter-once.js
@@ -50,11 +50,15 @@ e.once('e', common.mustCall());
e.emit('e');
// Verify that the listener must be a function
-assert.throws(() => {
+common.expectsError(() => {
const ee = new EventEmitter();
ee.once('foo', null);
-}, /^TypeError: "listener" argument must be a function$/);
+}, {
+ code: 'ERR_INVALID_ARG_TYPE',
+ type: TypeError,
+ message: 'The "listener" argument must be of type function'
+});
{
// once() has different code paths based on the number of arguments being
diff --git a/test/parallel/test-event-emitter-prepend.js b/test/parallel/test-event-emitter-prepend.js
index b511af9ae3691d..761eb6d9049b42 100644
--- a/test/parallel/test-event-emitter-prepend.js
+++ b/test/parallel/test-event-emitter-prepend.js
@@ -19,11 +19,15 @@ myEE.prependOnceListener('foo',
myEE.emit('foo');
// Verify that the listener must be a function
-assert.throws(() => {
+common.expectsError(() => {
const ee = new EventEmitter();
ee.prependOnceListener('foo', null);
-}, /^TypeError: "listener" argument must be a function$/);
+}, {
+ code: 'ERR_INVALID_ARG_TYPE',
+ type: TypeError,
+ message: 'The "listener" argument must be of type function'
+});
// Test fallback if prependListener is undefined.
const stream = require('stream');
diff --git a/test/parallel/test-event-emitter-remove-listeners.js b/test/parallel/test-event-emitter-remove-listeners.js
index d1c01e0bc3cfae..d4fb542270d85f 100644
--- a/test/parallel/test-event-emitter-remove-listeners.js
+++ b/test/parallel/test-event-emitter-remove-listeners.js
@@ -144,11 +144,15 @@ function listener2() {}
}
// Verify that the removed listener must be a function
-assert.throws(() => {
+common.expectsError(() => {
const ee = new EventEmitter();
ee.removeListener('foo', null);
-}, /^TypeError: "listener" argument must be a function$/);
+}, {
+ code: 'ERR_INVALID_ARG_TYPE',
+ type: TypeError,
+ message: 'The "listener" argument must be of type function'
+});
{
const ee = new EventEmitter();