| 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 |
| +}; |