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

Unified Diff: lib/filterClasses.js

Issue 29361668: Issue 4394 - Create a filter class for element hiding emulation filters (Closed) Base URL: https://bitbucket.org/fhd/adblockpluscore
Patch Set: Created Nov. 3, 2016, 3:42 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
@@ -16,16 +16,17 @@
*/
/**
* @fileOverview Definition of Filter class and its subclasses.
*/
let {FilterNotifier} = require("filterNotifier");
let {extend} = require("coreUtils");
+let {elemHideEmulationFeatureMap, filterToRegExp} = require("shared");
/**
* 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)
kzar 2016/11/04 15:45:56 The feature flags are a nice idea but I wonder wha
Felix Dahlke 2016/11/04 16:43:35 Well, if we detect NO feature here, this would jus
kzar 2016/11/07 12:36:26 I guess my question is what's the point of having
Felix Dahlke 2016/11/07 14:41:24 Well, we have to check for emulated features befor
kzar 2016/11/07 15:59:44 Well we don't need to set a boolean flag here eith
Felix Dahlke 2016/11/07 16:51:24 Yeah of course, my bad.
kzar 2016/11/07 17:10:22 That's not quite true, since if we're recording us
Felix Dahlke 2016/11/08 17:45:35 Well, sure, we don't have to run all checks if one
kzar 2016/11/15 16:54:13 Well no I think that if the only reason to add all
Felix Dahlke 2016/11/15 21:11:44 I still think it makes sense to start detecting (y
Wladimir Palant 2016/11/21 11:39:14 I actually have to agree with Dave here. You are d
Felix Dahlke 2016/11/21 14:38:58 Fair enough, I guess if we're not worried about ba
+ emulatedFeatures |= ElemHideEmulationFilter.featureMap.HAS_PSEUDO_CLASS;
+
+ if (emulatedFeatures != 0)
{
- // 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,
kzar 2016/11/04 15:45:56 I wonder if it's really a good idea to move the lo
Felix Dahlke 2016/11/04 16:43:35 Well, one part of the truth is that I don't know h
kzar 2016/11/07 17:19:25 That's a pretty good point actually, I didn't thin
+ emulatedFeatures);
}
return new ElemHideFilter(text, domain, selector);
};
/**
* Class for element hiding filters
* @param {String} text see Filter()
@@ -981,69 +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
kzar 2016/11/04 15:45:56 Perhaps describe it as bit flags instead of combin
Felix Dahlke 2016/11/04 16:43:35 I thought I'd keep this in line with the doc comme
kzar 2016/11/07 17:19:25 Well bitmap works too. (I guess if you're worried
+ * 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 = Filter.toRegExp(this.regexpSource);
- Object.defineProperty(this, "regexpString", {value: regexp});
- return regexp;
- }
-});
+/**
+ * @see elemHideEmulationFeatureMap
+ */
+ElemHideEmulationFilter.featureMap = elemHideEmulationFeatureMap;

Powered by Google App Engine
This is Rietveld