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

Unified Diff: lib/filterClasses.js

Issue 29912636: Issue 7052 - Use string-based matching for literal patterns (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore/
Patch Set: Created Oct. 17, 2018, 1:34 a.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
« no previous file with comments | « no previous file | test/filterClasses.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/filterClasses.js
===================================================================
--- a/lib/filterClasses.js
+++ b/lib/filterClasses.js
@@ -20,16 +20,18 @@
/**
* @fileOverview Definition of Filter class and its subclasses.
*/
const {filterNotifier} = require("./filterNotifier");
const {extend} = require("./coreUtils");
const {filterToRegExp} = require("./common");
+let tripleAnchorRegExp = new RegExp(filterToRegExp("|||"));
+
/**
* All known unique domain sources mapped to their parsed values.
* @type {Map.<string,Map.<string,boolean>>}
*/
let knownDomainMaps = new Map();
/**
* Abstract base class for filters
@@ -659,21 +661,22 @@
* letters
* @param {string} [domains]
* Domains that the filter is restricted to, e.g. "foo.com|bar.com|~baz.com"
* @param {boolean} [thirdParty]
* Defines whether the filter should apply to third-party or first-party
* content only
* @param {string} [sitekeys]
* Public keys of websites that this filter should apply to
- * @constructor
+ * @param {?string} [rewrite]
+ * The (optional) rule specifying how to rewrite the URL.
* @augments ActiveFilter
*/
function RegExpFilter(text, regexpSource, contentType, matchCase, domains,
- thirdParty, sitekeys)
+ thirdParty, sitekeys, rewrite)
{
ActiveFilter.call(this, text, domains);
if (contentType != null)
this.contentType = contentType;
if (matchCase)
this.matchCase = matchCase;
if (thirdParty != null)
@@ -690,16 +693,24 @@
let regexp = new RegExp(regexpSource.substr(1, regexpSource.length - 2),
this.matchCase ? "" : "i");
Object.defineProperty(this, "regexp", {value: regexp});
}
else
{
// No need to convert this filter to regular expression yet, do it on demand
this.pattern = regexpSource;
+
+ if (rewrite == null)
+ {
+ this.pattern = this.pattern.replace(/^\**/, "").replace(/\**$/, "");
+
+ if (!this.matchCase)
+ this.pattern = this.pattern.toLowerCase();
+ }
}
}
exports.RegExpFilter = RegExpFilter;
RegExpFilter.prototype = extend(ActiveFilter, {
/**
* Number of filters contained, will always be 1 (required to
* optimize {@link Matcher}).
@@ -719,20 +730,27 @@
*/
pattern: null,
/**
* Regular expression to be used when testing against this filter
* @type {RegExp}
*/
get regexp()
{
- let source = filterToRegExp(this.pattern, this.rewrite != null);
- let regexp = new RegExp(source, this.matchCase ? "" : "i");
- Object.defineProperty(this, "regexp", {value: regexp});
- return regexp;
+ let value = null;
+
+ let {pattern, rewrite} = this;
+ if (rewrite != null || /[*^|]/.test(pattern.replace(/^\|{1,2}/, "")))
+ {
+ value = new RegExp(filterToRegExp(pattern, rewrite != null),
+ this.matchCase ? "" : "i");
+ }
+
+ Object.defineProperty(this, "regexp", {value});
+ return value;
},
/**
* Content types the filter applies to, combination of values from
* RegExpFilter.typeMap
* @type {number}
*/
contentType: 0x7FFFFFFF,
/**
@@ -783,17 +801,44 @@
* @param {string} [sitekey] public key provided by the document
* @return {boolean} true in case of a match
*/
matches(location, typeMask, docDomain, thirdParty, sitekey)
{
return (this.contentType & typeMask) != 0 &&
(this.thirdParty == null || this.thirdParty == thirdParty) &&
this.isActiveOnDomain(docDomain, sitekey) &&
- this.regexp.test(location);
+ this.matchesLocation(location);
+ },
+
+ matchesLocation(location)
+ {
+ let {regexp} = this;
+
+ if (regexp)
+ return regexp.test(location);
+
+ if (!this.matchCase)
+ location = location.toLowerCase();
+
+ let {pattern} = this;
+
+ if (pattern[0] == "|")
+ {
+ if (pattern[1] == "|")
+ {
+ let index = location.indexOf(pattern.substring(2));
+ return index != -1 && location[index] != "/" &&
+ tripleAnchorRegExp.test(location.substring(0, index));
+ }
+
+ return location.startsWith(pattern.substring(1));
+ }
+
+ return location.includes(pattern);
}
});
/**
* Yields the filter itself (required to optimize {@link Matcher}).
* @yields {RegExpFilter}
*/
RegExpFilter.prototype[Symbol.iterator] = function*()
@@ -988,17 +1033,17 @@
* BlockingFilter.prototype.rewrite.
* @constructor
* @augments RegExpFilter
*/
function BlockingFilter(text, regexpSource, contentType, matchCase, domains,
thirdParty, sitekeys, collapse, csp, rewrite)
{
RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains,
- thirdParty, sitekeys);
+ thirdParty, sitekeys, rewrite);
if (collapse != null)
this.collapse = collapse;
if (csp != null)
this.csp = csp;
if (rewrite != null)
« no previous file with comments | « no previous file | test/filterClasses.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld