| 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] == "/" && |