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: Address some PS2 comments Created Oct. 23, 2018, 1:26 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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 /** 51 /**
52 * Blacklist/whitelist filter matching 52 * Blacklist/whitelist filter matching
53 */ 53 */
54 class Matcher 54 class Matcher
55 { 55 {
56 constructor() 56 constructor()
57 { 57 {
58 /** 58 /**
59 * Lookup table for filters by their associated keyword 59 * Lookup table for filters by their associated keyword
60 * @type {Map.<string,(Filter|Set.<Filter>)>} 60 * @type {Map.<string,(Filter|Set.<Filter>)>}
61 * @private
61 */ 62 */
62 this.filterByKeyword = new Map(); 63 this._filterByKeyword = new Map();
63 } 64 }
64 65
65 /** 66 /**
66 * Removes all known filters 67 * Removes all known filters
67 */ 68 */
68 clear() 69 clear()
69 { 70 {
70 this.filterByKeyword.clear(); 71 this._filterByKeyword.clear();
71 } 72 }
72 73
73 /** 74 /**
74 * Adds a filter to the matcher 75 * Adds a filter to the matcher
75 * @param {RegExpFilter} filter 76 * @param {RegExpFilter} filter
76 */ 77 */
77 add(filter) 78 add(filter)
78 { 79 {
79 // Look for a suitable keyword 80 // Look for a suitable keyword
80 let keyword = this.findKeyword(filter); 81 let keyword = this.findKeyword(filter);
81 let set = this.filterByKeyword.get(keyword); 82 let set = this._filterByKeyword.get(keyword);
82 if (typeof set == "undefined") 83 if (typeof set == "undefined")
83 { 84 {
84 this.filterByKeyword.set(keyword, filter); 85 this._filterByKeyword.set(keyword, filter);
85 } 86 }
86 else if (set.size == 1) 87 else if (set.size == 1)
87 { 88 {
88 if (filter != set) 89 if (filter != set)
89 this.filterByKeyword.set(keyword, new Set([set, filter])); 90 this._filterByKeyword.set(keyword, new Set([set, filter]));
90 } 91 }
91 else 92 else
92 { 93 {
93 set.add(filter); 94 set.add(filter);
94 } 95 }
95 } 96 }
96 97
97 /** 98 /**
98 * Removes a filter from the matcher 99 * Removes a filter from the matcher
99 * @param {RegExpFilter} filter 100 * @param {RegExpFilter} filter
100 */ 101 */
101 remove(filter) 102 remove(filter)
102 { 103 {
103 let keyword = this.findKeyword(filter); 104 let keyword = this.findKeyword(filter);
104 let set = this.filterByKeyword.get(keyword); 105 let set = this._filterByKeyword.get(keyword);
105 if (typeof set == "undefined") 106 if (typeof set == "undefined")
106 return; 107 return;
107 108
108 if (set.size == 1) 109 if (set.size == 1)
109 { 110 {
110 if (filter == set) 111 if (filter == set)
111 this.filterByKeyword.delete(keyword); 112 this._filterByKeyword.delete(keyword);
112 } 113 }
113 else 114 else
114 { 115 {
115 set.delete(filter); 116 set.delete(filter);
116 117
117 if (set.size == 1) 118 if (set.size == 1)
118 this.filterByKeyword.set(keyword, [...set][0]); 119 this._filterByKeyword.set(keyword, [...set][0]);
119 } 120 }
120 } 121 }
121 122
122 /** 123 /**
123 * Chooses a keyword to be associated with the filter 124 * Chooses a keyword to be associated with the filter
124 * @param {Filter} filter 125 * @param {Filter} filter
125 * @returns {string} keyword or an empty string if no keyword could be found 126 * @returns {string} keyword or an empty string if no keyword could be found
127 * @protected
126 */ 128 */
127 findKeyword(filter) 129 findKeyword(filter)
128 { 130 {
129 let result = ""; 131 let result = "";
130 let {pattern} = filter; 132 let {pattern} = filter;
131 if (pattern == null) 133 if (pattern == null)
132 return result; 134 return result;
133 135
134 let candidates = pattern.toLowerCase().match(allKeywordsRegExp); 136 let candidates = pattern.toLowerCase().match(allKeywordsRegExp);
135 if (!candidates) 137 if (!candidates)
136 return result; 138 return result;
137 139
138 let hash = this.filterByKeyword; 140 let hash = this._filterByKeyword;
139 let resultCount = 0xFFFFFF; 141 let resultCount = 0xFFFFFF;
140 let resultLength = 0; 142 let resultLength = 0;
141 for (let i = 0, l = candidates.length; i < l; i++) 143 for (let i = 0, l = candidates.length; i < l; i++)
142 { 144 {
143 let candidate = candidates[i].substr(1); 145 let candidate = candidates[i].substr(1);
144 let filters = hash.get(candidate); 146 let filters = hash.get(candidate);
145 let count = typeof filters != "undefined" ? filters.size : 0; 147 let count = typeof filters != "undefined" ? filters.size : 0;
146 if (count < resultCount || 148 if (count < resultCount ||
147 (count == resultCount && candidate.length > resultLength)) 149 (count == resultCount && candidate.length > resultLength))
148 { 150 {
149 result = candidate; 151 result = candidate;
150 resultCount = count; 152 resultCount = count;
151 resultLength = candidate.length; 153 resultLength = candidate.length;
152 } 154 }
153 } 155 }
154 return result; 156 return result;
155 } 157 }
156 158
157 /** 159 /**
158 * Checks whether the entries for a particular keyword match a URL 160 * Checks whether the entries for a particular keyword match a URL
159 * @param {string} keyword 161 * @param {string} keyword
160 * @param {string} location 162 * @param {string} location
161 * @param {number} typeMask 163 * @param {number} typeMask
162 * @param {string} [docDomain] 164 * @param {string} [docDomain]
163 * @param {boolean} [thirdParty] 165 * @param {boolean} [thirdParty]
164 * @param {string} [sitekey] 166 * @param {string} [sitekey]
165 * @param {boolean} [specificOnly] 167 * @param {boolean} [specificOnly]
166 * @returns {?Filter} 168 * @returns {?Filter}
169 * @protected
167 */ 170 */
168 _checkEntryMatch(keyword, location, typeMask, docDomain, thirdParty, sitekey, 171 checkEntryMatch(keyword, location, typeMask, docDomain, thirdParty, sitekey,
169 specificOnly) 172 specificOnly)
170 { 173 {
171 let set = this.filterByKeyword.get(keyword); 174 let set = this._filterByKeyword.get(keyword);
172 if (typeof set == "undefined") 175 if (typeof set == "undefined")
173 return null; 176 return null;
174 177
175 for (let filter of set) 178 for (let filter of set)
176 { 179 {
177 if (specificOnly && filter.isGeneric() && 180 if (specificOnly && filter.isGeneric() &&
178 !(filter instanceof WhitelistFilter)) 181 !(filter instanceof WhitelistFilter))
179 continue; 182 continue;
180 183
181 if (filter.matches(location, typeMask, docDomain, thirdParty, sitekey)) 184 if (filter.matches(location, typeMask, docDomain, thirdParty, sitekey))
(...skipping 20 matching lines...) Expand all
202 * matching filter or <code>null</code> 205 * matching filter or <code>null</code>
203 */ 206 */
204 matchesAny(location, typeMask, docDomain, thirdParty, sitekey, specificOnly) 207 matchesAny(location, typeMask, docDomain, thirdParty, sitekey, specificOnly)
205 { 208 {
206 let candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g); 209 let candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g);
207 if (candidates === null) 210 if (candidates === null)
208 candidates = []; 211 candidates = [];
209 candidates.push(""); 212 candidates.push("");
210 for (let i = 0, l = candidates.length; i < l; i++) 213 for (let i = 0, l = candidates.length; i < l; i++)
211 { 214 {
212 let result = this._checkEntryMatch(candidates[i], location, typeMask, 215 let result = this.checkEntryMatch(candidates[i], location, typeMask,
213 docDomain, thirdParty, sitekey, 216 docDomain, thirdParty, sitekey,
214 specificOnly); 217 specificOnly);
215 if (result) 218 if (result)
216 return result; 219 return result;
217 } 220 }
218 221
219 return null; 222 return null;
220 } 223 }
221 } 224 }
222 225
223 exports.Matcher = Matcher; 226 exports.Matcher = Matcher;
224 227
225 /** 228 /**
226 * Combines a matcher for blocking and exception rules, automatically sorts 229 * Combines a matcher for blocking and exception rules, automatically sorts
227 * rules into two {@link Matcher} instances. 230 * rules into two {@link Matcher} instances.
228 */ 231 */
229 class CombinedMatcher 232 class CombinedMatcher
230 { 233 {
231 constructor() 234 constructor()
232 { 235 {
233 /** 236 /**
234 * Maximal number of matching cache entries to be kept 237 * Maximal number of matching cache entries to be kept
235 * @type {number} 238 * @type {number}
236 */ 239 */
237 this.maxCacheEntries = 1000; 240 this.maxCacheEntries = 1000;
238 241
239 /** 242 /**
240 * Matcher for blocking rules. 243 * Matcher for blocking rules.
241 * @type {Matcher} 244 * @type {Matcher}
245 * @protected
242 */ 246 */
243 this.blacklist = new Matcher(); 247 this.blacklist = new Matcher();
244 248
245 /** 249 /**
246 * Matcher for exception rules. 250 * Matcher for exception rules.
247 * @type {Matcher} 251 * @type {Matcher}
252 * @protected
248 */ 253 */
249 this.whitelist = new Matcher(); 254 this.whitelist = new Matcher();
250 255
251 /** 256 /**
252 * Lookup table of previous {@link Matcher#matchesAny} results 257 * Lookup table of previous {@link Matcher#matchesAny} results
253 * @type {Map.<string,Filter>} 258 * @type {Map.<string,Filter>}
259 * @private
254 */ 260 */
255 this.resultCache = new Map(); 261 this._resultCache = new Map();
256 } 262 }
257 263
258 /** 264 /**
259 * @see Matcher#clear 265 * @see Matcher#clear
260 */ 266 */
261 clear() 267 clear()
262 { 268 {
263 this.blacklist.clear(); 269 this.blacklist.clear();
264 this.whitelist.clear(); 270 this.whitelist.clear();
265 this.resultCache.clear(); 271 this._resultCache.clear();
266 } 272 }
267 273
268 /** 274 /**
269 * @see Matcher#add 275 * @see Matcher#add
270 * @param {Filter} filter 276 * @param {Filter} filter
271 */ 277 */
272 add(filter) 278 add(filter)
273 { 279 {
274 if (filter instanceof WhitelistFilter) 280 if (filter instanceof WhitelistFilter)
275 this.whitelist.add(filter); 281 this.whitelist.add(filter);
276 else 282 else
277 this.blacklist.add(filter); 283 this.blacklist.add(filter);
278 284
279 this.resultCache.clear(); 285 this._resultCache.clear();
280 } 286 }
281 287
282 /** 288 /**
283 * @see Matcher#remove 289 * @see Matcher#remove
284 * @param {Filter} filter 290 * @param {Filter} filter
285 */ 291 */
286 remove(filter) 292 remove(filter)
287 { 293 {
288 if (filter instanceof WhitelistFilter) 294 if (filter instanceof WhitelistFilter)
289 this.whitelist.remove(filter); 295 this.whitelist.remove(filter);
290 else 296 else
291 this.blacklist.remove(filter); 297 this.blacklist.remove(filter);
292 298
293 this.resultCache.clear(); 299 this._resultCache.clear();
294 } 300 }
295 301
296 /** 302 /**
297 * @see Matcher#findKeyword 303 * @see Matcher#findKeyword
298 * @param {Filter} filter 304 * @param {Filter} filter
299 * @returns {string} keyword 305 * @returns {string} keyword
306 * @protected
300 */ 307 */
301 findKeyword(filter) 308 findKeyword(filter)
302 { 309 {
303 if (filter instanceof WhitelistFilter) 310 if (filter instanceof WhitelistFilter)
304 return this.whitelist.findKeyword(filter); 311 return this.whitelist.findKeyword(filter);
305 return this.blacklist.findKeyword(filter); 312 return this.blacklist.findKeyword(filter);
306 } 313 }
307 314
308 /** 315 /**
309 * Optimized filter matching testing both whitelist and blacklist matchers 316 * Optimized filter matching testing both whitelist and blacklist matchers
310 * simultaneously. For parameters see 317 * simultaneously. For parameters see
311 {@link Matcher#matchesAny Matcher.matchesAny()}. 318 {@link Matcher#matchesAny Matcher.matchesAny()}.
312 * @see Matcher#matchesAny 319 * @see Matcher#matchesAny
313 * @inheritdoc 320 * @inheritdoc
321 * @private
314 */ 322 */
315 matchesAnyInternal(location, typeMask, docDomain, thirdParty, sitekey, 323 _matchesAnyInternal(location, typeMask, docDomain, thirdParty, sitekey,
316 specificOnly) 324 specificOnly)
317 { 325 {
318 let candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g); 326 let candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g);
319 if (candidates === null) 327 if (candidates === null)
320 candidates = []; 328 candidates = [];
321 candidates.push(""); 329 candidates.push("");
322 330
323 let blacklistHit = null; 331 let blacklistHit = null;
324 for (let i = 0, l = candidates.length; i < l; i++) 332 for (let i = 0, l = candidates.length; i < l; i++)
325 { 333 {
326 let substr = candidates[i]; 334 let substr = candidates[i];
327 let result = this.whitelist._checkEntryMatch( 335 let result = this.whitelist.checkEntryMatch(
328 substr, location, typeMask, docDomain, thirdParty, sitekey 336 substr, location, typeMask, docDomain, thirdParty, sitekey
329 ); 337 );
330 if (result) 338 if (result)
331 return result; 339 return result;
332 if (blacklistHit === null) 340 if (blacklistHit === null)
333 { 341 {
334 blacklistHit = this.blacklist._checkEntryMatch( 342 blacklistHit = this.blacklist.checkEntryMatch(
335 substr, location, typeMask, docDomain, thirdParty, sitekey, 343 substr, location, typeMask, docDomain, thirdParty, sitekey,
336 specificOnly 344 specificOnly
337 ); 345 );
338 } 346 }
339 } 347 }
340 return blacklistHit; 348 return blacklistHit;
341 } 349 }
342 350
343 /** 351 /**
344 * @see Matcher#matchesAny 352 * @see Matcher#matchesAny
345 * @inheritdoc 353 * @inheritdoc
346 */ 354 */
347 matchesAny(location, typeMask, docDomain, thirdParty, sitekey, specificOnly) 355 matchesAny(location, typeMask, docDomain, thirdParty, sitekey, specificOnly)
348 { 356 {
349 let key = location + " " + typeMask + " " + docDomain + " " + thirdParty + 357 let key = location + " " + typeMask + " " + docDomain + " " + thirdParty +
350 " " + sitekey + " " + specificOnly; 358 " " + sitekey + " " + specificOnly;
351 359
352 let result = this.resultCache.get(key); 360 let result = this._resultCache.get(key);
353 if (typeof result != "undefined") 361 if (typeof result != "undefined")
354 return result; 362 return result;
355 363
356 result = this.matchesAnyInternal(location, typeMask, docDomain, 364 result = this._matchesAnyInternal(location, typeMask, docDomain,
357 thirdParty, sitekey, specificOnly); 365 thirdParty, sitekey, specificOnly);
358 366
359 if (this.resultCache.size >= this.maxCacheEntries) 367 if (this._resultCache.size >= this.maxCacheEntries)
360 this.resultCache.clear(); 368 this._resultCache.clear();
361 369
362 this.resultCache.set(key, result); 370 this._resultCache.set(key, result);
363 371
364 return result; 372 return result;
365 } 373 }
366 } 374 }
367 375
368 exports.CombinedMatcher = CombinedMatcher; 376 exports.CombinedMatcher = CombinedMatcher;
369 377
370 /** 378 /**
371 * Shared {@link CombinedMatcher} instance that should usually be used. 379 * Shared {@link CombinedMatcher} instance that should usually be used.
372 * @type {CombinedMatcher} 380 * @type {CombinedMatcher}
373 */ 381 */
374 let defaultMatcher = new CombinedMatcher(); 382 let defaultMatcher = new CombinedMatcher();
375 383
376 exports.defaultMatcher = defaultMatcher; 384 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