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

Unified Diff: lib/elemHide.js

Issue 29349187: Issue 4167 - getSelectorsForDomain criteria + keys (Closed)
Patch Set: Further improve tests Created Sept. 20, 2016, 2:42 p.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 2c81a2324f579247d53eca5eeb6ac459210a937a..1ca6f7910a2d3cd8953a05c4bebb0e0af001c5ef 100644
--- a/lib/elemHide.js
+++ b/lib/elemHide.js
@@ -36,14 +36,6 @@ var filterByKey = [];
var keyByFilter = Object.create(null);
/**
- * 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
@@ -51,19 +43,27 @@ var usingGetSelectorsForDomain = !("nsIStyleSheetService" in Ci);
var filtersByDomain = Object.create(null);
/**
- * Lookup table, filters by selector. (Only contains filters that have a
+ * Lookup table, filter keys by selector. (Only contains filters that have a
* selector that is unconditionally matched for all domains.)
*/
-var filtersBySelector = Object.create(null);
+var filterKeysBySelector = Object.create(null);
/**
- * This array caches the keys of filtersBySelector table (selectors which
+ * This array caches the keys of filterKeysBySelector table (selectors which
* unconditionally apply on all domains). It will be null if the cache needs to
* be rebuilt.
*/
var unconditionalSelectors = null;
/**
+ * This array caches the values of filterKeysBySelector table (filterIds for
+ * selectors which unconditionally apply on all domains). It will be null if the
+ * cache needs to be rebuilt. Note: Only the first filter key for each selector
+ * is cached.
+ */
+var unconditionalFilterKeys = null;
+
+/**
* Object to be used instead when a filter has a blank domains property.
*/
var defaultDomains = Object.create(null);
@@ -95,16 +95,15 @@ var ElemHide = exports.ElemHide =
filterByKey = [];
keyByFilter = Object.create(null);
filtersByDomain = Object.create(null);
- filtersBySelector = Object.create(null);
- unconditionalSelectors = null;
+ filterKeysBySelector = Object.create(null);
+ unconditionalSelectors = unconditionalFilterKeys = null;
knownExceptions = Object.create(null);
exceptions = Object.create(null);
FilterNotifier.emit("elemhideupdate");
},
- _addToFiltersByDomain: function(filter)
+ _addToFiltersByDomain: function(key, filter)
{
- let key = keyByFilter[filter.text];
let domains = filter.domains || defaultDomains;
for (let domain in domains)
{
@@ -135,19 +134,16 @@ var ElemHide = exports.ElemHide =
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 filterKeys = filterKeysBySelector[selector];
+ if (filterKeys)
{
- // 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;
- }
+ for (let filterKey of filterKeys)
+ this._addToFiltersByDomain(filterKey, filterByKey[filterKey]);
+ delete filterKeysBySelector[selector];
+ unconditionalSelectors = unconditionalFilterKeys = null;
}
knownExceptions[filter.text] = true;
@@ -160,28 +156,25 @@ var ElemHide = exports.ElemHide =
let key = filterByKey.push(filter) - 1;
keyByFilter[filter.text] = key;
- if (usingGetSelectorsForDomain)
+ if (!(filter.domains || filter.selector in exceptions))
{
- if (!(filter.domains || filter.selector in exceptions))
+ // The new filter's selector is unconditionally applied to all domains
+ let filterKeys = filterKeysBySelector[filter.selector];
+ if (filterKeys)
{
- // The new filter's selector is unconditionally applied to all domains
- let filters = filtersBySelector[filter.selector];
- if (filters)
- {
- filters.push(filter);
- }
- else
- {
- filtersBySelector[filter.selector] = [filter];
- unconditionalSelectors = null;
- }
+ filterKeys.push(key);
}
else
{
- // The new filter's selector only applies to some domains
- this._addToFiltersByDomain(filter);
+ filterKeysBySelector[filter.selector] = [key];
+ unconditionalSelectors = unconditionalFilterKeys = null;
}
}
+ else
+ {
+ // The new filter's selector only applies to some domains
+ this._addToFiltersByDomain(key, filter);
+ }
}
FilterNotifier.emit("elemhideupdate");
@@ -213,31 +206,42 @@ var ElemHide = exports.ElemHide =
delete filterByKey[key];
delete keyByFilter[filter.text];
- if (usingGetSelectorsForDomain)
+ let unconditional = !(filter.domains || filter.selector in exceptions);
+ if (unconditional)
{
- let filters = filtersBySelector[filter.selector];
- if (filters)
+ let filterKeys = filterKeysBySelector[filter.selector];
+ if (filterKeys)
{
- if (filters.length > 1)
+ if (filterKeys.length > 1)
{
- let index = filters.indexOf(filter);
- filters.splice(index, 1);
+ let index = filterKeys.indexOf(key);
+ filterKeys.splice(index, 1);
Wladimir Palant 2016/09/20 16:31:14 index should be positive but if we ever have a bug
kzar 2016/09/20 18:37:35 Done.
+ if (index == 0)
+ unconditionalFilterKeys = null;
}
else
{
- delete filtersBySelector[filter.selector];
- unconditionalSelectors = null;
+ delete filterKeysBySelector[filter.selector];
+ unconditionalSelectors = unconditionalFilterKeys = null;
}
}
else
{
- let domains = filter.domains || defaultDomains;
- for (let domain in domains)
- {
- let filters = filtersByDomain[domain];
- if (filters)
- delete filters[key];
- }
+ // Even if this filter appears unconditional its selector might not
+ // be. In that case we need to take care to remove it from
+ // filtersByDomain instead.
Wladimir Palant 2016/09/20 16:31:14 This comment makes little sense, should really be
kzar 2016/09/20 18:37:35 Done.
+ unconditional = false;
+ }
+ }
+
+ if (!unconditional)
+ {
+ let domains = filter.domains || defaultDomains;
+ for (let domain in domains)
+ {
+ let filters = filtersByDomain[domain];
+ if (filters)
+ delete filters[key];
}
}
}
@@ -265,7 +269,7 @@ var ElemHide = exports.ElemHide =
/**
* Retrieves an element hiding filter by the corresponding protocol key
*/
- getFilterByKey: function(/**String*/ key) /**Filter*/
+ getFilterByKey: function(/**Number*/ key) /**Filter*/
{
return (key in filterByKey ? filterByKey[key] : null);
},
@@ -298,18 +302,56 @@ var ElemHide = exports.ElemHide =
},
/**
- * Returns a list of all selectors active on a particular domain, must not be
- * used in Firefox (when usingGetSelectorsForDomain is false).
+ * Returns a list of selectors that apply on each website unconditionally.
+ * @returns {String[]}
*/
- getSelectorsForDomain: function(/**String*/ domain, /**Boolean*/ specificOnly)
+ getUnconditionalSelectors: function()
{
- if (!usingGetSelectorsForDomain)
- throw new Error("getSelectorsForDomain can not be used in Firefox!");
-
if (!unconditionalSelectors)
- unconditionalSelectors = Object.keys(filtersBySelector);
- let selectors = specificOnly ? [] : unconditionalSelectors.slice();
+ unconditionalSelectors = Object.keys(filterKeysBySelector);
+ return unconditionalSelectors.slice();
+ },
+ /**
+ * Returns a list of all selectors active on a particular domain.
+ * Returns a list of filterKeys for selectors that apply on each website
+ * unconditionally.
+ * @returns {Number[]}
+ */
+ getUnconditionalFilterKeys: function()
+ {
+ if (!unconditionalFilterKeys)
+ {
+ let selectors = this.getUnconditionalSelectors();
+ unconditionalFilterKeys = [];
+ for (let selector of selectors)
+ unconditionalFilterKeys.push(filterKeysBySelector[selector][0]);
+ }
+ return unconditionalFilterKeys.slice();
+ },
+
+ /**
+ * Returns a list of all selectors active on a particular domain. Optionally
+ * a list of corresponding filter keys for the selectors can be returned too.
+ * The optional criteria parameter restricts the results as follows:
+ * 0 - All selectors allowed (default)
+ * 1 - No unconditionally matching selectors allowed
+ * 2 - Only specifically matching selectors allowed
Wladimir Palant 2016/09/20 16:31:14 No magic numbers please, these should be exposed a
kzar 2016/09/20 18:37:35 Done.
+ */
+ getSelectorsForDomain: function(/**String*/ domain,
+ /**Number*/ criteria,
+ /**Boolean*/ provideFilterKeys)
+ {
+ let filterKeys = [];
+ let selectors = [];
+ if (!criteria)
Wladimir Palant 2016/09/20 16:31:14 Should be something like: if (typeof criteria =
kzar 2016/09/20 18:37:35 Done.
+ {
+ selectors = this.getUnconditionalSelectors();
+ if (provideFilterKeys)
+ filterKeys = this.getUnconditionalFilterKeys();
+ }
+
+ let specificOnly = criteria == 2;
Wladimir Palant 2016/09/20 16:31:14 Should be something like: let specificOnly = (c
kzar 2016/09/20 18:37:35 Done.
let seenFilters = Object.create(null);
let currentDomain = domain ? domain.toUpperCase() : "";
while (true)
@@ -328,7 +370,11 @@ var ElemHide = exports.ElemHide =
let filter = filters[filterKey];
if (filter && !this.getException(filter, domain))
+ {
selectors.push(filter.selector);
+ // It is faster to always push the key, even if not required.
+ filterKeys.push(filterKey);
+ }
}
}
@@ -339,6 +385,9 @@ var ElemHide = exports.ElemHide =
currentDomain = nextDot == -1 ? "" : currentDomain.substr(nextDot + 1);
}
- return selectors;
+ if (provideFilterKeys)
+ return [selectors, filterKeys.map(key => parseInt(key, 10))];
Wladimir Palant 2016/09/20 16:31:14 Keys are opaque to the caller, we used to have str
kzar 2016/09/20 18:37:35 Done.
+ else
+ return selectors;
}
};
« 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