Index: lib/elemHide.js |
=================================================================== |
--- a/lib/elemHide.js |
+++ b/lib/elemHide.js |
@@ -29,16 +29,22 @@ |
* <code>{@link createStyleSheet}</code> to split up a long list of selectors |
* into multiple rules. |
* @const {number} |
* @default |
*/ |
const selectorGroupSize = 1024; |
/** |
+ * The maximum number of entries to keep in |
+ * <code>{@link styleSheetCache}</code>. |
+ */ |
+const maxStyleSheetCacheEntries = 100; |
+ |
+/** |
* Lookup table, active flag, by filter by domain. |
* (Only contains filters that aren't unconditionally matched for all domains.) |
* @type {Map.<string,Map.<Filter,boolean>>} |
*/ |
let filtersByDomain = new Map(); |
/** |
* Lookup table, filter by selector. (Only used for selectors that are |
@@ -67,16 +73,24 @@ |
* concatenation of the default style sheet and an additional style sheet based |
* on selectors from all generic filters that are not in the |
* <code>{@link unconditionalSelectors}</code> list. |
* @type {?string} |
*/ |
let commonStyleSheet = null; |
/** |
+ * Cache of generated domain-specific style sheets. This contains entries for |
+ * only known domains. If a domain is unknown, it gets |
+ * <code>{@link commonStyleSheet}</code>. |
+ * @type {Map.<string,string>} |
+ */ |
+let styleSheetCache = new Map(); |
+ |
+/** |
* Map to be used instead when a filter has a blank domains property. |
* @type {Map.<string,boolean>} |
* @const |
*/ |
let defaultDomains = new Map([["", true]]); |
/** |
* Set containing known element hiding filters |
@@ -217,18 +231,41 @@ |
{ |
commonStyleSheet = getDefaultStyleSheet() + |
createStyleSheet(getConditionalSelectors("", false)); |
} |
return commonStyleSheet; |
} |
+/** |
+ * Returns the domain-specific style sheet that applies on a given domain. |
+ * @param {string} domain |
+ * @returns {string} |
+ */ |
+function getDomainSpecificStyleSheet(domain) |
+{ |
+ let styleSheet = styleSheetCache.get(domain); |
+ |
+ if (typeof styleSheet == "undefined") |
+ { |
+ styleSheet = createStyleSheet(getConditionalSelectors(domain, false)); |
+ |
+ if (styleSheetCache.size >= maxStyleSheetCacheEntries) |
+ styleSheetCache.clear(); |
+ |
+ styleSheetCache.set(domain, styleSheet); |
+ } |
+ |
+ return styleSheet; |
+} |
+ |
ElemHideExceptions.on("added", ({domains, selector}) => |
{ |
+ styleSheetCache.clear(); |
commonStyleSheet = null; |
if (domains) |
{ |
for (let domain of domains.keys()) |
{ |
// Note: Once an exception domain is known it never becomes unknown, even |
// when all the exceptions containing that domain are removed. This is a |
@@ -257,18 +294,18 @@ |
exports.ElemHide = { |
/** |
* Removes all known filters |
*/ |
clear() |
{ |
commonStyleSheet = null; |
- for (let collection of [filtersByDomain, filterBySelector, knownFilters, |
- knownExceptionDomains]) |
+ for (let collection of [styleSheetCache, filtersByDomain, filterBySelector, |
+ knownFilters, knownExceptionDomains]) |
{ |
collection.clear(); |
} |
unconditionalSelectors = null; |
defaultStyleSheet = null; |
filterNotifier.emit("elemhideupdate"); |
@@ -278,16 +315,17 @@ |
* Add a new element hiding filter |
* @param {ElemHideFilter} filter |
*/ |
add(filter) |
{ |
if (knownFilters.has(filter)) |
return; |
+ styleSheetCache.clear(); |
commonStyleSheet = null; |
let {domains, selector} = filter; |
if (!(domains || ElemHideExceptions.hasExceptions(selector))) |
{ |
// The new filter's selector is unconditionally applied to all domains |
filterBySelector.set(selector, filter); |
@@ -308,16 +346,17 @@ |
* Removes an element hiding filter |
* @param {ElemHideFilter} filter |
*/ |
remove(filter) |
{ |
if (!knownFilters.has(filter)) |
return; |
+ styleSheetCache.clear(); |
commonStyleSheet = null; |
let {selector} = filter; |
// Unconditially applied element hiding filters |
if (filterBySelector.get(selector) == filter) |
{ |
filterBySelector.delete(selector); |
@@ -391,18 +430,17 @@ |
(getDefaultStyleSheet() + createStyleSheet(selectors)); |
selectors = getUnconditionalSelectors().concat(selectors); |
} |
else |
{ |
code = knownSuffix == "" ? getCommonStyleSheet() : |
(getDefaultStyleSheet() + |
- createStyleSheet(getConditionalSelectors(knownSuffix, |
- false))); |
+ getDomainSpecificStyleSheet(knownSuffix)); |
} |
} |
return {code, selectors: includeSelectors ? selectors : null}; |
} |
}; |
/** |