Index: lib/elemHide.js |
diff --git a/lib/elemHide.js b/lib/elemHide.js |
index 2c81a2324f579247d53eca5eeb6ac459210a937a..c3df791db5e5b8420560e90b796bdfd37c254f5b 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,26 @@ var usingGetSelectorsForDomain = !("nsIStyleSheetService" in Ci); |
var filtersByDomain = Object.create(null); |
/** |
- * Lookup table, filters by selector. (Only contains filters that have a |
+ * Lookup table, filters key by selector. (Only contains filters that have a |
* selector that is unconditionally matched for all domains.) |
*/ |
-var filtersBySelector = Object.create(null); |
+var filterKeyBySelector = Object.create(null); |
/** |
- * This array caches the keys of filtersBySelector table (selectors which |
+ * This array caches the keys of filterKeyBySelector 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 filterKeyBySelector table (filterIds for |
+ * selectors which unconditionally apply on all domains). It will be null if the |
+ * cache needs to be rebuilt. |
+ */ |
+var unconditionalFilterKeys = null; |
+ |
+/** |
* Object to be used instead when a filter has a blank domains property. |
*/ |
var defaultDomains = Object.create(null); |
@@ -95,16 +94,15 @@ var ElemHide = exports.ElemHide = |
filterByKey = []; |
keyByFilter = Object.create(null); |
filtersByDomain = Object.create(null); |
- filtersBySelector = Object.create(null); |
- unconditionalSelectors = null; |
+ filterKeyBySelector = 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 +133,15 @@ 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 filterKey = filterKeyBySelector[selector]; |
+ if (filterKey) |
{ |
- // 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; |
- } |
+ this._addToFiltersByDomain(filterKey, filterByKey[filterKey]); |
+ delete filterKeyBySelector[selector]; |
+ unconditionalSelectors = unconditionalFilterKeys = null; |
} |
knownExceptions[filter.text] = true; |
@@ -160,27 +154,16 @@ 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 filters = filtersBySelector[filter.selector]; |
- if (filters) |
- { |
- filters.push(filter); |
- } |
- else |
- { |
- filtersBySelector[filter.selector] = [filter]; |
- unconditionalSelectors = null; |
- } |
- } |
- else |
- { |
- // The new filter's selector only applies to some domains |
- this._addToFiltersByDomain(filter); |
- } |
+ // The new filter's selector is unconditionally applied to all domains |
+ filterKeyBySelector[filter.selector] = key; |
+ unconditionalSelectors = unconditionalFilterKeys = null; |
+ } |
+ else |
+ { |
+ // The new filter's selector only applies to some domains |
+ this._addToFiltersByDomain(key, filter); |
} |
} |
@@ -213,31 +196,19 @@ var ElemHide = exports.ElemHide = |
delete filterByKey[key]; |
delete keyByFilter[filter.text]; |
- if (usingGetSelectorsForDomain) |
+ if (filter.selector in filterKeyBySelector) |
{ |
- let filters = filtersBySelector[filter.selector]; |
- if (filters) |
- { |
- if (filters.length > 1) |
- { |
- let index = filters.indexOf(filter); |
- filters.splice(index, 1); |
- } |
- else |
- { |
- delete filtersBySelector[filter.selector]; |
- unconditionalSelectors = null; |
- } |
- } |
- else |
+ delete filterKeyBySelector[filter.selector]; |
+ unconditionalSelectors = unconditionalFilterKeys = null; |
+ } |
+ else |
+ { |
+ let domains = filter.domains || defaultDomains; |
+ for (let domain in domains) |
{ |
- let domains = filter.domains || defaultDomains; |
- for (let domain in domains) |
- { |
- let filters = filtersByDomain[domain]; |
- if (filters) |
- delete filters[key]; |
- } |
+ let filters = filtersByDomain[domain]; |
+ if (filters) |
+ delete filters[key]; |
} |
} |
} |
@@ -265,7 +236,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,17 +269,50 @@ 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(filterKeyBySelector); |
+ 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(filterKeyBySelector[selector]); |
+ } |
+ 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. |
+ */ |
+ getSelectorsForDomain: function(/**String*/ domain, /**Boolean*/ specificOnly, |
+ /**Boolean*/ noUnconditional, |
+ /**Boolean*/ provideFilterKeys) |
+ { |
+ let filterKeys = []; |
+ let selectors = []; |
+ if (!specificOnly && !noUnconditional) |
+ { |
+ selectors = this.getUnconditionalSelectors(); |
+ if (provideFilterKeys) |
+ filterKeys = this.getUnconditionalFilterKeys(); |
+ } |
let seenFilters = Object.create(null); |
let currentDomain = domain ? domain.toUpperCase() : ""; |
@@ -328,7 +332,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 +347,9 @@ var ElemHide = exports.ElemHide = |
currentDomain = nextDot == -1 ? "" : currentDomain.substr(nextDot + 1); |
} |
- return selectors; |
+ if (provideFilterKeys) |
+ return [selectors, filterKeys]; |
+ else |
+ return selectors; |
} |
}; |