| Index: lib/filterClasses.js | 
| =================================================================== | 
| --- a/lib/filterClasses.js | 
| +++ b/lib/filterClasses.js | 
| @@ -16,16 +16,17 @@ | 
| */ | 
| /** | 
| * @fileOverview Definition of Filter class and its subclasses. | 
| */ | 
| let {FilterNotifier} = require("filterNotifier"); | 
| let {extend} = require("coreUtils"); | 
| +let {elemHideEmulationFeatureMap, filterToRegExp} = require("common"); | 
| /** | 
| * Abstract base class for filters | 
| * | 
| * @param {String} text string representation of the filter | 
| * @constructor | 
| */ | 
| function Filter(text) | 
| @@ -90,22 +91,16 @@ | 
| * @type RegExp | 
| */ | 
| 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 | 
| - * Properties must not contain " or ' | 
| - * @type RegExp | 
| - */ | 
| -Filter.csspropertyRegExp = /\[\-abp\-properties=(["'])([^"']+)\1\]/; | 
| /** | 
| * 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} | 
| */ | 
| @@ -171,35 +166,19 @@ | 
| let [, domain, separator, selector] = /^(.*?)(#\@?#?)(.*)$/.exec(text); | 
| return domain.replace(/\s/g, "") + separator + selector.trim(); | 
| } | 
| else | 
| return text.replace(/\s/g, ""); | 
| }; | 
| /** | 
| - * Converts filter text into regular expression string | 
| - * @param {String} text as in Filter() | 
| - * @return {String} regular expression representation of filter text | 
| + * @see filterToRegExp | 
| */ | 
| -Filter.toRegExp = function(text) | 
| -{ | 
| - return text | 
| - .replace(/\*+/g, "*") // remove multiple wildcards | 
| - .replace(/\^\|$/, "^") // remove anchors following separator placeholder | 
| - .replace(/\W/g, "\\$&") // escape special symbols | 
| - .replace(/\\\*/g, ".*") // replace wildcards by .* | 
| - // process separator placeholders (all ANSI characters but alphanumeric characters and _%.-) | 
| - .replace(/\\\^/g, "(?:[\\x00-\\x24\\x26-\\x2C\\x2F\\x3A-\\x40\\x5B-\\x5E\\x60\\x7B-\\x7F]|$)") | 
| - .replace(/^\\\|\\\|/, "^[\\w\\-]+:\\/+(?!\\/)(?:[^\\/]+\\.)?") // process extended anchor at expression start | 
| - .replace(/^\\\|/, "^") // process anchor at expression start | 
| - .replace(/\\\|$/, "$") // process anchor at expression end | 
| - .replace(/^(\.\*)/, "") // remove leading wildcards | 
| - .replace(/(\.\*)$/, ""); // remove trailing wildcards | 
| -} | 
| +Filter.toRegExp = filterToRegExp; | 
| /** | 
| * Class for invalid filters | 
| * @param {String} text see Filter() | 
| * @param {String} reason Reason why this filter is invalid | 
| * @constructor | 
| * @augments Filter | 
| */ | 
| @@ -878,17 +857,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 = ""; | 
| @@ -928,27 +907,31 @@ | 
| // Note: The ElemHide.prototype.domainSeparator is duplicated here, if that | 
| // changes this must be changed too. | 
| if (domain && /(^|,)~?(,|$)/.test(domain)) | 
| return new InvalidFilter(text, "filter_invalid_domain"); | 
| if (isException) | 
| return new ElemHideException(text, domain, selector); | 
| - let match = Filter.csspropertyRegExp.exec(selector); | 
| - if (match) | 
| + let emulatedFeatures = 0; | 
| + if (selector.indexOf("[-abp-properties") != -1) | 
| + emulatedFeatures |= ElemHideEmulationFilter.featureMap.PROPERTY_SELECTOR; | 
| + if (selector.indexOf(":has(") != -1) | 
| + emulatedFeatures |= ElemHideEmulationFilter.featureMap.HAS_PSEUDO_CLASS; | 
| + | 
| + if (emulatedFeatures != 0) | 
| 
 
Wladimir Palant
2016/11/21 11:39:15
Nit: `if (emulatedFeatures)`?
 
Felix Dahlke
2016/11/21 14:38:59
Removed along with the feature bitmask.
 
 | 
| { | 
| - // 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"); | 
| - return new CSSPropertyFilter(text, domain, selector, match[2], | 
| - selector.substr(0, match.index), | 
| - selector.substr(match.index + match[0].length)); | 
| + return new ElemHideEmulationFilter(text, domain, selector, | 
| + emulatedFeatures); | 
| } | 
| return new ElemHideFilter(text, domain, selector); | 
| }; | 
| /** | 
| * Class for element hiding filters | 
| * @param {String} text see Filter() | 
| @@ -981,74 +964,39 @@ | 
| } | 
| 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 | 
| * @constructor | 
| * @augments ElemHideBase | 
| */ | 
| -function CSSPropertyFilter(text, domains, selector, regexpSource, | 
| - selectorPrefix, selectorSuffix) | 
| +function ElemHideEmulationFilter(text, domains, selector, features) | 
| { | 
| ElemHideBase.call(this, text, domains, selector); | 
| - this.regexpSource = regexpSource; | 
| - this.selectorPrefix = selectorPrefix; | 
| - this.selectorSuffix = selectorSuffix; | 
| + this.features = features; | 
| } | 
| -exports.CSSPropertyFilter = CSSPropertyFilter; | 
| +exports.ElemHideEmulationFilter = ElemHideEmulationFilter; | 
| -CSSPropertyFilter.prototype = extend(ElemHideBase, { | 
| - type: "cssproperty", | 
| +ElemHideEmulationFilter.prototype = extend(ElemHideBase, { | 
| + type: "elemhideemulation", | 
| /** | 
| - * Expression from which a regular expression should be generated for matching | 
| - * CSS properties - for delayed creation of the regexpString property | 
| - * @type String | 
| + * Features used in this filter, combination of values from | 
| + * ElemHideEmulationFilter.featureMap | 
| + * @type Integer | 
| */ | 
| - regexpSource: null, | 
| - /** | 
| - * Substring of CSS selector before properties for the HTML elements that | 
| - * should be hidden | 
| - * @type String | 
| - */ | 
| - selectorPrefix: null, | 
| - /** | 
| - * Substring of CSS selector after properties for the HTML elements that | 
| - * should be hidden | 
| - * @type String | 
| - */ | 
| - selectorSuffix: null, | 
| + features: 0 | 
| +}); | 
| - /** | 
| - * Raw regular expression string to be used when testing CSS properties | 
| - * against this filter | 
| - * @type String | 
| - */ | 
| - get regexpString() | 
| - { | 
| - // Despite this property being cached, the getter is called | 
| - // several times on Safari, due to WebKit bug 132872 | 
| - let prop = Object.getOwnPropertyDescriptor(this, "regexpString"); | 
| - if (prop) | 
| - return prop.value; | 
| - | 
| - let regexp; | 
| - if (this.regexpSource.length >= 2 && this.regexpSource[0] == "/" && | 
| - this.regexpSource[this.regexpSource.length - 1] == "/") | 
| - regexp = this.regexpSource.slice(1, -1); | 
| - else | 
| - regexp = Filter.toRegExp(this.regexpSource); | 
| - Object.defineProperty(this, "regexpString", {value: regexp}); | 
| - return regexp; | 
| - } | 
| -}); | 
| +/** | 
| + * @see elemHideEmulationFeatureMap | 
| + */ | 
| +ElemHideEmulationFilter.featureMap = elemHideEmulationFeatureMap; |