| OLD | NEW |
| 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 const {indexOf} = require("../coreUtils"); | 21 const {indexOf} = require("../coreUtils"); |
| 22 | 22 |
| 23 let MIN_INVOCATION_INTERVAL = 3000; | 23 let MIN_INVOCATION_INTERVAL = 3000; |
| 24 const MAX_SYNCHRONOUS_PROCESSING_TIME = 50; | 24 const MAX_SYNCHRONOUS_PROCESSING_TIME = 50; |
| 25 const abpSelectorRegexp = /:-abp-([\w-]+)\(/i; | 25 const abpSelectorRegexp = /:-abp-([\w-]+)\(/i; |
| 26 | 26 |
| 27 function getCachedPropertyValue(object, name, defaultValueFunc = () => {}) | 27 function getCachedPropertyValue(object, name, defaultValueFunc = () => {}) |
| 28 { | 28 { |
| 29 let value = object[name]; | 29 let value = object[name]; |
| 30 if (typeof value == "undefined") | 30 if (typeof value === "undefined") |
| 31 Object.defineProperty(object, name, {value: value = defaultValueFunc()}); | 31 Object.defineProperty(object, name, {value: value = defaultValueFunc()}); |
| 32 return value; | 32 return value; |
| 33 } | 33 } |
| 34 | 34 |
| 35 /** Return position of node from parent. | 35 /** Return position of node from parent. |
| 36 * @param {Node} node the node to find the position of. | 36 * @param {Node} node the node to find the position of. |
| 37 * @return {number} One-based index like for :nth-child(), or 0 on error. | 37 * @return {number} One-based index like for :nth-child(), or 0 on error. |
| 38 */ | 38 */ |
| 39 function positionInParent(node) | 39 function positionInParent(node) |
| 40 { | 40 { |
| 41 return indexOf(node.parentNode.children, node) + 1; | 41 return indexOf(node.parentNode.children, node) + 1; |
| 42 } | 42 } |
| 43 | 43 |
| 44 function makeSelector(node, selector = "") | 44 function makeSelector(node, selector = "") |
| 45 { | 45 { |
| 46 if (node == null) | 46 if (!node) |
| 47 return null; | 47 return null; |
| 48 if (!node.parentElement) | 48 if (!node.parentElement) |
| 49 { | 49 { |
| 50 let newSelector = ":root"; | 50 let newSelector = ":root"; |
| 51 if (selector) | 51 if (selector) |
| 52 newSelector += " > " + selector; | 52 newSelector += " > " + selector; |
| 53 return newSelector; | 53 return newSelector; |
| 54 } | 54 } |
| 55 let idx = positionInParent(node); | 55 let idx = positionInParent(node); |
| 56 if (idx > 0) | 56 if (idx > 0) |
| 57 { | 57 { |
| 58 let newSelector = `${node.tagName}:nth-child(${idx})`; | 58 let newSelector = `${node.tagName}:nth-child(${idx})`; |
| 59 if (selector) | 59 if (selector) |
| 60 newSelector += " > " + selector; | 60 newSelector += " > " + selector; |
| 61 return makeSelector(node.parentElement, newSelector); | 61 return makeSelector(node.parentElement, newSelector); |
| 62 } | 62 } |
| 63 | 63 |
| 64 return selector; | 64 return selector; |
| 65 } | 65 } |
| 66 | 66 |
| 67 function parseSelectorContent(content, startIndex) | 67 function parseSelectorContent(content, startIndex) |
| 68 { | 68 { |
| 69 let parens = 1; | 69 let parens = 1; |
| 70 let quote = null; | 70 let quote = null; |
| 71 let i = startIndex; | 71 let i = startIndex; |
| 72 for (; i < content.length; i++) | 72 for (; i < content.length; i++) |
| 73 { | 73 { |
| 74 let c = content[i]; | 74 let c = content[i]; |
| 75 if (c == "\\") | 75 if (c === "\\") |
| 76 { | 76 { |
| 77 // Ignore escaped characters | 77 // Ignore escaped characters |
| 78 i++; | 78 i++; |
| 79 } | 79 } |
| 80 else if (quote) | 80 else if (quote) |
| 81 { | 81 { |
| 82 if (c == quote) | 82 if (c === quote) |
| 83 quote = null; | 83 quote = null; |
| 84 } | 84 } |
| 85 else if (c == "'" || c == '"') | 85 else if (c === "'" || c === '"') |
| 86 quote = c; | 86 quote = c; |
| 87 else if (c == "(") | 87 else if (c === "(") |
| 88 parens++; | 88 parens++; |
| 89 else if (c == ")") | 89 else if (c === ")") |
| 90 { | 90 { |
| 91 parens--; | 91 parens--; |
| 92 if (parens == 0) | 92 if (parens === 0) |
| 93 break; | 93 break; |
| 94 } | 94 } |
| 95 } | 95 } |
| 96 | 96 |
| 97 if (parens > 0) | 97 if (parens > 0) |
| 98 return null; | 98 return null; |
| 99 return {text: content.substring(startIndex, i), end: i}; | 99 return {text: content.substring(startIndex, i), end: i}; |
| 100 } | 100 } |
| 101 | 101 |
| 102 /** Stringified style objects | 102 /** Stringified style objects |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 | 148 |
| 149 /** | 149 /** |
| 150 * Query selector. If it is relative, will try :scope. | 150 * Query selector. If it is relative, will try :scope. |
| 151 * @param {Node} subtree the element to query selector | 151 * @param {Node} subtree the element to query selector |
| 152 * @param {string} selector the selector to query | 152 * @param {string} selector the selector to query |
| 153 * @param {bool} [all=false] true to perform querySelectorAll() | 153 * @param {bool} [all=false] true to perform querySelectorAll() |
| 154 * @returns {?(Node|NodeList)} result of the query. null in case of error. | 154 * @returns {?(Node|NodeList)} result of the query. null in case of error. |
| 155 */ | 155 */ |
| 156 function scopedQuerySelector(subtree, selector, all) | 156 function scopedQuerySelector(subtree, selector, all) |
| 157 { | 157 { |
| 158 if (selector[0] == ">") | 158 if (selector[0] === ">") |
| 159 { | 159 { |
| 160 selector = ":scope" + selector; | 160 selector = ":scope" + selector; |
| 161 if (scopeSupported) | 161 if (scopeSupported) |
| 162 { | 162 { |
| 163 return all ? subtree.querySelectorAll(selector) : | 163 return all ? subtree.querySelectorAll(selector) : |
| 164 subtree.querySelector(selector); | 164 subtree.querySelector(selector); |
| 165 } | 165 } |
| 166 if (scopeSupported == null) | 166 if (scopeSupported === null) |
| 167 return tryQuerySelector(subtree, selector, all); | 167 return tryQuerySelector(subtree, selector, all); |
| 168 return null; | 168 return null; |
| 169 } | 169 } |
| 170 return all ? subtree.querySelectorAll(selector) : | 170 return all ? subtree.querySelectorAll(selector) : |
| 171 subtree.querySelector(selector); | 171 subtree.querySelector(selector); |
| 172 } | 172 } |
| 173 | 173 |
| 174 function scopedQuerySelectorAll(subtree, selector) | 174 function scopedQuerySelectorAll(subtree, selector) |
| 175 { | 175 { |
| 176 return scopedQuerySelector(subtree, selector, true); | 176 return scopedQuerySelector(subtree, selector, true); |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 348 else | 348 else |
| 349 yield null; | 349 yield null; |
| 350 } | 350 } |
| 351 } | 351 } |
| 352 } | 352 } |
| 353 }; | 353 }; |
| 354 | 354 |
| 355 function PropsSelector(propertyExpression) | 355 function PropsSelector(propertyExpression) |
| 356 { | 356 { |
| 357 let regexpString; | 357 let regexpString; |
| 358 if (propertyExpression.length >= 2 && propertyExpression[0] == "/" && | 358 if (propertyExpression.length >= 2 && propertyExpression[0] === "/" && |
| 359 propertyExpression[propertyExpression.length - 1] == "/") | 359 propertyExpression[propertyExpression.length - 1] === "/") |
| 360 { | 360 { |
| 361 regexpString = propertyExpression.slice(1, -1) | 361 regexpString = propertyExpression.slice(1, -1) |
| 362 .replace("\\7B ", "{").replace("\\7D ", "}"); | 362 .replace("\\7B ", "{").replace("\\7D ", "}"); |
| 363 } | 363 } |
| 364 else | 364 else |
| 365 regexpString = filterToRegExp(propertyExpression); | 365 regexpString = filterToRegExp(propertyExpression); |
| 366 | 366 |
| 367 this._regexp = new RegExp(regexpString, "i"); | 367 this._regexp = new RegExp(regexpString, "i"); |
| 368 } | 368 } |
| 369 | 369 |
| 370 PropsSelector.prototype = { | 370 PropsSelector.prototype = { |
| 371 dependsOnStyles: true, | 371 dependsOnStyles: true, |
| 372 | 372 |
| 373 *findPropsSelectors(styles, prefix, regexp) | 373 *findPropsSelectors(styles, prefix, regexp) |
| 374 { | 374 { |
| 375 for (let style of styles) | 375 for (let style of styles) |
| 376 if (regexp.test(style.style)) | 376 if (regexp.test(style.style)) |
| 377 for (let subSelector of style.subSelectors) | 377 for (let subSelector of style.subSelectors) |
| 378 { | 378 { |
| 379 if (subSelector.startsWith("*") && | 379 if (subSelector.startsWith("*") && |
| 380 !incompletePrefixRegexp.test(prefix)) | 380 !incompletePrefixRegexp.test(prefix)) |
| 381 { | 381 { |
| 382 subSelector = subSelector.substr(1); | 382 subSelector = subSelector.substr(1); |
| 383 } | 383 } |
| 384 let idx = subSelector.lastIndexOf("::"); | 384 let idx = subSelector.lastIndexOf("::"); |
| 385 if (idx != -1) | 385 if (idx !== -1) |
| 386 subSelector = subSelector.substr(0, idx); | 386 subSelector = subSelector.substr(0, idx); |
| 387 yield prefix + subSelector; | 387 yield prefix + subSelector; |
| 388 } | 388 } |
| 389 }, | 389 }, |
| 390 | 390 |
| 391 *getSelectors(prefix, subtree, styles) | 391 *getSelectors(prefix, subtree, styles) |
| 392 { | 392 { |
| 393 for (let selector of this.findPropsSelectors(styles, prefix, this._regexp)) | 393 for (let selector of this.findPropsSelectors(styles, prefix, this._regexp)) |
| 394 yield [selector, subtree]; | 394 yield [selector, subtree]; |
| 395 } | 395 } |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 480 function extractMutationTypes(mutations) | 480 function extractMutationTypes(mutations) |
| 481 { | 481 { |
| 482 let types = new Set(); | 482 let types = new Set(); |
| 483 | 483 |
| 484 for (let mutation of mutations) | 484 for (let mutation of mutations) |
| 485 { | 485 { |
| 486 types.add(mutation.type); | 486 types.add(mutation.type); |
| 487 | 487 |
| 488 // There are only 3 types of mutations: "attributes", "characterData", and | 488 // There are only 3 types of mutations: "attributes", "characterData", and |
| 489 // "childList". | 489 // "childList". |
| 490 if (types.size == 3) | 490 if (types.size === 3) |
| 491 break; | 491 break; |
| 492 } | 492 } |
| 493 | 493 |
| 494 return types; | 494 return types; |
| 495 } | 495 } |
| 496 | 496 |
| 497 function filterPatterns(patterns, {stylesheets, mutations}) | 497 function filterPatterns(patterns, {stylesheets, mutations}) |
| 498 { | 498 { |
| 499 if (!stylesheets && !mutations) | 499 if (!stylesheets && !mutations) |
| 500 return patterns.slice(); | 500 return patterns.slice(); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 525 this.hideElemsFunc = hideElemsFunc; | 525 this.hideElemsFunc = hideElemsFunc; |
| 526 this.observer = new MutationObserver(this.observe.bind(this)); | 526 this.observer = new MutationObserver(this.observe.bind(this)); |
| 527 this.useInlineStyles = true; | 527 this.useInlineStyles = true; |
| 528 } | 528 } |
| 529 | 529 |
| 530 ElemHideEmulation.prototype = { | 530 ElemHideEmulation.prototype = { |
| 531 isSameOrigin(stylesheet) | 531 isSameOrigin(stylesheet) |
| 532 { | 532 { |
| 533 try | 533 try |
| 534 { | 534 { |
| 535 return new URL(stylesheet.href).origin == this.document.location.origin; | 535 return new URL(stylesheet.href).origin === this.document.location.origin; |
| 536 } | 536 } |
| 537 catch (e) | 537 catch (e) |
| 538 { | 538 { |
| 539 // Invalid URL, assume that it is first-party. | 539 // Invalid URL, assume that it is first-party. |
| 540 return true; | 540 return true; |
| 541 } | 541 } |
| 542 }, | 542 }, |
| 543 | 543 |
| 544 /** Parse the selector | 544 /** Parse the selector |
| 545 * @param {string} selector the selector to parse | 545 * @param {string} selector the selector to parse |
| 546 * @return {Array} selectors is an array of objects, | 546 * @return {Array} selectors is an array of objects, |
| 547 * or null in case of errors. | 547 * or null in case of errors. |
| 548 */ | 548 */ |
| 549 parseSelector(selector) | 549 parseSelector(selector) |
| 550 { | 550 { |
| 551 if (selector.length == 0) | 551 if (selector.length === 0) |
| 552 return []; | 552 return []; |
| 553 | 553 |
| 554 let match = abpSelectorRegexp.exec(selector); | 554 let match = abpSelectorRegexp.exec(selector); |
| 555 if (!match) | 555 if (!match) |
| 556 return [new PlainSelector(selector)]; | 556 return [new PlainSelector(selector)]; |
| 557 | 557 |
| 558 let selectors = []; | 558 let selectors = []; |
| 559 if (match.index > 0) | 559 if (match.index > 0) |
| 560 selectors.push(new PlainSelector(selector.substr(0, match.index))); | 560 selectors.push(new PlainSelector(selector.substr(0, match.index))); |
| 561 | 561 |
| 562 let startIndex = match.index + match[0].length; | 562 let startIndex = match.index + match[0].length; |
| 563 let content = parseSelectorContent(selector, startIndex); | 563 let content = parseSelectorContent(selector, startIndex); |
| 564 if (!content) | 564 if (!content) |
| 565 { | 565 { |
| 566 console.error(new SyntaxError("Failed to parse Adblock Plus " + | 566 console.error(new SyntaxError("Failed to parse Adblock Plus " + |
| 567 `selector ${selector} ` + | 567 `selector ${selector} ` + |
| 568 "due to unmatched parentheses.")); | 568 "due to unmatched parentheses.")); |
| 569 return null; | 569 return null; |
| 570 } | 570 } |
| 571 if (match[1] == "properties") | 571 if (match[1] === "properties") |
| 572 selectors.push(new PropsSelector(content.text)); | 572 selectors.push(new PropsSelector(content.text)); |
| 573 else if (match[1] == "has") | 573 else if (match[1] === "has") |
| 574 { | 574 { |
| 575 let hasSelectors = this.parseSelector(content.text); | 575 let hasSelectors = this.parseSelector(content.text); |
| 576 if (hasSelectors == null) | 576 if (hasSelectors === null) |
| 577 return null; | 577 return null; |
| 578 selectors.push(new HasSelector(hasSelectors)); | 578 selectors.push(new HasSelector(hasSelectors)); |
| 579 } | 579 } |
| 580 else if (match[1] == "contains") | 580 else if (match[1] === "contains") |
| 581 selectors.push(new ContainsSelector(content.text)); | 581 selectors.push(new ContainsSelector(content.text)); |
| 582 else | 582 else |
| 583 { | 583 { |
| 584 // this is an error, can't parse selector. | 584 // this is an error, can't parse selector. |
| 585 console.error(new SyntaxError("Failed to parse Adblock Plus " + | 585 console.error(new SyntaxError("Failed to parse Adblock Plus " + |
| 586 `selector ${selector}, invalid ` + | 586 `selector ${selector}, invalid ` + |
| 587 `pseudo-class :-abp-${match[1]}().`)); | 587 `pseudo-class :-abp-${match[1]}().`)); |
| 588 return null; | 588 return null; |
| 589 } | 589 } |
| 590 | 590 |
| 591 let suffix = this.parseSelector(selector.substr(content.end + 1)); | 591 let suffix = this.parseSelector(selector.substr(content.end + 1)); |
| 592 if (suffix == null) | 592 if (suffix === null) |
| 593 return null; | 593 return null; |
| 594 | 594 |
| 595 selectors.push(...suffix); | 595 selectors.push(...suffix); |
| 596 | 596 |
| 597 if (selectors.length == 1 && selectors[0] instanceof ContainsSelector) | 597 if (selectors.length === 1 && selectors[0] instanceof ContainsSelector) |
| 598 { | 598 { |
| 599 console.error(new SyntaxError("Failed to parse Adblock Plus " + | 599 console.error(new SyntaxError("Failed to parse Adblock Plus " + |
| 600 `selector ${selector}, can't ` + | 600 `selector ${selector}, can't ` + |
| 601 "have a lonely :-abp-contains().")); | 601 "have a lonely :-abp-contains().")); |
| 602 return null; | 602 return null; |
| 603 } | 603 } |
| 604 return selectors; | 604 return selectors; |
| 605 }, | 605 }, |
| 606 | 606 |
| 607 /** | 607 /** |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 664 // in that case. | 664 // in that case. |
| 665 // See https://searchfox.org/mozilla-central/rev/f65d7528e34ef1a7665b4a1
a7b7cdb1388fcd3aa/layout/style/StyleSheet.cpp#699 | 665 // See https://searchfox.org/mozilla-central/rev/f65d7528e34ef1a7665b4a1
a7b7cdb1388fcd3aa/layout/style/StyleSheet.cpp#699 |
| 666 continue; | 666 continue; |
| 667 } | 667 } |
| 668 | 668 |
| 669 if (!rules) | 669 if (!rules) |
| 670 continue; | 670 continue; |
| 671 | 671 |
| 672 for (let rule of rules) | 672 for (let rule of rules) |
| 673 { | 673 { |
| 674 if (rule.type != rule.STYLE_RULE) | 674 if (rule.type !== rule.STYLE_RULE) |
| 675 continue; | 675 continue; |
| 676 | 676 |
| 677 cssStyles.push(stringifyStyle(rule)); | 677 cssStyles.push(stringifyStyle(rule)); |
| 678 } | 678 } |
| 679 } | 679 } |
| 680 | 680 |
| 681 let pattern = null; | 681 let pattern = null; |
| 682 let generator = null; | 682 let generator = null; |
| 683 | 683 |
| 684 let processPatterns = () => | 684 let processPatterns = () => |
| 685 { | 685 { |
| 686 let cycleStart = performance.now(); | 686 let cycleStart = performance.now(); |
| 687 | 687 |
| 688 if (!pattern) | 688 if (!pattern) |
| 689 { | 689 { |
| 690 if (!patterns.length) | 690 if (!patterns.length) |
| 691 { | 691 { |
| 692 if (selectors.length > 0) | 692 if (selectors.length > 0) |
| 693 this.addSelectorsFunc(selectors, selectorFilters); | 693 this.addSelectorsFunc(selectors, selectorFilters); |
| 694 if (elements.length > 0) | 694 if (elements.length > 0) |
| 695 this.hideElemsFunc(elements, elementFilters); | 695 this.hideElemsFunc(elements, elementFilters); |
| 696 if (typeof done == "function") | 696 if (typeof done === "function") |
| 697 done(); | 697 done(); |
| 698 return; | 698 return; |
| 699 } | 699 } |
| 700 | 700 |
| 701 pattern = patterns.shift(); | 701 pattern = patterns.shift(); |
| 702 | 702 |
| 703 generator = evaluate(pattern.selectors, 0, "", | 703 generator = evaluate(pattern.selectors, 0, "", |
| 704 this.document, cssStyles); | 704 this.document, cssStyles); |
| 705 } | 705 } |
| 706 for (let selector of generator) | 706 for (let selector of generator) |
| 707 { | 707 { |
| 708 if (selector != null) | 708 if (selector !== null) |
| 709 { | 709 { |
| 710 if (!this.useInlineStyles) | 710 if (!this.useInlineStyles) |
| 711 { | 711 { |
| 712 selectors.push(selector); | 712 selectors.push(selector); |
| 713 selectorFilters.push(pattern.text); | 713 selectorFilters.push(pattern.text); |
| 714 } | 714 } |
| 715 else | 715 else |
| 716 { | 716 { |
| 717 for (let element of this.document.querySelectorAll(selector)) | 717 for (let element of this.document.querySelectorAll(selector)) |
| 718 { | 718 { |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 805 this._scheduledProcessing = {stylesheets, mutations}; | 805 this._scheduledProcessing = {stylesheets, mutations}; |
| 806 setTimeout(() => | 806 setTimeout(() => |
| 807 { | 807 { |
| 808 let params = Object.assign({}, this._scheduledProcessing); | 808 let params = Object.assign({}, this._scheduledProcessing); |
| 809 this._filteringInProgress = true; | 809 this._filteringInProgress = true; |
| 810 this._scheduledProcessing = null; | 810 this._scheduledProcessing = null; |
| 811 this._addSelectors(params.stylesheets, params.mutations, completion); | 811 this._addSelectors(params.stylesheets, params.mutations, completion); |
| 812 }, | 812 }, |
| 813 MIN_INVOCATION_INTERVAL - (performance.now() - this._lastInvocation)); | 813 MIN_INVOCATION_INTERVAL - (performance.now() - this._lastInvocation)); |
| 814 } | 814 } |
| 815 else if (this.document.readyState == "loading") | 815 else if (this.document.readyState === "loading") |
| 816 { | 816 { |
| 817 this._scheduledProcessing = {stylesheets, mutations}; | 817 this._scheduledProcessing = {stylesheets, mutations}; |
| 818 let handler = () => | 818 let handler = () => |
| 819 { | 819 { |
| 820 this.document.removeEventListener("DOMContentLoaded", handler); | 820 this.document.removeEventListener("DOMContentLoaded", handler); |
| 821 let params = Object.assign({}, this._scheduledProcessing); | 821 let params = Object.assign({}, this._scheduledProcessing); |
| 822 this._filteringInProgress = true; | 822 this._filteringInProgress = true; |
| 823 this._scheduledProcessing = null; | 823 this._scheduledProcessing = null; |
| 824 this._addSelectors(params.stylesheets, params.mutations, completion); | 824 this._addSelectors(params.stylesheets, params.mutations, completion); |
| 825 }; | 825 }; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 843 { | 843 { |
| 844 this.queueFiltering(null, mutations); | 844 this.queueFiltering(null, mutations); |
| 845 }, | 845 }, |
| 846 | 846 |
| 847 apply(patterns) | 847 apply(patterns) |
| 848 { | 848 { |
| 849 this.patterns = []; | 849 this.patterns = []; |
| 850 for (let pattern of patterns) | 850 for (let pattern of patterns) |
| 851 { | 851 { |
| 852 let selectors = this.parseSelector(pattern.selector); | 852 let selectors = this.parseSelector(pattern.selector); |
| 853 if (selectors != null && selectors.length > 0) | 853 if (selectors !== null && selectors.length > 0) |
| 854 this.patterns.push(new Pattern(selectors, pattern.text)); | 854 this.patterns.push(new Pattern(selectors, pattern.text)); |
| 855 } | 855 } |
| 856 | 856 |
| 857 if (this.patterns.length > 0) | 857 if (this.patterns.length > 0) |
| 858 { | 858 { |
| 859 this.queueFiltering(); | 859 this.queueFiltering(); |
| 860 this.observer.observe( | 860 this.observer.observe( |
| 861 this.document, | 861 this.document, |
| 862 { | 862 { |
| 863 childList: true, | 863 childList: true, |
| 864 attributes: shouldObserveAttributes(this.patterns), | 864 attributes: shouldObserveAttributes(this.patterns), |
| 865 characterData: shouldObserveCharacterData(this.patterns), | 865 characterData: shouldObserveCharacterData(this.patterns), |
| 866 subtree: true | 866 subtree: true |
| 867 } | 867 } |
| 868 ); | 868 ); |
| 869 this.document.addEventListener("load", this.onLoad.bind(this), true); | 869 this.document.addEventListener("load", this.onLoad.bind(this), true); |
| 870 } | 870 } |
| 871 } | 871 } |
| 872 }; | 872 }; |
| 873 | 873 |
| 874 exports.ElemHideEmulation = ElemHideEmulation; | 874 exports.ElemHideEmulation = ElemHideEmulation; |
| OLD | NEW |