Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: lib/elemHide.js

Issue 29882558: Issue 6955 - Avoid making copies of common selector list (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore/
Patch Set: Cache common selector list Created Sept. 17, 2018, 9:20 a.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | test/elemHide.js » ('j') | test/elemHide.js » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/elemHide.js
===================================================================
--- a/lib/elemHide.js
+++ b/lib/elemHide.js
@@ -42,16 +42,24 @@
* This array caches the keys of filterBySelector table (selectors
* which unconditionally apply on all domains). It will be null if the
* cache needs to be rebuilt.
* @type {?string[]}
*/
let unconditionalSelectors = null;
/**
+ * Cached list of selectors that apply on any domain that neither has any
Manish Jethani 2018/09/17 09:28:43 Here we are introducing the idea of "common" selec
+ * domain-specific filters or exceptions nor is specifically excluded from any
+ * generic filters or exceptions.
+ * @type {?string[]}
+ */
+let commonSelectors = null;
+
+/**
* 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
@@ -88,16 +96,18 @@
if (!unconditionalSelectors)
unconditionalSelectors = [...filterBySelector.keys()];
return unconditionalSelectors;
}
ElemHideExceptions.on("added", ({selector}) =>
{
+ commonSelectors = null;
+
// If this is the first exception for a previously unconditionally applied
// element hiding selector we need to take care to update the lookups.
let unconditionalFilterForSelector = filterBySelector.get(selector);
if (unconditionalFilterForSelector)
{
addToFiltersByDomain(unconditionalFilterForSelector);
filterBySelector.delete(selector);
unconditionalSelectors = null;
@@ -112,29 +122,33 @@
/**
* Removes all known filters
*/
clear()
{
for (let collection of [filtersByDomain, filterBySelector, knownFilters])
collection.clear();
+ commonSelectors = null;
unconditionalSelectors = null;
+
filterNotifier.emit("elemhideupdate");
},
/**
* Add a new element hiding filter
* @param {ElemHideFilter} filter
*/
add(filter)
{
if (knownFilters.has(filter))
return;
+ commonSelectors = null;
+
let {selector} = filter;
if (!(filter.domains || ElemHideExceptions.hasExceptions(selector)))
{
// The new filter's selector is unconditionally applied to all domains
filterBySelector.set(selector, filter);
unconditionalSelectors = null;
}
@@ -152,16 +166,18 @@
* Removes an element hiding filter
* @param {ElemHideFilter} filter
*/
remove(filter)
{
if (!knownFilters.has(filter))
return;
+ commonSelectors = null;
+
let {selector} = filter;
// Unconditially applied element hiding filters
if (filterBySelector.get(selector) == filter)
{
filterBySelector.delete(selector);
unconditionalSelectors = null;
}
@@ -195,49 +211,75 @@
*/
getSelectorsForDomain(domain, specificOnly = false)
{
let selectors = [];
let excluded = new Set();
let currentDomain = domain ? domain.replace(/\.+$/, "").toLowerCase() : "";
+ let commonCase = true;
+
// This code is a performance hot-spot, which is why we've made certain
// micro-optimisations. Please be careful before making changes.
while (true)
{
if (specificOnly && currentDomain == "")
break;
let filters = filtersByDomain.get(currentDomain);
if (filters)
{
+ if (currentDomain != "")
+ commonCase = false;
+
for (let [filter, isIncluded] of filters)
{
if (!isIncluded)
{
excluded.add(filter);
}
else
{
let {selector} = filter;
- if ((excluded.size == 0 || !excluded.has(filter)) &&
- !ElemHideExceptions.getException(selector, domain))
+ if (excluded.size == 0 || !excluded.has(filter))
{
- selectors.push(selector);
+ let exception = ElemHideExceptions.getException(selector, domain);
+ if (!exception)
+ selectors.push(selector);
+ else if (commonCase && exception.domains)
+ commonCase = false;
}
}
}
}
if (currentDomain == "")
break;
let nextDot = currentDomain.indexOf(".");
currentDomain = nextDot == -1 ? "" : currentDomain.substr(nextDot + 1);
}
if (!specificOnly)
- selectors = getUnconditionalSelectors().concat(selectors);
+ {
+ // Use the cache of common selectors if there are no filters or
+ // exceptions that apply or don't apply specifically to this domain.
+ if (commonCase)
+ {
+ if (!commonSelectors)
+ {
+ let unconditional = getUnconditionalSelectors();
+ commonSelectors = Object.freeze(unconditional.concat(selectors));
+ }
+
+ selectors = commonSelectors;
+ }
+ else
+ {
+ let unconditional = getUnconditionalSelectors();
+ selectors = Object.freeze(unconditional.concat(selectors));
+ }
+ }
return selectors;
}
};
« no previous file with comments | « no previous file | test/elemHide.js » ('j') | test/elemHide.js » ('J')

Powered by Google App Engine
This is Rietveld