Index: lib/content/elemHideEmulation.js |
=================================================================== |
--- a/lib/content/elemHideEmulation.js |
+++ b/lib/content/elemHideEmulation.js |
@@ -117,16 +117,64 @@ |
} |
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) |
+ { |
+ scopeSupported = false; |
Manish Jethani
2018/01/30 05:53:41
Maybe we should add that comment here saying that
hub
2018/01/30 16:03:57
Done.
|
+ } |
+ return elements; |
+} |
+ |
+/** |
+ * Query selector. If it is relative, will try :scoped. |
Manish Jethani
2018/01/30 05:53:41
You meant ":scope" (without the D)?
hub
2018/01/30 16:03:57
Done.
|
+ * @param {Node} subtree the element to query selector |
+ * @param {string} selector the selector to query |
+ * @param {bool} all True to perform querySelectorAll() |
Manish Jethani
2018/01/30 05:53:41
Since all is optional and defaults to false, I gue
hub
2018/01/30 16:03:57
Done.
|
+ * @returns {Node|NodeList} result of the query. null in case of error. |
Manish Jethani
2018/01/30 05:53:41
Since this can return null I think it should be "{
lainverse
2018/01/30 15:28:29
BTW, wouldn't it be better to return empty array w
hub
2018/01/30 16:03:57
Done.
|
+ */ |
+function scopedQuerySelector(subtree, selector, all) |
+{ |
+ if (relativeSelectorRegexp.test(selector)) |
+ { |
+ 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 +206,17 @@ |
*/ |
*getSelectors(prefix, subtree, styles) |
{ |
yield [prefix + this._selector, subtree]; |
} |
}; |
const incompletePrefixRegexp = /[\s>+~]$/; |
-const relativeSelectorRegexp = /^[>+~]/; |
+const relativeSelectorRegexp = /^>/; |
Manish Jethani
2018/01/30 06:13:06
So I ran this on Chrome and Firefox:
{
let u =
hub
2018/01/30 16:03:57
Done.
|
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] == "/" && |