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: Further improvements Created May 21, 2016, 4:41 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 && !(filter.text in filterIdByFilterText))
159 { 176 {
177 let filterId = selectorByFilterId.push(filter.selector) - 1;
178 filterIdByFilterText[filter.text] = filterId;
179
160 let domains = filter.domains || defaultDomains; 180 let domains = filter.domains || defaultDomains;
161 for (let domain in domains) 181 for (let domain in domains)
162 { 182 {
163 let filters = filtersByDomain[domain]; 183 let lookup;
164 if (!filters) 184 if (domains[domain])
165 filters = filtersByDomain[domain] = Object.create(null); 185 lookup = activeFilterIdsByDomain;
186 else
187 lookup = inactiveFilterIdsByDomain;
166 188
167 if (domains[domain]) 189 let filterIds = lookup[domain];
168 filters[filter.text] = filter; 190 if (filterIds == undefined)
169 else 191 filterIds = lookup[domain] = [];
170 filters[filter.text] = false; 192
193 filterIds.push(filterId);
171 } 194 }
172 } 195 }
173 196
174 ElemHide.isDirty = true; 197 ElemHide.isDirty = true;
175 } 198 }
176 }, 199 },
177 200
178 /** 201 /**
179 * Removes an element hiding filter 202 * Removes an element hiding filter
180 * @param {ElemHideFilter} filter 203 * @param {ElemHideFilter} filter
(...skipping 14 matching lines...) Expand all
195 else 218 else
196 { 219 {
197 if (!(filter.text in keyByFilter)) 220 if (!(filter.text in keyByFilter))
198 return; 221 return;
199 222
200 let key = keyByFilter[filter.text]; 223 let key = keyByFilter[filter.text];
201 delete filterByKey[key]; 224 delete filterByKey[key];
202 delete keyByFilter[filter.text]; 225 delete keyByFilter[filter.text];
203 ElemHide.isDirty = true; 226 ElemHide.isDirty = true;
204 227
205 if (usingFiltersByDomain) 228 if (usingGetSelectorsByDomain)
206 { 229 {
207 let domains = filter.domains || defaultDomains; 230 let filterId = filterIdByFilterText[filter.text];
208 for (let domain in domains) 231 if (filterId)
209 { 232 {
210 let filters = filtersByDomain[domain]; 233 delete filterIdByFilterText[filter.text];
211 if (filters) 234 delete selectorByFilterId[filterId];
212 delete filters[filter.text]; 235
236 let domains = filter.domains || defaultDomains;
237 let filterIdsByDomainLookups = [activeFilterIdsByDomain,
238 inactiveFilterIdsByDomain];
239 for (let domain in domains)
240 {
241 for (let filterIdsByDomain of filterIdsByDomainLookups)
242 {
243 let lookup = filterIdsByDomain[domain];
244 if (lookup)
245 {
246 let index = lookup.indexOf(filterId);
247 if (index != -1)
248 lookup.splice(index, 1);
249 }
250 }
251 }
213 } 252 }
214 } 253 }
215 } 254 }
216 }, 255 },
217 256
218 /** 257 /**
219 * Checks whether an exception rule is registered for a filter on a particular 258 * Checks whether an exception rule is registered for a filter on a particular
220 * domain. 259 * domain.
221 */ 260 */
222 getException: function(/**Filter*/ filter, /**String*/ docDomain) /**ElemHideE xception*/ 261 getException: function(/**String*/ selector, /**String*/ docDomain) /**ElemHid eException*/
223 { 262 {
224 if (!(filter.selector in exceptions)) 263 if (!(selector in exceptions))
225 return null; 264 return null;
226 265
227 let list = exceptions[filter.selector]; 266 let list = exceptions[selector];
228 for (let i = list.length - 1; i >= 0; i--) 267 for (let i = list.length - 1; i >= 0; i--)
229 if (list[i].isActiveOnDomain(docDomain)) 268 if (list[i].isActiveOnDomain(docDomain))
230 return list[i]; 269 return list[i];
231 270
232 return null; 271 return null;
233 }, 272 },
234 273
235 /** 274 /**
236 * Will be set to true if apply() is running (reentrance protection). 275 * Will be set to true if apply() is running (reentrance protection).
237 * @type Boolean 276 * @type Boolean
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 { 453 {
415 return (key in filterByKey ? filterByKey[key] : null); 454 return (key in filterByKey ? filterByKey[key] : null);
416 }, 455 },
417 456
418 /** 457 /**
419 * Returns a list of all selectors active on a particular domain, must not be 458 * Returns a list of all selectors active on a particular domain, must not be
420 * used in Firefox (when usingFiltersByDomain is false). 459 * used in Firefox (when usingFiltersByDomain is false).
421 */ 460 */
422 getSelectorsForDomain: function(/**String*/ domain, /**Boolean*/ specificOnly) 461 getSelectorsForDomain: function(/**String*/ domain, /**Boolean*/ specificOnly)
423 { 462 {
424 if (!usingFiltersByDomain) 463 if (!usingGetSelectorsByDomain)
425 throw new Error("getSelectorsForDomain can not be used in Firefox!"); 464 throw new Error("getSelectorsForDomain can not be used in Firefox!");
426 465
427 let selectors = []; 466 let selectors = [];
428 467
429 let seenFilters = Object.create(null); 468 let seenFilterIds = Object.create(null);
430 let currentDomain = domain ? domain.toUpperCase() : ""; 469 let currentDomain = domain ? domain.toUpperCase() : "";
431 while (true) 470 while (true)
432 { 471 {
433 if (specificOnly && currentDomain == "") 472 if (specificOnly && currentDomain == "")
434 break; 473 break;
435 474
436 let filters = filtersByDomain[currentDomain]; 475 let inactiveFilterIds = inactiveFilterIdsByDomain[currentDomain];
437 if (filters) 476 if (inactiveFilterIds)
477 for (let filterId of inactiveFilterIds)
478 seenFilterIds[filterId] = true;
479
480 let activeFilterIds = activeFilterIdsByDomain[currentDomain];
481 if (activeFilterIds)
438 { 482 {
439 for (let filterText in filters) 483 for (let filterId of activeFilterIds)
440 { 484 {
441 if (filterText in seenFilters) 485 if (filterId in seenFilterIds)
442 continue; 486 continue;
443 seenFilters[filterText] = true; 487 seenFilterIds[filterId] = true;
444 488
445 let filter = filters[filterText]; 489 let selector = selectorByFilterId[filterId];
446 if (filter && !this.getException(filter, domain)) 490 if (!this.getException(selector, domain))
447 selectors.push(filter.selector); 491 selectors.push(selector);
448 } 492 }
449 } 493 }
450 494
451 if (currentDomain == "") 495 if (currentDomain == "")
452 break; 496 break;
453 497
454 let nextDot = currentDomain.indexOf("."); 498 let nextDot = currentDomain.indexOf(".");
455 currentDomain = nextDot == -1 ? "" : currentDomain.substr(nextDot + 1); 499 currentDomain = nextDot == -1 ? "" : currentDomain.substr(nextDot + 1);
456 } 500 }
457 501
458 return selectors; 502 return selectors;
459 } 503 }
460 }; 504 };
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