| 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}; |
| } |
| }; |
| /** |