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

Unified Diff: lib/elemHide.js

Issue 29784555: Issue 6665 - Abstract element hiding container logic into its own module Base URL: https://hg.adblockplus.org/adblockpluscore/
Patch Set: Move base class into lib/contentFilterModule.js Created Aug. 15, 2018, 8:56 p.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
Index: lib/elemHide.js
===================================================================
--- a/lib/elemHide.js
+++ b/lib/elemHide.js
@@ -16,174 +16,50 @@
*/
"use strict";
/**
* @fileOverview Element hiding implementation.
*/
+const {ContentFilterModule} = require("./contentFilterModule");
const {ElemHideExceptions} = require("./elemHideExceptions");
const {FilterNotifier} = require("./filterNotifier");
/**
- * 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
- * unconditionally matched for all domains.)
- * @type {Map.<string,Filter>}
- */
-let filterBySelector = new Map();
-
-/**
- * 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;
-
-/**
- * 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
- * @type {Set.<ElemHideFilter>}
- */
-let knownFilters = new Set();
-
-/**
- * Adds a filter to the lookup table of filters by domain.
- * @param {Filter} filter
- */
-function addToFiltersByDomain(filter)
-{
- let domains = filter.domains || defaultDomains;
- for (let [domain, isIncluded] of domains)
- {
- // There's no need to note that a filter is generically disabled.
- if (!isIncluded && domain == "")
- continue;
-
- let filters = filtersByDomain.get(domain);
- if (!filters)
- filtersByDomain.set(domain, filters = new Map());
- filters.set(filter, isIncluded);
- }
-}
-
-/**
- * Returns a list of selectors that apply on each website unconditionally.
- * @returns {string[]}
- */
-function getUnconditionalSelectors()
-{
- if (!unconditionalSelectors)
- unconditionalSelectors = [...filterBySelector.keys()];
-
- return unconditionalSelectors;
-}
-
-ElemHideExceptions.on("added", ({selector}) =>
-{
- // 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;
- }
-});
-
-/**
* Container for element hiding filters
* @class
*/
-exports.ElemHide = {
- /**
- * Removes all known filters
- */
+exports.ElemHide = Object.assign(new ContentFilterModule(), {
clear()
{
- for (let collection of [filtersByDomain, filterBySelector, knownFilters])
- collection.clear();
+ ContentFilterModule.prototype.clear.call(this);
- unconditionalSelectors = null;
FilterNotifier.emit("elemhideupdate");
},
- /**
- * Add a new element hiding filter
- * @param {ElemHideFilter} filter
- */
add(filter)
{
- if (knownFilters.has(filter))
- return;
-
- let {selector} = filter;
+ let {size} = this._knownFilters;
- if (!(filter.domains || ElemHideExceptions.hasExceptions(selector)))
- {
- // The new filter's selector is unconditionally applied to all domains
- filterBySelector.set(selector, filter);
- unconditionalSelectors = null;
- }
- else
- {
- // The new filter's selector only applies to some domains
- addToFiltersByDomain(filter);
- }
+ ContentFilterModule.prototype.add.call(this, filter);
- knownFilters.add(filter);
- FilterNotifier.emit("elemhideupdate");
+ if (size != this._knownFilters.size)
+ FilterNotifier.emit("elemhideupdate");
},
- /**
- * Removes an element hiding filter
- * @param {ElemHideFilter} filter
- */
remove(filter)
{
- if (!knownFilters.has(filter))
- return;
-
- let {selector} = filter;
+ let {size} = this._knownFilters;
- // Unconditially applied element hiding filters
- if (filterBySelector.get(selector) == filter)
- {
- filterBySelector.delete(selector);
- unconditionalSelectors = null;
- }
- // Conditionally applied element hiding filters
- else
- {
- let domains = filter.domains || defaultDomains;
- for (let domain of domains.keys())
- {
- let filters = filtersByDomain.get(domain);
- if (filters)
- filters.delete(filter);
- }
- }
+ ContentFilterModule.prototype.remove.call(this, filter);
- knownFilters.delete(filter);
- FilterNotifier.emit("elemhideupdate");
+ if (size != this._knownFilters.size)
+ FilterNotifier.emit("elemhideupdate");
},
/**
* Determines from the current filter list which selectors should be applied
* on a particular host name.
* @param {string} domain
* @param {boolean} [specificOnly] true if generic filters should not apply.
* @returns {string[]} List of selectors.
@@ -197,17 +73,17 @@
// 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);
+ let filters = this._filtersByDomain.get(currentDomain);
if (filters)
{
for (let [filter, isIncluded] of filters)
{
if (!isIncluded)
{
excluded.add(filter);
}
@@ -226,13 +102,13 @@
if (currentDomain == "")
break;
let nextDot = currentDomain.indexOf(".");
currentDomain = nextDot == -1 ? "" : currentDomain.substr(nextDot + 1);
}
if (!specificOnly)
- selectors = getUnconditionalSelectors().concat(selectors);
+ selectors = this._getUnconditionalSelectors().concat(selectors);
return selectors;
}
-};
+});

Powered by Google App Engine
This is Rietveld