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

Side by Side Diff: lib/elemHide.js

Issue 29342830: Issue 4057 - Further speedup ElemHide.getSelectorsforDomain (Closed)
Patch Set: Take care to remove filters from lookups Created May 20, 2016, 10:45 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/cssRules.js ('k') | no next file » | 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-2016 Eyeo GmbH 3 * Copyright (C) 2006-2016 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 22 matching lines...) Expand all
33 */ 33 */
34 var filterByKey = Object.create(null); 34 var filterByKey = Object.create(null);
35 35
36 /** 36 /**
37 * Lookup table, keys of the filters by filter text 37 * Lookup table, keys of the filters by filter text
38 * @type Object 38 * @type Object
39 */ 39 */
40 var keyByFilter = Object.create(null); 40 var keyByFilter = Object.create(null);
41 41
42 /** 42 /**
43 * Nested lookup table, filter (or false if inactive) by filter text by domain 43 * Indicates whether we are using getSelectorsByDomain and maintaining the
44 * @type Object 44 * required lookup tables. (Will be false for Firefox)
45 * @type Boolean
45 */ 46 */
46 var filtersByDomain = Object.create(null); 47 var usingGetSelectorsByDomain = !("nsIStyleSheetService" in Ci);
47 48
48 /** 49 /**
49 * Indicates whether we are using (and maintaining) the filtersByDomain lookup. 50 * Lookup table, filter selector by filter ID.
50 * (Will be false for Firefox)
51 * @type Boolean
52 */ 51 */
53 var usingFiltersByDomain = !("nsIStyleSheetService" in Ci); 52 var selectorByFilterId = [];
53
54 /**
55 * Lookup table, active filter IDs by domain.
56 */
57 var activeFilterIdsByDomain = Object.create(null);
58
59 /**
60 * Lookup table, inactive filter IDs by domain.
61 */
62 var inactiveFilterIdsByDomain = Object.create(null);
63
64 /**
65 * Lookup table, filter ID by filter text.
66 */
67 var filterIdByFilterText = Object.create(null);
54 68
55 /** 69 /**
56 * Object to be used instead when a filter has a blank domains property. 70 * Object to be used instead when a filter has a blank domains property.
57 */ 71 */
58 var defaultDomains = Object.create(null); 72 var defaultDomains = Object.create(null);
59 defaultDomains[""] = true; 73 defaultDomains[""] = true;
60 74
61 /** 75 /**
62 * Lookup table, keys are known element hiding exceptions 76 * Lookup table, keys are known element hiding exceptions
63 * @type Object 77 * @type Object
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 styleURL = Services.io.newFileURI(styleFile).QueryInterface(Ci.nsIFileURL); 125 styleURL = Services.io.newFileURI(styleFile).QueryInterface(Ci.nsIFileURL);
112 }, 126 },
113 127
114 /** 128 /**
115 * Removes all known filters 129 * Removes all known filters
116 */ 130 */
117 clear: function() 131 clear: function()
118 { 132 {
119 filterByKey = Object.create(null); 133 filterByKey = Object.create(null);
120 keyByFilter = Object.create(null); 134 keyByFilter = Object.create(null);
121 filtersByDomain = Object.create(null); 135 selectorByFilterId = [];
136 activeFilterIdsByDomain = Object.create(null);
137 inactiveFilterIdsByDomain = Object.create(null);
138 filterIdByFilterText = Object.create(null);
122 knownExceptions = Object.create(null); 139 knownExceptions = Object.create(null);
123 exceptions = Object.create(null); 140 exceptions = Object.create(null);
124 ElemHide.isDirty = false; 141 ElemHide.isDirty = false;
125 ElemHide.unapply(); 142 ElemHide.unapply();
126 }, 143 },
127 144
128 /** 145 /**
129 * Add a new element hiding filter 146 * Add a new element hiding filter
130 * @param {ElemHideFilter} filter 147 * @param {ElemHideFilter} filter
131 */ 148 */
(...skipping 16 matching lines...) Expand all
148 return; 165 return;
149 166
150 let key; 167 let key;
151 do { 168 do {
152 key = Math.random().toFixed(15).substr(5); 169 key = Math.random().toFixed(15).substr(5);
153 } while (key in filterByKey); 170 } while (key in filterByKey);
154 171
155 filterByKey[key] = filter; 172 filterByKey[key] = filter;
156 keyByFilter[filter.text] = key; 173 keyByFilter[filter.text] = key;
157 174
158 if (usingFiltersByDomain) 175 if (usingGetSelectorsByDomain)
159 { 176 {
177 let filterId = filterIdByFilterText[filter.text];
178 if (filterId == undefined)
Wladimir Palant 2016/05/20 12:33:27 That's one of the few cases where you need ===, be
Sebastian Noack 2016/05/20 13:03:04 We always use typeof when checking for undefined.
kzar 2016/05/21 04:43:09 Acknowledged.
179 {
180 filterId = selectorByFilterId.push(filter.selector) - 1;
181 filterIdByFilterText[filter.text] = filterId;
182 }
183
160 let domainMatches = filter.domains || defaultDomains; 184 let domainMatches = filter.domains || defaultDomains;
185
Sebastian Noack 2016/05/20 13:03:03 Nit: It seems the code reads better without the bl
kzar 2016/05/21 04:43:09 Done.
161 for (let domain in domainMatches) 186 for (let domain in domainMatches)
162 { 187 {
163 let filters = filtersByDomain[domain]; 188 let lookup;
164 if (!filters) 189 if (domainMatches[domain])
165 filters = filtersByDomain[domain] = Object.create(null); 190 lookup = activeFilterIdsByDomain;
191 else
192 lookup = inactiveFilterIdsByDomain;
166 193
167 if (domainMatches[domain]) 194 let filterIds = lookup[domain];
168 filters[filter.text] = filter; 195 if (filterIds == undefined)
169 else 196 filterIds = lookup[domain] = [];
170 filters[filter.text] = false; 197
198 filterIds.push(filterId);
171 } 199 }
172 } 200 }
173 201
174 ElemHide.isDirty = true; 202 ElemHide.isDirty = true;
175 } 203 }
176 }, 204 },
177 205
178 /** 206 /**
179 * Removes an element hiding filter 207 * Removes an element hiding filter
180 * @param {ElemHideFilter} filter 208 * @param {ElemHideFilter} filter
(...skipping 13 matching lines...) Expand all
194 } 222 }
195 else 223 else
196 { 224 {
197 if (!(filter.text in keyByFilter)) 225 if (!(filter.text in keyByFilter))
198 return; 226 return;
199 227
200 let key = keyByFilter[filter.text]; 228 let key = keyByFilter[filter.text];
201 delete filterByKey[key]; 229 delete filterByKey[key];
202 delete keyByFilter[filter.text]; 230 delete keyByFilter[filter.text];
203 ElemHide.isDirty = true; 231 ElemHide.isDirty = true;
232
233 if (usingGetSelectorsByDomain)
kzar 2016/05/20 10:55:17 I'm not too happy with this change it's kind of sl
234 {
235 let filterId = filterIdByFilterText[filter.text];
236 if (filterId)
237 {
238 delete filterIdByFilterText[filter.text];
239 delete selectorByFilterId[filterId];
240
241 let domains = Object.keys(filter.domains || defaultDomains);
Wladimir Palant 2016/05/20 12:33:27 Why use Object.keys() here all the sudden rather t
kzar 2016/05/21 04:43:09 Done.
242 let filterIdsByDomainLookups = [activeFilterIdsByDomain,
243 inactiveFilterIdsByDomain];
244 for (let domain of domains)
245 {
246 for (let filterIdsByDomain of filterIdsByDomainLookups)
247 {
248 let lookup = filterIdsByDomain[domain];
249 if (lookup)
250 {
251 let index = lookup.indexOf(filterId);
252 if (index != -1)
253 lookup.splice(index, 1);
254 }
255 }
256 }
257 }
258 }
204 } 259 }
205 }, 260 },
206 261
207 /** 262 /**
208 * Checks whether an exception rule is registered for a filter on a particular 263 * Checks whether an exception rule is registered for a filter on a particular
209 * domain. 264 * domain.
210 */ 265 */
211 getException: function(/**Filter*/ filter, /**String*/ docDomain) /**ElemHideE xception*/ 266 getException: function(/**String*/ selector, /**String*/ docDomain) /**ElemHid eException*/
212 { 267 {
213 if (!(filter.selector in exceptions)) 268 if (!(selector in exceptions))
214 return null; 269 return null;
215 270
216 let list = exceptions[filter.selector]; 271 let list = exceptions[selector];
217 for (let i = list.length - 1; i >= 0; i--) 272 for (let i = list.length - 1; i >= 0; i--)
218 if (list[i].isActiveOnDomain(docDomain)) 273 if (list[i].isActiveOnDomain(docDomain))
219 return list[i]; 274 return list[i];
220 275
221 return null; 276 return null;
222 }, 277 },
223 278
224 /** 279 /**
225 * Will be set to true if apply() is running (reentrance protection). 280 * Will be set to true if apply() is running (reentrance protection).
226 * @type Boolean 281 * @type Boolean
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 { 458 {
404 return (key in filterByKey ? filterByKey[key] : null); 459 return (key in filterByKey ? filterByKey[key] : null);
405 }, 460 },
406 461
407 /** 462 /**
408 * Returns a list of all selectors active on a particular domain, must not be 463 * Returns a list of all selectors active on a particular domain, must not be
409 * used in Firefox (when usingFiltersByDomain is false). 464 * used in Firefox (when usingFiltersByDomain is false).
410 */ 465 */
411 getSelectorsForDomain: function(/**String*/ domain, /**Boolean*/ specificOnly) 466 getSelectorsForDomain: function(/**String*/ domain, /**Boolean*/ specificOnly)
412 { 467 {
413 if (!usingFiltersByDomain) 468 if (!usingGetSelectorsByDomain)
414 throw new Error("getSelectorsForDomain can not be used in Firefox!"); 469 throw new Error("getSelectorsForDomain can not be used in Firefox!");
415 470
416 let selectors = []; 471 let selectors = [];
417 472
418 let seenFilters = Object.create(null); 473 let seenFilterIds = Object.create(null);
419 let currentDomain = domain ? domain.toUpperCase() : ""; 474 let currentDomain = domain ? domain.toUpperCase() : "";
420 while (true) 475 while (true)
421 { 476 {
422 if (specificOnly && currentDomain == "") 477 if (specificOnly && currentDomain == "")
423 break; 478 break;
424 479
425 let filters = filtersByDomain[currentDomain]; 480 let inactiveFilterIds = inactiveFilterIdsByDomain[currentDomain];
426 if (filters) 481 if (inactiveFilterIds)
482 for (let filterId of inactiveFilterIds)
483 seenFilterIds[filterId] = true;
484
485 let activeFilterIds = activeFilterIdsByDomain[currentDomain];
486 if (activeFilterIds)
427 { 487 {
428 for (let filterText in filters) 488 for (let filterId of activeFilterIds)
429 { 489 {
430 if (filterText in seenFilters) 490 if (filterId in seenFilterIds)
431 continue; 491 continue;
432 seenFilters[filterText] = true; 492 seenFilterIds[filterId] = true;
433 493
434 let filter = filters[filterText]; 494 let selector = selectorByFilterId[filterId];
435 if (filter && !this.getException(filter, domain)) 495 if (!this.getException(selector, domain))
436 selectors.push(filter.selector); 496 selectors.push(selector);
437 } 497 }
438 } 498 }
439 499
440 if (currentDomain == "") 500 if (currentDomain == "")
441 break; 501 break;
442 502
443 let nextDot = currentDomain.indexOf("."); 503 let nextDot = currentDomain.indexOf(".");
444 currentDomain = nextDot == -1 ? "" : currentDomain.substr(nextDot + 1); 504 currentDomain = nextDot == -1 ? "" : currentDomain.substr(nextDot + 1);
445 } 505 }
446 506
447 return selectors; 507 return selectors;
448 } 508 }
449 }; 509 };
OLDNEW
« no previous file with comments | « lib/cssRules.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld