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

Side by Side Diff: lib/content/elemHideEmulation.js

Issue 29585589: Issue 6423 - Observe only relevant mutation types (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore/
Patch Set: Rebase Created Feb. 22, 2018, 7:11 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 <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 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 } 188 }
189 // Just in case the getSelectors() generator above had to run some heavy 189 // Just in case the getSelectors() generator above had to run some heavy
190 // document.querySelectorAll() call which didn't produce any results, make 190 // document.querySelectorAll() call which didn't produce any results, make
191 // sure there is at least one point where execution can pause. 191 // sure there is at least one point where execution can pause.
192 yield null; 192 yield null;
193 } 193 }
194 194
195 function PlainSelector(selector) 195 function PlainSelector(selector)
196 { 196 {
197 this._selector = selector; 197 this._selector = selector;
198 this.maybeDependsOnAttributes = /[#.]|\[.+\]/.test(selector);
198 } 199 }
199 200
200 PlainSelector.prototype = { 201 PlainSelector.prototype = {
201 /** 202 /**
202 * Generator function returning a pair of selector 203 * Generator function returning a pair of selector
203 * string and subtree. 204 * string and subtree.
204 * @param {string} prefix the prefix for the selector. 205 * @param {string} prefix the prefix for the selector.
205 * @param {Node} subtree the subtree we work on. 206 * @param {Node} subtree the subtree we work on.
206 * @param {StringifiedStyle[]} styles the stringified style objects. 207 * @param {StringifiedStyle[]} styles the stringified style objects.
207 */ 208 */
(...skipping 11 matching lines...) Expand all
219 } 220 }
220 221
221 HasSelector.prototype = { 222 HasSelector.prototype = {
222 requiresHiding: true, 223 requiresHiding: true,
223 224
224 get dependsOnStyles() 225 get dependsOnStyles()
225 { 226 {
226 return this._innerSelectors.some(selector => selector.dependsOnStyles); 227 return this._innerSelectors.some(selector => selector.dependsOnStyles);
227 }, 228 },
228 229
230 get dependsOnCharacterData()
231 {
232 return this._innerSelectors.some(
233 selector => selector.dependsOnCharacterData
234 );
235 },
236
237 get maybeDependsOnAttributes()
238 {
239 return this._innerSelectors.some(
240 selector => selector.maybeDependsOnAttributes
241 );
242 },
243
229 *getSelectors(prefix, subtree, styles) 244 *getSelectors(prefix, subtree, styles)
230 { 245 {
231 for (let element of this.getElements(prefix, subtree, styles)) 246 for (let element of this.getElements(prefix, subtree, styles))
232 yield [makeSelector(element, ""), element]; 247 yield [makeSelector(element, ""), element];
233 }, 248 },
234 249
235 /** 250 /**
236 * Generator function returning selected elements. 251 * Generator function returning selected elements.
237 * @param {string} prefix the prefix for the selector. 252 * @param {string} prefix the prefix for the selector.
238 * @param {Node} subtree the subtree we work on. 253 * @param {Node} subtree the subtree we work on.
(...skipping 22 matching lines...) Expand all
261 } 276 }
262 }; 277 };
263 278
264 function ContainsSelector(textContent) 279 function ContainsSelector(textContent)
265 { 280 {
266 this._text = textContent; 281 this._text = textContent;
267 } 282 }
268 283
269 ContainsSelector.prototype = { 284 ContainsSelector.prototype = {
270 requiresHiding: true, 285 requiresHiding: true,
286 dependsOnCharacterData: true,
271 287
272 *getSelectors(prefix, subtree, stylesheet) 288 *getSelectors(prefix, subtree, stylesheet)
273 { 289 {
274 for (let element of this.getElements(prefix, subtree, stylesheet)) 290 for (let element of this.getElements(prefix, subtree, stylesheet))
275 yield [makeSelector(element, ""), subtree]; 291 yield [makeSelector(element, ""), subtree];
276 }, 292 },
277 293
278 *getElements(prefix, subtree, stylesheet) 294 *getElements(prefix, subtree, stylesheet)
279 { 295 {
280 let actualPrefix = (!prefix || incompletePrefixRegexp.test(prefix)) ? 296 let actualPrefix = (!prefix || incompletePrefixRegexp.test(prefix)) ?
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 yield [selector, subtree]; 353 yield [selector, subtree];
338 } 354 }
339 }; 355 };
340 356
341 function isSelectorHidingOnlyPattern(pattern) 357 function isSelectorHidingOnlyPattern(pattern)
342 { 358 {
343 return pattern.selectors.some(s => s.preferHideWithSelector) && 359 return pattern.selectors.some(s => s.preferHideWithSelector) &&
344 !pattern.selectors.some(s => s.requiresHiding); 360 !pattern.selectors.some(s => s.requiresHiding);
345 } 361 }
346 362
363 function shouldObserveAttributes(patterns)
364 {
365 // Observe changes to attributes if either there's a plain selector that
366 // looks like an ID selector, class selector, or attribute selector in one of
367 // the patterns (e.g. "a[href='https://example.com/']")
368 // or there's a properties selector nested inside a has selector
369 // (e.g. "div:-abp-has(:-abp-properties(color: blue))")
370 return patterns.some(
371 pattern => pattern.selectors.some(
372 selector => selector.maybeDependsOnAttributes ||
373 selector instanceof HasSelector &&
374 selector.dependsOnStyles
375 )
376 );
377 }
378
379 function shouldObserveCharacterData(patterns)
380 {
381 // Observe changes to character data only if there's a contains selector in
382 // one of the patterns.
383 return patterns.some(
384 pattern => pattern.selectors.some(
385 selector => selector.dependsOnCharacterData
386 )
387 );
388 }
389
347 function ElemHideEmulation(addSelectorsFunc, hideElemsFunc) 390 function ElemHideEmulation(addSelectorsFunc, hideElemsFunc)
348 { 391 {
349 this.document = document; 392 this.document = document;
350 this.addSelectorsFunc = addSelectorsFunc; 393 this.addSelectorsFunc = addSelectorsFunc;
351 this.hideElemsFunc = hideElemsFunc; 394 this.hideElemsFunc = hideElemsFunc;
352 this.observer = new MutationObserver(this.observe.bind(this)); 395 this.observer = new MutationObserver(this.observe.bind(this));
353 } 396 }
354 397
355 ElemHideEmulation.prototype = { 398 ElemHideEmulation.prototype = {
356 isSameOrigin(stylesheet) 399 isSameOrigin(stylesheet)
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
635 this.patterns.push({selectors, text: pattern.text}); 678 this.patterns.push({selectors, text: pattern.text});
636 } 679 }
637 680
638 if (this.patterns.length > 0) 681 if (this.patterns.length > 0)
639 { 682 {
640 this.queueFiltering(); 683 this.queueFiltering();
641 this.observer.observe( 684 this.observer.observe(
642 this.document, 685 this.document,
643 { 686 {
644 childList: true, 687 childList: true,
645 attributes: true, 688 attributes: shouldObserveAttributes(this.patterns),
646 characterData: true, 689 characterData: shouldObserveCharacterData(this.patterns),
647 subtree: true 690 subtree: true
648 } 691 }
649 ); 692 );
650 this.document.addEventListener("load", this.onLoad.bind(this), true); 693 this.document.addEventListener("load", this.onLoad.bind(this), true);
651 } 694 }
652 } 695 }
653 }; 696 };
654 697
655 exports.ElemHideEmulation = ElemHideEmulation; 698 exports.ElemHideEmulation = ElemHideEmulation;
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