Index: lib/content/elemHideEmulation.js |
=================================================================== |
--- a/lib/content/elemHideEmulation.js |
+++ b/lib/content/elemHideEmulation.js |
@@ -234,73 +234,75 @@ |
yield* evaluate(chain, index + 1, selector, element, styles, targets); |
} |
// Just in case the getSelectors() generator above had to run some heavy |
// document.querySelectorAll() call which didn't produce any results, make |
// sure there is at least one point where execution can pause. |
yield null; |
} |
-function PlainSelector(selector) |
+class PlainSelector |
{ |
- this._selector = selector; |
- this.maybeDependsOnAttributes = /[#.]|\[.+\]/.test(selector); |
- this.dependsOnDOM = this.maybeDependsOnAttributes; |
- this.maybeContainsSiblingCombinators = /[~+]/.test(selector); |
-} |
+ constructor(selector) |
+ { |
+ this._selector = selector; |
+ this.maybeDependsOnAttributes = /[#.]|\[.+\]/.test(selector); |
+ this.dependsOnDOM = this.maybeDependsOnAttributes; |
+ this.maybeContainsSiblingCombinators = /[~+]/.test(selector); |
+ } |
-PlainSelector.prototype = { |
/** |
* Generator function returning a pair of selector |
* string and subtree. |
* @param {string} prefix the prefix for the selector. |
* @param {Node} subtree the subtree we work on. |
* @param {StringifiedStyle[]} styles the stringified style objects. |
* @param {Node[]} [targets] the nodes we are interested in. |
*/ |
*getSelectors(prefix, subtree, styles, targets) |
{ |
yield [prefix + this._selector, subtree]; |
} |
-}; |
+} |
const incompletePrefixRegexp = /[\s>+~]$/; |
-function HasSelector(selectors) |
+class HasSelector |
{ |
- this._innerSelectors = selectors; |
-} |
+ constructor(selectors) |
+ { |
+ this.dependsOnDOM = true; |
-HasSelector.prototype = { |
- dependsOnDOM: true, |
+ this._innerSelectors = selectors; |
+ } |
get dependsOnStyles() |
{ |
return this._innerSelectors.some(selector => selector.dependsOnStyles); |
- }, |
+ } |
get dependsOnCharacterData() |
{ |
return this._innerSelectors.some( |
selector => selector.dependsOnCharacterData |
); |
- }, |
+ } |
get maybeDependsOnAttributes() |
{ |
return this._innerSelectors.some( |
selector => selector.maybeDependsOnAttributes |
); |
- }, |
+ } |
*getSelectors(prefix, subtree, styles, targets) |
{ |
for (let element of this.getElements(prefix, subtree, styles, targets)) |
yield [makeSelector(element), element]; |
- }, |
+ } |
/** |
* Generator function returning selected elements. |
* @param {string} prefix the prefix for the selector. |
* @param {Node} subtree the subtree we work on. |
* @param {StringifiedStyle[]} styles the stringified style objects. |
* @param {Node[]} [targets] the nodes we are interested in. |
*/ |
@@ -333,32 +335,33 @@ |
} |
yield null; |
if (testInfo) |
testInfo.lastProcessedElements.add(element); |
} |
} |
} |
-}; |
- |
-function ContainsSelector(textContent) |
-{ |
- this._regexp = makeRegExpParameter(textContent); |
} |
-ContainsSelector.prototype = { |
- dependsOnDOM: true, |
- dependsOnCharacterData: true, |
+class ContainsSelector |
+{ |
+ constructor(textContent) |
+ { |
+ this.dependsOnDOM = true; |
+ this.dependsOnCharacterData = true; |
+ |
+ this._regexp = makeRegExpParameter(textContent); |
+ } |
*getSelectors(prefix, subtree, styles, targets) |
{ |
for (let element of this.getElements(prefix, subtree, styles, targets)) |
yield [makeSelector(element), subtree]; |
- }, |
+ } |
*getElements(prefix, subtree, styles, targets) |
{ |
let actualPrefix = (!prefix || incompletePrefixRegexp.test(prefix)) ? |
prefix + "*" : prefix; |
let elements = scopedQuerySelectorAll(subtree, actualPrefix); |
@@ -390,36 +393,37 @@ |
else |
yield null; |
if (testInfo) |
testInfo.lastProcessedElements.add(element); |
} |
} |
} |
-}; |
- |
-function PropsSelector(propertyExpression) |
-{ |
- let regexpString; |
- if (propertyExpression.length >= 2 && propertyExpression[0] == "/" && |
- propertyExpression[propertyExpression.length - 1] == "/") |
- { |
- regexpString = propertyExpression.slice(1, -1) |
- .replace("\\7B ", "{").replace("\\7D ", "}"); |
- } |
- else |
- regexpString = filterToRegExp(propertyExpression); |
- |
- this._regexp = new RegExp(regexpString, "i"); |
} |
-PropsSelector.prototype = { |
- dependsOnStyles: true, |
- dependsOnDOM: true, |
+class PropsSelector |
+{ |
+ constructor(propertyExpression) |
+ { |
+ this.dependsOnStyles = true; |
+ this.dependsOnDOM = true; |
+ |
+ let regexpString; |
+ if (propertyExpression.length >= 2 && propertyExpression[0] == "/" && |
+ propertyExpression[propertyExpression.length - 1] == "/") |
+ { |
+ regexpString = propertyExpression.slice(1, -1) |
+ .replace("\\7B ", "{").replace("\\7D ", "}"); |
+ } |
+ else |
+ regexpString = filterToRegExp(propertyExpression); |
+ |
+ this._regexp = new RegExp(regexpString, "i"); |
+ } |
*findPropsSelectors(styles, prefix, regexp) |
{ |
for (let style of styles) |
if (regexp.test(style.style)) |
for (let subSelector of style.subSelectors) |
{ |
if (subSelector.startsWith("*") && |
@@ -427,92 +431,93 @@ |
{ |
subSelector = subSelector.substr(1); |
} |
let idx = subSelector.lastIndexOf("::"); |
if (idx != -1) |
subSelector = subSelector.substr(0, idx); |
yield qualifySelector(subSelector, prefix); |
} |
- }, |
+ } |
*getSelectors(prefix, subtree, styles, targets) |
{ |
for (let selector of this.findPropsSelectors(styles, prefix, this._regexp)) |
yield [selector, subtree]; |
} |
-}; |
- |
-function Pattern(selectors, text) |
-{ |
- this.selectors = selectors; |
- this.text = text; |
} |
-Pattern.prototype = { |
+class Pattern |
+{ |
+ constructor(selectors, text) |
+ { |
+ this.selectors = selectors; |
+ this.text = text; |
+ } |
+ |
get dependsOnStyles() |
{ |
return getCachedPropertyValue( |
this, "_dependsOnStyles", |
() => this.selectors.some(selector => selector.dependsOnStyles) |
); |
- }, |
+ } |
get dependsOnDOM() |
{ |
return getCachedPropertyValue( |
this, "_dependsOnDOM", |
() => this.selectors.some(selector => selector.dependsOnDOM) |
); |
- }, |
+ } |
get dependsOnStylesAndDOM() |
{ |
return getCachedPropertyValue( |
this, "_dependsOnStylesAndDOM", |
() => this.selectors.some(selector => selector.dependsOnStyles && |
selector.dependsOnDOM) |
); |
- }, |
+ } |
get maybeDependsOnAttributes() |
{ |
// Observe changes to attributes if either there's a plain selector that |
// looks like an ID selector, class selector, or attribute selector in one |
// of the patterns (e.g. "a[href='https://example.com/']") |
// or there's a properties selector nested inside a has selector |
// (e.g. "div:-abp-has(:-abp-properties(color: blue))") |
return getCachedPropertyValue( |
this, "_maybeDependsOnAttributes", |
() => this.selectors.some( |
selector => selector.maybeDependsOnAttributes || |
(selector instanceof HasSelector && |
selector.dependsOnStyles) |
) |
); |
- }, |
+ } |
get dependsOnCharacterData() |
{ |
// Observe changes to character data only if there's a contains selector in |
// one of the patterns. |
return getCachedPropertyValue( |
this, "_dependsOnCharacterData", |
() => this.selectors.some(selector => selector.dependsOnCharacterData) |
); |
- }, |
+ } |
get maybeContainsSiblingCombinators() |
{ |
return getCachedPropertyValue( |
this, "_maybeContainsSiblingCombinators", |
() => this.selectors.some(selector => |
selector.maybeContainsSiblingCombinators) |
); |
- }, |
+ } |
matchesMutationTypes(mutationTypes) |
{ |
let mutationTypeMatchMap = getCachedPropertyValue( |
this, "_mutationTypeMatchMap", |
() => new Map([ |
// All types of DOM-dependent patterns are affected by mutations of |
// type "childList". |
@@ -525,17 +530,17 @@ |
for (let mutationType of mutationTypes) |
{ |
if (mutationTypeMatchMap.get(mutationType)) |
return true; |
} |
return false; |
} |
-}; |
+} |
function extractMutationTypes(mutations) |
{ |
let types = new Set(); |
for (let mutation of mutations) |
{ |
types.add(mutation.type); |
@@ -593,37 +598,42 @@ |
return patterns.some(pattern => pattern.maybeDependsOnAttributes); |
} |
function shouldObserveCharacterData(patterns) |
{ |
return patterns.some(pattern => pattern.dependsOnCharacterData); |
} |
-function ElemHideEmulation(addSelectorsFunc, hideElemsFunc) |
+class ElemHideEmulation |
{ |
- this.document = document; |
- this.addSelectorsFunc = addSelectorsFunc; |
- this.hideElemsFunc = hideElemsFunc; |
- this.observer = new MutationObserver(this.observe.bind(this)); |
-} |
+ constructor(addSelectorsFunc, hideElemsFunc) |
+ { |
+ this._filteringInProgress = false; |
+ this._lastInvocation = -MIN_INVOCATION_INTERVAL; |
+ this._scheduledProcessing = null; |
-ElemHideEmulation.prototype = { |
+ this.document = document; |
+ this.addSelectorsFunc = addSelectorsFunc; |
+ this.hideElemsFunc = hideElemsFunc; |
+ this.observer = new MutationObserver(this.observe.bind(this)); |
+ } |
+ |
isSameOrigin(stylesheet) |
{ |
try |
{ |
return new URL(stylesheet.href).origin == this.document.location.origin; |
} |
catch (e) |
{ |
// Invalid URL, assume that it is first-party. |
return true; |
} |
- }, |
+ } |
/** Parse the selector |
* @param {string} selector the selector to parse |
* @return {Array} selectors is an array of objects, |
* or null in case of errors. |
*/ |
parseSelector(selector) |
{ |
@@ -676,17 +686,17 @@ |
if (selectors.length == 1 && selectors[0] instanceof ContainsSelector) |
{ |
console.error(new SyntaxError("Failed to parse Adblock Plus " + |
`selector ${selector}, can't ` + |
"have a lonely :-abp-contains().")); |
return null; |
} |
return selectors; |
- }, |
+ } |
/** |
* Processes the current document and applies all rules to it. |
* @param {CSSStyleSheet[]} [stylesheets] |
* The list of new stylesheets that have been added to the document and |
* made reprocessing necessary. This parameter shouldn't be passed in for |
* the initial processing, all of document's stylesheets will be considered |
* then and all rules, including the ones not dependent on styles. |
@@ -812,33 +822,29 @@ |
return; |
} |
} |
pattern = null; |
return processPatterns(); |
}; |
processPatterns(); |
- }, |
+ } |
// This property is only used in the tests |
// to shorten the invocation interval |
get MIN_INVOCATION_INTERVAL() |
{ |
return MIN_INVOCATION_INTERVAL; |
- }, |
+ } |
set MIN_INVOCATION_INTERVAL(interval) |
{ |
MIN_INVOCATION_INTERVAL = interval; |
- }, |
- |
- _filteringInProgress: false, |
- _lastInvocation: -MIN_INVOCATION_INTERVAL, |
- _scheduledProcessing: null, |
+ } |
/** |
* Re-run filtering either immediately or queued. |
* @param {CSSStyleSheet[]} [stylesheets] |
* new stylesheets to be processed. This parameter should be omitted |
* for full reprocessing. |
* @param {MutationRecord[]} [mutations] |
* new DOM mutations to be processed. This parameter should be omitted |
@@ -910,24 +916,24 @@ |
}; |
this.document.addEventListener("DOMContentLoaded", handler); |
} |
else |
{ |
this._filteringInProgress = true; |
this._addSelectors(stylesheets, mutations, completion); |
} |
- }, |
+ } |
onLoad(event) |
{ |
let stylesheet = event.target.sheet; |
if (stylesheet) |
this.queueFiltering([stylesheet]); |
- }, |
+ } |
observe(mutations) |
{ |
if (testInfo) |
{ |
// In test mode, filter out any mutations likely done by us |
// (i.e. style="display: none !important"). This makes it easier to |
// observe how the code responds to DOM mutations. |
@@ -937,17 +943,17 @@ |
newValue.display == "none" && oldValue.display != "none") |
); |
if (mutations.length == 0) |
return; |
} |
this.queueFiltering(null, mutations); |
- }, |
+ } |
apply(patterns) |
{ |
this.patterns = []; |
for (let pattern of patterns) |
{ |
let selectors = this.parseSelector(pattern.selector); |
if (selectors != null && selectors.length > 0) |
@@ -964,11 +970,11 @@ |
attributes: shouldObserveAttributes(this.patterns), |
characterData: shouldObserveCharacterData(this.patterns), |
subtree: true |
} |
); |
this.document.addEventListener("load", this.onLoad.bind(this), true); |
} |
} |
-}; |
+} |
exports.ElemHideEmulation = ElemHideEmulation; |