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

Side by Side Diff: lib/elemHide.js

Issue 4875173639487488: Optmize filter list in elemHide.js for memory usage (Closed)
Patch Set: Created April 4, 2014, 11:34 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 | 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 <http://adblockplus.org/>, 2 * This file is part of Adblock Plus <http://adblockplus.org/>,
3 * Copyright (C) 2006-2014 Eyeo GmbH 3 * Copyright (C) 2006-2014 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 12 matching lines...) Expand all
23 23
24 let {Utils} = require("utils"); 24 let {Utils} = require("utils");
25 let {IO} = require("io"); 25 let {IO} = require("io");
26 let {Prefs} = require("prefs"); 26 let {Prefs} = require("prefs");
27 let {ElemHideException} = require("filterClasses"); 27 let {ElemHideException} = require("filterClasses");
28 let {FilterNotifier} = require("filterNotifier"); 28 let {FilterNotifier} = require("filterNotifier");
29 let {AboutHandler} = require("elemHideHitRegistration"); 29 let {AboutHandler} = require("elemHideHitRegistration");
30 let {TimeLine} = require("timeline"); 30 let {TimeLine} = require("timeline");
31 31
32 /** 32 /**
33 * Lookup table, filters by their associated key 33 * List of all filters. Index is used as key.
34 * @type Object 34 * @type Object
35 */ 35 */
36 let filterByKey = {__proto__: null}; 36 let filters = [];
37
38 /**
39 * Lookup table, keys of the filters by filter text
40 * @type Object
41 */
42 let keyByFilter = {__proto__: null};
43 37
44 /** 38 /**
45 * Lookup table, keys are known element hiding exceptions 39 * Lookup table, keys are known element hiding exceptions
46 * @type Object 40 * @type Object
47 */ 41 */
48 let knownExceptions = {__proto__: null}; 42 let knownExceptions = {__proto__: null};
49 43
50 /** 44 /**
51 * Lookup table, lists of element hiding exceptions by selector 45 * Lookup table, lists of element hiding exceptions by selector
52 * @type Object 46 * @type Object
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 TimeLine.log("done determining stylesheet URL"); 95 TimeLine.log("done determining stylesheet URL");
102 96
103 TimeLine.leave("ElemHide.init() done"); 97 TimeLine.leave("ElemHide.init() done");
104 }, 98 },
105 99
106 /** 100 /**
107 * Removes all known filters 101 * Removes all known filters
108 */ 102 */
109 clear: function() 103 clear: function()
110 { 104 {
111 filterByKey = {__proto__: null}; 105 filters = [];
112 keyByFilter = {__proto__: null};
113 knownExceptions = {__proto__: null}; 106 knownExceptions = {__proto__: null};
114 exceptions = {__proto__: null}; 107 exceptions = {__proto__: null};
115 ElemHide.isDirty = false; 108 ElemHide.isDirty = false;
116 ElemHide.unapply(); 109 ElemHide.unapply();
117 }, 110 },
118 111
119 /** 112 /**
120 * Add a new element hiding filter 113 * Add a new element hiding filter
121 * @param {ElemHideFilter} filter 114 * @param {ElemHideFilter} filter
122 */ 115 */
123 add: function(filter) 116 add: function(filter)
124 { 117 {
125 if (filter instanceof ElemHideException) 118 if (filter instanceof ElemHideException)
126 { 119 {
127 if (filter.text in knownExceptions) 120 if (filter.text in knownExceptions)
128 return; 121 return;
129 122
130 let selector = filter.selector; 123 let selector = filter.selector;
131 if (!(selector in exceptions)) 124 if (!(selector in exceptions))
132 exceptions[selector] = []; 125 exceptions[selector] = [];
133 exceptions[selector].push(filter); 126 exceptions[selector].push(filter);
134 knownExceptions[filter.text] = true; 127 knownExceptions[filter.text] = true;
135 } 128 }
136 else 129 else
137 { 130 {
138 if (filter.text in keyByFilter) 131 filters.push(filter);
139 return; 132 // XXX: Maybe check for duplicate filters?
140 133 // That would require searching through all filters,
141 let key; 134 // and in almost all cases there won't be any duplicates ...
142 do {
143 key = Math.random().toFixed(15).substr(5);
144 } while (key in filterByKey);
145
146 filterByKey[key] = filter;
147 keyByFilter[filter.text] = key;
148 ElemHide.isDirty = true; 135 ElemHide.isDirty = true;
149 } 136 }
150 }, 137 },
151 138
152 /** 139 /**
153 * Removes an element hiding filter 140 * Removes an element hiding filter
154 * @param {ElemHideFilter} filter 141 * @param {ElemHideFilter} filter
155 */ 142 */
156 remove: function(filter) 143 remove: function(filter)
157 { 144 {
158 if (filter instanceof ElemHideException) 145 if (filter instanceof ElemHideException)
159 { 146 {
160 if (!(filter.text in knownExceptions)) 147 if (!(filter.text in knownExceptions))
161 return; 148 return;
162 149
163 let list = exceptions[filter.selector]; 150 let list = exceptions[filter.selector];
164 let index = list.indexOf(filter); 151 let index = list.indexOf(filter);
165 if (index >= 0) 152 if (index >= 0)
166 list.splice(index, 1); 153 list.splice(index, 1);
167 delete knownExceptions[filter.text]; 154 delete knownExceptions[filter.text];
168 } 155 }
169 else 156 else
170 { 157 {
171 if (!(filter.text in keyByFilter)) 158 let index = filters.indexOf(filter);
159 if (index < 0)
172 return; 160 return;
161 filters[index] = undefined; // Indicates deleted.
Wladimir Palant 2014/04/08 11:24:53 This won't work correctly if the filter is duplica
173 162
174 let key = keyByFilter[filter.text];
175 delete filterByKey[key];
176 delete keyByFilter[filter.text];
177 ElemHide.isDirty = true; 163 ElemHide.isDirty = true;
178 } 164 }
179 }, 165 },
180 166
181 /** 167 /**
182 * Checks whether an exception rule is registered for a filter on a particular 168 * Checks whether an exception rule is registered for a filter on a particular
183 * domain. 169 * domain.
184 */ 170 */
185 getException: function(/**Filter*/ filter, /**String*/ docDomain) /**ElemHideE xception*/ 171 getException: function(/**Filter*/ filter, /**String*/ docDomain) /**ElemHideE xception*/
186 { 172 {
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
293 279
294 TimeLine.leave("ElemHide.apply() done", "ElemHideWrite"); 280 TimeLine.leave("ElemHide.apply() done", "ElemHideWrite");
295 }, 281 },
296 282
297 _generateCSSContent: function() 283 _generateCSSContent: function()
298 { 284 {
299 // Grouping selectors by domains 285 // Grouping selectors by domains
300 TimeLine.log("start grouping selectors"); 286 TimeLine.log("start grouping selectors");
301 let domains = {__proto__: null}; 287 let domains = {__proto__: null};
302 let hasFilters = false; 288 let hasFilters = false;
303 for (let key in filterByKey) 289 let seen = [];
290 for (let i = 0; i < filters.length; i++)
304 { 291 {
305 let filter = filterByKey[key]; 292 let filter = filters[i];
293 if (!filter)
294 continue;
295
296 // Lazily de-duplicate filters.
297 if (seen.indexOf(filter) >= 0) {
tschuster 2014/04/04 13:17:45 I am afraid this piece of code is causing noticeab
Wladimir Palant 2014/04/08 11:24:53 In fact, we are very likely to see duplicates - th
298 filters[i] = undefined;
299 continue;
300 } else {
301 seen.push(filter);
302 }
303
306 let domain = filter.selectorDomain || ""; 304 let domain = filter.selectorDomain || "";
307 305
308 let list; 306 let list;
309 if (domain in domains) 307 if (domain in domains)
310 list = domains[domain]; 308 list = domains[domain];
311 else 309 else
312 { 310 {
313 list = {__proto__: null}; 311 list = {__proto__: null};
314 domains[domain] = list; 312 domains[domain] = list;
315 } 313 }
316 list[filter.selector] = key; 314 list[filter.selector] = i;
317 hasFilters = true; 315 hasFilters = true;
318 } 316 }
319 TimeLine.log("done grouping selectors"); 317 TimeLine.log("done grouping selectors");
320 318
321 if (!hasFilters) 319 if (!hasFilters)
322 throw Cr.NS_ERROR_NOT_AVAILABLE; 320 throw Cr.NS_ERROR_NOT_AVAILABLE;
323 321
324 function escapeChar(match) 322 function escapeChar(match)
325 { 323 {
326 return "\\" + match.charCodeAt(0).toString(16) + " "; 324 return "\\" + match.charCodeAt(0).toString(16) + " ";
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 * Retrieves the currently applied stylesheet URL 370 * Retrieves the currently applied stylesheet URL
373 * @type String 371 * @type String
374 */ 372 */
375 get styleURL() ElemHide.applied ? styleURL.spec : null, 373 get styleURL() ElemHide.applied ? styleURL.spec : null,
376 374
377 /** 375 /**
378 * Retrieves an element hiding filter by the corresponding protocol key 376 * Retrieves an element hiding filter by the corresponding protocol key
379 */ 377 */
380 getFilterByKey: function(/**String*/ key) /**Filter*/ 378 getFilterByKey: function(/**String*/ key) /**Filter*/
381 { 379 {
382 return (key in filterByKey ? filterByKey[key] : null); 380 return filters[key] || null;
383 }, 381 },
384 382
385 /** 383 /**
386 * Returns a list of all selectors active on a particular domain (currently 384 * Returns a list of all selectors active on a particular domain (currently
387 * used only in Chrome). 385 * used only in Chrome).
388 */ 386 */
389 getSelectorsForDomain: function(/**String*/ domain, /**Boolean*/ specificOnly) 387 getSelectorsForDomain: function(/**String*/ domain, /**Boolean*/ specificOnly)
390 { 388 {
391 let result = []; 389 let result = [];
392 for (let key in filterByKey) 390 for (let i = 0; i < filters.length; i++)
393 { 391 {
394 let filter = filterByKey[key]; 392 let filter = filters[i];
395 if (specificOnly && (!filter.domains || filter.domains[""])) 393 if (specificOnly && (!filter.domains || filter.domains[""]))
396 continue; 394 continue;
397 395
398 if (filter.isActiveOnDomain(domain) && !this.getException(filter, domain)) 396 if (filter.isActiveOnDomain(domain) && !this.getException(filter, domain))
399 result.push(filter.selector); 397 result.push(filter.selector);
400 } 398 }
401 return result; 399 return result;
402 } 400 }
403 }; 401 };
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld