-
Notifications
You must be signed in to change notification settings - Fork 30k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
events: migrate to internal/errors #15623
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you know where the circular reference is coming from? If so - is there any possibility in untying that? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not a circular reference that is the concern. The |
||
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'listener', | ||
'function'); | ||
} | ||
|
||
events = this._events; | ||
if (!events) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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)' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The message looks somewhat weird here because of the dot before the brackets. |
||
} | ||
); | ||
|
||
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])' | ||
} | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to lazily load this? Is this the pattern used everywhere? Should we?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is because events.js is loaded before all the other modules in the dependency tree (because of bootstrapping
process
. Lazy loadingerrors
preventserrors
from being loaded before events is loaded.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would still rather inline this instead of using the function form but it should not be a blocker.