-
Notifications
You must be signed in to change notification settings - Fork 0
/
done-mutation-observer.js
123 lines (104 loc) · 3.22 KB
/
done-mutation-observer.js
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
var installCharacterData = require("./characterData");
var installChildList = require("./childList");
var installAttributes = require("./attributes");
var MutationRecord = require("./mutation-record");
var mutationObserverSymbol = Symbol.for("done.MutationObserver");
var onCharacterDataSymbol = Symbol.for("done.onCharacterData");
var onChildListSymbol = Symbol.for("done.onChildList");
var onAttributeSymbol = Symbol.for("done.onAttribute");
var asap = Promise.resolve().then.bind(Promise.resolve());
exports.addMutationObserver = function(window) {
var Node = window.Node;
var Element = window.Element;
console.assert(Node, "Cannot install MutationObserver on a window without [Node]");
console.assert(Element, "Cannot install MutationObserver on a window without [Element]");
function MutationObserver(callback) {
this.options = null;
this.root = null;
this.callback = callback;
this.records = [];
this._enqueued = false;
this._connected = false;
}
MutationObserver.prototype.observe = function(root, options) {
this.root = root;
this.options = options;
window[mutationObserverSymbol].add(this);
this._connected = true;
};
MutationObserver.prototype.disconnect = function(){
window[mutationObserverSymbol].delete(this);
this._connected = false;
};
MutationObserver.prototype._enqueue = function(record) {
this.records.push(record);
if(!this._enqueued) {
this._enqueued = true;
asap(function(){
if(!this._connected) {
return;
}
this._enqueued = false;
var records = this.records;
this.records = [];
this.callback.call(this, records);
}.bind(this));
}
};
window.MutationObserver = MutationObserver;
window[mutationObserverSymbol] = new Set();
function enqueue(record) {
var mos = window[mutationObserverSymbol];
var iter = mos[Symbol.iterator]();
var res = iter.next();
while(!res.done) {
var mo = res.value;
if(mo.root.contains(record.target) || mo.root === record.target) {
mo._enqueue(record);
}
res = iter.next();
}
}
window.document[onCharacterDataSymbol] = function(node) {
var record = new MutationRecord();
record.type = "characterData";
record.target = node;
enqueue(record);
};
window.document[onChildListSymbol] = function(parentNode, addedNodes, removedNode) {
var record = new MutationRecord();
record.type = "childList";
record.target = parentNode;
if(addedNodes) {
record.addedNodes = addedNodes;
}
if(removedNode) {
record.removedNodes.push(removedNode);
}
enqueue(record);
};
window.document[onAttributeSymbol] = function(node, attrName) {
var record = new MutationRecord();
record.type = "attributes";
record.target = node;
record.attributeName = attrName;
enqueue(record);
};
// Do not add MutationObserver if already added.
if(!Node[mutationObserverSymbol]) {
Node[mutationObserverSymbol] = [
installCharacterData(Node),
installChildList(Node),
installAttributes(Element)
];
}
return MutationObserver;
};
exports.removeMutationObserver = function(window){
var deregisterFunctions = window.Node[mutationObserverSymbol] || [];
deregisterFunctions.forEach(function(deregister) {
deregister();
});
delete window.Node[mutationObserverSymbol];
delete window.MutationObserver;
};