Index: chrome/content/elemHideEmulation.js |
=================================================================== |
--- a/chrome/content/elemHideEmulation.js |
+++ b/chrome/content/elemHideEmulation.js |
@@ -125,71 +125,16 @@ |
} |
} |
if (parens > 0) |
return null; |
return {text: content.substring(startIndex, i), end: i}; |
} |
-/** Parse the selector |
- * @param {string} selector the selector to parse |
- * @return {Object} selectors is an array of objects, |
- * or null in case of errors. hide is true if we'll hide |
- * elements instead of styles.. |
- */ |
-function parseSelector(selector) |
-{ |
- if (selector.length == 0) |
- return []; |
- |
- let match = abpSelectorRegexp.exec(selector); |
- if (!match) |
- return [new PlainSelector(selector)]; |
- |
- let selectors = []; |
- if (match.index > 0) |
- selectors.push(new PlainSelector(selector.substr(0, match.index))); |
- |
- let startIndex = match.index + match[0].length; |
- let content = parseSelectorContent(selector, startIndex); |
- if (!content) |
- { |
- reportError(new SyntaxError("Failed to parse Adblock Plus " + |
- `selector ${selector}, ` + |
- "due to unmatched parentheses.")); |
- return null; |
- } |
- if (match[1] == "properties") |
- selectors.push(new PropsSelector(content.text)); |
- else if (match[1] == "has") |
- { |
- let hasSelector = new HasSelector(content.text); |
- if (!hasSelector.valid()) |
- return null; |
- selectors.push(hasSelector); |
- } |
- else |
- { |
- // this is an error, can't parse selector. |
- reportError(new SyntaxError("Failed to parse Adblock Plus " + |
- `selector ${selector}, invalid ` + |
- `pseudo-class :-abp-${match[1]}().`)); |
- return null; |
- } |
- |
- let suffix = parseSelector(selector.substr(content.end + 1)); |
- if (suffix == null) |
- return null; |
- |
- selectors.push(...suffix); |
- |
- return selectors; |
-} |
- |
/** Stringified style objects |
* @typedef {Object} StringifiedStyle |
* @property {string} style CSS style represented by a string. |
* @property {string[]} subSelectors selectors the CSS properties apply to. |
*/ |
/** |
* Produce a string representation of the stylesheet entry. |
@@ -241,29 +186,24 @@ |
*getSelectors(prefix, subtree, styles) |
{ |
yield [prefix + this._selector, subtree]; |
} |
}; |
const incompletePrefixRegexp = /[\s>+~]$/; |
-function HasSelector(selector) |
+function HasSelector(selectors) |
{ |
- this._innerSelectors = parseSelector(selector); |
+ this._innerSelectors = selectors; |
} |
HasSelector.prototype = { |
requiresHiding: true, |
- valid() |
- { |
- return this._innerSelectors != null; |
- }, |
- |
*getSelectors(prefix, subtree, styles) |
{ |
for (let element of this.getElements(prefix, subtree, styles)) |
yield [makeSelector(element, ""), element]; |
}, |
/** |
* Generator function returning selected elements. |
@@ -339,16 +279,72 @@ |
} |
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) |
+ { |
+ if (selector.length == 0) |
+ return []; |
+ |
+ let match = abpSelectorRegexp.exec(selector); |
+ if (!match) |
+ return [new PlainSelector(selector)]; |
+ |
+ let selectors = []; |
+ if (match.index > 0) |
+ selectors.push(new PlainSelector(selector.substr(0, match.index))); |
+ |
+ let startIndex = match.index + match[0].length; |
+ let content = parseSelectorContent(selector, startIndex); |
+ if (!content) |
+ { |
+ this.window.console.error( |
+ new SyntaxError("Failed to parse Adblock Plus " + |
+ `selector ${selector} ` + |
+ "due to unmatched parentheses.")); |
+ return null; |
+ } |
+ if (match[1] == "properties") |
+ selectors.push(new PropsSelector(content.text)); |
+ else if (match[1] == "has") |
+ { |
+ let hasSelectors = this.parseSelector(content.text); |
+ if (hasSelectors == null) |
+ return null; |
+ selectors.push(new HasSelector(hasSelectors)); |
+ } |
+ else |
+ { |
+ // this is an error, can't parse selector. |
+ this.window.console.error( |
+ new SyntaxError("Failed to parse Adblock Plus " + |
+ `selector ${selector}, invalid ` + |
+ `pseudo-class :-abp-${match[1]}().`)); |
+ return null; |
+ } |
+ |
+ let suffix = this.parseSelector(selector.substr(content.end + 1)); |
+ if (suffix == null) |
+ return null; |
+ |
+ selectors.push(...suffix); |
+ |
+ return selectors; |
+ }, |
+ |
addSelectors(stylesheets) |
{ |
let selectors = []; |
let selectorFilters = []; |
let elements = []; |
let elementFilters = []; |
@@ -406,29 +402,25 @@ |
if (stylesheet) |
this.addSelectors([stylesheet]); |
}, |
apply() |
{ |
this.getFiltersFunc(patterns => |
{ |
- let oldReportError = reportError; |
- reportError = error => this.window.console.error(error); |
- |
this.patterns = []; |
for (let pattern of patterns) |
{ |
- let selectors = parseSelector(pattern.selector); |
+ let selectors = this.parseSelector(pattern.selector); |
if (selectors != null && selectors.length > 0) |
this.patterns.push({selectors, text: pattern.text}); |
} |
if (this.patterns.length > 0) |
{ |
let {document} = this.window; |
this.addSelectors(document.styleSheets); |
document.addEventListener("load", this.onLoad.bind(this), true); |
} |
- reportError = oldReportError; |
}); |
} |
}; |