Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: lib/elemHide.js

Issue 29342830: Issue 4057 - Further speedup ElemHide.getSelectorsforDomain (Closed)
Patch Set: Addressed nits Created May 25, 2016, 10:50 a.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | test/elemHide.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/elemHide.js
diff --git a/lib/elemHide.js b/lib/elemHide.js
index 574ef91dff6340a1e9408571fef1b31726cec78c..ee309d1d4a823b798804f41693dc97c22236d598 100644
--- a/lib/elemHide.js
+++ b/lib/elemHide.js
@@ -40,17 +40,32 @@ var filterByKey = [];
var keyByFilter = Object.create(null);
/**
- * Nested lookup table, filter (or false if inactive) by filter text by domain
+ * Indicates whether we are using the getSelectorsForDomain function and
+ * therefore mainting the required filtersByDomain, filtersBySelector and
+ * unconditionalSelectors lookups. (Will be false for Firefox)
+ * @type Boolean
+ */
+var usingGetSelectorsForDomain = !("nsIStyleSheetService" in Ci);
+
+/**
+ * Nested lookup table, filter (or false if inactive) by filter key by domain.
+ * (Only contains filters that aren't unconditionally matched for all domains.)
* @type Object
*/
var filtersByDomain = Object.create(null);
/**
- * Indicates whether we are using (and maintaining) the filtersByDomain lookup.
- * (Will be false for Firefox)
- * @type Boolean
+ * Lookup table, filters by selector. (Only contains filters that have a
+ * selector that is unconditionally matched for all domains.)
*/
-var usingFiltersByDomain = !("nsIStyleSheetService" in Ci);
+var filtersBySelector = Object.create(null);
+
+/**
+ * This array caches the keys of filtersBySelector table (selectors which
+ * unconditionally apply on all domains). It will be null if the cache needs to
+ * be rebuilt.
+ */
+var unconditionalSelectors = null;
/**
* Object to be used instead when a filter has a blank domains property.
@@ -119,12 +134,31 @@ var ElemHide = exports.ElemHide =
filterByKey = [];
keyByFilter = Object.create(null);
filtersByDomain = Object.create(null);
+ filtersBySelector = Object.create(null);
+ unconditionalSelectors = null;
knownExceptions = Object.create(null);
exceptions = Object.create(null);
ElemHide.isDirty = false;
ElemHide.unapply();
},
+ _addToFiltersByDomain: function(filter)
+ {
+ let key = keyByFilter[filter.text];
+ let domains = filter.domains || defaultDomains;
+ for (let domain in domains)
+ {
+ let filters = filtersByDomain[domain];
+ if (!filters)
+ filters = filtersByDomain[domain] = Object.create(null);
+
+ if (domains[domain])
+ filters[key] = filter;
+ else
+ filters[key] = false;
+ }
+ },
+
/**
* Add a new element hiding filter
* @param {ElemHideFilter} filter
@@ -140,6 +174,22 @@ var ElemHide = exports.ElemHide =
if (!(selector in exceptions))
exceptions[selector] = [];
exceptions[selector].push(filter);
+
+ if (usingGetSelectorsForDomain)
+ {
+ // If this is the first exception for a previously unconditionally
+ // applied element hiding selector we need to take care to update the
+ // lookups.
+ let unconditionalFilters = filtersBySelector[selector];
+ if (unconditionalFilters)
+ {
+ for (let f of unconditionalFilters)
+ this._addToFiltersByDomain(f);
+ delete filtersBySelector[selector];
+ unconditionalSelectors = null;
+ }
+ }
+
knownExceptions[filter.text] = true;
}
else
@@ -150,19 +200,26 @@ var ElemHide = exports.ElemHide =
let key = filterByKey.push(filter) - 1;
keyByFilter[filter.text] = key;
- if (usingFiltersByDomain)
+ if (usingGetSelectorsForDomain)
{
- let domains = filter.domains || defaultDomains;
- for (let domain in domains)
+ if (!(filter.domains || filter.selector in exceptions))
{
- let filters = filtersByDomain[domain];
- if (!filters)
- filters = filtersByDomain[domain] = Object.create(null);
-
- if (domains[domain])
- filters[filter.text] = filter;
+ // The new filter's selector is unconditionally applied to all domains
+ let filters = filtersBySelector[filter.selector];
+ if (filters)
+ {
+ filters.push(filter);
+ }
else
- filters[filter.text] = false;
+ {
+ filtersBySelector[filter.selector] = [filter];
+ unconditionalSelectors = null;
+ }
+ }
+ else
+ {
+ // The new filter's selector only applies to some domains
+ this._addToFiltersByDomain(filter);
}
}
@@ -197,14 +254,31 @@ var ElemHide = exports.ElemHide =
delete keyByFilter[filter.text];
ElemHide.isDirty = true;
- if (usingFiltersByDomain)
+ if (usingGetSelectorsForDomain)
{
- let domains = filter.domains || defaultDomains;
- for (let domain in domains)
+ let filters = filtersBySelector[filter.selector];
+ if (filters)
{
- let filters = filtersByDomain[domain];
- if (filters)
- delete filters[filter.text];
+ if (filters.length > 1)
+ {
+ let index = filters.indexOf(filter);
+ filters.splice(index, 1);
+ }
+ else
+ {
+ delete filtersBySelector[filter.selector];
+ unconditionalSelectors = null;
+ }
+ }
+ else
+ {
+ let domains = filter.domains || defaultDomains;
+ for (let domain in domains)
+ {
+ let filters = filtersByDomain[domain];
+ if (filters)
+ delete filters[key];
+ }
}
}
}
@@ -416,14 +490,16 @@ var ElemHide = exports.ElemHide =
/**
* Returns a list of all selectors active on a particular domain, must not be
- * used in Firefox (when usingFiltersByDomain is false).
+ * used in Firefox (when usingGetSelectorsForDomain is false).
*/
getSelectorsForDomain: function(/**String*/ domain, /**Boolean*/ specificOnly)
{
- if (!usingFiltersByDomain)
+ if (!usingGetSelectorsForDomain)
throw new Error("getSelectorsForDomain can not be used in Firefox!");
- let selectors = [];
+ if (!unconditionalSelectors)
+ unconditionalSelectors = Object.keys(filtersBySelector);
+ let selectors = specificOnly ? [] : unconditionalSelectors.slice();
let seenFilters = Object.create(null);
let currentDomain = domain ? domain.toUpperCase() : "";
@@ -435,13 +511,13 @@ var ElemHide = exports.ElemHide =
let filters = filtersByDomain[currentDomain];
if (filters)
{
- for (let filterText in filters)
+ for (let filterKey in filters)
{
- if (filterText in seenFilters)
+ if (filterKey in seenFilters)
continue;
- seenFilters[filterText] = true;
+ seenFilters[filterKey] = true;
- let filter = filters[filterText];
+ let filter = filters[filterKey];
if (filter && !this.getException(filter, domain))
selectors.push(filter.selector);
}
« no previous file with comments | « no previous file | test/elemHide.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld