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

Unified Diff: lib/filterClasses.js

Issue 29354827: Issue 4394 - Create a filter class for element hiding emulation filters [WIP] (Closed)
Patch Set: Created Sept. 23, 2016, 4:21 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/filterClasses.js
===================================================================
--- a/lib/filterClasses.js
+++ b/lib/filterClasses.js
@@ -91,21 +91,28 @@
*/
Filter.regexpRegExp = /^(@@)?\/.*\/(?:\$~?[\w\-]+(?:=[^,\s]+)?(?:,~?[\w\-]+(?:=[^,\s]+)?)*)?$/;
/**
* Regular expression that options on a RegExp filter should match
* @type RegExp
*/
Filter.optionsRegExp = /\$(~?[\w\-]+(?:=[^,\s]+)?(?:,~?[\w\-]+(?:=[^,\s]+)?)*)$/;
/**
- * Regular expression that CSS property filters should match
+ * Regular expression that element hiding filters using property selectors
+ * should match
* Properties must not contain " or '
* @type RegExp
*/
-Filter.csspropertyRegExp = /\[\-abp\-properties=(["'])([^"']+)\1\]/;
+Filter.propertyselectorRegExp = /\[\-abp\-properties=(["'])([^"']+)\1\]/;
+/**
+ * Regular expression that element hiding filters using the :has pseudo-class
+ * should match
+ * @type RegExp
+ */
+Filter.haspseudoclassRegExp = /:has\(/;
Felix Dahlke 2016/09/23 16:41:59 Didn't want to put too much energy into this regex
Felix Dahlke 2016/10/05 10:08:26 In-person comment from Wladimir: We probably don't
kzar 2016/10/05 11:58:15 Acknowledged.
/**
* Creates a filter of correct type from its text representation - does the basic parsing and
* calls the right constructor then.
*
* @param {String} text as in Filter()
* @return {Filter}
*/
@@ -878,17 +885,17 @@
* Creates an element hiding filter from a pre-parsed text representation
*
* @param {String} text same as in Filter()
* @param {String} domain domain part of the text representation (can be empty)
* @param {Boolean} isException exception rule indicator
* @param {String} tagName tag name part (can be empty)
* @param {String} attrRules attribute matching rules (can be empty)
* @param {String} selector raw CSS selector (can be empty)
- * @return {ElemHideFilter|ElemHideException|CSSPropertyFilter|InvalidFilter}
+ * @return {ElemHideFilter|ElemHideException|ElemHideEmulationFilter|InvalidFilter}
*/
ElemHideBase.fromText = function(text, domain, isException, tagName, attrRules, selector)
{
if (!selector)
{
if (tagName == "*")
tagName = "";
@@ -922,27 +929,42 @@
selector = tagName + additional;
else
return new InvalidFilter(text, "filter_elemhide_nocriteria");
}
if (isException)
return new ElemHideException(text, domain, selector);
- let match = Filter.csspropertyRegExp.exec(selector);
- if (match)
+ let hasSelectorUsed = Filter.haspseudoclassRegExp.test(selector);
Felix Dahlke 2016/09/23 16:41:59 This code block is all about checking if the eleme
kzar 2016/10/05 11:58:14 Yea I agree, if you don't move this into a separat
Felix Dahlke 2016/11/03 16:14:13 The code is quite a bit shorter now that I reduced
+ let propertySelectorMatch = Filter.propertyselectorRegExp.exec(selector);
Felix Dahlke 2016/09/23 16:41:59 I'm not really happy that we need to run every fea
kzar 2016/09/25 14:52:06 Could we have a regexp which matches all element h
Felix Dahlke 2016/09/30 10:22:26 Yeah, I think that should be possible. But it woul
+ if (hasSelectorUsed || propertySelectorMatch)
{
- // CSS property filters are inefficient so we need to make sure that
- // they're only applied if they specify active domains
+ // Element hiding emulation filters are inefficient so we need to make sure
+ // that they're only applied if they specify active domains
if (!/,[^~][^,.]*\.[^,]/.test("," + domain))
- return new InvalidFilter(text, "filter_cssproperty_nodomain");
+ return new InvalidFilter(text, "filter_elemhideemulation_nodomain");
kzar 2016/09/25 15:51:12 (I guess we'll have to update this string in adblo
Felix Dahlke 2016/09/30 10:22:26 Yup, I was planning to roll out my adblockplus cha
Felix Dahlke 2016/10/05 10:08:27 In-person comment from Wladimir: It's a different
- return new CSSPropertyFilter(text, domain, selector, match[2],
- selector.substr(0, match.index),
- selector.substr(match.index + match[0].length));
+ let regexpSource, selectorPrefix, selectorSuffix;
+ if (propertySelectorMatch)
+ {
+ regexpSource = propertySelectorMatch[2];
Felix Dahlke 2016/09/23 16:41:59 These properties are only necessary for the CSSPro
kzar 2016/09/25 14:52:07 But we still need the selector suffix and prefix f
Felix Dahlke 2016/09/30 10:22:26 Well, a filter can have both :has and property sel
kzar 2016/10/05 11:58:15 OK fair enough, me neither to be honest.
+ selectorPrefix = selector.substr(0, propertySelectorMatch.index);
+ selectorSuffix = selector.substr(propertySelectorMatch.index
+ + propertySelectorMatch[0].length);
+ }
+
+ let features = 0;
+ if (hasSelectorUsed)
+ features |= ElemHideEmulationFilter.featureMap.HAS_PSEUDO_CLASS;
+ if (propertySelectorMatch)
+ features |= ElemHideEmulationFilter.featureMap.PROPERTY_SELECTOR;
+
+ return new ElemHideEmulationFilter(text, domain, selector, features,
+ regexpSourcex, selectorPrefix, selectorSuffix);
}
return new ElemHideFilter(text, domain, selector);
};
/**
* Class for element hiding filters
* @param {String} text see Filter()
@@ -975,39 +997,48 @@
}
exports.ElemHideException = ElemHideException;
ElemHideException.prototype = extend(ElemHideBase, {
type: "elemhideexception"
});
/**
- * Class for CSS property filters
+ * Class for element hiding emulation filters
* @param {String} text see Filter()
* @param {String} domains see ElemHideBase()
* @param {String} selector see ElemHideBase()
- * @param {String} regexpSource see CSSPropertyFilter.regexpSource
- * @param {String} selectorPrefix see CSSPropertyFilter.selectorPrefix
- * @param {String} selectorSuffix see CSSPropertyFilter.selectorSuffix
+ * @param {Integer} features see ElemHideEmulationFilter.features
+ * @param {String} regexpSource see ElemHideEmulationFilter.regexpSource
+ * @param {String} selectorPrefix see ElemHideEmulationFilter.selectorPrefix
+ * @param {String} selectorSuffix see ElemHideEmulationFilter.selectorSuffix
* @constructor
* @augments ElemHideBase
*/
-function CSSPropertyFilter(text, domains, selector, regexpSource,
- selectorPrefix, selectorSuffix)
+function ElemHideEmulationFilter(text, domains, selector, features,
+ regexpSource, selectorPrefix, selectorSuffix)
{
ElemHideBase.call(this, text, domains, selector);
+ this.features = features;
this.regexpSource = regexpSource;
this.selectorPrefix = selectorPrefix;
this.selectorSuffix = selectorSuffix;
}
-exports.CSSPropertyFilter = CSSPropertyFilter;
+exports.ElemHideEmulationFilter = ElemHideEmulationFilter;
-CSSPropertyFilter.prototype = extend(ElemHideBase, {
- type: "cssproperty",
+ElemHideEmulationFilter.prototype = extend(ElemHideBase, {
+ type: "elemhideemulation",
+
+ /**
+ * Features used in this filter, combination of values from
+ * ElemHideEmulationFilter.featureMap
+ * @type Integer
+ */
+ features: 0,
/**
* Expression from which a regular expression should be generated for matching
* CSS properties - for delayed creation of the regexpString property
* @type String
*/
regexpSource: null,
/**
@@ -1036,8 +1067,16 @@
if (prop)
return prop.value;
let regexp = Filter.toRegExp(this.regexpSource);
Object.defineProperty(this, "regexpString", {value: regexp});
return regexp;
}
});
+
+/**
+ * Map of features supported by element hiding emulation filters
+ */
+ElemHideEmulationFilter.featureMap = {
+ PROPERTY_SELECTOR: 1,
+ HAS_PSEUDO_CLASS: 2
+};

Powered by Google App Engine
This is Rietveld