Index: lib/elemHide.js |
=================================================================== |
--- a/lib/elemHide.js |
+++ b/lib/elemHide.js |
@@ -25,26 +25,20 @@ let {Utils} = require("utils"); |
let {IO} = require("io"); |
let {Prefs} = require("prefs"); |
let {ElemHideException} = require("filterClasses"); |
let {FilterNotifier} = require("filterNotifier"); |
let {AboutHandler} = require("elemHideHitRegistration"); |
let {TimeLine} = require("timeline"); |
/** |
- * Lookup table, filters by their associated key |
+ * List of all filters. Index is used as key. |
* @type Object |
*/ |
-let filterByKey = {__proto__: null}; |
- |
-/** |
- * Lookup table, keys of the filters by filter text |
- * @type Object |
- */ |
-let keyByFilter = {__proto__: null}; |
+let filters = []; |
/** |
* Lookup table, keys are known element hiding exceptions |
* @type Object |
*/ |
let knownExceptions = {__proto__: null}; |
/** |
@@ -103,18 +97,17 @@ let ElemHide = exports.ElemHide = |
TimeLine.leave("ElemHide.init() done"); |
}, |
/** |
* Removes all known filters |
*/ |
clear: function() |
{ |
- filterByKey = {__proto__: null}; |
- keyByFilter = {__proto__: null}; |
+ filters = []; |
knownExceptions = {__proto__: null}; |
exceptions = {__proto__: null}; |
ElemHide.isDirty = false; |
ElemHide.unapply(); |
}, |
/** |
* Add a new element hiding filter |
@@ -130,26 +123,20 @@ let ElemHide = exports.ElemHide = |
let selector = filter.selector; |
if (!(selector in exceptions)) |
exceptions[selector] = []; |
exceptions[selector].push(filter); |
knownExceptions[filter.text] = true; |
} |
else |
{ |
- if (filter.text in keyByFilter) |
- return; |
- |
- let key; |
- do { |
- key = Math.random().toFixed(15).substr(5); |
- } while (key in filterByKey); |
- |
- filterByKey[key] = filter; |
- keyByFilter[filter.text] = key; |
+ filters.push(filter); |
+ // XXX: Maybe check for duplicate filters? |
+ // That would require searching through all filters, |
+ // and in almost all cases there won't be any duplicates ... |
ElemHide.isDirty = true; |
} |
}, |
/** |
* Removes an element hiding filter |
* @param {ElemHideFilter} filter |
*/ |
@@ -163,22 +150,21 @@ let ElemHide = exports.ElemHide = |
let list = exceptions[filter.selector]; |
let index = list.indexOf(filter); |
if (index >= 0) |
list.splice(index, 1); |
delete knownExceptions[filter.text]; |
} |
else |
{ |
- if (!(filter.text in keyByFilter)) |
+ let index = filters.indexOf(filter); |
+ if (index < 0) |
return; |
+ filters[index] = undefined; // Indicates deleted. |
Wladimir Palant
2014/04/08 11:24:53
This won't work correctly if the filter is duplica
|
- let key = keyByFilter[filter.text]; |
- delete filterByKey[key]; |
- delete keyByFilter[filter.text]; |
ElemHide.isDirty = true; |
} |
}, |
/** |
* Checks whether an exception rule is registered for a filter on a particular |
* domain. |
*/ |
@@ -295,30 +281,42 @@ let ElemHide = exports.ElemHide = |
}, |
_generateCSSContent: function() |
{ |
// Grouping selectors by domains |
TimeLine.log("start grouping selectors"); |
let domains = {__proto__: null}; |
let hasFilters = false; |
- for (let key in filterByKey) |
+ let seen = []; |
+ for (let i = 0; i < filters.length; i++) |
{ |
- let filter = filterByKey[key]; |
+ let filter = filters[i]; |
+ if (!filter) |
+ continue; |
+ |
+ // Lazily de-duplicate filters. |
+ if (seen.indexOf(filter) >= 0) { |
tschuster
2014/04/04 13:17:45
I am afraid this piece of code is causing noticeab
Wladimir Palant
2014/04/08 11:24:53
In fact, we are very likely to see duplicates - th
|
+ filters[i] = undefined; |
+ continue; |
+ } else { |
+ seen.push(filter); |
+ } |
+ |
let domain = filter.selectorDomain || ""; |
let list; |
if (domain in domains) |
list = domains[domain]; |
else |
{ |
list = {__proto__: null}; |
domains[domain] = list; |
} |
- list[filter.selector] = key; |
+ list[filter.selector] = i; |
hasFilters = true; |
} |
TimeLine.log("done grouping selectors"); |
if (!hasFilters) |
throw Cr.NS_ERROR_NOT_AVAILABLE; |
function escapeChar(match) |
@@ -374,29 +372,29 @@ let ElemHide = exports.ElemHide = |
*/ |
get styleURL() ElemHide.applied ? styleURL.spec : null, |
/** |
* Retrieves an element hiding filter by the corresponding protocol key |
*/ |
getFilterByKey: function(/**String*/ key) /**Filter*/ |
{ |
- return (key in filterByKey ? filterByKey[key] : null); |
+ return filters[key] || null; |
}, |
/** |
* Returns a list of all selectors active on a particular domain (currently |
* used only in Chrome). |
*/ |
getSelectorsForDomain: function(/**String*/ domain, /**Boolean*/ specificOnly) |
{ |
let result = []; |
- for (let key in filterByKey) |
+ for (let i = 0; i < filters.length; i++) |
{ |
- let filter = filterByKey[key]; |
+ let filter = filters[i]; |
if (specificOnly && (!filter.domains || filter.domains[""])) |
continue; |
if (filter.isActiveOnDomain(domain) && !this.getException(filter, domain)) |
result.push(filter.selector); |
} |
return result; |
} |