| Index: lib/matcher.js |
| =================================================================== |
| --- a/lib/matcher.js |
| +++ b/lib/matcher.js |
| @@ -53,94 +53,96 @@ |
| */ |
| class Matcher |
| { |
| constructor() |
| { |
| /** |
| * Lookup table for filters by their associated keyword |
| * @type {Map.<string,(Filter|Set.<Filter>)>} |
| + * @private |
| */ |
| - this.filterByKeyword = new Map(); |
| + this._filterByKeyword = new Map(); |
| } |
| /** |
| * Removes all known filters |
| */ |
| clear() |
| { |
| - this.filterByKeyword.clear(); |
| + this._filterByKeyword.clear(); |
| } |
| /** |
| * Adds a filter to the matcher |
| * @param {RegExpFilter} filter |
| */ |
| add(filter) |
| { |
| // Look for a suitable keyword |
| let keyword = this.findKeyword(filter); |
| - let set = this.filterByKeyword.get(keyword); |
| + let set = this._filterByKeyword.get(keyword); |
| if (typeof set == "undefined") |
| { |
| - this.filterByKeyword.set(keyword, filter); |
| + this._filterByKeyword.set(keyword, filter); |
| } |
| else if (set.size == 1) |
| { |
| if (filter != set) |
| - this.filterByKeyword.set(keyword, new Set([set, filter])); |
| + this._filterByKeyword.set(keyword, new Set([set, filter])); |
| } |
| else |
| { |
| set.add(filter); |
| } |
| } |
| /** |
| * Removes a filter from the matcher |
| * @param {RegExpFilter} filter |
| */ |
| remove(filter) |
| { |
| let keyword = this.findKeyword(filter); |
| - let set = this.filterByKeyword.get(keyword); |
| + let set = this._filterByKeyword.get(keyword); |
| if (typeof set == "undefined") |
| return; |
| if (set.size == 1) |
| { |
| if (filter == set) |
| - this.filterByKeyword.delete(keyword); |
| + this._filterByKeyword.delete(keyword); |
| } |
| else |
| { |
| set.delete(filter); |
| if (set.size == 1) |
| - this.filterByKeyword.set(keyword, [...set][0]); |
| + this._filterByKeyword.set(keyword, [...set][0]); |
| } |
| } |
| /** |
| * Chooses a keyword to be associated with the filter |
| * @param {Filter} filter |
| * @returns {string} keyword or an empty string if no keyword could be found |
| + * @protected |
| */ |
| findKeyword(filter) |
| { |
| let result = ""; |
| let {pattern} = filter; |
| if (pattern == null) |
| return result; |
| let candidates = pattern.toLowerCase().match(allKeywordsRegExp); |
| if (!candidates) |
| return result; |
| - let hash = this.filterByKeyword; |
| + let hash = this._filterByKeyword; |
| let resultCount = 0xFFFFFF; |
| let resultLength = 0; |
| for (let i = 0, l = candidates.length; i < l; i++) |
| { |
| let candidate = candidates[i].substr(1); |
| let filters = hash.get(candidate); |
| let count = typeof filters != "undefined" ? filters.size : 0; |
| if (count < resultCount || |
| @@ -159,21 +161,22 @@ |
| * @param {string} keyword |
| * @param {string} location |
| * @param {number} typeMask |
| * @param {string} [docDomain] |
| * @param {boolean} [thirdParty] |
| * @param {string} [sitekey] |
| * @param {boolean} [specificOnly] |
| * @returns {?Filter} |
| + * @protected |
| */ |
| - _checkEntryMatch(keyword, location, typeMask, docDomain, thirdParty, sitekey, |
| + checkEntryMatch(keyword, location, typeMask, docDomain, thirdParty, sitekey, |
| specificOnly) |
| { |
| - let set = this.filterByKeyword.get(keyword); |
| + let set = this._filterByKeyword.get(keyword); |
| if (typeof set == "undefined") |
| return null; |
| for (let filter of set) |
| { |
| if (specificOnly && filter.isGeneric() && |
| !(filter instanceof WhitelistFilter)) |
| continue; |
| @@ -204,17 +207,17 @@ |
| matchesAny(location, typeMask, docDomain, thirdParty, sitekey, specificOnly) |
| { |
| let candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g); |
| if (candidates === null) |
| candidates = []; |
| candidates.push(""); |
| for (let i = 0, l = candidates.length; i < l; i++) |
| { |
| - let result = this._checkEntryMatch(candidates[i], location, typeMask, |
| + let result = this.checkEntryMatch(candidates[i], location, typeMask, |
| docDomain, thirdParty, sitekey, |
| specificOnly); |
| if (result) |
| return result; |
| } |
| return null; |
| } |
| @@ -234,109 +237,114 @@ |
| * Maximal number of matching cache entries to be kept |
| * @type {number} |
| */ |
| this.maxCacheEntries = 1000; |
| /** |
| * Matcher for blocking rules. |
| * @type {Matcher} |
| + * @protected |
| */ |
| this.blacklist = new Matcher(); |
| /** |
| * Matcher for exception rules. |
| * @type {Matcher} |
| + * @protected |
| */ |
| this.whitelist = new Matcher(); |
| /** |
| * Lookup table of previous {@link Matcher#matchesAny} results |
| * @type {Map.<string,Filter>} |
| + * @private |
| */ |
| - this.resultCache = new Map(); |
| + this._resultCache = new Map(); |
| } |
| /** |
| * @see Matcher#clear |
| */ |
| clear() |
| { |
| this.blacklist.clear(); |
| this.whitelist.clear(); |
| - this.resultCache.clear(); |
| + this._resultCache.clear(); |
| } |
| /** |
| * @see Matcher#add |
| * @param {Filter} filter |
| */ |
| add(filter) |
| { |
| if (filter instanceof WhitelistFilter) |
| this.whitelist.add(filter); |
| else |
| this.blacklist.add(filter); |
| - this.resultCache.clear(); |
| + this._resultCache.clear(); |
| } |
| /** |
| * @see Matcher#remove |
| * @param {Filter} filter |
| */ |
| remove(filter) |
| { |
| if (filter instanceof WhitelistFilter) |
| this.whitelist.remove(filter); |
| else |
| this.blacklist.remove(filter); |
| - this.resultCache.clear(); |
| + this._resultCache.clear(); |
| } |
| /** |
| * @see Matcher#findKeyword |
| * @param {Filter} filter |
| * @returns {string} keyword |
| + * @protected |
| */ |
| findKeyword(filter) |
| { |
| if (filter instanceof WhitelistFilter) |
| return this.whitelist.findKeyword(filter); |
| return this.blacklist.findKeyword(filter); |
| } |
| /** |
| * Optimized filter matching testing both whitelist and blacklist matchers |
| * simultaneously. For parameters see |
| {@link Matcher#matchesAny Matcher.matchesAny()}. |
| * @see Matcher#matchesAny |
| * @inheritdoc |
| + * @private |
| */ |
| - matchesAnyInternal(location, typeMask, docDomain, thirdParty, sitekey, |
| + _matchesAnyInternal(location, typeMask, docDomain, thirdParty, sitekey, |
| specificOnly) |
| { |
| let candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g); |
| if (candidates === null) |
| candidates = []; |
| candidates.push(""); |
| let blacklistHit = null; |
| for (let i = 0, l = candidates.length; i < l; i++) |
| { |
| let substr = candidates[i]; |
| - let result = this.whitelist._checkEntryMatch( |
| + let result = this.whitelist.checkEntryMatch( |
| substr, location, typeMask, docDomain, thirdParty, sitekey |
| ); |
| if (result) |
| return result; |
| if (blacklistHit === null) |
| { |
| - blacklistHit = this.blacklist._checkEntryMatch( |
| + blacklistHit = this.blacklist.checkEntryMatch( |
| substr, location, typeMask, docDomain, thirdParty, sitekey, |
| specificOnly |
| ); |
| } |
| } |
| return blacklistHit; |
| } |
| @@ -344,27 +352,27 @@ |
| * @see Matcher#matchesAny |
| * @inheritdoc |
| */ |
| matchesAny(location, typeMask, docDomain, thirdParty, sitekey, specificOnly) |
| { |
| let key = location + " " + typeMask + " " + docDomain + " " + thirdParty + |
| " " + sitekey + " " + specificOnly; |
| - let result = this.resultCache.get(key); |
| + let result = this._resultCache.get(key); |
| if (typeof result != "undefined") |
| return result; |
| - result = this.matchesAnyInternal(location, typeMask, docDomain, |
| + result = this._matchesAnyInternal(location, typeMask, docDomain, |
| thirdParty, sitekey, specificOnly); |
| - if (this.resultCache.size >= this.maxCacheEntries) |
| - this.resultCache.clear(); |
| + if (this._resultCache.size >= this.maxCacheEntries) |
| + this._resultCache.clear(); |
| - this.resultCache.set(key, result); |
| + this._resultCache.set(key, result); |
| return result; |
| } |
| } |
| exports.CombinedMatcher = CombinedMatcher; |
| /** |