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

Delta Between Two Patch Sets: lib/content/elemHideEmulation.js

Issue 29713583: Issue 6504 - Add useInlineStyles flag to ElemHideEmulation (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore/
Left Patch Set: Change to ElemHideEmulation.useInlineStyles Created March 5, 2018, 1:17 p.m.
Right Patch Set: Rebase Created March 20, 2018, 1:35 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18 "use strict"; 18 "use strict";
19 19
20 const {textToRegExp, filterToRegExp, splitSelector} = require("../common"); 20 const {textToRegExp, filterToRegExp, splitSelector} = require("../common");
21 21
22 let MIN_INVOCATION_INTERVAL = 3000; 22 let MIN_INVOCATION_INTERVAL = 3000;
23 const MAX_SYNCHRONOUS_PROCESSING_TIME = 50; 23 const MAX_SYNCHRONOUS_PROCESSING_TIME = 50;
24 const abpSelectorRegexp = /:-abp-([\w-]+)\(/i; 24 const abpSelectorRegexp = /:-abp-([\w-]+)\(/i;
25 25
26 function getCachedPropertyValue(object, name, defaultValueFunc = () => {})
27 {
28 let value = object[name];
29 if (typeof value == "undefined")
30 Object.defineProperty(object, name, {value: value = defaultValueFunc()});
31 return value;
32 }
33
26 /** Return position of node from parent. 34 /** Return position of node from parent.
27 * @param {Node} node the node to find the position of. 35 * @param {Node} node the node to find the position of.
28 * @return {number} One-based index like for :nth-child(), or 0 on error. 36 * @return {number} One-based index like for :nth-child(), or 0 on error.
29 */ 37 */
30 function positionInParent(node) 38 function positionInParent(node)
31 { 39 {
32 let {children} = node.parentNode; 40 let {children} = node.parentNode;
33 for (let i = 0; i < children.length; i++) 41 for (let i = 0; i < children.length; i++)
34 if (children[i] == node) 42 if (children[i] == node)
35 return i + 1; 43 return i + 1;
36 return 0; 44 return 0;
37 } 45 }
38 46
39 function makeSelector(node, selector) 47 function makeSelector(node, selector = "")
40 { 48 {
41 if (node == null) 49 if (node == null)
42 return null; 50 return null;
43 if (!node.parentElement) 51 if (!node.parentElement)
44 { 52 {
45 let newSelector = ":root"; 53 let newSelector = ":root";
46 if (selector) 54 if (selector)
47 newSelector += " > " + selector; 55 newSelector += " > " + selector;
48 return newSelector; 56 return newSelector;
49 } 57 }
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 245
238 const incompletePrefixRegexp = /[\s>+~]$/; 246 const incompletePrefixRegexp = /[\s>+~]$/;
239 247
240 function HasSelector(selectors) 248 function HasSelector(selectors)
241 { 249 {
242 this._innerSelectors = selectors; 250 this._innerSelectors = selectors;
243 } 251 }
244 252
245 HasSelector.prototype = { 253 HasSelector.prototype = {
246 requiresHiding: true, 254 requiresHiding: true,
255 dependsOnDOM: true,
247 256
248 get dependsOnStyles() 257 get dependsOnStyles()
249 { 258 {
250 return this._innerSelectors.some(selector => selector.dependsOnStyles); 259 return this._innerSelectors.some(selector => selector.dependsOnStyles);
251 }, 260 },
252 261
253 get dependsOnCharacterData() 262 get dependsOnCharacterData()
254 { 263 {
255 return this._innerSelectors.some( 264 return this._innerSelectors.some(
256 selector => selector.dependsOnCharacterData 265 selector => selector.dependsOnCharacterData
257 ); 266 );
258 }, 267 },
259 268
260 get maybeDependsOnAttributes() 269 get maybeDependsOnAttributes()
261 { 270 {
262 return this._innerSelectors.some( 271 return this._innerSelectors.some(
263 selector => selector.maybeDependsOnAttributes 272 selector => selector.maybeDependsOnAttributes
264 ); 273 );
265 }, 274 },
266 275
267 *getSelectors(prefix, subtree, styles) 276 *getSelectors(prefix, subtree, styles)
268 { 277 {
269 for (let element of this.getElements(prefix, subtree, styles)) 278 for (let element of this.getElements(prefix, subtree, styles))
270 yield [makeSelector(element, ""), element]; 279 yield [makeSelector(element), element];
271 }, 280 },
272 281
273 /** 282 /**
274 * Generator function returning selected elements. 283 * Generator function returning selected elements.
275 * @param {string} prefix the prefix for the selector. 284 * @param {string} prefix the prefix for the selector.
276 * @param {Node} subtree the subtree we work on. 285 * @param {Node} subtree the subtree we work on.
277 * @param {StringifiedStyle[]} styles the stringified style objects. 286 * @param {StringifiedStyle[]} styles the stringified style objects.
278 */ 287 */
279 *getElements(prefix, subtree, styles) 288 *getElements(prefix, subtree, styles)
280 { 289 {
(...skipping 18 matching lines...) Expand all
299 } 308 }
300 }; 309 };
301 310
302 function ContainsSelector(textContent) 311 function ContainsSelector(textContent)
303 { 312 {
304 this._regexp = makeRegExpParameter(textContent); 313 this._regexp = makeRegExpParameter(textContent);
305 } 314 }
306 315
307 ContainsSelector.prototype = { 316 ContainsSelector.prototype = {
308 requiresHiding: true, 317 requiresHiding: true,
318 dependsOnDOM: true,
309 dependsOnCharacterData: true, 319 dependsOnCharacterData: true,
310 320
311 *getSelectors(prefix, subtree, styles) 321 *getSelectors(prefix, subtree, styles)
312 { 322 {
313 for (let element of this.getElements(prefix, subtree, styles)) 323 for (let element of this.getElements(prefix, subtree, styles))
314 yield [makeSelector(element, ""), subtree]; 324 yield [makeSelector(element), subtree];
315 }, 325 },
316 326
317 *getElements(prefix, subtree, styles) 327 *getElements(prefix, subtree, styles)
318 { 328 {
319 let actualPrefix = (!prefix || incompletePrefixRegexp.test(prefix)) ? 329 let actualPrefix = (!prefix || incompletePrefixRegexp.test(prefix)) ?
320 prefix + "*" : prefix; 330 prefix + "*" : prefix;
321 331
322 let elements = scopedQuerySelectorAll(subtree, actualPrefix); 332 let elements = scopedQuerySelectorAll(subtree, actualPrefix);
323 if (elements) 333 if (elements)
324 { 334 {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 } 380 }
371 }, 381 },
372 382
373 *getSelectors(prefix, subtree, styles) 383 *getSelectors(prefix, subtree, styles)
374 { 384 {
375 for (let selector of this.findPropsSelectors(styles, prefix, this._regexp)) 385 for (let selector of this.findPropsSelectors(styles, prefix, this._regexp))
376 yield [selector, subtree]; 386 yield [selector, subtree];
377 } 387 }
378 }; 388 };
379 389
380 function isSelectorHidingOnlyPattern(pattern) 390 function Pattern(selectors, text)
381 { 391 {
382 return pattern.selectors.some(s => s.preferHideWithSelector) && 392 this.selectors = selectors;
383 !pattern.selectors.some(s => s.requiresHiding); 393 this.text = text;
394 }
395
396 Pattern.prototype = {
397 isSelectorHidingOnlyPattern()
398 {
399 return getCachedPropertyValue(
400 this, "_selectorHidingOnlyPattern",
401 () => this.selectors.some(selector => selector.preferHideWithSelector) &&
402 !this.selectors.some(selector => selector.requiresHiding)
403 );
404 },
405
406 get dependsOnStyles()
407 {
408 return getCachedPropertyValue(
409 this, "_dependsOnStyles",
410 () => this.selectors.some(selector => selector.dependsOnStyles)
411 );
412 },
413
414 get dependsOnDOM()
415 {
416 return getCachedPropertyValue(
417 this, "_dependsOnDOM",
418 () => this.selectors.some(selector => selector.dependsOnDOM)
419 );
420 },
421
422 get dependsOnStylesAndDOM()
423 {
424 return getCachedPropertyValue(
425 this, "_dependsOnStylesAndDOM",
426 () => this.selectors.some(selector => selector.dependsOnStyles &&
427 selector.dependsOnDOM)
428 );
429 },
430
431 get maybeDependsOnAttributes()
432 {
433 // Observe changes to attributes if either there's a plain selector that
434 // looks like an ID selector, class selector, or attribute selector in one
435 // of the patterns (e.g. "a[href='https://example.com/']")
436 // or there's a properties selector nested inside a has selector
437 // (e.g. "div:-abp-has(:-abp-properties(color: blue))")
438 return getCachedPropertyValue(
439 this, "_maybeDependsOnAttributes",
440 () => this.selectors.some(
441 selector => selector.maybeDependsOnAttributes ||
442 (selector instanceof HasSelector &&
443 selector.dependsOnStyles)
444 )
445 );
446 },
447
448 get dependsOnCharacterData()
449 {
450 // Observe changes to character data only if there's a contains selector in
451 // one of the patterns.
452 return getCachedPropertyValue(
453 this, "_dependsOnCharacterData",
454 () => this.selectors.some(selector => selector.dependsOnCharacterData)
455 );
456 }
457 };
458
459 function filterPatterns(patterns, {stylesheets, mutations})
460 {
461 if (!stylesheets && !mutations)
462 return patterns.slice();
463
464 return patterns.filter(
465 pattern => (stylesheets && pattern.dependsOnStyles) ||
466 (mutations && pattern.dependsOnDOM)
467 );
384 } 468 }
385 469
386 function shouldObserveAttributes(patterns) 470 function shouldObserveAttributes(patterns)
387 { 471 {
388 // Observe changes to attributes if either there's a plain selector that 472 return patterns.some(pattern => pattern.maybeDependsOnAttributes);
389 // looks like an ID selector, class selector, or attribute selector in one of
390 // the patterns (e.g. "a[href='https://example.com/']")
391 // or there's a properties selector nested inside a has selector
392 // (e.g. "div:-abp-has(:-abp-properties(color: blue))")
393 return patterns.some(
394 pattern => pattern.selectors.some(
395 selector => selector.maybeDependsOnAttributes ||
396 (selector instanceof HasSelector &&
397 selector.dependsOnStyles)
398 )
399 );
400 } 473 }
401 474
402 function shouldObserveCharacterData(patterns) 475 function shouldObserveCharacterData(patterns)
403 { 476 {
404 // Observe changes to character data only if there's a contains selector in 477 return patterns.some(pattern => pattern.dependsOnCharacterData);
405 // one of the patterns.
406 return patterns.some(
407 pattern => pattern.selectors.some(
408 selector => selector.dependsOnCharacterData
409 )
410 );
411 } 478 }
412 479
413 function ElemHideEmulation(addSelectorsFunc, hideElemsFunc) 480 function ElemHideEmulation(addSelectorsFunc, hideElemsFunc)
414 { 481 {
415 this.document = document; 482 this.document = document;
416 this.addSelectorsFunc = addSelectorsFunc; 483 this.addSelectorsFunc = addSelectorsFunc;
417 this.hideElemsFunc = hideElemsFunc; 484 this.hideElemsFunc = hideElemsFunc;
418 this.observer = new MutationObserver(this.observe.bind(this)); 485 this.observer = new MutationObserver(this.observe.bind(this));
419 this.useInlineStyles = true; 486 this.useInlineStyles = true;
kzar 2018/03/19 21:18:54 This doesn't match `alwaysHideWithSelector` in the
Manish Jethani 2018/03/20 11:20:23 Done.
420 } 487 }
421 488
422 ElemHideEmulation.prototype = { 489 ElemHideEmulation.prototype = {
423 isSameOrigin(stylesheet) 490 isSameOrigin(stylesheet)
424 { 491 {
425 try 492 try
426 { 493 {
427 return new URL(stylesheet.href).origin == this.document.location.origin; 494 return new URL(stylesheet.href).origin == this.document.location.origin;
428 } 495 }
429 catch (e) 496 catch (e)
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 return selectors; 563 return selectors;
497 }, 564 },
498 565
499 /** 566 /**
500 * Processes the current document and applies all rules to it. 567 * Processes the current document and applies all rules to it.
501 * @param {CSSStyleSheet[]} [stylesheets] 568 * @param {CSSStyleSheet[]} [stylesheets]
502 * The list of new stylesheets that have been added to the document and 569 * The list of new stylesheets that have been added to the document and
503 * made reprocessing necessary. This parameter shouldn't be passed in for 570 * made reprocessing necessary. This parameter shouldn't be passed in for
504 * the initial processing, all of document's stylesheets will be considered 571 * the initial processing, all of document's stylesheets will be considered
505 * then and all rules, including the ones not dependent on styles. 572 * then and all rules, including the ones not dependent on styles.
573 * @param {MutationRecord[]} [mutations]
574 * The list of DOM mutations that have been applied to the document and
575 * made reprocessing necessary. This parameter shouldn't be passed in for
576 * the initial processing, the entire document will be considered
577 * then and all rules, including the ones not dependent on the DOM.
506 * @param {function} [done] 578 * @param {function} [done]
507 * Callback to call when done. 579 * Callback to call when done.
508 */ 580 */
509 _addSelectors(stylesheets, done) 581 _addSelectors(stylesheets, mutations, done)
510 { 582 {
583 let patterns = filterPatterns(this.patterns, {stylesheets, mutations});
584
511 let selectors = []; 585 let selectors = [];
512 let selectorFilters = []; 586 let selectorFilters = [];
513 587
514 let elements = []; 588 let elements = [];
515 let elementFilters = []; 589 let elementFilters = [];
516 590
517 let cssStyles = []; 591 let cssStyles = [];
518 592
519 let stylesheetOnlyChange = !!stylesheets; 593 // If neither any style sheets nor any DOM mutations have been specified,
520 if (!stylesheets) 594 // do full processing.
595 if (!stylesheets && !mutations)
521 stylesheets = this.document.styleSheets; 596 stylesheets = this.document.styleSheets;
522 597
523 for (let stylesheet of stylesheets) 598 // If there are any DOM mutations and any of the patterns depends on both
599 // style sheets and the DOM (e.g. -abp-has(-abp-properties)), find all the
600 // rules in every style sheet in the document, because we need to run
601 // querySelectorAll afterwards. On the other hand, if we only have patterns
602 // that depend on either styles or DOM both not both
603 // (e.g. -abp-properties or -abp-contains), we can skip this part.
604 if (mutations && patterns.some(pattern => pattern.dependsOnStylesAndDOM))
605 stylesheets = this.document.styleSheets;
606
607 for (let stylesheet of stylesheets || [])
524 { 608 {
525 // Explicitly ignore third-party stylesheets to ensure consistent behavior 609 // Explicitly ignore third-party stylesheets to ensure consistent behavior
526 // between Firefox and Chrome. 610 // between Firefox and Chrome.
527 if (!this.isSameOrigin(stylesheet)) 611 if (!this.isSameOrigin(stylesheet))
528 continue; 612 continue;
529 613
530 let rules = stylesheet.cssRules; 614 let rules = stylesheet.cssRules;
531 if (!rules) 615 if (!rules)
532 continue; 616 continue;
533 617
534 for (let rule of rules) 618 for (let rule of rules)
535 { 619 {
536 if (rule.type != rule.STYLE_RULE) 620 if (rule.type != rule.STYLE_RULE)
537 continue; 621 continue;
538 622
539 cssStyles.push(stringifyStyle(rule)); 623 cssStyles.push(stringifyStyle(rule));
540 } 624 }
541 } 625 }
542 626
543 let patterns = this.patterns.slice();
544 let pattern = null; 627 let pattern = null;
545 let generator = null; 628 let generator = null;
546 629
547 let processPatterns = () => 630 let processPatterns = () =>
548 { 631 {
549 let cycleStart = performance.now(); 632 let cycleStart = performance.now();
550 633
551 if (!pattern) 634 if (!pattern)
552 { 635 {
553 if (!patterns.length) 636 if (!patterns.length)
554 { 637 {
555 this.addSelectorsFunc(selectors, selectorFilters); 638 if (selectors.length > 0)
556 this.hideElemsFunc(elements, elementFilters); 639 this.addSelectorsFunc(selectors, selectorFilters);
640 if (elements.length > 0)
641 this.hideElemsFunc(elements, elementFilters);
557 if (typeof done == "function") 642 if (typeof done == "function")
558 done(); 643 done();
559 return; 644 return;
560 } 645 }
561 646
562 pattern = patterns.shift(); 647 pattern = patterns.shift();
563 648
564 if (stylesheetOnlyChange &&
565 !pattern.selectors.some(selector => selector.dependsOnStyles))
566 {
567 pattern = null;
568 return processPatterns();
569 }
570 generator = evaluate(pattern.selectors, 0, "", 649 generator = evaluate(pattern.selectors, 0, "",
571 this.document, cssStyles); 650 this.document, cssStyles);
572 } 651 }
573 for (let selector of generator) 652 for (let selector of generator)
574 { 653 {
575 if (selector != null) 654 if (selector != null)
576 { 655 {
577 if (!this.useInlineStyles || 656 if (!this.useInlineStyles ||
578 isSelectorHidingOnlyPattern(pattern)) 657 pattern.isSelectorHidingOnlyPattern())
579 { 658 {
580 selectors.push(selector); 659 selectors.push(selector);
581 selectorFilters.push(pattern.text); 660 selectorFilters.push(pattern.text);
582 } 661 }
583 else 662 else
584 { 663 {
585 for (let element of this.document.querySelectorAll(selector)) 664 for (let element of this.document.querySelectorAll(selector))
586 { 665 {
587 elements.push(element); 666 elements.push(element);
588 elementFilters.push(pattern.text); 667 elementFilters.push(pattern.text);
(...skipping 26 matching lines...) Expand all
615 }, 694 },
616 695
617 _filteringInProgress: false, 696 _filteringInProgress: false,
618 _lastInvocation: -MIN_INVOCATION_INTERVAL, 697 _lastInvocation: -MIN_INVOCATION_INTERVAL,
619 _scheduledProcessing: null, 698 _scheduledProcessing: null,
620 699
621 /** 700 /**
622 * Re-run filtering either immediately or queued. 701 * Re-run filtering either immediately or queued.
623 * @param {CSSStyleSheet[]} [stylesheets] 702 * @param {CSSStyleSheet[]} [stylesheets]
624 * new stylesheets to be processed. This parameter should be omitted 703 * new stylesheets to be processed. This parameter should be omitted
625 * for DOM modification (full reprocessing required). 704 * for full reprocessing.
705 * @param {MutationRecord[]} [mutations]
706 * new DOM mutations to be processed. This parameter should be omitted
707 * for full reprocessing.
626 */ 708 */
627 queueFiltering(stylesheets) 709 queueFiltering(stylesheets, mutations)
628 { 710 {
629 let completion = () => 711 let completion = () =>
630 { 712 {
631 this._lastInvocation = performance.now(); 713 this._lastInvocation = performance.now();
632 this._filteringInProgress = false; 714 this._filteringInProgress = false;
633 if (this._scheduledProcessing) 715 if (this._scheduledProcessing)
634 { 716 {
635 let newStylesheets = this._scheduledProcessing.stylesheets; 717 let params = Object.assign({}, this._scheduledProcessing);
636 this._scheduledProcessing = null; 718 this._scheduledProcessing = null;
637 this.queueFiltering(newStylesheets); 719 this.queueFiltering(params.stylesheets, params.mutations);
638 } 720 }
639 }; 721 };
640 722
641 if (this._scheduledProcessing) 723 if (this._scheduledProcessing)
642 { 724 {
643 if (!stylesheets) 725 if (!stylesheets && !mutations)
644 this._scheduledProcessing.stylesheets = null; 726 {
645 else if (this._scheduledProcessing.stylesheets) 727 this._scheduledProcessing = {};
646 this._scheduledProcessing.stylesheets.push(...stylesheets); 728 }
729 else
730 {
731 if (stylesheets)
732 {
733 if (!this._scheduledProcessing.stylesheets)
734 this._scheduledProcessing.stylesheets = [];
735 this._scheduledProcessing.stylesheets.push(...stylesheets);
736 }
737 if (mutations)
738 {
739 if (!this._scheduledProcessing.mutations)
740 this._scheduledProcessing.mutations = [];
741 this._scheduledProcessing.mutations.push(...mutations);
742 }
743 }
647 } 744 }
648 else if (this._filteringInProgress) 745 else if (this._filteringInProgress)
649 { 746 {
650 this._scheduledProcessing = {stylesheets}; 747 this._scheduledProcessing = {stylesheets, mutations};
651 } 748 }
652 else if (performance.now() - this._lastInvocation < MIN_INVOCATION_INTERVAL) 749 else if (performance.now() - this._lastInvocation < MIN_INVOCATION_INTERVAL)
653 { 750 {
654 this._scheduledProcessing = {stylesheets}; 751 this._scheduledProcessing = {stylesheets, mutations};
655 setTimeout(() => 752 setTimeout(() =>
656 { 753 {
657 let newStylesheets = this._scheduledProcessing.stylesheets; 754 let params = Object.assign({}, this._scheduledProcessing);
658 this._filteringInProgress = true; 755 this._filteringInProgress = true;
659 this._scheduledProcessing = null; 756 this._scheduledProcessing = null;
660 this._addSelectors(newStylesheets, completion); 757 this._addSelectors(params.stylesheets, params.mutations, completion);
661 }, 758 },
662 MIN_INVOCATION_INTERVAL - (performance.now() - this._lastInvocation)); 759 MIN_INVOCATION_INTERVAL - (performance.now() - this._lastInvocation));
663 } 760 }
664 else if (this.document.readyState == "loading") 761 else if (this.document.readyState == "loading")
665 { 762 {
666 this._scheduledProcessing = {stylesheets}; 763 this._scheduledProcessing = {stylesheets, mutations};
667 let handler = () => 764 let handler = () =>
668 { 765 {
669 document.removeEventListener("DOMContentLoaded", handler); 766 document.removeEventListener("DOMContentLoaded", handler);
670 let newStylesheets = this._scheduledProcessing.stylesheets; 767 let params = Object.assign({}, this._scheduledProcessing);
671 this._filteringInProgress = true; 768 this._filteringInProgress = true;
672 this._scheduledProcessing = null; 769 this._scheduledProcessing = null;
673 this._addSelectors(newStylesheets, completion); 770 this._addSelectors(params.stylesheets, params.mutations, completion);
674 }; 771 };
675 document.addEventListener("DOMContentLoaded", handler); 772 document.addEventListener("DOMContentLoaded", handler);
676 } 773 }
677 else 774 else
678 { 775 {
679 this._filteringInProgress = true; 776 this._filteringInProgress = true;
680 this._addSelectors(stylesheets, completion); 777 this._addSelectors(stylesheets, mutations, completion);
681 } 778 }
682 }, 779 },
683 780
684 onLoad(event) 781 onLoad(event)
685 { 782 {
686 let stylesheet = event.target.sheet; 783 let stylesheet = event.target.sheet;
687 if (stylesheet) 784 if (stylesheet)
688 this.queueFiltering([stylesheet]); 785 this.queueFiltering([stylesheet]);
689 }, 786 },
690 787
691 observe(mutations) 788 observe(mutations)
692 { 789 {
693 this.queueFiltering(); 790 this.queueFiltering(null, mutations);
694 }, 791 },
695 792
696 apply(patterns) 793 apply(patterns)
697 { 794 {
698 this.patterns = []; 795 this.patterns = [];
699 for (let pattern of patterns) 796 for (let pattern of patterns)
700 { 797 {
701 let selectors = this.parseSelector(pattern.selector); 798 let selectors = this.parseSelector(pattern.selector);
702 if (selectors != null && selectors.length > 0) 799 if (selectors != null && selectors.length > 0)
703 this.patterns.push({selectors, text: pattern.text}); 800 this.patterns.push(new Pattern(selectors, pattern.text));
704 } 801 }
705 802
706 if (this.patterns.length > 0) 803 if (this.patterns.length > 0)
707 { 804 {
708 this.queueFiltering(); 805 this.queueFiltering();
709 this.observer.observe( 806 this.observer.observe(
710 this.document, 807 this.document,
711 { 808 {
712 childList: true, 809 childList: true,
713 attributes: shouldObserveAttributes(this.patterns), 810 attributes: shouldObserveAttributes(this.patterns),
714 characterData: shouldObserveCharacterData(this.patterns), 811 characterData: shouldObserveCharacterData(this.patterns),
715 subtree: true 812 subtree: true
716 } 813 }
717 ); 814 );
718 this.document.addEventListener("load", this.onLoad.bind(this), true); 815 this.document.addEventListener("load", this.onLoad.bind(this), true);
719 } 816 }
720 } 817 }
721 }; 818 };
722 819
723 exports.ElemHideEmulation = ElemHideEmulation; 820 exports.ElemHideEmulation = ElemHideEmulation;
LEFTRIGHT
« no previous file | no next file » | Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Toggle Comments ('s')

Powered by Google App Engine
This is Rietveld