| Index: lib/filterClasses.js |
| =================================================================== |
| --- a/lib/filterClasses.js |
| +++ b/lib/filterClasses.js |
| @@ -28,32 +28,40 @@ |
| /** |
| * Regular expression used to match the <code>||</code> prefix in an otherwise |
| * literal pattern. |
| * @type {RegExp} |
| */ |
| let doubleAnchorRegExp = new RegExp(filterToRegExp("||") + "$"); |
| /** |
| + * Regular expression used to match the <code>^</code> suffix in an otherwise |
| + * literal pattern. |
| + * @type {RegExp} |
| + */ |
| +// Note: This should match the pattern in lib/common.js |
| +let separatorRegExp = /[\x00-\x24\x26-\x2C\x2F\x3A-\x40\x5B-\x5E\x60\x7B-\x7F]/; |
| + |
| +/** |
| * All known unique domain sources mapped to their parsed values. |
| * @type {Map.<string,Map.<string,boolean>>} |
| */ |
| let knownDomainMaps = new Map(); |
| /** |
| * Checks whether the given pattern is a string of literal characters with no |
| * wildcards or any other special characters. If the pattern is prefixed with a |
| - * <code>||</code> but otherwise contains no special characters, it is still |
| - * considered to be a literal pattern. |
| + * <code>||</code> or suffixed with a <code>^</code> but otherwise contains no |
| + * special characters, it is still considered to be a literal pattern. |
| * @param {string} pattern |
| * @returns {boolean} |
| */ |
| function isLiteralPattern(pattern) |
| { |
| - return !/[*^|]/.test(pattern.replace(/^\|{2}/, "")); |
| + return !/[*^|]/.test(pattern.replace(/^\|{2}/, "").replace(/\^$/, "")); |
| } |
| /** |
| * Abstract base class for filters |
| * |
| * @param {string} text string representation of the filter |
| * @constructor |
| */ |
| @@ -837,27 +845,34 @@ |
| if (regexp) |
| return regexp.test(location); |
| if (!this.matchCase) |
| location = location.toLowerCase(); |
| let {pattern} = this; |
| - if (pattern[0] == "|" && pattern[1] == "|") |
| - { |
| - let index = location.indexOf(pattern.substring(2)); |
| + let startsWithDoubleAnchor = pattern[0] == "|" && pattern[1] == "|"; |
| + let endsWithSeparator = pattern[pattern.length - 1] == "^"; |
| + |
| + if (startsWithDoubleAnchor) |
| + pattern = pattern.substr(2); |
| + |
| + if (endsWithSeparator) |
| + pattern = pattern.slice(0, -1); |
| - // The "||" prefix requires that the text that follows does not start |
| - // with a forward slash. |
| - return index != -1 && location[index] != "/" && |
| - doubleAnchorRegExp.test(location.substring(0, index)); |
| - } |
| + let index = location.indexOf(pattern); |
| - return location.includes(pattern); |
| + // The "||" prefix requires that the text that follows does not start |
| + // with a forward slash. |
| + return index != -1 && |
| + (!startsWithDoubleAnchor || location[index] != "/" && |
| + doubleAnchorRegExp.test(location.substring(0, index))) && |
| + (!endsWithSeparator || !location[index + pattern.length] || |
| + separatorRegExp.test(location[index + pattern.length])); |
| }, |
| /** |
| * Checks whether this filter has only a URL pattern and no content type, |
| * third-party flag, domains, or sitekeys. |
| * @returns {boolean} |
| */ |
| isLocationOnly() |