-
Notifications
You must be signed in to change notification settings - Fork 459
Expand file tree
/
Copy pathdoc-presence-emitter.js
More file actions
75 lines (61 loc) · 2.2 KB
/
doc-presence-emitter.js
File metadata and controls
75 lines (61 loc) · 2.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
var util = require('../../util');
var EventEmitter = require('events').EventEmitter;
var EVENTS = [
'create',
'del',
'destroy',
'load',
'op'
];
module.exports = DocPresenceEmitter;
function DocPresenceEmitter() {
this._docs = Object.create(null);
this._forwarders = Object.create(null);
this._emitters = Object.create(null);
}
DocPresenceEmitter.prototype.addEventListener = function(doc, event, listener) {
this._registerDoc(doc);
var emitter = util.dig(this._emitters, doc.collection, doc.id);
emitter.on(event, listener);
};
DocPresenceEmitter.prototype.removeEventListener = function(doc, event, listener) {
var emitter = util.dig(this._emitters, doc.collection, doc.id);
if (!emitter) return;
emitter.off(event, listener);
// We'll always have at least one, because of the destroy listener
if (emitter._eventsCount === 1) this._unregisterDoc(doc);
};
DocPresenceEmitter.prototype._registerDoc = function(doc) {
var alreadyRegistered = true;
util.digOrCreate(this._docs, doc.collection, doc.id, function() {
alreadyRegistered = false;
return doc;
});
if (alreadyRegistered) return;
var emitter = util.digOrCreate(this._emitters, doc.collection, doc.id, function() {
var e = new EventEmitter();
// Set a high limit to avoid unnecessary warnings, but still
// retain some degree of memory leak detection
e.setMaxListeners(1000);
return e;
});
var self = this;
EVENTS.forEach(function(event) {
var forwarder = util.digOrCreate(self._forwarders, doc.collection, doc.id, event, function() {
return emitter.emit.bind(emitter, event);
});
doc.on(event, forwarder);
});
this.addEventListener(doc, 'destroy', this._unregisterDoc.bind(this, doc));
};
DocPresenceEmitter.prototype._unregisterDoc = function(doc) {
var forwarders = util.dig(this._forwarders, doc.collection, doc.id);
for (var event in forwarders) {
doc.off(event, forwarders[event]);
}
var emitter = util.dig(this._emitters, doc.collection, doc.id);
emitter.removeAllListeners();
util.digAndRemove(this._forwarders, doc.collection, doc.id);
util.digAndRemove(this._emitters, doc.collection, doc.id);
util.digAndRemove(this._docs, doc.collection, doc.id);
};