Index: lib/elemHide.js |
diff --git a/lib/elemHide.js b/lib/elemHide.js |
index 700db132d52c5ee81e90e3f122f6ac701a1d074c..0ed899e99c3f9052c587761f725f751b692a7f8a 100644 |
--- a/lib/elemHide.js |
+++ b/lib/elemHide.js |
@@ -40,17 +40,31 @@ var filterByKey = Object.create(null); |
var keyByFilter = Object.create(null); |
/** |
- * Nested lookup table, filter (or false if inactive) by filter text by domain |
- * @type Object |
+ * Indicates whether we are using getSelectorsByDomain and maintaining the |
+ * required lookup tables. (Will be false for Firefox) |
+ * @type Boolean |
*/ |
-var filtersByDomain = Object.create(null); |
+var usingGetSelectorsByDomain = !("nsIStyleSheetService" in Ci); |
/** |
- * Indicates whether we are using (and maintaining) the filtersByDomain lookup. |
- * (Will be false for Firefox) |
- * @type Boolean |
+ * Lookup table, filter selector by filter ID. |
+ */ |
+var selectorByFilterId = []; |
+ |
+/** |
+ * Lookup table, active filter IDs by domain. |
+ */ |
+var activeFilterIdsByDomain = Object.create(null); |
+ |
+/** |
+ * Lookup table, inactive filter IDs by domain. |
+ */ |
+var inactiveFilterIdsByDomain = Object.create(null); |
+ |
+/** |
+ * Lookup table, filter ID by filter text. |
*/ |
-var usingFiltersByDomain = !("nsIStyleSheetService" in Ci); |
+var filterIdByFilterText = Object.create(null); |
/** |
* Object to be used instead when a filter has a blank domains property. |
@@ -118,7 +132,10 @@ var ElemHide = exports.ElemHide = |
{ |
filterByKey = Object.create(null); |
keyByFilter = Object.create(null); |
- filtersByDomain = Object.create(null); |
+ selectorByFilterId = []; |
+ activeFilterIdsByDomain = Object.create(null); |
+ inactiveFilterIdsByDomain = Object.create(null); |
+ filterIdByFilterText = Object.create(null); |
knownExceptions = Object.create(null); |
exceptions = Object.create(null); |
ElemHide.isDirty = false; |
@@ -155,19 +172,25 @@ var ElemHide = exports.ElemHide = |
filterByKey[key] = filter; |
keyByFilter[filter.text] = key; |
- if (usingFiltersByDomain) |
+ if (usingGetSelectorsByDomain && !(filter.text in filterIdByFilterText)) |
{ |
+ let filterId = selectorByFilterId.push(filter.selector) - 1; |
+ filterIdByFilterText[filter.text] = filterId; |
+ |
let domains = filter.domains || defaultDomains; |
for (let domain in domains) |
{ |
- let filters = filtersByDomain[domain]; |
- if (!filters) |
- filters = filtersByDomain[domain] = Object.create(null); |
- |
+ let lookup; |
if (domains[domain]) |
- filters[filter.text] = filter; |
+ lookup = activeFilterIdsByDomain; |
else |
- filters[filter.text] = false; |
+ lookup = inactiveFilterIdsByDomain; |
+ |
+ let filterIds = lookup[domain]; |
+ if (filterIds == undefined) |
+ filterIds = lookup[domain] = []; |
+ |
+ filterIds.push(filterId); |
} |
} |
@@ -202,14 +225,30 @@ var ElemHide = exports.ElemHide = |
delete keyByFilter[filter.text]; |
ElemHide.isDirty = true; |
- if (usingFiltersByDomain) |
+ if (usingGetSelectorsByDomain) |
{ |
- let domains = filter.domains || defaultDomains; |
- for (let domain in domains) |
+ let filterId = filterIdByFilterText[filter.text]; |
+ if (filterId) |
{ |
- let filters = filtersByDomain[domain]; |
- if (filters) |
- delete filters[filter.text]; |
+ delete filterIdByFilterText[filter.text]; |
+ delete selectorByFilterId[filterId]; |
+ |
+ let domains = filter.domains || defaultDomains; |
+ let filterIdsByDomainLookups = [activeFilterIdsByDomain, |
+ inactiveFilterIdsByDomain]; |
+ for (let domain in domains) |
+ { |
+ for (let filterIdsByDomain of filterIdsByDomainLookups) |
+ { |
+ let lookup = filterIdsByDomain[domain]; |
+ if (lookup) |
+ { |
+ let index = lookup.indexOf(filterId); |
+ if (index != -1) |
+ lookup.splice(index, 1); |
+ } |
+ } |
+ } |
} |
} |
} |
@@ -219,12 +258,12 @@ var ElemHide = exports.ElemHide = |
* Checks whether an exception rule is registered for a filter on a particular |
* domain. |
*/ |
- getException: function(/**Filter*/ filter, /**String*/ docDomain) /**ElemHideException*/ |
+ getException: function(/**String*/ selector, /**String*/ docDomain) /**ElemHideException*/ |
{ |
- if (!(filter.selector in exceptions)) |
+ if (!(selector in exceptions)) |
return null; |
- let list = exceptions[filter.selector]; |
+ let list = exceptions[selector]; |
for (let i = list.length - 1; i >= 0; i--) |
if (list[i].isActiveOnDomain(docDomain)) |
return list[i]; |
@@ -421,30 +460,35 @@ var ElemHide = exports.ElemHide = |
*/ |
getSelectorsForDomain: function(/**String*/ domain, /**Boolean*/ specificOnly) |
{ |
- if (!usingFiltersByDomain) |
+ if (!usingGetSelectorsByDomain) |
throw new Error("getSelectorsForDomain can not be used in Firefox!"); |
let selectors = []; |
- let seenFilters = Object.create(null); |
+ let seenFilterIds = Object.create(null); |
let currentDomain = domain ? domain.toUpperCase() : ""; |
while (true) |
{ |
if (specificOnly && currentDomain == "") |
break; |
- let filters = filtersByDomain[currentDomain]; |
- if (filters) |
+ let inactiveFilterIds = inactiveFilterIdsByDomain[currentDomain]; |
+ if (inactiveFilterIds) |
+ for (let filterId of inactiveFilterIds) |
+ seenFilterIds[filterId] = true; |
+ |
+ let activeFilterIds = activeFilterIdsByDomain[currentDomain]; |
+ if (activeFilterIds) |
{ |
- for (let filterText in filters) |
+ for (let filterId of activeFilterIds) |
{ |
- if (filterText in seenFilters) |
+ if (filterId in seenFilterIds) |
continue; |
- seenFilters[filterText] = true; |
+ seenFilterIds[filterId] = true; |
- let filter = filters[filterText]; |
- if (filter && !this.getException(filter, domain)) |
- selectors.push(filter.selector); |
+ let selector = selectorByFilterId[filterId]; |
+ if (!this.getException(selector, domain)) |
+ selectors.push(selector); |
} |
} |