Browse Source

events: migrate to internal/errors

PR-URL: https://github.com/nodejs/node/pull/15623
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
v9.x-staging
James M Snell 8 years ago
parent
commit
e5ad5456a2
  1. 6
      doc/api/errors.md
  2. 55
      lib/events.js
  3. 6
      lib/internal/errors.js
  4. 9
      test/parallel/test-event-emitter-add-listeners.js
  5. 25
      test/parallel/test-event-emitter-errors.js
  6. 22
      test/parallel/test-event-emitter-max-listeners.js
  7. 8
      test/parallel/test-event-emitter-once.js
  8. 8
      test/parallel/test-event-emitter-prepend.js
  9. 8
      test/parallel/test-event-emitter-remove-listeners.js

6
doc/api/errors.md

@ -1251,6 +1251,12 @@ buffer.
Used when a string that contains unescaped characters was received. Used when a string that contains unescaped characters was received.
<a id="ERR_UNHANDLED_ERROR"></a>
### 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).
<a id="ERR_UNKNOWN_ENCODING"></a> <a id="ERR_UNKNOWN_ENCODING"></a>
### ERR_UNKNOWN_ENCODING ### ERR_UNKNOWN_ENCODING

55
lib/events.js

@ -41,6 +41,13 @@ EventEmitter.prototype._maxListeners = undefined;
// added to it. This is a useful default which helps finding memory leaks. // added to it. This is a useful default which helps finding memory leaks.
var defaultMaxListeners = 10; var defaultMaxListeners = 10;
var errors;
function lazyErrors() {
if (errors === undefined)
errors = require('internal/errors');
return errors;
}
Object.defineProperty(EventEmitter, 'defaultMaxListeners', { Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
enumerable: true, enumerable: true,
get: function() { get: function() {
@ -52,8 +59,10 @@ Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
console; console;
// check whether the input is a positive number (whose value is zero or // check whether the input is a positive number (whose value is zero or
// greater and not a NaN). // greater and not a NaN).
if (typeof arg !== 'number' || arg < 0 || arg !== arg) if (typeof arg !== 'number' || arg < 0 || arg !== arg) {
throw new TypeError('"defaultMaxListeners" must be a positive number'); const errors = lazyErrors();
throw new errors.TypeError('ERR_OUT_OF_RANGE', 'defaultMaxListeners');
}
defaultMaxListeners = arg; defaultMaxListeners = arg;
} }
}); });
@ -79,8 +88,10 @@ EventEmitter.init = function() {
// Obviously not all Emitters should be limited to 10. This function allows // Obviously not all Emitters should be limited to 10. This function allows
// that to be increased. Set to zero for unlimited. // that to be increased. Set to zero for unlimited.
EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
if (typeof n !== 'number' || n < 0 || isNaN(n)) if (typeof n !== 'number' || n < 0 || isNaN(n)) {
throw new TypeError('"n" argument must be a positive number'); const errors = lazyErrors();
throw new errors.TypeError('ERR_OUT_OF_RANGE', 'n');
}
this._maxListeners = n; this._maxListeners = n;
return this; return this;
}; };
@ -170,8 +181,10 @@ EventEmitter.prototype.emit = function emit(type) {
if (arguments.length > 1) if (arguments.length > 1)
er = arguments[1]; er = arguments[1];
if (domain) { if (domain) {
if (!er) if (!er) {
er = new Error('Unhandled "error" event'); const errors = lazyErrors();
er = new errors.Error('ERR_UNHANDLED_ERROR');
}
if (typeof er === 'object' && er !== null) { if (typeof er === 'object' && er !== null) {
er.domainEmitter = this; er.domainEmitter = this;
er.domain = domain; er.domain = domain;
@ -182,7 +195,8 @@ EventEmitter.prototype.emit = function emit(type) {
throw er; // Unhandled 'error' event throw er; // Unhandled 'error' event
} else { } else {
// At least give some kind of context to the user // 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; err.context = er;
throw err; throw err;
} }
@ -234,8 +248,10 @@ function _addListener(target, type, listener, prepend) {
var events; var events;
var existing; var existing;
if (typeof listener !== 'function') if (typeof listener !== 'function') {
throw new TypeError('"listener" argument must be a function'); const errors = lazyErrors();
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'listener', 'function');
}
events = target._events; events = target._events;
if (!events) { if (!events) {
@ -278,6 +294,7 @@ function _addListener(target, type, listener, prepend) {
m = $getMaxListeners(target); m = $getMaxListeners(target);
if (m && m > 0 && existing.length > m) { if (m && m > 0 && existing.length > m) {
existing.warned = true; existing.warned = true;
// No error code for this since it is a Warning
const w = new Error('Possible EventEmitter memory leak detected. ' + const w = new Error('Possible EventEmitter memory leak detected. ' +
`${existing.length} ${String(type)} listeners ` + `${existing.length} ${String(type)} listeners ` +
'added. Use emitter.setMaxListeners() to ' + 'added. Use emitter.setMaxListeners() to ' +
@ -337,16 +354,21 @@ function _onceWrap(target, type, listener) {
} }
EventEmitter.prototype.once = function once(type, listener) { EventEmitter.prototype.once = function once(type, listener) {
if (typeof listener !== 'function') if (typeof listener !== 'function') {
throw new TypeError('"listener" argument must be a function'); const errors = lazyErrors();
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'listener', 'function');
}
this.on(type, _onceWrap(this, type, listener)); this.on(type, _onceWrap(this, type, listener));
return this; return this;
}; };
EventEmitter.prototype.prependOnceListener = EventEmitter.prototype.prependOnceListener =
function prependOnceListener(type, listener) { function prependOnceListener(type, listener) {
if (typeof listener !== 'function') if (typeof listener !== 'function') {
throw new TypeError('"listener" argument must be a function'); const errors = lazyErrors();
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'listener',
'function');
}
this.prependListener(type, _onceWrap(this, type, listener)); this.prependListener(type, _onceWrap(this, type, listener));
return this; return this;
}; };
@ -356,8 +378,11 @@ EventEmitter.prototype.removeListener =
function removeListener(type, listener) { function removeListener(type, listener) {
var list, events, position, i, originalListener; var list, events, position, i, originalListener;
if (typeof listener !== 'function') if (typeof listener !== 'function') {
throw new TypeError('"listener" argument must be a function'); const errors = lazyErrors();
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'listener',
'function');
}
events = this._events; events = this._events;
if (!events) if (!events)

6
lib/internal/errors.js

@ -327,6 +327,12 @@ E('ERR_TRANSFORM_WITH_LENGTH_0',
'Calling transform done when writableState.length != 0'); 'Calling transform done when writableState.length != 0');
E('ERR_UNESCAPED_CHARACTERS', E('ERR_UNESCAPED_CHARACTERS',
(name) => `${name} contains 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_ENCODING', 'Unknown encoding: %s');
E('ERR_UNKNOWN_FILE_EXTENSION', 'Unknown file extension: %s'); E('ERR_UNKNOWN_FILE_EXTENSION', 'Unknown file extension: %s');
E('ERR_UNKNOWN_MODULE_FORMAT', 'Unknown module format: %s'); E('ERR_UNKNOWN_MODULE_FORMAT', 'Unknown module format: %s');

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

@ -86,8 +86,11 @@ const EventEmitter = require('events');
} }
// Verify that the listener must be a function // Verify that the listener must be a function
assert.throws(() => { common.expectsError(() => {
const ee = new EventEmitter(); const ee = new EventEmitter();
ee.on('foo', null); 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'
});

25
test/parallel/test-event-emitter-errors.js

@ -1,14 +1,23 @@
'use strict'; 'use strict';
require('../common'); const common = require('../common');
const EventEmitter = require('events'); const EventEmitter = require('events');
const assert = require('assert');
const EE = new EventEmitter(); const EE = new EventEmitter();
assert.throws(() => { common.expectsError(
EE.emit('error', 'Accepts a string'); () => EE.emit('error', 'Accepts a string'),
}, /^Error: Unhandled "error" event\. \(Accepts a string\)$/); {
code: 'ERR_UNHANDLED_ERROR',
type: Error,
message: 'Unhandled error. (Accepts a string)'
}
);
assert.throws(() => { common.expectsError(
EE.emit('error', { message: 'Error!' }); () => EE.emit('error', { message: 'Error!' }),
}, /^Error: Unhandled "error" event\. \(\[object Object\]\)$/); {
code: 'ERR_UNHANDLED_ERROR',
type: Error,
message: 'Unhandled error. ([object Object])'
}
);

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

@ -21,7 +21,6 @@
'use strict'; 'use strict';
const common = require('../common'); const common = require('../common');
const assert = require('assert');
const events = require('events'); const events = require('events');
const e = new events.EventEmitter(); const e = new events.EventEmitter();
@ -31,12 +30,25 @@ e.on('maxListeners', common.mustCall());
e.setMaxListeners(42); e.setMaxListeners(42);
const throwsObjs = [NaN, -1, 'and even this']; 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) { for (const obj of throwsObjs) {
assert.throws(() => e.setMaxListeners(obj), maxError); common.expectsError(
assert.throws(() => events.defaultMaxListeners = obj, defError); () => 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'); e.emit('maxListeners');

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

@ -50,11 +50,15 @@ e.once('e', common.mustCall());
e.emit('e'); e.emit('e');
// Verify that the listener must be a function // Verify that the listener must be a function
assert.throws(() => { common.expectsError(() => {
const ee = new EventEmitter(); const ee = new EventEmitter();
ee.once('foo', null); 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 // once() has different code paths based on the number of arguments being

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

@ -19,11 +19,15 @@ myEE.prependOnceListener('foo',
myEE.emit('foo'); myEE.emit('foo');
// Verify that the listener must be a function // Verify that the listener must be a function
assert.throws(() => { common.expectsError(() => {
const ee = new EventEmitter(); const ee = new EventEmitter();
ee.prependOnceListener('foo', null); 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. // Test fallback if prependListener is undefined.
const stream = require('stream'); const stream = require('stream');

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

@ -144,11 +144,15 @@ function listener2() {}
} }
// Verify that the removed listener must be a function // Verify that the removed listener must be a function
assert.throws(() => { common.expectsError(() => {
const ee = new EventEmitter(); const ee = new EventEmitter();
ee.removeListener('foo', null); 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(); const ee = new EventEmitter();

Loading…
Cancel
Save