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

Side by Side Diff: lib/matcher.js

Issue 29907586: Issue 6994 - Use shortcut matching for location only filters (Closed)
Patch Set: Created Oct. 21, 2018, 3:51 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 | « lib/filterClasses.js ('k') | 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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 */ 61 */
62 this.filterByKeyword = new Map(); 62 this.filterByKeyword = new Map();
63
64 /**
65 * Lookup table for location only filters by their associated keyword
66 * for shortcut matching.
67 * @private
68 * @type {Map.<string,(Filter|Set.<Filter>)>}
69 */
70 this._fastFilterByKeyword = new Map();
63 } 71 }
64 72
65 /** 73 /**
66 * Removes all known filters 74 * Removes all known filters
67 */ 75 */
68 clear() 76 clear()
69 { 77 {
70 this.filterByKeyword.clear(); 78 this.filterByKeyword.clear();
79 this._fastFilterByKeyword.clear();
71 } 80 }
72 81
73 /** 82 /**
74 * Adds a filter to the matcher 83 * Adds a filter to the matcher
75 * @param {RegExpFilter} filter 84 * @param {RegExpFilter} filter
76 */ 85 */
77 add(filter) 86 add(filter)
78 { 87 {
79 // Look for a suitable keyword 88 // Look for a suitable keyword
80 let keyword = this.findKeyword(filter); 89 let keyword = this.findKeyword(filter);
81 let set = this.filterByKeyword.get(keyword); 90 let set = filter.isLocationOnly ? this._fastFilterByKeyword.get(keyword) :
91 this.filterByKeyword.get(keyword);
92
82 if (typeof set == "undefined") 93 if (typeof set == "undefined")
83 { 94 {
84 this.filterByKeyword.set(keyword, filter); 95 filter.isLocationOnly ?
96 this._fastFilterByKeyword.set(keyword, filter) :
97 this.filterByKeyword.set(keyword, filter);
85 } 98 }
86 else if (set.size == 1) 99 else if (set.size == 1)
87 { 100 {
88 if (filter != set) 101 if (filter != set)
89 this.filterByKeyword.set(keyword, new Set([set, filter])); 102 filter.isLocationOnly ?
103 this._fastFilterByKeyword.set(keyword, new Set([set, filter])) :
104 this.filterByKeyword.set(keyword, new Set([set, filter]));
90 } 105 }
91 else 106 else
92 { 107 {
93 set.add(filter); 108 set.add(filter);
94 } 109 }
95 } 110 }
96 111
97 /** 112 /**
98 * Removes a filter from the matcher 113 * Removes a filter from the matcher
99 * @param {RegExpFilter} filter 114 * @param {RegExpFilter} filter
100 */ 115 */
101 remove(filter) 116 remove(filter)
102 { 117 {
103 let keyword = this.findKeyword(filter); 118 let keyword = this.findKeyword(filter);
104 let set = this.filterByKeyword.get(keyword); 119 let set = filter.isLocationOnly ? this._fastFilterByKeyword.get(keyword) :
120 this.filterByKeyword.get(keyword);
121
105 if (typeof set == "undefined") 122 if (typeof set == "undefined")
106 return; 123 return;
107 124
108 if (set.size == 1) 125 if (set.size == 1)
109 { 126 {
110 if (filter == set) 127 if (filter == set)
111 this.filterByKeyword.delete(keyword); 128 filter.isLocationOnly ?
129 this._fastFilterByKeyword.delete(keyword) :
130 this.filterByKeyword.delete(keyword);
112 } 131 }
113 else 132 else
114 { 133 {
115 set.delete(filter); 134 set.delete(filter);
116 135
117 if (set.size == 1) 136 if (set.size == 1)
118 this.filterByKeyword.set(keyword, [...set][0]); 137 filter.isLocationOnly ?
138 this._fastFilterByKeyword.set(keyword, [...set][0]) :
139 this.filterByKeyword.set(keyword, [...set][0]);
119 } 140 }
120 } 141 }
121 142
122 /** 143 /**
123 * Chooses a keyword to be associated with the filter 144 * Chooses a keyword to be associated with the filter
124 * @param {Filter} filter 145 * @param {Filter} filter
125 * @returns {string} keyword or an empty string if no keyword could be found 146 * @returns {string} keyword or an empty string if no keyword could be found
126 */ 147 */
127 findKeyword(filter) 148 findKeyword(filter)
128 { 149 {
129 let result = ""; 150 let result = "";
130 let {pattern} = filter; 151 let {pattern} = filter;
131 if (pattern == null) 152 if (pattern == null)
132 return result; 153 return result;
133 154
134 let candidates = pattern.toLowerCase().match(allKeywordsRegExp); 155 let candidates = pattern.toLowerCase().match(allKeywordsRegExp);
135 if (!candidates) 156 if (!candidates)
136 return result; 157 return result;
137 158
138 let hash = this.filterByKeyword; 159 let hash = filter.isLocationOnly ? this._fastFilterByKeyword :
160 this.filterByKeyword;
139 let resultCount = 0xFFFFFF; 161 let resultCount = 0xFFFFFF;
140 let resultLength = 0; 162 let resultLength = 0;
141 for (let i = 0, l = candidates.length; i < l; i++) 163 for (let i = 0, l = candidates.length; i < l; i++)
142 { 164 {
143 let candidate = candidates[i].substr(1); 165 let candidate = candidates[i].substr(1);
144 let filters = hash.get(candidate); 166 let filters = hash.get(candidate);
145 let count = typeof filters != "undefined" ? filters.size : 0; 167 let count = typeof filters != "undefined" ? filters.size : 0;
146 if (count < resultCount || 168 if (count < resultCount ||
147 (count == resultCount && candidate.length > resultLength)) 169 (count == resultCount && candidate.length > resultLength))
148 { 170 {
(...skipping 12 matching lines...) Expand all
161 * @param {number} typeMask 183 * @param {number} typeMask
162 * @param {string} [docDomain] 184 * @param {string} [docDomain]
163 * @param {boolean} [thirdParty] 185 * @param {boolean} [thirdParty]
164 * @param {string} [sitekey] 186 * @param {string} [sitekey]
165 * @param {boolean} [specificOnly] 187 * @param {boolean} [specificOnly]
166 * @returns {?Filter} 188 * @returns {?Filter}
167 */ 189 */
168 _checkEntryMatch(keyword, location, typeMask, docDomain, thirdParty, sitekey, 190 _checkEntryMatch(keyword, location, typeMask, docDomain, thirdParty, sitekey,
169 specificOnly) 191 specificOnly)
170 { 192 {
193 let fastSet = this._fastFilterByKeyword.get(keyword);
194 if (typeof fastSet != "undefined")
195 {
196 for (let filter of fastSet)
197 {
198 if (filter.contentType == 0 && typeMask == 0)
199 continue;
200
201 if (specificOnly && filter.isGeneric() &&
202 !(filter instanceof WhitelistFilter))
203 continue;
204
205 if (filter.matchesLocation(location))
206 return filter;
207 }
208 }
171 let set = this.filterByKeyword.get(keyword); 209 let set = this.filterByKeyword.get(keyword);
172 if (typeof set == "undefined") 210 if (typeof set == "undefined")
173 return null; 211 return null;
174 212
175 for (let filter of set) 213 for (let filter of set)
176 { 214 {
177 if (specificOnly && filter.isGeneric() && 215 if (specificOnly && filter.isGeneric() &&
178 !(filter instanceof WhitelistFilter)) 216 !(filter instanceof WhitelistFilter))
179 continue; 217 continue;
180 218
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 405
368 exports.CombinedMatcher = CombinedMatcher; 406 exports.CombinedMatcher = CombinedMatcher;
369 407
370 /** 408 /**
371 * Shared {@link CombinedMatcher} instance that should usually be used. 409 * Shared {@link CombinedMatcher} instance that should usually be used.
372 * @type {CombinedMatcher} 410 * @type {CombinedMatcher}
373 */ 411 */
374 let defaultMatcher = new CombinedMatcher(); 412 let defaultMatcher = new CombinedMatcher();
375 413
376 exports.defaultMatcher = defaultMatcher; 414 exports.defaultMatcher = defaultMatcher;
OLDNEW
« no previous file with comments | « lib/filterClasses.js ('k') | test/filterListener.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld