Created
September 17, 2012 19:28
-
-
Save dsc/3739267 to your computer and use it in GitHub Desktop.
events.co
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Technically, this is Coco, not CoffeeScript, but close enough. | |
{ toString:objToString } = Object:: | |
isArray = Array.isArray or (o) -> objToString.call(o) is '[object Array]' | |
slice = [].slice | |
class exports.EventEmitter | |
emit: (type) -> | |
arg = arguments[1] | |
if type is 'error' and | |
not @_events?.error or | |
( isArray(@_events.error) and not @_events.error.length ) | |
if arg instanceof Error | |
throw arg # Unhandled 'error' event | |
else | |
throw new Error("Uncaught, unspecified 'error' event.") | |
return false | |
queue = @_events?[type] | |
if typeof queue is 'function' | |
listener = queue | |
switch arguments.length | |
# fast cases | |
case 1 then listener.call this | |
case 2 then listener.call this, arg | |
case 3 then listener.call this, arg, arguments[2] | |
# slower | |
default then listener.apply this, slice.call(arguments, 1) | |
else if isArray queue | |
args = slice.call(arguments, 1) | |
listener.apply(this, args) for listener of queue | |
else | |
return false | |
return true | |
trigger: -> | |
@emit ... | |
on: (type, listener) -> | |
if typeof listener is not 'function' | |
throw new TypeError "addListener only takes instances of Function" | |
@emit 'newListener', type, listener | |
events = @_events or= {} | |
if not events[type] | |
events[type] = listener | |
else if not isArray events[type] | |
# Upgrade single listener to Array | |
events[type] = [ events[type], listener ] | |
else | |
# Copy now to avoid copying on emit (which is way more common) | |
( events[type] = events[type].slice() ).push(listener) | |
return this | |
addListener: -> | |
@on ... | |
off: (type, listener) -> | |
if typeof listener is not 'function' | |
throw new TypeError "addListener only takes instances of Function" | |
queue = @_events?[type] | |
return this unless queue | |
if typeof queue is 'function' | |
if queue is listener or queue.listener is listener | |
delete @_events[type] | |
return this | |
idx = -1 | |
for fn, i of queue | |
if fn is listener or (fn.listener is listener) | |
idx = i | |
break | |
return this if idx < 0 | |
if queue.length is 1 | |
delete @_events[type] | |
else | |
queue = @_events[type] = queue.slice() | |
queue.splice idx, 1 | |
return this | |
removeListener: -> | |
@off ... | |
removeAllListeners: (type) -> | |
if arguments.length is 0 | |
@_events = {} | |
return this | |
delete @_events[type] if @_events?[type] | |
return this | |
once: (type, listener) -> | |
if typeof listener is not 'function' | |
throw new TypeError "once only takes instances of Function" | |
self = this | |
_once = -> | |
self.removeListener type, _once | |
listener ... | |
void | |
_once.listener = listener | |
return @on type, _once | |
listeners: (type) -> | |
events = @_events or= {} | |
queue = events[type] or= [] | |
queue = events[type] = [events[type]] unless isArray queue | |
return queue | |
setMaxListeners: (n) -> | |
console.debug 'setMaxListeners is unsupported' | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment