Bug 982322 - Part 5: Delay node registrations. r=ochameau

This commit is contained in:
"J. Ryan Stinnett" 2014-03-17 12:06:00 +01:00
parent 8ccc9f5e7c
commit 2de747a346

View File

@ -70,6 +70,8 @@ function Template(root, store, l10nResolver) {
this._root = root;
this._doc = this._root.ownerDocument;
this._queuedNodeRegistrations = [];
this._storeChanged = this._storeChanged.bind(this);
this._store.on("set", this._storeChanged);
}
@ -77,6 +79,7 @@ function Template(root, store, l10nResolver) {
Template.prototype = {
start: function() {
this._processTree(this._root);
this._registerQueuedNodes();
},
destroy: function() {
@ -99,6 +102,8 @@ Template.prototype = {
this._invalidate(registeredPath);
}
}
this._registerQueuedNodes();
},
_invalidate: function(path) {
@ -127,24 +132,36 @@ Template.prototype = {
}
},
_registerNode: function(path, element) {
// Delay node registration until the last step of starting / updating the UI.
// This allows us to avoid doing double work in _storeChanged where the first
// call to |_invalidate| registers new nodes, which would then be visited a
// second time when it iterates over node listeners.
_queueNodeRegistration: function(path, element) {
this._queuedNodeRegistrations.push([path, element]);
},
// We map a node to a path.
// If the value behind this path is updated,
// we get notified from the ObjectEmitter,
// and then we know which objects to update.
if (!this._nodeListeners.has(path)) {
this._nodeListeners.set(path, new Set());
_registerQueuedNodes: function() {
for (let [path, element] of this._queuedNodeRegistrations) {
// We map a node to a path.
// If the value behind this path is updated,
// we get notified from the ObjectEmitter,
// and then we know which objects to update.
if (!this._nodeListeners.has(path)) {
this._nodeListeners.set(path, new Set());
}
let set = this._nodeListeners.get(path);
set.add(element);
}
let set = this._nodeListeners.get(path);
set.add(element);
this._queuedNodeRegistrations.length = 0;
},
_unregisterNodes: function(nodes) {
for (let e of nodes) {
for (let registeredPath of e.registeredPaths) {
let set = this._nodeListeners.get(registeredPath);
if (!set) {
continue;
}
set.delete(e);
if (set.size === 0) {
this._nodeListeners.delete(registeredPath);
@ -195,8 +212,8 @@ Template.prototype = {
}
// paths is an array that will store all the paths we needed
// to expand the node. We will then, via _registerNode, link
// this element to these paths.
// to expand the node. We will then, via
// _registerQueuedNodes, link this element to these paths.
let paths = [];
@ -239,7 +256,7 @@ Template.prototype = {
}
if (paths.length > 0) {
for (let path of paths) {
this._registerNode(path, e);
this._queueNodeRegistration(path, e);
}
}
// Store all the paths on the node, to speed up unregistering later