Skip to content

Commit e5ad545

Browse files
committed
events: migrate to internal/errors
PR-URL: #15623 Reviewed-By: Joyee Cheung <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: Michael Dawson <[email protected]> Reviewed-By: Matteo Collina <[email protected]>
1 parent a26c1bf commit e5ad545

9 files changed

+110
-37
lines changed

doc/api/errors.md

+6
Original file line numberDiff line numberDiff line change
@@ -1251,6 +1251,12 @@ buffer.
12511251

12521252
Used when a string that contains unescaped characters was received.
12531253

1254+
<a id="ERR_UNHANDLED_ERROR"></a>
1255+
### ERR_UNHANDLED_ERROR
1256+
1257+
Used when an unhandled "error" occurs (for instance, when an `'error'` event
1258+
is emitted by an `EventEmitter` but an `'error'` handler is not registered).
1259+
12541260
<a id="ERR_UNKNOWN_ENCODING"></a>
12551261
### ERR_UNKNOWN_ENCODING
12561262

lib/events.js

+40-15
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,13 @@ EventEmitter.prototype._maxListeners = undefined;
4141
// added to it. This is a useful default which helps finding memory leaks.
4242
var defaultMaxListeners = 10;
4343

44+
var errors;
45+
function lazyErrors() {
46+
if (errors === undefined)
47+
errors = require('internal/errors');
48+
return errors;
49+
}
50+
4451
Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
4552
enumerable: true,
4653
get: function() {
@@ -52,8 +59,10 @@ Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
5259
console;
5360
// check whether the input is a positive number (whose value is zero or
5461
// greater and not a NaN).
55-
if (typeof arg !== 'number' || arg < 0 || arg !== arg)
56-
throw new TypeError('"defaultMaxListeners" must be a positive number');
62+
if (typeof arg !== 'number' || arg < 0 || arg !== arg) {
63+
const errors = lazyErrors();
64+
throw new errors.TypeError('ERR_OUT_OF_RANGE', 'defaultMaxListeners');
65+
}
5766
defaultMaxListeners = arg;
5867
}
5968
});
@@ -79,8 +88,10 @@ EventEmitter.init = function() {
7988
// Obviously not all Emitters should be limited to 10. This function allows
8089
// that to be increased. Set to zero for unlimited.
8190
EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
82-
if (typeof n !== 'number' || n < 0 || isNaN(n))
83-
throw new TypeError('"n" argument must be a positive number');
91+
if (typeof n !== 'number' || n < 0 || isNaN(n)) {
92+
const errors = lazyErrors();
93+
throw new errors.TypeError('ERR_OUT_OF_RANGE', 'n');
94+
}
8495
this._maxListeners = n;
8596
return this;
8697
};
@@ -170,8 +181,10 @@ EventEmitter.prototype.emit = function emit(type) {
170181
if (arguments.length > 1)
171182
er = arguments[1];
172183
if (domain) {
173-
if (!er)
174-
er = new Error('Unhandled "error" event');
184+
if (!er) {
185+
const errors = lazyErrors();
186+
er = new errors.Error('ERR_UNHANDLED_ERROR');
187+
}
175188
if (typeof er === 'object' && er !== null) {
176189
er.domainEmitter = this;
177190
er.domain = domain;
@@ -182,7 +195,8 @@ EventEmitter.prototype.emit = function emit(type) {
182195
throw er; // Unhandled 'error' event
183196
} else {
184197
// At least give some kind of context to the user
185-
const err = new Error('Unhandled "error" event. (' + er + ')');
198+
const errors = lazyErrors();
199+
const err = new errors.Error('ERR_UNHANDLED_ERROR', er);
186200
err.context = er;
187201
throw err;
188202
}
@@ -234,8 +248,10 @@ function _addListener(target, type, listener, prepend) {
234248
var events;
235249
var existing;
236250

237-
if (typeof listener !== 'function')
238-
throw new TypeError('"listener" argument must be a function');
251+
if (typeof listener !== 'function') {
252+
const errors = lazyErrors();
253+
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'listener', 'function');
254+
}
239255

240256
events = target._events;
241257
if (!events) {
@@ -278,6 +294,7 @@ function _addListener(target, type, listener, prepend) {
278294
m = $getMaxListeners(target);
279295
if (m && m > 0 && existing.length > m) {
280296
existing.warned = true;
297+
// No error code for this since it is a Warning
281298
const w = new Error('Possible EventEmitter memory leak detected. ' +
282299
`${existing.length} ${String(type)} listeners ` +
283300
'added. Use emitter.setMaxListeners() to ' +
@@ -337,16 +354,21 @@ function _onceWrap(target, type, listener) {
337354
}
338355

339356
EventEmitter.prototype.once = function once(type, listener) {
340-
if (typeof listener !== 'function')
341-
throw new TypeError('"listener" argument must be a function');
357+
if (typeof listener !== 'function') {
358+
const errors = lazyErrors();
359+
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'listener', 'function');
360+
}
342361
this.on(type, _onceWrap(this, type, listener));
343362
return this;
344363
};
345364

346365
EventEmitter.prototype.prependOnceListener =
347366
function prependOnceListener(type, listener) {
348-
if (typeof listener !== 'function')
349-
throw new TypeError('"listener" argument must be a function');
367+
if (typeof listener !== 'function') {
368+
const errors = lazyErrors();
369+
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'listener',
370+
'function');
371+
}
350372
this.prependListener(type, _onceWrap(this, type, listener));
351373
return this;
352374
};
@@ -356,8 +378,11 @@ EventEmitter.prototype.removeListener =
356378
function removeListener(type, listener) {
357379
var list, events, position, i, originalListener;
358380

359-
if (typeof listener !== 'function')
360-
throw new TypeError('"listener" argument must be a function');
381+
if (typeof listener !== 'function') {
382+
const errors = lazyErrors();
383+
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'listener',
384+
'function');
385+
}
361386

362387
events = this._events;
363388
if (!events)

lib/internal/errors.js

+6
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,12 @@ E('ERR_TRANSFORM_WITH_LENGTH_0',
327327
'Calling transform done when writableState.length != 0');
328328
E('ERR_UNESCAPED_CHARACTERS',
329329
(name) => `${name} contains unescaped characters`);
330+
E('ERR_UNHANDLED_ERROR',
331+
(err) => {
332+
const msg = 'Unhandled error.';
333+
if (err === undefined) return msg;
334+
return `${msg} (${err})`;
335+
});
330336
E('ERR_UNKNOWN_ENCODING', 'Unknown encoding: %s');
331337
E('ERR_UNKNOWN_FILE_EXTENSION', 'Unknown file extension: %s');
332338
E('ERR_UNKNOWN_MODULE_FORMAT', 'Unknown module format: %s');

test/parallel/test-event-emitter-add-listeners.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,11 @@ const EventEmitter = require('events');
8686
}
8787

8888
// Verify that the listener must be a function
89-
assert.throws(() => {
89+
common.expectsError(() => {
9090
const ee = new EventEmitter();
91-
9291
ee.on('foo', null);
93-
}, /^TypeError: "listener" argument must be a function$/);
92+
}, {
93+
code: 'ERR_INVALID_ARG_TYPE',
94+
type: TypeError,
95+
message: 'The "listener" argument must be of type function'
96+
});
+17-8
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,23 @@
11
'use strict';
2-
require('../common');
2+
const common = require('../common');
33
const EventEmitter = require('events');
4-
const assert = require('assert');
54

65
const EE = new EventEmitter();
76

8-
assert.throws(() => {
9-
EE.emit('error', 'Accepts a string');
10-
}, /^Error: Unhandled "error" event\. \(Accepts a string\)$/);
7+
common.expectsError(
8+
() => EE.emit('error', 'Accepts a string'),
9+
{
10+
code: 'ERR_UNHANDLED_ERROR',
11+
type: Error,
12+
message: 'Unhandled error. (Accepts a string)'
13+
}
14+
);
1115

12-
assert.throws(() => {
13-
EE.emit('error', { message: 'Error!' });
14-
}, /^Error: Unhandled "error" event\. \(\[object Object\]\)$/);
16+
common.expectsError(
17+
() => EE.emit('error', { message: 'Error!' }),
18+
{
19+
code: 'ERR_UNHANDLED_ERROR',
20+
type: Error,
21+
message: 'Unhandled error. ([object Object])'
22+
}
23+
);

test/parallel/test-event-emitter-max-listeners.js

+17-5
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121

2222
'use strict';
2323
const common = require('../common');
24-
const assert = require('assert');
2524
const events = require('events');
2625
const e = new events.EventEmitter();
2726

@@ -31,12 +30,25 @@ e.on('maxListeners', common.mustCall());
3130
e.setMaxListeners(42);
3231

3332
const throwsObjs = [NaN, -1, 'and even this'];
34-
const maxError = /^TypeError: "n" argument must be a positive number$/;
35-
const defError = /^TypeError: "defaultMaxListeners" must be a positive number$/;
3633

3734
for (const obj of throwsObjs) {
38-
assert.throws(() => e.setMaxListeners(obj), maxError);
39-
assert.throws(() => events.defaultMaxListeners = obj, defError);
35+
common.expectsError(
36+
() => e.setMaxListeners(obj),
37+
{
38+
code: 'ERR_OUT_OF_RANGE',
39+
type: TypeError,
40+
message: 'The "n" argument is out of range'
41+
}
42+
);
43+
44+
common.expectsError(
45+
() => events.defaultMaxListeners = obj,
46+
{
47+
code: 'ERR_OUT_OF_RANGE',
48+
type: TypeError,
49+
message: 'The "defaultMaxListeners" argument is out of range'
50+
}
51+
);
4052
}
4153

4254
e.emit('maxListeners');

test/parallel/test-event-emitter-once.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,15 @@ e.once('e', common.mustCall());
5050
e.emit('e');
5151

5252
// Verify that the listener must be a function
53-
assert.throws(() => {
53+
common.expectsError(() => {
5454
const ee = new EventEmitter();
5555

5656
ee.once('foo', null);
57-
}, /^TypeError: "listener" argument must be a function$/);
57+
}, {
58+
code: 'ERR_INVALID_ARG_TYPE',
59+
type: TypeError,
60+
message: 'The "listener" argument must be of type function'
61+
});
5862

5963
{
6064
// once() has different code paths based on the number of arguments being

test/parallel/test-event-emitter-prepend.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,15 @@ myEE.prependOnceListener('foo',
1919
myEE.emit('foo');
2020

2121
// Verify that the listener must be a function
22-
assert.throws(() => {
22+
common.expectsError(() => {
2323
const ee = new EventEmitter();
2424

2525
ee.prependOnceListener('foo', null);
26-
}, /^TypeError: "listener" argument must be a function$/);
26+
}, {
27+
code: 'ERR_INVALID_ARG_TYPE',
28+
type: TypeError,
29+
message: 'The "listener" argument must be of type function'
30+
});
2731

2832
// Test fallback if prependListener is undefined.
2933
const stream = require('stream');

test/parallel/test-event-emitter-remove-listeners.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,15 @@ function listener2() {}
144144
}
145145

146146
// Verify that the removed listener must be a function
147-
assert.throws(() => {
147+
common.expectsError(() => {
148148
const ee = new EventEmitter();
149149

150150
ee.removeListener('foo', null);
151-
}, /^TypeError: "listener" argument must be a function$/);
151+
}, {
152+
code: 'ERR_INVALID_ARG_TYPE',
153+
type: TypeError,
154+
message: 'The "listener" argument must be of type function'
155+
});
152156

153157
{
154158
const ee = new EventEmitter();

0 commit comments

Comments
 (0)