continuation-local-storage
Advanced tools
Comparing version 2.2.1 to 2.3.0
'use strict'; | ||
var assert = require('assert'); | ||
var wrap = require('shimmer').wrap; | ||
@@ -83,2 +84,62 @@ // load polyfill if native support is unavailable | ||
Namespace.prototype.bindEmitter = function (source) { | ||
assert.ok(source.on && source.addListener && source.emit, "can only bind real EEs"); | ||
var namespace = this; | ||
var contextName = '__' + this.name; | ||
function capturer(on) { | ||
return function (event, listener) { | ||
listener[contextName] = namespace.active; | ||
var returned = on.call(this, event, listener); | ||
// FIXME: ReadableStreams overwrite on / addListener; find out why | ||
wrap(this, 'on', capturer); | ||
wrap(this, 'addListener', capturer); | ||
return returned; | ||
}; | ||
} | ||
function prepare(handlers) { | ||
var replacements = []; | ||
for (var i = 0; i < handlers.length; i++) { | ||
var handler = handlers[i]; | ||
if (handler[contextName]) { | ||
replacements.push(namespace.bind(handler, handler[contextName])); | ||
} | ||
else { | ||
replacements.push(handler); | ||
} | ||
} | ||
return replacements; | ||
} | ||
function puncher(emit) { | ||
return function (event) { | ||
if (!this._events[event]) return emit.apply(this, arguments); | ||
// setup | ||
var events = this._events[event]; | ||
if (typeof events === 'function' && events[contextName]) { | ||
this._events[event] = namespace.bind(events, events[contextName]); | ||
} | ||
else if (events.length) { | ||
this._events[event] = prepare(events); | ||
} | ||
// application | ||
var returned = emit.apply(this, arguments); | ||
this._events[event] = events; | ||
return returned; | ||
}; | ||
} | ||
wrap(source, 'addListener', capturer); | ||
wrap(source, 'on', capturer); | ||
wrap(source, 'emit', puncher); | ||
}; | ||
function get(name) { | ||
@@ -85,0 +146,0 @@ return namespaces[name]; |
{ | ||
"name": "continuation-local-storage", | ||
"version": "2.2.1", | ||
"version": "2.3.0", | ||
"description": "userland implementation of https://github.com/joyent/node/issues/5243", | ||
@@ -35,3 +35,6 @@ "main": "context.js", | ||
"async-listener": ">=0.1.2" | ||
}, | ||
"dependencies": { | ||
"shimmer": "~0.7" | ||
} | ||
} |
@@ -189,2 +189,22 @@ # Continuation-Local Storage | ||
### namespace.bindEmitter(emitter) | ||
Bind an EventEmitter to a namespace. Operates similarly to `domain.add`, with a | ||
less generic name and the additional caveat that unlike domains, namespaces | ||
never implicitly bind EventEmitters to themselves when they're created within | ||
the context of an active namespace. | ||
The most likely time you'd want to use this is when you're using Express or | ||
Connect and want to make sure your middleware execution plays nice with CLS, or | ||
are doing other things with HTTP listeners: | ||
```javascript | ||
http.createServer(function (req, res) { | ||
writer.add(req); | ||
writer.add(rew); | ||
// do other stuff, some of which is asynchronous | ||
}); | ||
``` | ||
### namespace.createContext() | ||
@@ -191,0 +211,0 @@ |
'use strict'; | ||
var test = require('tap').test | ||
, EventEmitter = require('events').EventEmitter | ||
, cls = require('../context.js') | ||
; | ||
function fresh(name, context) { | ||
context.tearDown(function () { | ||
cls.destroyNamespace(name); | ||
}); | ||
return cls.createNamespace(name); | ||
} | ||
test("event emitters bound to CLS context", function (t) { | ||
t.plan(3); | ||
t.test("handler registered in context", function (t) { | ||
t.plan(1); | ||
var n = fresh('in', this) | ||
, ee = new EventEmitter() | ||
; | ||
n.run(function () { | ||
n.set('value', 'hello'); | ||
n.bindEmitter(ee); | ||
ee.on('event', function () { | ||
t.equal(n.get('value'), 'hello', "value still set in EE."); | ||
}); | ||
}); | ||
ee.emit('event'); | ||
}); | ||
t.test("handler registered out of context", function (t) { | ||
t.plan(1); | ||
var n = fresh('out', this) | ||
, ee = new EventEmitter() | ||
; | ||
ee.on('event', function () { | ||
t.equal(n.get('value'), 'hello', "value still set in EE."); | ||
}); | ||
n.run(function () { | ||
n.set('value', 'hello'); | ||
n.bindEmitter(ee); | ||
ee.emit('event'); | ||
}); | ||
}); | ||
t.test("handler added but used entirely out of context", function (t) { | ||
t.plan(1); | ||
var n = fresh('none', this) | ||
, ee = new EventEmitter() | ||
; | ||
ee.on('event', function () { | ||
t.notOk(n.get('value'), "value shouldn't be visible"); | ||
}); | ||
n.run(function () { | ||
n.set('value', 'hello'); | ||
n.bindEmitter(ee); | ||
}); | ||
ee.emit('event'); | ||
}); | ||
}); |
72154
1694
240
2
+ Addedshimmer@~0.7
+ Addedshimmer@0.7.3(transitive)