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

Side by Side Diff: lib/matcher.js

Issue 29897555: Issue 6940 - Use underscore prefixes lib/matcher.js (Closed)
Patch Set: Rebase Created Oct. 23, 2018, 4:05 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | test/filterListener.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-present eyeo GmbH 3 * Copyright (C) 2006-present eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 /** 61 /**
62 * Blacklist/whitelist filter matching 62 * Blacklist/whitelist filter matching
63 */ 63 */
64 class Matcher 64 class Matcher
65 { 65 {
66 constructor() 66 constructor()
67 { 67 {
68 /** 68 /**
69 * Lookup table for filters by their associated keyword 69 * Lookup table for filters by their associated keyword
70 * @type {Map.<string,(Filter|Set.<Filter>)>} 70 * @type {Map.<string,(Filter|Set.<Filter>)>}
71 * @private
71 */ 72 */
72 this.filterByKeyword = new Map(); 73 this._filterByKeyword = new Map();
73 } 74 }
74 75
75 /** 76 /**
76 * Removes all known filters 77 * Removes all known filters
77 */ 78 */
78 clear() 79 clear()
79 { 80 {
80 this.filterByKeyword.clear(); 81 this._filterByKeyword.clear();
81 } 82 }
82 83
83 /** 84 /**
84 * Adds a filter to the matcher 85 * Adds a filter to the matcher
85 * @param {RegExpFilter} filter 86 * @param {RegExpFilter} filter
86 */ 87 */
87 add(filter) 88 add(filter)
88 { 89 {
89 // Look for a suitable keyword 90 // Look for a suitable keyword
90 let keyword = this.findKeyword(filter); 91 let keyword = this.findKeyword(filter);
91 let set = this.filterByKeyword.get(keyword); 92 let set = this._filterByKeyword.get(keyword);
92 if (typeof set == "undefined") 93 if (typeof set == "undefined")
93 { 94 {
94 this.filterByKeyword.set(keyword, filter); 95 this._filterByKeyword.set(keyword, filter);
95 } 96 }
96 else if (set.size == 1) 97 else if (set.size == 1)
97 { 98 {
98 if (filter != set) 99 if (filter != set)
99 this.filterByKeyword.set(keyword, new Set([set, filter])); 100 this._filterByKeyword.set(keyword, new Set([set, filter]));
100 } 101 }
101 else 102 else
102 { 103 {
103 set.add(filter); 104 set.add(filter);
104 } 105 }
105 } 106 }
106 107
107 /** 108 /**
108 * Removes a filter from the matcher 109 * Removes a filter from the matcher
109 * @param {RegExpFilter} filter 110 * @param {RegExpFilter} filter
110 */ 111 */
111 remove(filter) 112 remove(filter)
112 { 113 {
113 let keyword = this.findKeyword(filter); 114 let keyword = this.findKeyword(filter);
114 let set = this.filterByKeyword.get(keyword); 115 let set = this._filterByKeyword.get(keyword);
115 if (typeof set == "undefined") 116 if (typeof set == "undefined")
116 return; 117 return;
117 118
118 if (set.size == 1) 119 if (set.size == 1)
119 { 120 {
120 if (filter == set) 121 if (filter == set)
121 this.filterByKeyword.delete(keyword); 122 this._filterByKeyword.delete(keyword);
122 } 123 }
123 else 124 else
124 { 125 {
125 set.delete(filter); 126 set.delete(filter);
126 127
127 if (set.size == 1) 128 if (set.size == 1)
128 this.filterByKeyword.set(keyword, [...set][0]); 129 this._filterByKeyword.set(keyword, [...set][0]);
129 } 130 }
130 } 131 }
131 132
132 /** 133 /**
133 * Chooses a keyword to be associated with the filter 134 * Chooses a keyword to be associated with the filter
134 * @param {Filter} filter 135 * @param {Filter} filter
135 * @returns {string} keyword or an empty string if no keyword could be found 136 * @returns {string} keyword or an empty string if no keyword could be found
137 * @protected
136 */ 138 */
137 findKeyword(filter) 139 findKeyword(filter)
138 { 140 {
139 let result = ""; 141 let result = "";
140 let {pattern} = filter; 142 let {pattern} = filter;
141 if (pattern == null) 143 if (pattern == null)
142 return result; 144 return result;
143 145
144 let candidates = pattern.toLowerCase().match(allKeywordsRegExp); 146 let candidates = pattern.toLowerCase().match(allKeywordsRegExp);
145 if (!candidates) 147 if (!candidates)
146 return result; 148 return result;
147 149
148 let hash = this.filterByKeyword; 150 let hash = this._filterByKeyword;
149 let resultCount = 0xFFFFFF; 151 let resultCount = 0xFFFFFF;
150 let resultLength = 0; 152 let resultLength = 0;
151 for (let i = 0, l = candidates.length; i < l; i++) 153 for (let i = 0, l = candidates.length; i < l; i++)
152 { 154 {
153 let candidate = candidates[i].substr(1); 155 let candidate = candidates[i].substr(1);
154 let filters = hash.get(candidate); 156 let filters = hash.get(candidate);
155 let count = typeof filters != "undefined" ? filters.size : 0; 157 let count = typeof filters != "undefined" ? filters.size : 0;
156 if (count < resultCount || 158 if (count < resultCount ||
157 (count == resultCount && candidate.length > resultLength)) 159 (count == resultCount && candidate.length > resultLength))
158 { 160 {
159 result = candidate; 161 result = candidate;
160 resultCount = count; 162 resultCount = count;
161 resultLength = candidate.length; 163 resultLength = candidate.length;
162 } 164 }
163 } 165 }
164 return result; 166 return result;
165 } 167 }
166 168
167 /** 169 /**
168 * Checks whether the entries for a particular keyword match a URL 170 * Checks whether the entries for a particular keyword match a URL
169 * @param {string} keyword 171 * @param {string} keyword
170 * @param {string} location 172 * @param {string} location
171 * @param {number} typeMask 173 * @param {number} typeMask
172 * @param {string} [docDomain] 174 * @param {string} [docDomain]
173 * @param {boolean} [thirdParty] 175 * @param {boolean} [thirdParty]
174 * @param {string} [sitekey] 176 * @param {string} [sitekey]
175 * @param {boolean} [specificOnly] 177 * @param {boolean} [specificOnly]
176 * @returns {?Filter} 178 * @returns {?Filter}
179 * @protected
177 */ 180 */
178 _checkEntryMatch(keyword, location, typeMask, docDomain, thirdParty, sitekey, 181 checkEntryMatch(keyword, location, typeMask, docDomain, thirdParty, sitekey,
179 specificOnly) 182 specificOnly)
180 { 183 {
181 let set = this.filterByKeyword.get(keyword); 184 let set = this._filterByKeyword.get(keyword);
182 if (typeof set == "undefined") 185 if (typeof set == "undefined")
183 return null; 186 return null;
184 187
185 for (let filter of set) 188 for (let filter of set)
186 { 189 {
187 if (specificOnly && filter.isGeneric() && 190 if (specificOnly && filter.isGeneric() &&
188 !(filter instanceof WhitelistFilter)) 191 !(filter instanceof WhitelistFilter))
189 continue; 192 continue;
190 193
191 if (filter.matches(location, typeMask, docDomain, thirdParty, sitekey)) 194 if (filter.matches(location, typeMask, docDomain, thirdParty, sitekey))
(...skipping 20 matching lines...) Expand all
212 * matching filter or <code>null</code> 215 * matching filter or <code>null</code>
213 */ 216 */
214 matchesAny(location, typeMask, docDomain, thirdParty, sitekey, specificOnly) 217 matchesAny(location, typeMask, docDomain, thirdParty, sitekey, specificOnly)
215 { 218 {
216 let candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g); 219 let candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g);
217 if (candidates === null) 220 if (candidates === null)
218 candidates = []; 221 candidates = [];
219 candidates.push(""); 222 candidates.push("");
220 for (let i = 0, l = candidates.length; i < l; i++) 223 for (let i = 0, l = candidates.length; i < l; i++)
221 { 224 {
222 let result = this._checkEntryMatch(candidates[i], location, typeMask, 225 let result = this.checkEntryMatch(candidates[i], location, typeMask,
223 docDomain, thirdParty, sitekey, 226 docDomain, thirdParty, sitekey,
224 specificOnly); 227 specificOnly);
225 if (result) 228 if (result)
226 return result; 229 return result;
227 } 230 }
228 231
229 return null; 232 return null;
230 } 233 }
231 } 234 }
232 235
(...skipping 10 matching lines...) Expand all
243 /** 246 /**
244 * Maximal number of matching cache entries to be kept 247 * Maximal number of matching cache entries to be kept
245 * @type {number} 248 * @type {number}
246 */ 249 */
247 this.maxCacheEntries = 1000; 250 this.maxCacheEntries = 1000;
248 251
249 /** 252 /**
250 * Matcher for blocking rules. 253 * Matcher for blocking rules.
251 * @type {Matcher} 254 * @type {Matcher}
252 */ 255 */
253 this.blacklist = new Matcher(); 256 this._blacklist = new Matcher();
254 257
255 /** 258 /**
256 * Matcher for exception rules. 259 * Matcher for exception rules.
257 * @type {Matcher} 260 * @type {Matcher}
258 */ 261 */
259 this.whitelist = new Matcher(); 262 this._whitelist = new Matcher();
260 263
261 /** 264 /**
262 * Lookup table of previous {@link Matcher#matchesAny} results 265 * Lookup table of previous {@link Matcher#matchesAny} results
263 * @type {Map.<string,Filter>} 266 * @type {Map.<string,Filter>}
264 */ 267 */
265 this.resultCache = new Map(); 268 this._resultCache = new Map();
266 } 269 }
267 270
268 /** 271 /**
269 * @see Matcher#clear 272 * @see Matcher#clear
270 */ 273 */
271 clear() 274 clear()
272 { 275 {
273 this.blacklist.clear(); 276 this._blacklist.clear();
274 this.whitelist.clear(); 277 this._whitelist.clear();
275 this.resultCache.clear(); 278 this._resultCache.clear();
276 } 279 }
277 280
278 /** 281 /**
279 * @see Matcher#add 282 * @see Matcher#add
280 * @param {Filter} filter 283 * @param {Filter} filter
281 */ 284 */
282 add(filter) 285 add(filter)
283 { 286 {
284 if (filter instanceof WhitelistFilter) 287 if (filter instanceof WhitelistFilter)
285 this.whitelist.add(filter); 288 this._whitelist.add(filter);
286 else 289 else
287 this.blacklist.add(filter); 290 this._blacklist.add(filter);
288 291
289 this.resultCache.clear(); 292 this._resultCache.clear();
290 } 293 }
291 294
292 /** 295 /**
293 * @see Matcher#remove 296 * @see Matcher#remove
294 * @param {Filter} filter 297 * @param {Filter} filter
295 */ 298 */
296 remove(filter) 299 remove(filter)
297 { 300 {
298 if (filter instanceof WhitelistFilter) 301 if (filter instanceof WhitelistFilter)
299 this.whitelist.remove(filter); 302 this._whitelist.remove(filter);
300 else 303 else
301 this.blacklist.remove(filter); 304 this._blacklist.remove(filter);
302 305
303 this.resultCache.clear(); 306 this._resultCache.clear();
304 } 307 }
305 308
306 /** 309 /**
307 * @see Matcher#findKeyword 310 * @see Matcher#findKeyword
308 * @param {Filter} filter 311 * @param {Filter} filter
309 * @returns {string} keyword 312 * @returns {string} keyword
313 * @protected
310 */ 314 */
311 findKeyword(filter) 315 findKeyword(filter)
312 { 316 {
313 if (filter instanceof WhitelistFilter) 317 if (filter instanceof WhitelistFilter)
314 return this.whitelist.findKeyword(filter); 318 return this._whitelist.findKeyword(filter);
315 return this.blacklist.findKeyword(filter); 319 return this._blacklist.findKeyword(filter);
316 } 320 }
317 321
318 /** 322 /**
319 * Optimized filter matching testing both whitelist and blacklist matchers 323 * Optimized filter matching testing both whitelist and blacklist matchers
320 * simultaneously. For parameters see 324 * simultaneously. For parameters see
321 {@link Matcher#matchesAny Matcher.matchesAny()}. 325 {@link Matcher#matchesAny Matcher.matchesAny()}.
322 * @see Matcher#matchesAny 326 * @see Matcher#matchesAny
323 * @inheritdoc 327 * @inheritdoc
328 * @private
324 */ 329 */
325 matchesAnyInternal(location, typeMask, docDomain, thirdParty, sitekey, 330 _matchesAnyInternal(location, typeMask, docDomain, thirdParty, sitekey,
326 specificOnly) 331 specificOnly)
327 { 332 {
328 let candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g); 333 let candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g);
329 if (candidates === null) 334 if (candidates === null)
330 candidates = []; 335 candidates = [];
331 candidates.push(""); 336 candidates.push("");
332 337
333 let whitelistHit = null; 338 let whitelistHit = null;
334 let blacklistHit = null; 339 let blacklistHit = null;
335 340
336 // If the type mask includes no types other than whitelist-only types, we 341 // If the type mask includes no types other than whitelist-only types, we
337 // can skip the blacklist. 342 // can skip the blacklist.
338 if ((typeMask & ~WHITELIST_ONLY_TYPES) != 0) 343 if ((typeMask & ~WHITELIST_ONLY_TYPES) != 0)
339 { 344 {
340 for (let i = 0, l = candidates.length; !blacklistHit && i < l; i++) 345 for (let i = 0, l = candidates.length; !blacklistHit && i < l; i++)
341 { 346 {
342 blacklistHit = this.blacklist._checkEntryMatch(candidates[i], location, 347 blacklistHit = this._blacklist.checkEntryMatch(candidates[i], location,
343 typeMask, docDomain, 348 typeMask, docDomain,
344 thirdParty, sitekey, 349 thirdParty, sitekey,
345 specificOnly); 350 specificOnly);
346 } 351 }
347 } 352 }
348 353
349 // If the type mask includes any whitelist-only types, we need to check the 354 // If the type mask includes any whitelist-only types, we need to check the
350 // whitelist. 355 // whitelist.
351 if (blacklistHit || (typeMask & WHITELIST_ONLY_TYPES) != 0) 356 if (blacklistHit || (typeMask & WHITELIST_ONLY_TYPES) != 0)
352 { 357 {
353 for (let i = 0, l = candidates.length; !whitelistHit && i < l; i++) 358 for (let i = 0, l = candidates.length; !whitelistHit && i < l; i++)
354 { 359 {
355 whitelistHit = this.whitelist._checkEntryMatch(candidates[i], location, 360 whitelistHit = this._whitelist.checkEntryMatch(candidates[i], location,
356 typeMask, docDomain, 361 typeMask, docDomain,
357 thirdParty, sitekey); 362 thirdParty, sitekey);
358 } 363 }
359 } 364 }
360 365
361 return whitelistHit || blacklistHit; 366 return whitelistHit || blacklistHit;
362 } 367 }
363 368
364 /** 369 /**
365 * @see Matcher#matchesAny 370 * @see Matcher#matchesAny
366 * @inheritdoc 371 * @inheritdoc
367 */ 372 */
368 matchesAny(location, typeMask, docDomain, thirdParty, sitekey, specificOnly) 373 matchesAny(location, typeMask, docDomain, thirdParty, sitekey, specificOnly)
369 { 374 {
370 let key = location + " " + typeMask + " " + docDomain + " " + thirdParty + 375 let key = location + " " + typeMask + " " + docDomain + " " + thirdParty +
371 " " + sitekey + " " + specificOnly; 376 " " + sitekey + " " + specificOnly;
372 377
373 let result = this.resultCache.get(key); 378 let result = this._resultCache.get(key);
374 if (typeof result != "undefined") 379 if (typeof result != "undefined")
375 return result; 380 return result;
376 381
377 result = this.matchesAnyInternal(location, typeMask, docDomain, 382 result = this._matchesAnyInternal(location, typeMask, docDomain,
378 thirdParty, sitekey, specificOnly); 383 thirdParty, sitekey, specificOnly);
379 384
380 if (this.resultCache.size >= this.maxCacheEntries) 385 if (this._resultCache.size >= this.maxCacheEntries)
381 this.resultCache.clear(); 386 this._resultCache.clear();
382 387
383 this.resultCache.set(key, result); 388 this._resultCache.set(key, result);
384 389
385 return result; 390 return result;
386 } 391 }
387 } 392 }
388 393
389 exports.CombinedMatcher = CombinedMatcher; 394 exports.CombinedMatcher = CombinedMatcher;
390 395
391 /** 396 /**
392 * Shared {@link CombinedMatcher} instance that should usually be used. 397 * Shared {@link CombinedMatcher} instance that should usually be used.
393 * @type {CombinedMatcher} 398 * @type {CombinedMatcher}
394 */ 399 */
395 let defaultMatcher = new CombinedMatcher(); 400 let defaultMatcher = new CombinedMatcher();
396 401
397 exports.defaultMatcher = defaultMatcher; 402 exports.defaultMatcher = defaultMatcher;
OLDNEW
« no previous file with comments | « no previous file | test/filterListener.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld