eventemitter2
Advanced tools
Comparing version 0.2.7 to 0.3.5
@@ -1,170 +0,145 @@ | ||
;!function(root, undefined) { | ||
var EventEmitter2 = root.EventEmitter2 = function EventEmitter2(conf) { | ||
;!function(environment, undefined) { | ||
// If *_listeners* is undefined invoke *initializeEvents* to set the | ||
// default properties. | ||
if (!this._listeners) this.initializeEvents(conf); | ||
var EventEmitter2 = environment.EventEmitter2 = function(conf) { | ||
this.setConf(conf); | ||
this.init(); | ||
}; | ||
EventEmitter2.prototype.initializeEvents = function(conf) { | ||
conf = conf || {}; | ||
var self = this; | ||
EventEmitter2.prototype.init = function() { | ||
this._events = new Object; | ||
this.defaultMaxListeners = 10; | ||
}; | ||
conf.delimiter = conf.delimiter || '.'; | ||
var isArray = Array.isArray; | ||
if (conf.delimiter === '*' && conf.delimiter.length === 1) { | ||
throw new Error('initializeEvents doesn\'t accept a "*" (wild-card) character as delimiter'); | ||
} else { | ||
self._delimiter = conf.delimiter; | ||
} | ||
// By default EventEmitters will print a warning if more than | ||
// 10 listeners are added to it. This is a useful default which | ||
// helps finding memory leaks. | ||
// | ||
// Obviously not all Emitters should be limited to 10. This function allows | ||
// that to be increased. Set to zero for unlimited. | ||
self._caseSensitive = typeof conf.caseSensitive === 'undefined' ? true : conf.caseSensitive; | ||
self.setMaxListeners(conf.maxListeners); | ||
self._listeners = {}; | ||
self._allListenerFn = []; | ||
return self; | ||
} | ||
EventEmitter2.prototype.setConf = function(conf) { | ||
this.wildcard = conf && conf.wildcard; | ||
this.verbose = conf && conf.verbose; | ||
EventEmitter2.prototype.addListener = function(event, fn) { | ||
var self = this; | ||
// If *fn* is not a function throw an error. An *fn* that is not a function | ||
// can not be invoked when an event is emitted and therefor is not allowed | ||
// to be added. | ||
if (typeof fn !== 'function') { | ||
throw new Error('addListener only accepts instances of Function'); | ||
if(this.wildcard) { | ||
this.listenerTree = new Object; | ||
} | ||
}; | ||
// If *_listeners* is undefined invoke *initializeEvents* to set the | ||
// default properties. | ||
if (!self._listeners) self.initializeEvents(); | ||
EventEmitter2.prototype.setMaxListeners = function(n) { | ||
this._events || this.init(); | ||
this._events.maxListeners = n; | ||
}; | ||
// Set variables. | ||
var i = 0, l = 0, | ||
delimiter = self._delimiter, | ||
doubleDelimiter = delimiter + delimiter, | ||
caseSensitive = self._caseSensitive, | ||
listeners = self._listeners, | ||
maxListeners = self._maxListeners, | ||
event = caseSensitive ? event : event.toLowerCase(), | ||
namespaced = ~event.indexOf(delimiter), | ||
ns, exploreNs = listeners, | ||
listenToEvent, eventListeners; | ||
EventEmitter2.prototype.event = ''; | ||
// If the event is namespaced loop through the namespaces, set seperate | ||
// events for each namespace and set *listenToEvent* to the last | ||
// namespace to attach the listener function to this event after the loop. | ||
if (namespaced) { | ||
EventEmitter2.prototype.delimiter = '.'; | ||
// If an event starts or ends with a delimiter character or two or more | ||
// delimiter characters are used after each other throw an error. | ||
// Starting or ending an event with a delimiter character or combining | ||
// characters creates empty namespaces which don't work and therefor are | ||
// not allowed. | ||
if (event[event.length - 1] === delimiter || event[0] === delimiter || ~event.indexOf(doubleDelimiter)) { | ||
self.eventDelimiterError('addListener'); | ||
return false; | ||
} | ||
EventEmitter2.prototype.verbose = false; | ||
// Split the event into a namespace array for looping. | ||
ns = event.split(delimiter); | ||
var searchListenerTree = function(handlers, type, tree, i) { | ||
var listeners; | ||
// Loop through the namespaces. | ||
for (i = 0, l = ns.length; i < l; i++) { | ||
if(i === type.length && tree && tree._listeners) { | ||
// If the namespace contains a wildcard character check if this | ||
// character is the only one in the namespace. If it is not the only | ||
// character in the namespace this namespace is invalid and therefor | ||
// an error is thrown. | ||
if (ns[i].indexOf('*') !== -1 && ns[i].length !== 1) { | ||
self.eventWildcardError('addListener'); | ||
return false; | ||
if(typeof tree._listeners === 'function') { | ||
handlers && handlers.push(tree._listeners); | ||
return tree; | ||
} | ||
else { | ||
for(var leaf = 0, len = tree._listeners.length; leaf < len; leaf++) { | ||
handlers && handlers.push(tree._listeners[leaf]); | ||
} | ||
return tree; | ||
} | ||
} | ||
// If the event is undefined in *exploreNs* it means it doesn't exist | ||
// in *listeners* so a new event should be created. | ||
if (!exploreNs[ns[i]]) { | ||
exploreNs[ns[i]] = { | ||
_name: ns[i], | ||
_fn: [], | ||
_ns: {} | ||
}; | ||
if(tree && (type[i] === '*' || tree[type[i]])) { | ||
if(type[i] === '*') { | ||
for(var branch in tree) { | ||
if(tree.hasOwnProperty(branch)) { | ||
listeners = searchListenerTree(handlers, type, tree[branch], i+1); | ||
} | ||
} | ||
return; | ||
} | ||
// If the loop is at the end set *listenToEvent* to the current | ||
// namespace - which is the last one - to attach the listener to this | ||
// event. If the loop is not at the end rebase *exploreNs* to loop the | ||
// current event's namespaces. | ||
if (i === ns.length - 1) { | ||
listenToEvent = exploreNs[ns[i]]; | ||
} else { | ||
exploreNs = exploreNs[ns[i]]._ns; | ||
tree = tree[type[i]]; | ||
if(tree['*']) { | ||
i++; | ||
for(var branch in tree) { | ||
if(tree.hasOwnProperty(branch)) { | ||
listeners = searchListenerTree(handlers, type, tree[branch], i+1); | ||
} | ||
} | ||
} | ||
else { | ||
listeners = searchListenerTree(handlers, type, tree, i+1); | ||
} | ||
} | ||
return listeners; | ||
}; | ||
// If the event is not namespaced set the single event and set | ||
// *listenToEvent* to this event to attach the listener to. | ||
else { | ||
var growListenerTree = function(type, listener) { | ||
// If the event contains a wildcard character check if this | ||
// character is the only one in the event. If it is not the only | ||
// character in the event this event is invalid and therefor | ||
// an error is thrown. | ||
if (event.indexOf('*') !== -1 && event.length !== 1) { | ||
self.eventWildcardError('addListener'); | ||
return false; | ||
} | ||
var d = this.delimiter; | ||
// If the event is undefined in *listeners* it means it doesn't exist | ||
// so a new event should be created. | ||
if (!listeners[event]) { | ||
listeners[event] = { | ||
_name: event, | ||
_fn: [], | ||
_ns: {} | ||
}; | ||
if (type.charAt(0) === d || | ||
type.charAt(type.length-1) === d || | ||
~type.indexOf(this.delimiter)) { | ||
this.emit('error', 'bad event name: ' + type); | ||
} | ||
type = type.split(d); | ||
var tree = this.listenerTree; | ||
var name = type.shift(); | ||
while (name) { | ||
if (!tree[name]) { | ||
tree[name] = new Object(); | ||
} | ||
// Set *listenToEvent* to the current event to attach the listener to. | ||
listenToEvent = listeners[event]; | ||
} | ||
tree = tree[name]; | ||
eventListeners = listenToEvent._fn; | ||
if (type.length === 0) { | ||
// Signal that a new listener is being added. | ||
self.emit('newListener', event, fn); | ||
if (!tree._listeners) { | ||
tree._listeners = listener; | ||
} | ||
else if(typeof tree._listeners === 'function') { | ||
tree._listeners = [tree._listeners, listener]; | ||
} | ||
else if (isArray(tree._listeners)) { | ||
// If the max amount of listeners has been reached signal and return to | ||
// cancel the addition of this new listener. | ||
if (maxListeners > 0 && eventListeners.length >= maxListeners) { | ||
self.emit('maxListeners', event); | ||
return self; | ||
} | ||
tree._listeners.push(listener); | ||
// Add the function to the event listener collection. | ||
eventListeners.push(fn); | ||
return self; | ||
}; | ||
if (!tree._listeners.warned) { | ||
EventEmitter2.prototype.onAny = function(fn) { | ||
var m = this.defaultMaxListeners; | ||
// If *fn* is not a function throw an error. An *fn* that is not a function | ||
// can not be invoked when an event is emitted and therefor is not allowed | ||
// to be added. | ||
if (typeof fn !== 'function') { | ||
throw new Error('onAny only accepts instances of Function'); | ||
if (m > 0 && tree._listeners.length > m) { | ||
tree._listeners.warned = true; | ||
console.error('(node) warning: possible EventEmitter memory ' + | ||
'leak detected. %d listeners added. ' + | ||
'Use emitter.setMaxListeners() to increase limit.', | ||
tree._listeners.length); | ||
console.trace(); | ||
} | ||
} | ||
} | ||
return true; | ||
} | ||
name = type.shift(); | ||
} | ||
// If *_listeners* is undefined invoke *initializeEvents* to set the | ||
// default properties. | ||
if (!this._listeners) this.initializeEvents(); | ||
// Add the function to the event listener collection. | ||
this._allListenerFn.push(fn); | ||
return true; | ||
}; | ||
EventEmitter2.prototype.on = EventEmitter2.prototype.addListener; | ||
EventEmitter2.prototype.once = function(event, fn) { | ||
@@ -178,5 +153,2 @@ this.many(event, 1, fn); | ||
// If *fn* is not a function throw an error. An *fn* that is not a function | ||
// can not be invoked when an event is emitted and therefor is not allowed | ||
// to be added. | ||
if (typeof fn !== 'function') { | ||
@@ -188,9 +160,10 @@ throw new Error('many only accepts instances of Function'); | ||
if (--ttl == 0) { | ||
self.removeListener(event, listener); | ||
self.un(event, listener); | ||
} | ||
fn.apply(null, arguments); | ||
}; | ||
listener._origin = fn; | ||
self.addListener(event, listener); | ||
this.on(event, listener); | ||
@@ -200,238 +173,205 @@ return self; | ||
EventEmitter2.prototype.emit = function(event) { | ||
var self = this, | ||
args = arguments, | ||
i = 0, l = 0, | ||
delimiter = self._delimiter, | ||
doubleDelimiter = delimiter + delimiter, | ||
caseSensitive = self._caseSensitive, | ||
listeners = self._listeners, | ||
event = caseSensitive ? event : event.toLowerCase(), | ||
namespaced = ~event.indexOf(delimiter), | ||
ns, exploreNs = [listeners], collectedListeners = [], collectedErrors = false, | ||
invoked = false; | ||
EventEmitter2.prototype.emit = function() { | ||
this._events || this.init(); | ||
var type = arguments[0]; | ||
// If there is no 'error' event listener then throw. | ||
// If no listeners are defined the emit will not be able to invoke a | ||
// function. Therefore return *invoked* to exit. | ||
if (!listeners) return invoked; | ||
if (type === 'newListener') { | ||
if(!this._events.newListener) { return false; } | ||
} | ||
// If the event is namespaced loop through the namespaces, find all the | ||
// listeners for the namespaces and wildcards and add them to the | ||
// *collectedListeners* array for listener invocation after the loop. | ||
if (namespaced || event === '*') { | ||
// If an event starts or ends with a delimiter character or two or more | ||
// delimiter characters are used after each other throw an error. | ||
// Starting or ending an event with a delimiter character or combining | ||
// characters creates empty namespaces which don't work and therefor are | ||
// not allowed. | ||
if (event[event.length - 1] === delimiter || event[0] === delimiter || ~event.indexOf(doubleDelimiter)) { | ||
self.eventDelimiterError('emit'); | ||
else if (type === 'error') { | ||
if (this._events.error && typeof this._events.error !== 'function') { | ||
if (arguments[1] instanceof Error) { | ||
throw arguments[1]; // Unhandled 'error' event | ||
} else { | ||
throw new Error("Uncaught, unspecified 'error' event."); | ||
} | ||
return false; | ||
} | ||
} | ||
// Split the event into a namespace array for looping. | ||
ns = event.split(delimiter); | ||
var handler; | ||
// Loop through the namespaces. | ||
for (i = 0; i < ns.length; i++) { | ||
if(this.wildcard) { | ||
this.event = type; | ||
handler = []; | ||
var ns = type.split(this.delimiter); | ||
searchListenerTree.call(this, handler, ns, this.listenerTree, 0); | ||
} | ||
else { | ||
handler = this._events[type]; | ||
} | ||
// If the namespace contains a wildcard character check if this | ||
// character is the only one in the namespace. If it is not the only | ||
// character in the namespace this namespace is invalid and therefor | ||
// an error is thrown. | ||
if (ns[i].indexOf('*') !== -1 && ns[i].length !== 1) { | ||
self.eventWildcardError('addListener'); | ||
return false; | ||
if (typeof handler === 'function') { | ||
if(arguments.length === 1) { | ||
handler.call(this); | ||
} | ||
else if(arguments.length > 1) | ||
switch (arguments.length) { | ||
case 2: | ||
handler.call(this, arguments[1]); | ||
break; | ||
case 3: | ||
handler.call(this, arguments[1], arguments[2]); | ||
break; | ||
// slower | ||
default: | ||
var l = arguments.length; | ||
var args = new Array(l - 1); | ||
for (var i = 1; i < l; i++) args[i - 1] = arguments[i]; | ||
handler.apply(this, args); | ||
} | ||
return true; | ||
} | ||
else if (handler) { | ||
// While looping through the namespace array loop through *exploreNs* | ||
// with *i* as well. This is basically the same as looping through the | ||
// the different levels of *events*. *collectedNs* is used to collect | ||
// all the namespaces that are going to be explored for the next level | ||
// of *events*. | ||
var currentNs = ns[i], | ||
currentExploreNs = exploreNs[i], | ||
collectedNs = []; | ||
var l = arguments.length; | ||
var args = new Array(l - 1); | ||
for (var i = 1; i < l; i++) args[i - 1] = arguments[i]; | ||
// Loop through the current level of *events*. | ||
for (var key1 in currentExploreNs) { | ||
var listeners = handler.slice(); | ||
for (var i = 0, l = listeners.length; i < l; i++) { | ||
listeners[i].apply(this, args); | ||
} | ||
return true; | ||
} | ||
}; | ||
// Set the current namespace in *events* that is being explored. | ||
var exploredNs = currentExploreNs[key1], | ||
name = caseSensitive ? exploredNs._name : exploredNs._name.toLowerCase(); | ||
EventEmitter2.prototype.on = function(type, listener) { | ||
this._events || this.init(); | ||
// If there is a match for the namespace or a wildcard collect the | ||
// next level of namespaces or collect the listeners of this | ||
// particular namespace. | ||
if (currentNs === '*' || (name === currentNs || name === '*')) { | ||
// To avoid recursion in the case that type == "newListeners"! Before | ||
// adding it to the listeners, first emit "newListeners". | ||
this.emit('newListener', type, listener); | ||
// If the loop is at the end collect the listeners for this | ||
// particular event and add them to the *collectedListeners* array | ||
// for listener invocation after the loop. If the loop is not at | ||
// the end collect the next level of namespaces. | ||
if (i === ns.length - 1) { | ||
var listeners = exploredNs._fn; | ||
if(this.wildcard) { | ||
growListenerTree.call(this, type, listener); | ||
return this; | ||
} | ||
if (listeners.length > 0) { | ||
collectedListeners = collectedListeners.concat(listeners); | ||
} | ||
} else { | ||
for (var key2 in exploredNs._ns) { | ||
collectedNs.push(exploredNs._ns[key2]); | ||
} | ||
} | ||
} | ||
if (!this._events[type]) { | ||
// Optimize the case of one listener. Don't need the extra array object. | ||
this._events[type] = listener; | ||
} | ||
else if(typeof this._events[type] === 'function') { | ||
// Adding the second element, need to change to array. | ||
this._events[type] = [this._events[type], listener]; | ||
} | ||
else if (isArray(this._events[type])) { | ||
// If we've already got an array, just append. | ||
this._events[type].push(listener); | ||
// Check for listener leak | ||
if (!this._events[type].warned) { | ||
var m; | ||
if (this._events.maxListeners !== undefined) { | ||
m = this._events.maxListeners; | ||
} else { | ||
m = this.defaultMaxListeners; | ||
} | ||
exploreNs.push(collectedNs); | ||
if (m && m > 0 && this._events[type].length > m) { | ||
this._events[type].warned = true; | ||
console.error('(node) warning: possible EventEmitter memory ' + | ||
'leak detected. %d listeners added. ' + | ||
'Use emitter.setMaxListeners() to increase limit.', | ||
this._events[type].length); | ||
console.trace(); | ||
} | ||
} | ||
} | ||
return this; | ||
}; | ||
// If the event is not namespaced collect all the functions for this | ||
// particular event and from the wildcard event and add them to | ||
// the *collectedListeners* array for invocation. | ||
else { | ||
EventEmitter2.prototype.addListener = EventEmitter2.prototype.on; | ||
// If the event contains a wildcard character check if this | ||
// character is the only one in the event. If it is not the only | ||
// character in the event this event is invalid and therefor | ||
// an error is thrown. | ||
if (event.indexOf('*') !== -1 && event.length !== 1) { | ||
self.eventWildcardError('addListener'); | ||
return false; | ||
} | ||
EventEmitter2.prototype.un = function(type, listener) { | ||
if (typeof listener !== 'function') { | ||
throw new Error('removeListener only takes instances of Function'); | ||
} | ||
// following coreEE convention, only events called 'error' should throw | ||
// an actual Error if there are no error listeners registered | ||
if (event === 'error') { | ||
var handlers; | ||
// ... | ||
if ( | ||
!listeners || | ||
!listeners['error'] || listeners['error']._fn.length === 0 && | ||
(!self._allListenerFn || self._allListenerFn.length === 0) | ||
) { | ||
if(this.wildcard) { | ||
var ns = type.split(this.delimiter); | ||
var leaf = searchListenerTree.call(this, null, ns, this.listenerTree, 0); | ||
// ... | ||
if (arguments[1] instanceof Error) { | ||
throw arguments[1]; | ||
} else { | ||
throw new Error("Uncaught, unspecified 'error' event."); | ||
} | ||
if('undefined' === typeof leaf) { return this; } | ||
handlers = leaf._listeners; | ||
} | ||
else { | ||
// does not use listeners(), so no side effect of creating _events[type] | ||
if (!this._events[type]) return this; | ||
handlers = this._events[type]; | ||
} | ||
return invoked; | ||
if (isArray(handlers)) { | ||
var position = -1; | ||
for (var i = 0, length = handlers.length; i < length; i++) { | ||
if (handlers[i] === listener || | ||
(handlers[i].listener && handlers[i].listener === listener) || | ||
(handlers[i]._origin && handlers[i]._origin === listener)) { | ||
position = i; | ||
break; | ||
} | ||
} | ||
if (listeners[event] && listeners[event]._fn.length > 0) { | ||
collectedListeners = collectedListeners.concat(listeners[event]._fn); | ||
if (position < 0) { | ||
return this; | ||
} | ||
if (listeners['*'] && listeners['*']._fn.length > 0) { | ||
collectedListeners = collectedListeners.concat(listeners['*']._fn); | ||
if(this.wildcard) { | ||
leaf._listeners.splice(position, 1) | ||
} | ||
} | ||
// Loop through the collected functions and invoke them. | ||
if (collectedListeners.length > 0) { | ||
for (i = 0, l = collectedListeners.length; i < l; i++) { | ||
collectedListeners[i].apply(self, args); | ||
invoked = true; | ||
else { | ||
this._events[type].splice(position, 1); | ||
} | ||
} | ||
// Loop through the *_allListenerFn* functions and invoke them. | ||
if (self._allListenerFn && self._allListenerFn.length > 0) { | ||
for (i = 0, l = self._allListenerFn.length; i < l; i++) { | ||
self._allListenerFn[i].apply(self, args); | ||
invoked = true; | ||
} | ||
} | ||
return invoked; | ||
}; | ||
EventEmitter2.prototype.emitAll = function() {}; | ||
EventEmitter2.prototype.removeListener = function(event, fn) { | ||
var i = 0, l = 0, fns, | ||
names, ns = this._listeners; | ||
event = this._caseSensitive ? event : event.toLowerCase(); | ||
// fn not being a function does nothing | ||
if (~event.indexOf(this._delimiter)) { | ||
// namespaced, so try to find the ns | ||
names = event.split(this._delimiter); | ||
for (i = 0, l = names.length; i < l; i++) { | ||
if (!ns || !ns[names[i]]) { | ||
// if this namespace was never defined, return | ||
return this; | ||
if (handlers.length === 0) { | ||
if(this.wildcard) { | ||
delete leaf._listeners; | ||
} | ||
if (i === names.length-1){ | ||
ns = ns[names[i]]; | ||
} else { | ||
ns = ns[names[i]]._ns; | ||
else { | ||
delete this._events[type]; | ||
} | ||
} | ||
if (!ns._fn) { | ||
// if this ns is empty for some reason | ||
return this; | ||
} | ||
else if (handlers === listener || | ||
(handlers.listener && handlers.listener === listener) || | ||
(handlers._origin && handlers._origin === listener)) { | ||
if(this.wildcard) { | ||
delete leaf._listeners; | ||
} | ||
// above we stop 1 _ns before the last one | ||
// so we havet go INTO the _ns, and grab it's _ns | ||
fns = ns._fn; | ||
for(var i = 0, l = fns.length; i < l; i++) { | ||
if(fn === fns[i] || fn === fns[i]._origin) { | ||
fns.splice(i, 1); | ||
return this; | ||
} | ||
else { | ||
delete this._events[type]; | ||
} | ||
} | ||
else { | ||
if (ns[event]) { | ||
// if this is not a namespaced event, just remove | ||
fns = ns[event]._fn; | ||
for (var i = 0, l = fns.length; i < l; i++) { | ||
if(fn === fns[i] || fn === fns[i]._origin) { | ||
fns.splice(i, 1); | ||
return this; | ||
} | ||
} | ||
} | ||
} | ||
// if we get here just return | ||
} | ||
return this; | ||
}; | ||
EventEmitter2.prototype.un = EventEmitter2.prototype.removeListener; | ||
EventEmitter2.prototype.removeListener = EventEmitter2.prototype.un; | ||
EventEmitter2.prototype.unAny = function(fn) { | ||
var i = 0, l = 0, fns; | ||
if (fn && this._allListenerFn && this._allListenerFn.length > 0) { | ||
fns = this._allListenerFn; | ||
for(i = 0, l = fns.length; i < l; i++) { | ||
if(fn === fns[i]) { | ||
fns.splice(i, 1); | ||
return this; | ||
} | ||
} | ||
} else { | ||
this._allListenerFn = []; | ||
EventEmitter2.prototype.removeAllListeners = function(type) { | ||
if (arguments.length === 0) { | ||
this._events || this.init(); | ||
return this; | ||
} | ||
return this; | ||
}; | ||
EventEmitter2.prototype.removeAllListeners = function(event) { | ||
var listeners, i, l; | ||
// if there is an event, then remove every listener on that listener | ||
if (!event) { | ||
this._listeners = {}; | ||
this._allListenerFn = []; | ||
if(this.wildcard) { | ||
var ns = type.split(this.delimiter); | ||
var leaf = searchListenerTree.call(this, null, ns, this.listenerTree, 0); | ||
if('undefined' === typeof leaf) { return this; } | ||
leaf._listeners = null; | ||
} | ||
else { | ||
listeners = this.listeners(event); | ||
for (i = 0, l = listeners.length; i < l; i++) { | ||
this.removeListener(event, listeners[i]); | ||
} | ||
if (!this._events[type]) return this; | ||
this._events[type] = null; | ||
} | ||
@@ -441,51 +381,19 @@ return this; | ||
EventEmitter2.prototype.setMaxListeners = function(n) { | ||
this._maxListeners = n === 0 ? 0 : n || 10; | ||
return this; | ||
}; | ||
EventEmitter2.prototype.listeners = function(event) { | ||
var ns = this._listeners, | ||
i = 0, l = 0, fns, | ||
names, | ||
toReturn; | ||
// case sensititivty | ||
event = this._caseSensitive ? event : event.toLowerCase(); | ||
// check if we are namespaced | ||
if (~event.indexOf(this._delimiter)) { | ||
// namespaced so, find it | ||
names = event.split(this._delimiter); | ||
for (i = 0, l = names.length; i < l; i++) { | ||
if (!ns || !ns[names[i]]) { | ||
// if this namespace was never defined, return | ||
return []; | ||
} | ||
if (i === names.length-1){ | ||
ns = ns[names[i]]; | ||
} else { | ||
ns = ns[names[i]]._ns; | ||
} | ||
} | ||
return ns._fn || []; | ||
EventEmitter2.prototype.listeners = function(type) { | ||
if(this.wildcard) { | ||
var handlers = []; | ||
var ns = type.split(this.delimiter); | ||
searchListenerTree.call(this, handlers, ns, this.listenerTree, 0); | ||
return handlers; | ||
} | ||
else { | ||
if (!ns[event]) { | ||
return []; | ||
} | ||
return ns[event]._fn || []; | ||
} | ||
}; | ||
EventEmitter2.prototype.listenersAny = function() { | ||
return this._allListenerFn; | ||
} | ||
this._events || this.init(); | ||
EventEmitter2.prototype.eventDelimiterError = function(fn) { | ||
throw new Error(fn + ' doesn\'t accept empty namespaces or events starting or ending with a "' + this._delimiter + '" (delimiter) character'); | ||
if (!this._events[type]) this._events[type] = []; | ||
if (!isArray(this._events[type])) { | ||
this._events[type] = [this._events[type]]; | ||
} | ||
return this._events[type]; | ||
}; | ||
EventEmitter2.prototype.eventWildcardError = function(fn) { | ||
throw new Error(fn + ' doesn\'t accept events starting, ending or containing a "*" (wildcard) character'); | ||
}; | ||
}(typeof exports === 'undefined' ? window : exports); |
{ | ||
"name": "eventemitter2", | ||
"version": "0.2.7", | ||
"version": "0.3.5", | ||
"description": "A Node.js event emitter implementation with namespaces, wildcards, TTL and browser support.", | ||
@@ -23,6 +23,11 @@ "keywords": ["event", "events", "emitter", "eventemitter"], | ||
"devDependencies": { | ||
"nodeunit": "*" | ||
"nodeunit": "*", | ||
"benchmark" : ">= 0.2.2" | ||
}, | ||
"engines": ["node"], | ||
"main": "./lib/eventemitter2.js" | ||
"main": "./lib/eventemitter2.js", | ||
"scripts" : { | ||
"test" : "nodeunit test/simple/* && nodeunit test/wildcardEvents/*", | ||
"benchmark" : "node test/perf/benchmark-listener.js" | ||
} | ||
} |
@@ -6,11 +6,26 @@ | ||
# ATTENTION! BREAKING CHANGES TO BE COMPATIBLE WITH NODE.JS EVENT EMITTER. | ||
Wrong | ||
```javascript | ||
server.on('foo.*', function(event, value1, value2) { // DOES NOT PASS THE EVENT AS FIRST ARGUMENT. | ||
console.log(event, value1, value2); | ||
}); | ||
``` | ||
Right | ||
```javascript | ||
server.on('foo.*', function(value1, value2) { | ||
console.log(this.event, value1, value2); | ||
}); | ||
``` | ||
## Features | ||
- Namespaced events | ||
- Wildcards for namespaces | ||
- Namespaces/Wildcards | ||
- Times To Listen (TTL), extends the `once` concept | ||
- Browser environment compatibility | ||
- As good or better performance for emission and listener registration as Node.js core EventEmitter | ||
- Smaller. EventEmitter2.js (2.2K Minified) VS. events.js (2.7K Minified) | ||
- 2x faster than Node.js event emitter for non-namespaced events. | ||
@@ -22,22 +37,23 @@ ## Differences (Non breaking, compatible with existing EventEmitter) | ||
```javascript | ||
var server = EventEmitter2({ | ||
delimiter: '/', // the delimiter used to segment namespaces, defaults to `.`. | ||
maxListeners: 20, // the max number of listeners that can be assigned to an event, defaults to 10. | ||
caseSensitive: true // this is a big red button, don't press it... or else... I'm just warning you. | ||
}); | ||
var server = EventEmitter2({ | ||
wildcard: true, // should the event emitter use wildcards (**caution, this has a performance impact**). | ||
delimiter: '/', // the delimiter used to segment namespaces, defaults to `.`. | ||
maxListeners: 20, // the max number of listeners that can be assigned to an event, defaults to 10. | ||
caseSensitive: true // this is a big red button, don't press it... or else... I'm just warning you. | ||
}); | ||
``` | ||
- The first parameter of a listener is the actual event name that the listener reacted to (because of wildcards). | ||
- Getting the actual event that fired. | ||
```javascript | ||
server.on('foo.*', function(event, value1, value2) { | ||
console.log('a values were', value1, value2); | ||
server.on('foo.*', function(value1, value2) { | ||
console.log(this.event, value1, value2); | ||
}); | ||
``` | ||
- A new method was added. Times to listen, an extension of the `once` concept. | ||
- Fire an event N times and then remove it, an extension of the `once` concept. | ||
```javascript | ||
server.many('foo', 4, function(event, value1, value2) { | ||
console.log('a values were', value1, value2); | ||
server.many('foo', 4, function() { | ||
console.log('hello'); | ||
}); | ||
@@ -64,3 +80,3 @@ ``` | ||
```javascript | ||
server.on('data', function(event, value) { | ||
server.on('data', function(value1, value2, value3 /* accepts any number of expected values... */) { | ||
console.log('The event was raised!'); | ||
@@ -71,3 +87,3 @@ }); | ||
```javascript | ||
server.on('data', function(event, value) { | ||
server.on('data', function(value) { | ||
console.log('This event will be listened to exactly four times.'); | ||
@@ -82,3 +98,3 @@ }); | ||
```javascript | ||
server.onAny(function(event, value) { | ||
server.onAny(function(value) { | ||
console.log('This event will be listened to exactly four times.'); | ||
@@ -93,3 +109,3 @@ }); | ||
```javascript | ||
server.unAny(function(event, value) { | ||
server.unAny(function(value) { | ||
console.log('This event will be listened to exactly four times.'); | ||
@@ -104,3 +120,3 @@ }); | ||
```javascript | ||
server.once('get', function (event, value) { | ||
server.once('get', function (value) { | ||
console.log('Ah, we have our first value!'); | ||
@@ -115,3 +131,3 @@ }); | ||
```javascript | ||
server.many('get', 4, function (event, value) { | ||
server.many('get', 4, function (value) { | ||
console.log('Ah, we have our first value!'); | ||
@@ -128,3 +144,3 @@ }); | ||
```javascript | ||
var callback = function(event, value) { | ||
var callback = function(value) { | ||
console.log('someone connected!'); | ||
@@ -153,3 +169,3 @@ }; | ||
```javascript | ||
server.on('get', function(event, value) { | ||
server.on('get', function(value) { | ||
console.log('someone connected!'); | ||
@@ -165,3 +181,3 @@ }); | ||
```javascript | ||
server.onAny(function(event, value) { | ||
server.onAny(function(value) { | ||
console.log('someone connected!'); | ||
@@ -168,0 +184,0 @@ }); |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
201
101594
2
19
2760
10