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: Created May 20, 2016, 5:54 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)
kzar 2016/05/20 08:11:12 I guess we can remove filterIdByFilterText lookup
kzar 2016/05/20 10:55:17 Nevermind, pretty sure we need it
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
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 20 matching lines...) Expand all
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;
204 } 232 }
205 }, 233 },
206 234
207 /** 235 /**
208 * Checks whether an exception rule is registered for a filter on a particular 236 * Checks whether an exception rule is registered for a filter on a particular
209 * domain. 237 * domain.
210 */ 238 */
211 getException: function(/**Filter*/ filter, /**String*/ docDomain) /**ElemHideE xception*/ 239 getException: function(/**String*/ selector, /**String*/ docDomain) /**ElemHid eException*/
212 { 240 {
213 if (!(filter.selector in exceptions)) 241 if (!(selector in exceptions))
214 return null; 242 return null;
215 243
216 let list = exceptions[filter.selector]; 244 let list = exceptions[selector];
217 for (let i = list.length - 1; i >= 0; i--) 245 for (let i = list.length - 1; i >= 0; i--)
218 if (list[i].isActiveOnDomain(docDomain)) 246 if (list[i].isActiveOnDomain(docDomain))
219 return list[i]; 247 return list[i];
220 248
221 return null; 249 return null;
222 }, 250 },
223 251
224 /** 252 /**
225 * Will be set to true if apply() is running (reentrance protection). 253 * Will be set to true if apply() is running (reentrance protection).
226 * @type Boolean 254 * @type Boolean
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 { 431 {
404 return (key in filterByKey ? filterByKey[key] : null); 432 return (key in filterByKey ? filterByKey[key] : null);
405 }, 433 },
406 434
407 /** 435 /**
408 * Returns a list of all selectors active on a particular domain, must not be 436 * Returns a list of all selectors active on a particular domain, must not be
409 * used in Firefox (when usingFiltersByDomain is false). 437 * used in Firefox (when usingFiltersByDomain is false).
410 */ 438 */
411 getSelectorsForDomain: function(/**String*/ domain, /**Boolean*/ specificOnly) 439 getSelectorsForDomain: function(/**String*/ domain, /**Boolean*/ specificOnly)
412 { 440 {
413 if (!usingFiltersByDomain) 441 if (!usingGetSelectorsByDomain)
414 throw new Error("getSelectorsForDomain can not be used in Firefox!"); 442 throw new Error("getSelectorsForDomain can not be used in Firefox!");
415 443
416 let selectors = []; 444 let selectors = [];
417 445
418 let seenFilters = Object.create(null); 446 let seenFilterIds = Object.create(null);
419 let currentDomain = domain ? domain.toUpperCase() : ""; 447 let currentDomain = domain ? domain.toUpperCase() : "";
420 while (true) 448 while (true)
421 { 449 {
422 if (specificOnly && currentDomain == "") 450 if (specificOnly && currentDomain == "")
423 break; 451 break;
424 452
425 let filters = filtersByDomain[currentDomain]; 453 let inactiveFilterIds = inactiveFilterIdsByDomain[currentDomain];
426 if (filters) 454 if (inactiveFilterIds)
455 for (let filterId of inactiveFilterIds)
456 seenFilterIds[filterId] = true;
457
458 let activeFilterIds = activeFilterIdsByDomain[currentDomain];
459 if (activeFilterIds)
427 { 460 {
428 for (let filterText in filters) 461 for (let filterId of activeFilterIds)
429 { 462 {
430 if (filterText in seenFilters) 463 if (filterId in seenFilterIds)
431 continue; 464 continue;
432 seenFilters[filterText] = true; 465 seenFilterIds[filterId] = true;
433 466
434 let filter = filters[filterText]; 467 let selector = selectorByFilterId[filterId];
435 if (filter && !this.getException(filter, domain)) 468 if (!this.getException(selector, domain))
436 selectors.push(filter.selector); 469 selectors.push(selector);
437 } 470 }
438 } 471 }
439 472
440 if (currentDomain == "") 473 if (currentDomain == "")
441 break; 474 break;
442 475
443 let nextDot = currentDomain.indexOf("."); 476 let nextDot = currentDomain.indexOf(".");
444 currentDomain = nextDot == -1 ? "" : currentDomain.substr(nextDot + 1); 477 currentDomain = nextDot == -1 ? "" : currentDomain.substr(nextDot + 1);
445 } 478 }
446 479
447 return selectors; 480 return selectors;
448 } 481 }
449 }; 482 };
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