Index: lib/content/elemHideEmulation.js |
=================================================================== |
--- a/lib/content/elemHideEmulation.js |
+++ b/lib/content/elemHideEmulation.js |
@@ -117,16 +117,65 @@ |
} |
styles.sort(); |
return { |
style: styles.join(" "), |
subSelectors: splitSelector(rule.selectorText) |
}; |
} |
+let scopeSupported = null; |
+ |
+function tryQuerySelector(subtree, selector, all) |
+{ |
+ let elements = null; |
+ try |
+ { |
+ elements = all ? subtree.querySelectorAll(selector) : |
+ subtree.querySelector(selector); |
+ scopeSupported = true; |
+ } |
+ catch (e) |
+ { |
+ // Edge doesn't support ":scope" |
+ scopeSupported = false; |
+ } |
+ return elements; |
+} |
+ |
+/** |
+ * Query selector. If it is relative, will try :scope. |
+ * @param {Node} subtree the element to query selector |
+ * @param {string} selector the selector to query |
+ * @param {bool} [all=false] true to perform querySelectorAll() |
+ * @returns {?(Node|NodeList)} result of the query. null in case of error. |
+ */ |
+function scopedQuerySelector(subtree, selector, all) |
+{ |
+ if (selector[0] == ">") |
+ { |
+ selector = ":scope" + selector; |
+ if (scopeSupported) |
+ { |
+ return all ? subtree.querySelectorAll(selector) : |
+ subtree.querySelector(selector); |
+ } |
+ if (scopeSupported == null) |
+ return tryQuerySelector(subtree, selector, all); |
+ return null; |
+ } |
+ return all ? subtree.querySelectorAll(selector) : |
+ subtree.querySelector(selector); |
+} |
+ |
+function scopedQuerySelectorAll(subtree, selector) |
+{ |
+ return scopedQuerySelector(subtree, selector, true); |
+} |
+ |
function* evaluate(chain, index, prefix, subtree, styles) |
{ |
if (index >= chain.length) |
{ |
yield prefix; |
return; |
} |
for (let [selector, element] of |
@@ -158,17 +207,16 @@ |
*/ |
*getSelectors(prefix, subtree, styles) |
{ |
yield [prefix + this._selector, subtree]; |
} |
}; |
const incompletePrefixRegexp = /[\s>+~]$/; |
lainverse
2018/01/30 18:07:28
Since that other regexp were replaced with string
Manish Jethani
2018/01/30 20:23:20
If we do this then I think that it should be a sep
|
-const relativeSelectorRegexp = /^[>+~]/; |
function HasSelector(selectors) |
{ |
this._innerSelectors = selectors; |
} |
HasSelector.prototype = { |
requiresHiding: true, |
@@ -189,40 +237,31 @@ |
* @param {string} prefix the prefix for the selector. |
* @param {Node} subtree the subtree we work on. |
* @param {StringifiedStyle[]} styles the stringified style objects. |
*/ |
*getElements(prefix, subtree, styles) |
{ |
let actualPrefix = (!prefix || incompletePrefixRegexp.test(prefix)) ? |
prefix + "*" : prefix; |
- let elements = subtree.querySelectorAll(actualPrefix); |
- for (let element of elements) |
+ let elements = scopedQuerySelectorAll(subtree, actualPrefix); |
+ if (elements) |
{ |
- let iter = evaluate(this._innerSelectors, 0, "", element, styles); |
- for (let selector of iter) |
+ for (let element of elements) |
{ |
- if (selector == null) |
+ let iter = evaluate(this._innerSelectors, 0, "", element, styles); |
+ for (let selector of iter) |
{ |
- yield null; |
- continue; |
- } |
- if (relativeSelectorRegexp.test(selector)) |
- selector = ":scope" + selector; |
- try |
- { |
- if (element.querySelector(selector)) |
+ if (selector == null) |
+ yield null; |
+ else if (scopedQuerySelector(element, selector)) |
yield element; |
} |
- catch (e) |
- { |
- // :scope isn't supported on Edge, ignore error caused by it. |
- } |
+ yield null; |
} |
- yield null; |
} |
} |
}; |
function ContainsSelector(textContent) |
{ |
this._text = textContent; |
} |
@@ -235,24 +274,27 @@ |
for (let element of this.getElements(prefix, subtree, stylesheet)) |
yield [makeSelector(element, ""), subtree]; |
}, |
*getElements(prefix, subtree, stylesheet) |
{ |
let actualPrefix = (!prefix || incompletePrefixRegexp.test(prefix)) ? |
prefix + "*" : prefix; |
- let elements = subtree.querySelectorAll(actualPrefix); |
- for (let element of elements) |
+ let elements = scopedQuerySelectorAll(subtree, actualPrefix); |
+ if (elements) |
{ |
- if (element.textContent.includes(this._text)) |
- yield element; |
- else |
- yield null; |
+ for (let element of elements) |
+ { |
+ if (element.textContent.includes(this._text)) |
+ yield element; |
+ else |
+ yield null; |
+ } |
} |
} |
}; |
function PropsSelector(propertyExpression) |
{ |
let regexpString; |
if (propertyExpression.length >= 2 && propertyExpression[0] == "/" && |