Last active
December 24, 2015 13:09
-
-
Save othiym23/6802613 to your computer and use it in GitHub Desktop.
The things I do to keep event emitters safe...
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
Namespace.prototype.bindEmitter = function (source) { | |
assert.ok(source.on && source.addListener && source.emit, "can only bind real EEs"); | |
var namespace = this; | |
var contextName = 'context@' + this.name; | |
/** | |
* Attach a context to a listener, and make sure that this hook stays | |
* attached to the emitter forevermore. | |
*/ | |
function capturer(on) { | |
return function captured(event, listener) { | |
listener[contextName] = namespace.active; | |
try { | |
return on.call(this, event, listener); | |
} | |
finally { | |
// old-style streaming overwrites .on and .addListener, so rewrap | |
if (!this.on.__wrapped) shimmer.wrap(this, 'on', capturer); | |
if (!this.addListener.__wrapped) shimmer.wrap(this, 'addListener', capturer); | |
} | |
}; | |
} | |
/** | |
* Evaluate listeners within the CLS contexts in which they were originally | |
* captured. | |
*/ | |
function puncher(emit) { | |
// find all the handlers with attached contexts | |
function prepare(unwrapped) { | |
if (typeof unwrapped === 'function' && unwrapped[contextName]) { | |
return namespace.bind(unwrapped, unwrapped[contextName]); | |
} | |
else if (unwrapped && unwrapped.length) { | |
var replacements = []; | |
for (var i = 0; i < unwrapped.length; i++) { | |
var handler = unwrapped[i]; | |
var context = handler[contextName]; | |
if (context) handler = namespace.bind(handler, context); | |
replacements[i] = handler; | |
} | |
return replacements; | |
} | |
else { | |
return unwrapped; | |
} | |
} | |
return function punched(event) { | |
if (!this._events || !this._events[event]) return emit.apply(this, arguments); | |
// wrap | |
var unwrapped = this._events[event]; | |
function releaser(removeListener) { | |
return function unwrapRemove() { | |
this._events[event] = unwrapped; | |
try { | |
return removeListener.apply(this, arguments); | |
} | |
finally { | |
unwrapped = this._events[event]; | |
this._events[event] = prepare(unwrapped); | |
} | |
}; | |
} | |
shimmer.wrap(this, 'removeListener', releaser); | |
this._events[event] = prepare(unwrapped); | |
try { | |
// apply | |
return emit.apply(this, arguments); | |
} | |
finally { | |
// reset | |
shimmer.unwrap(this, 'removeListener'); | |
this._events[event] = unwrapped; | |
} | |
}; | |
} | |
shimmer.wrap(source, 'addListener', capturer); | |
shimmer.wrap(source, 'on', capturer); | |
shimmer.wrap(source, 'emit', puncher); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment