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

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

Issue 29712655: Issue 6437 - Skip styles-only patterns on DOM mutations (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore/
Left Patch Set: Created March 1, 2018, 5:11 p.m.
Right Patch Set: Use typeof Created March 14, 2018, 2:54 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;
(...skipping 201 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,
247 dependsOnDOM: true, 255 dependsOnDOM: true,
Manish Jethani 2018/03/01 17:18:11 -abp-has and -abp-contains definitely, one hundred
248 256
249 get dependsOnStyles() 257 get dependsOnStyles()
250 { 258 {
251 return this._innerSelectors.some(selector => selector.dependsOnStyles); 259 return this._innerSelectors.some(selector => selector.dependsOnStyles);
252 }, 260 },
253 261
254 get dependsOnCharacterData() 262 get dependsOnCharacterData()
255 { 263 {
256 return this._innerSelectors.some( 264 return this._innerSelectors.some(
257 selector => selector.dependsOnCharacterData 265 selector => selector.dependsOnCharacterData
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 function ContainsSelector(textContent) 311 function ContainsSelector(textContent)
304 { 312 {
305 this._regexp = makeRegExpParameter(textContent); 313 this._regexp = makeRegExpParameter(textContent);
306 } 314 }
307 315
308 ContainsSelector.prototype = { 316 ContainsSelector.prototype = {
309 requiresHiding: true, 317 requiresHiding: true,
310 dependsOnDOM: true, 318 dependsOnDOM: true,
311 dependsOnCharacterData: true, 319 dependsOnCharacterData: true,
312 320
313 *getSelectors(prefix, subtree, stylesheet) 321 *getSelectors(prefix, subtree, styles)
314 { 322 {
315 for (let element of this.getElements(prefix, subtree, stylesheet)) 323 for (let element of this.getElements(prefix, subtree, styles))
316 yield [makeSelector(element, ""), subtree]; 324 yield [makeSelector(element, ""), subtree];
317 }, 325 },
318 326
319 *getElements(prefix, subtree, stylesheet) 327 *getElements(prefix, subtree, styles)
320 { 328 {
321 let actualPrefix = (!prefix || incompletePrefixRegexp.test(prefix)) ? 329 let actualPrefix = (!prefix || incompletePrefixRegexp.test(prefix)) ?
322 prefix + "*" : prefix; 330 prefix + "*" : prefix;
323 331
324 let elements = scopedQuerySelectorAll(subtree, actualPrefix); 332 let elements = scopedQuerySelectorAll(subtree, actualPrefix);
325 if (elements) 333 if (elements)
326 { 334 {
327 for (let element of elements) 335 for (let element of elements)
328 { 336 {
329 if (this._regexp && this._regexp.test(element.textContent)) 337 if (this._regexp && this._regexp.test(element.textContent))
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 } 380 }
373 }, 381 },
374 382
375 *getSelectors(prefix, subtree, styles) 383 *getSelectors(prefix, subtree, styles)
376 { 384 {
377 for (let selector of this.findPropsSelectors(styles, prefix, this._regexp)) 385 for (let selector of this.findPropsSelectors(styles, prefix, this._regexp))
378 yield [selector, subtree]; 386 yield [selector, subtree];
379 } 387 }
380 }; 388 };
381 389
382 function isSelectorHidingOnlyPattern(pattern) 390 function Pattern(selectors, text)
383 { 391 {
384 return pattern.selectors.some(s => s.preferHideWithSelector) && 392 this.selectors = selectors;
385 !pattern.selectors.some(s => s.requiresHiding); 393 this.text = text;
386 } 394 }
387 395
388 function patternDependsOnStyles(pattern) 396 Pattern.prototype = {
389 { 397 isSelectorHidingOnlyPattern()
390 return pattern.selectors.some(s => s.dependsOnStyles); 398 {
391 } 399 return getCachedPropertyValue(
392 400 this, "_selectorHidingOnlyPattern",
393 function patternDependsOnDOM(pattern) 401 () => this.selectors.some(selector => selector.preferHideWithSelector) &&
394 { 402 !this.selectors.some(selector => selector.requiresHiding)
395 return pattern.selectors.some(s => s.dependsOnDOM); 403 );
396 } 404 },
397 405
398 function patternDependsOnBothStylesAndDOM(pattern) 406 get dependsOnStyles()
399 { 407 {
400 return pattern.selectors.some(s => s.dependsOnStyles && s.dependsOnDOM); 408 return getCachedPropertyValue(
401 } 409 this, "_dependsOnStyles",
402 410 () => this.selectors.some(selector => selector.dependsOnStyles)
403 function shouldProcessPattern(pattern, stylesheets, mutations) 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})
404 { 460 {
405 if (!stylesheets && !mutations) 461 if (!stylesheets && !mutations)
406 // Process everything. 462 return patterns.slice();
407 return true; 463
408 464 return patterns.filter(
409 if (!stylesheets && !patternDependsOnDOM(pattern)) 465 pattern => (stylesheets && pattern.dependsOnStyles) ||
410 return false; 466 (mutations && pattern.dependsOnDOM)
411 467 );
412 if (!mutations && !patternDependsOnStyles(pattern))
413 return false;
414
415 return true;
416 } 468 }
417 469
418 function shouldObserveAttributes(patterns) 470 function shouldObserveAttributes(patterns)
419 { 471 {
420 // Observe changes to attributes if either there's a plain selector that 472 return patterns.some(pattern => pattern.maybeDependsOnAttributes);
421 // looks like an ID selector, class selector, or attribute selector in one of
422 // the patterns (e.g. "a[href='https://example.com/']")
423 // or there's a properties selector nested inside a has selector
424 // (e.g. "div:-abp-has(:-abp-properties(color: blue))")
425 return patterns.some(
426 pattern => pattern.selectors.some(
427 selector => selector.maybeDependsOnAttributes ||
428 (selector instanceof HasSelector &&
429 selector.dependsOnStyles)
430 )
431 );
432 } 473 }
433 474
434 function shouldObserveCharacterData(patterns) 475 function shouldObserveCharacterData(patterns)
435 { 476 {
436 // Observe changes to character data only if there's a contains selector in 477 return patterns.some(pattern => pattern.dependsOnCharacterData);
437 // one of the patterns.
438 return patterns.some(
439 pattern => pattern.selectors.some(
440 selector => selector.dependsOnCharacterData
441 )
442 );
443 } 478 }
444 479
445 function ElemHideEmulation(addSelectorsFunc, hideElemsFunc) 480 function ElemHideEmulation(addSelectorsFunc, hideElemsFunc)
446 { 481 {
447 this.document = document; 482 this.document = document;
448 this.addSelectorsFunc = addSelectorsFunc; 483 this.addSelectorsFunc = addSelectorsFunc;
449 this.hideElemsFunc = hideElemsFunc; 484 this.hideElemsFunc = hideElemsFunc;
450 this.observer = new MutationObserver(this.observe.bind(this)); 485 this.observer = new MutationObserver(this.observe.bind(this));
451 } 486 }
452 487
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
537 * @param {MutationRecord[]} [mutations] 572 * @param {MutationRecord[]} [mutations]
538 * The list of DOM mutations that have been applied to the document and 573 * The list of DOM mutations that have been applied to the document and
539 * made reprocessing necessary. This parameter shouldn't be passed in for 574 * made reprocessing necessary. This parameter shouldn't be passed in for
540 * the initial processing, the entire document will be considered 575 * the initial processing, the entire document will be considered
541 * then and all rules, including the ones not dependent on the DOM. 576 * then and all rules, including the ones not dependent on the DOM.
542 * @param {function} [done] 577 * @param {function} [done]
543 * Callback to call when done. 578 * Callback to call when done.
544 */ 579 */
545 _addSelectors(stylesheets, mutations, done) 580 _addSelectors(stylesheets, mutations, done)
546 { 581 {
582 let patterns = filterPatterns(this.patterns, {stylesheets, mutations});
583
547 let selectors = []; 584 let selectors = [];
548 let selectorFilters = []; 585 let selectorFilters = [];
549 586
550 let elements = []; 587 let elements = [];
551 let elementFilters = []; 588 let elementFilters = [];
552 589
553 let cssStyles = []; 590 let cssStyles = [];
554
555 let patterns = null;
556 591
557 // If neither any style sheets nor any DOM mutations have been specified, 592 // If neither any style sheets nor any DOM mutations have been specified,
558 // do full processing. 593 // do full processing.
559 if (!stylesheets && !mutations) 594 if (!stylesheets && !mutations)
560 {
561 patterns = this.patterns.slice();
562 stylesheets = this.document.styleSheets; 595 stylesheets = this.document.styleSheets;
563 }
564 else
565 {
566 patterns = this.patterns.filter(
567 pattern => shouldProcessPattern(pattern, stylesheets, mutations)
568 );
569 }
570 596
571 // If there are any DOM mutations and any of the patterns depends on both 597 // If there are any DOM mutations and any of the patterns depends on both
572 // style sheets and the DOM (e.g. -abp-has(-abp-properties)), find all the 598 // style sheets and the DOM (e.g. -abp-has(-abp-properties)), find all the
573 // rules in every style sheet in the document, because we need to run 599 // rules in every style sheet in the document, because we need to run
574 // querySelectorAll afterwards. On the other hand, if we only have patterns 600 // querySelectorAll afterwards. On the other hand, if we only have patterns
575 // that depend on either styles or DOM both not both 601 // that depend on either styles or DOM both not both
576 // (e.g. -abp-properties or -abp-contains), we can skip this part. 602 // (e.g. -abp-properties or -abp-contains), we can skip this part.
577 if (mutations && patterns.some(patternDependsOnBothStylesAndDOM)) 603 if (mutations && patterns.some(pattern => pattern.dependsOnStylesAndDOM))
578 stylesheets = this.document.styleSheets; 604 stylesheets = this.document.styleSheets;
579 605
580 for (let stylesheet of stylesheets || []) 606 for (let stylesheet of stylesheets || [])
581 { 607 {
582 // Explicitly ignore third-party stylesheets to ensure consistent behavior 608 // Explicitly ignore third-party stylesheets to ensure consistent behavior
583 // between Firefox and Chrome. 609 // between Firefox and Chrome.
584 if (!this.isSameOrigin(stylesheet)) 610 if (!this.isSameOrigin(stylesheet))
585 continue; 611 continue;
586 612
587 let rules = stylesheet.cssRules; 613 let rules = stylesheet.cssRules;
(...skipping 13 matching lines...) Expand all
601 let generator = null; 627 let generator = null;
602 628
603 let processPatterns = () => 629 let processPatterns = () =>
604 { 630 {
605 let cycleStart = performance.now(); 631 let cycleStart = performance.now();
606 632
607 if (!pattern) 633 if (!pattern)
608 { 634 {
609 if (!patterns.length) 635 if (!patterns.length)
610 { 636 {
611 this.addSelectorsFunc(selectors, selectorFilters); 637 if (selectors.length > 0)
612 this.hideElemsFunc(elements, elementFilters); 638 this.addSelectorsFunc(selectors, selectorFilters);
639 if (elements.length > 0)
640 this.hideElemsFunc(elements, elementFilters);
613 if (typeof done == "function") 641 if (typeof done == "function")
614 done(); 642 done();
615 return; 643 return;
616 } 644 }
617 645
618 pattern = patterns.shift(); 646 pattern = patterns.shift();
619 647
620 generator = evaluate(pattern.selectors, 0, "", 648 generator = evaluate(pattern.selectors, 0, "",
621 this.document, cssStyles); 649 this.document, cssStyles);
622 } 650 }
623 for (let selector of generator) 651 for (let selector of generator)
624 { 652 {
625 if (selector != null) 653 if (selector != null)
626 { 654 {
627 if (isSelectorHidingOnlyPattern(pattern)) 655 if (pattern.isSelectorHidingOnlyPattern())
628 { 656 {
629 selectors.push(selector); 657 selectors.push(selector);
630 selectorFilters.push(pattern.text); 658 selectorFilters.push(pattern.text);
631 } 659 }
632 else 660 else
633 { 661 {
634 for (let element of this.document.querySelectorAll(selector)) 662 for (let element of this.document.querySelectorAll(selector))
635 { 663 {
636 elements.push(element); 664 elements.push(element);
637 elementFilters.push(pattern.text); 665 elementFilters.push(pattern.text);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
669 697
670 /** 698 /**
671 * Re-run filtering either immediately or queued. 699 * Re-run filtering either immediately or queued.
672 * @param {CSSStyleSheet[]} [stylesheets] 700 * @param {CSSStyleSheet[]} [stylesheets]
673 * new stylesheets to be processed. This parameter should be omitted 701 * new stylesheets to be processed. This parameter should be omitted
674 * for full reprocessing. 702 * for full reprocessing.
675 * @param {MutationRecord[]} [mutations] 703 * @param {MutationRecord[]} [mutations]
676 * new DOM mutations to be processed. This parameter should be omitted 704 * new DOM mutations to be processed. This parameter should be omitted
677 * for full reprocessing. 705 * for full reprocessing.
678 */ 706 */
679 queueFiltering(stylesheets, mutations) 707 queueFiltering(stylesheets, mutations)
Manish Jethani 2018/03/01 17:18:11 The addition of the mutations parameter here is ma
680 { 708 {
681 let completion = () => 709 let completion = () =>
682 { 710 {
683 this._lastInvocation = performance.now(); 711 this._lastInvocation = performance.now();
684 this._filteringInProgress = false; 712 this._filteringInProgress = false;
685 if (this._scheduledProcessing) 713 if (this._scheduledProcessing)
686 { 714 {
687 let newStylesheets = this._scheduledProcessing.stylesheets; 715 let params = Object.assign({}, this._scheduledProcessing);
688 let newMutations = this._scheduledProcessing.mutations;
689 this._scheduledProcessing = null; 716 this._scheduledProcessing = null;
690 this.queueFiltering(newStylesheets, newMutations); 717 this.queueFiltering(params.stylesheets, params.mutations);
691 } 718 }
692 }; 719 };
693 720
694 if (this._scheduledProcessing) 721 if (this._scheduledProcessing)
695 { 722 {
696 if (!stylesheets && !mutations) 723 if (!stylesheets && !mutations)
697 { 724 {
698 this._scheduledProcessing.stylesheets = null; 725 this._scheduledProcessing = {};
699 this._scheduledProcessing.mutations = null;
700 } 726 }
701 else 727 else
702 { 728 {
703 if (stylesheets) 729 if (stylesheets)
704 { 730 {
705 if (!this._scheduledProcessing.stylesheets) 731 if (!this._scheduledProcessing.stylesheets)
706 this._scheduledProcessing.stylesheets = []; 732 this._scheduledProcessing.stylesheets = [];
707 this._scheduledProcessing.stylesheets.push(...stylesheets); 733 this._scheduledProcessing.stylesheets.push(...stylesheets);
708 } 734 }
709 if (mutations) 735 if (mutations)
710 { 736 {
711 if (!this._scheduledProcessing.mutations) 737 if (!this._scheduledProcessing.mutations)
712 this._scheduledProcessing.mutations = []; 738 this._scheduledProcessing.mutations = [];
713 this._scheduledProcessing.mutations.push(...mutations); 739 this._scheduledProcessing.mutations.push(...mutations);
714 } 740 }
715 } 741 }
716 } 742 }
717 else if (this._filteringInProgress) 743 else if (this._filteringInProgress)
718 { 744 {
719 this._scheduledProcessing = {stylesheets, mutations}; 745 this._scheduledProcessing = {stylesheets, mutations};
720 } 746 }
721 else if (performance.now() - this._lastInvocation < MIN_INVOCATION_INTERVAL) 747 else if (performance.now() - this._lastInvocation < MIN_INVOCATION_INTERVAL)
722 { 748 {
723 this._scheduledProcessing = {stylesheets, mutations}; 749 this._scheduledProcessing = {stylesheets, mutations};
724 setTimeout(() => 750 setTimeout(() =>
725 { 751 {
726 let newStylesheets = this._scheduledProcessing.stylesheets; 752 let params = Object.assign({}, this._scheduledProcessing);
727 let newMutations = this._scheduledProcessing.mutations;
728 this._filteringInProgress = true; 753 this._filteringInProgress = true;
729 this._scheduledProcessing = null; 754 this._scheduledProcessing = null;
730 this._addSelectors(newStylesheets, newMutations, completion); 755 this._addSelectors(params.stylesheets, params.mutations, completion);
731 }, 756 },
732 MIN_INVOCATION_INTERVAL - (performance.now() - this._lastInvocation)); 757 MIN_INVOCATION_INTERVAL - (performance.now() - this._lastInvocation));
733 } 758 }
734 else if (this.document.readyState == "loading") 759 else if (this.document.readyState == "loading")
735 { 760 {
736 this._scheduledProcessing = {stylesheets, mutations}; 761 this._scheduledProcessing = {stylesheets, mutations};
737 let handler = () => 762 let handler = () =>
738 { 763 {
739 document.removeEventListener("DOMContentLoaded", handler); 764 document.removeEventListener("DOMContentLoaded", handler);
740 let newStylesheets = this._scheduledProcessing.stylesheets; 765 let params = Object.assign({}, this._scheduledProcessing);
741 let newMutations = this._scheduledProcessing.mutations;
742 this._filteringInProgress = true; 766 this._filteringInProgress = true;
743 this._scheduledProcessing = null; 767 this._scheduledProcessing = null;
744 this._addSelectors(newStylesheets, newMutations, completion); 768 this._addSelectors(params.stylesheets, params.mutations, completion);
745 }; 769 };
746 document.addEventListener("DOMContentLoaded", handler); 770 document.addEventListener("DOMContentLoaded", handler);
747 } 771 }
748 else 772 else
749 { 773 {
750 this._filteringInProgress = true; 774 this._filteringInProgress = true;
751 this._addSelectors(stylesheets, mutations, completion); 775 this._addSelectors(stylesheets, mutations, completion);
752 } 776 }
753 }, 777 },
754 778
755 onLoad(event) 779 onLoad(event)
756 { 780 {
757 let stylesheet = event.target.sheet; 781 let stylesheet = event.target.sheet;
758 if (stylesheet) 782 if (stylesheet)
759 this.queueFiltering([stylesheet]); 783 this.queueFiltering([stylesheet]);
760 }, 784 },
761 785
762 observe(mutations) 786 observe(mutations)
763 { 787 {
764 this.queueFiltering(null, mutations); 788 this.queueFiltering(null, mutations);
765 }, 789 },
766 790
767 apply(patterns) 791 apply(patterns)
768 { 792 {
769 this.patterns = []; 793 this.patterns = [];
770 for (let pattern of patterns) 794 for (let pattern of patterns)
771 { 795 {
772 let selectors = this.parseSelector(pattern.selector); 796 let selectors = this.parseSelector(pattern.selector);
773 if (selectors != null && selectors.length > 0) 797 if (selectors != null && selectors.length > 0)
774 this.patterns.push({selectors, text: pattern.text}); 798 this.patterns.push(new Pattern(selectors, pattern.text));
775 } 799 }
776 800
777 if (this.patterns.length > 0) 801 if (this.patterns.length > 0)
778 { 802 {
779 this.queueFiltering(); 803 this.queueFiltering();
780 this.observer.observe( 804 this.observer.observe(
781 this.document, 805 this.document,
782 { 806 {
783 childList: true, 807 childList: true,
784 attributes: shouldObserveAttributes(this.patterns), 808 attributes: shouldObserveAttributes(this.patterns),
785 characterData: shouldObserveCharacterData(this.patterns), 809 characterData: shouldObserveCharacterData(this.patterns),
786 subtree: true 810 subtree: true
787 } 811 }
788 ); 812 );
789 this.document.addEventListener("load", this.onLoad.bind(this), true); 813 this.document.addEventListener("load", this.onLoad.bind(this), true);
790 } 814 }
791 } 815 }
792 }; 816 };
793 817
794 exports.ElemHideEmulation = ElemHideEmulation; 818 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