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: Account for nested selectors Created Oct. 23, 2017, 12:10 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 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 } 139 }
140 // Just in case the getSelectors() generator above had to run some heavy 140 // Just in case the getSelectors() generator above had to run some heavy
141 // document.querySelectorAll() call which didn't produce any results, make 141 // document.querySelectorAll() call which didn't produce any results, make
142 // sure there is at least one point where execution can pause. 142 // sure there is at least one point where execution can pause.
143 yield null; 143 yield null;
144 } 144 }
145 145
146 function PlainSelector(selector) 146 function PlainSelector(selector)
147 { 147 {
148 this._selector = selector; 148 this._selector = selector;
149 this.maybeDependsOnAttributes = /\[.+\]/.test(selector);
hub 2017/10/23 13:18:55 What about the changes of `class` and `id` ?
Manish Jethani 2017/10/23 22:52:07 Done.
149 } 150 }
150 151
151 PlainSelector.prototype = { 152 PlainSelector.prototype = {
152 /** 153 /**
153 * Generator function returning a pair of selector 154 * Generator function returning a pair of selector
154 * string and subtree. 155 * string and subtree.
155 * @param {string} prefix the prefix for the selector. 156 * @param {string} prefix the prefix for the selector.
156 * @param {Node} subtree the subtree we work on. 157 * @param {Node} subtree the subtree we work on.
157 * @param {StringifiedStyle[]} styles the stringified style objects. 158 * @param {StringifiedStyle[]} styles the stringified style objects.
158 */ 159 */
(...skipping 12 matching lines...) Expand all
171 } 172 }
172 173
173 HasSelector.prototype = { 174 HasSelector.prototype = {
174 requiresHiding: true, 175 requiresHiding: true,
175 176
176 get dependsOnStyles() 177 get dependsOnStyles()
177 { 178 {
178 return this._innerSelectors.some(selector => selector.dependsOnStyles); 179 return this._innerSelectors.some(selector => selector.dependsOnStyles);
179 }, 180 },
180 181
182 get dependsOnCharacterData()
183 {
184 return this._innerSelectors.some(
185 selector => selector.dependsOnCharacterData
186 );
187 },
188
189 get maybeDependsOnAttributes()
190 {
191 return this._innerSelectors.some(
192 selector => selector.maybeDependsOnAttributes
193 );
194 },
195
181 *getSelectors(prefix, subtree, styles) 196 *getSelectors(prefix, subtree, styles)
182 { 197 {
183 for (let element of this.getElements(prefix, subtree, styles)) 198 for (let element of this.getElements(prefix, subtree, styles))
184 yield [makeSelector(element, ""), element]; 199 yield [makeSelector(element, ""), element];
185 }, 200 },
186 201
187 /** 202 /**
188 * Generator function returning selected elements. 203 * Generator function returning selected elements.
189 * @param {string} prefix the prefix for the selector. 204 * @param {string} prefix the prefix for the selector.
190 * @param {Node} subtree the subtree we work on. 205 * @param {Node} subtree the subtree we work on.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 } 237 }
223 }; 238 };
224 239
225 function ContainsSelector(textContent) 240 function ContainsSelector(textContent)
226 { 241 {
227 this._text = textContent; 242 this._text = textContent;
228 } 243 }
229 244
230 ContainsSelector.prototype = { 245 ContainsSelector.prototype = {
231 requiresHiding: true, 246 requiresHiding: true,
247 dependsOnCharacterData: true,
232 248
233 *getSelectors(prefix, subtree, stylesheet) 249 *getSelectors(prefix, subtree, stylesheet)
234 { 250 {
235 for (let element of this.getElements(prefix, subtree, stylesheet)) 251 for (let element of this.getElements(prefix, subtree, stylesheet))
236 yield [makeSelector(element, ""), subtree]; 252 yield [makeSelector(element, ""), subtree];
237 }, 253 },
238 254
239 *getElements(prefix, subtree, stylesheet) 255 *getElements(prefix, subtree, stylesheet)
240 { 256 {
241 let actualPrefix = (!prefix || incompletePrefixRegexp.test(prefix)) ? 257 let actualPrefix = (!prefix || incompletePrefixRegexp.test(prefix)) ?
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 yield [selector, subtree]; 311 yield [selector, subtree];
296 } 312 }
297 }; 313 };
298 314
299 function isSelectorHidingOnlyPattern(pattern) 315 function isSelectorHidingOnlyPattern(pattern)
300 { 316 {
301 return pattern.selectors.some(s => s.preferHideWithSelector) && 317 return pattern.selectors.some(s => s.preferHideWithSelector) &&
302 !pattern.selectors.some(s => s.requiresHiding); 318 !pattern.selectors.some(s => s.requiresHiding);
303 } 319 }
304 320
321 function shouldObserveAttributes(patterns)
322 {
323 // Observe changes to attributes if either there's a plain selector that
324 // looks like an attribute selector in one of the patterns
325 // (e.g. "a[href='https://example.com/']")
326 // or there's a properties selector nested inside a has selector
327 // (e.g. "div:-abp-has(:-abp-properties(color: blue))")
328 return patterns.some(
329 pattern => pattern.selectors.some(
330 selector => selector.maybeDependsOnAttributes ||
331 selector instanceof HasSelector &&
332 selector.dependsOnStyles
333 )
334 );
335 }
336
337 function shouldObserveCharacterData(patterns)
338 {
339 // Observe changes to character data only if there's a contains selector in
340 // one of the patterns.
341 return patterns.some(
342 pattern => pattern.selectors.some(
343 selector => selector.dependsOnCharacterData
344 )
345 );
346 }
347
305 function ElemHideEmulation(addSelectorsFunc, hideElemsFunc) 348 function ElemHideEmulation(addSelectorsFunc, hideElemsFunc)
306 { 349 {
307 this.document = document; 350 this.document = document;
308 this.addSelectorsFunc = addSelectorsFunc; 351 this.addSelectorsFunc = addSelectorsFunc;
309 this.hideElemsFunc = hideElemsFunc; 352 this.hideElemsFunc = hideElemsFunc;
310 this.observer = new MutationObserver(this.observe.bind(this)); 353 this.observer = new MutationObserver(this.observe.bind(this));
311 } 354 }
312 355
313 ElemHideEmulation.prototype = { 356 ElemHideEmulation.prototype = {
314 isSameOrigin(stylesheet) 357 isSameOrigin(stylesheet)
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
580 this.patterns.push({selectors, text: pattern.text}); 623 this.patterns.push({selectors, text: pattern.text});
581 } 624 }
582 625
583 if (this.patterns.length > 0) 626 if (this.patterns.length > 0)
584 { 627 {
585 this.queueFiltering(); 628 this.queueFiltering();
586 this.observer.observe( 629 this.observer.observe(
587 this.document, 630 this.document,
588 { 631 {
589 childList: true, 632 childList: true,
590 attributes: true, 633 attributes: shouldObserveAttributes(this.patterns),
591 characterData: true, 634 characterData: shouldObserveCharacterData(this.patterns),
592 subtree: true 635 subtree: true
593 } 636 }
594 ); 637 );
595 this.document.addEventListener("load", this.onLoad.bind(this), true); 638 this.document.addEventListener("load", this.onLoad.bind(this), true);
596 } 639 }
597 } 640 }
598 }; 641 };
599 642
600 exports.ElemHideEmulation = ElemHideEmulation; 643 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