Index: lib/content/elemHideEmulation.js |
=================================================================== |
--- a/lib/content/elemHideEmulation.js |
+++ b/lib/content/elemHideEmulation.js |
@@ -395,52 +395,85 @@ |
return pattern.selectors.some(s => s.dependsOnDOM); |
} |
function patternDependsOnStylesAndDOM(pattern) |
{ |
return pattern.selectors.some(s => s.dependsOnStyles && s.dependsOnDOM); |
} |
-function filterPatterns(patterns, {stylesheets, mutations}) |
-{ |
- if (stylesheets && !mutations) |
- return patterns.filter(patternDependsOnStyles); |
- |
- if (!stylesheets && mutations) |
- return patterns.filter(patternDependsOnDOM); |
- |
- return patterns.slice(); |
-} |
- |
-function shouldObserveAttributes(patterns) |
+function patternMaybeDependsOnAttributes(pattern) |
{ |
// 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 patterns.some( |
- pattern => pattern.selectors.some( |
- selector => selector.maybeDependsOnAttributes || |
- (selector instanceof HasSelector && |
- selector.dependsOnStyles) |
- ) |
+ return pattern.selectors.some( |
+ selector => selector.maybeDependsOnAttributes || |
+ (selector instanceof HasSelector && |
+ selector.dependsOnStyles) |
); |
} |
+function patternDependsOnCharacterData(pattern) |
+{ |
+ // Observe changes to character data only if there's a contains selector in |
+ // one of the patterns. |
+ return pattern.selectors.some(selector => selector.dependsOnCharacterData); |
+} |
+ |
+function patternMatchesMutationTypes(pattern, mutationTypes) |
+{ |
+ return mutationTypes.has("childList") || |
+ (mutationTypes.has("attributes") && |
+ patternMaybeDependsOnAttributes(pattern)) || |
+ (mutationTypes.has("characterData") && |
+ patternDependsOnCharacterData(pattern)); |
+} |
+ |
+function extractMutationTypes(mutations) |
+{ |
+ let types = new Set(); |
+ |
+ for (let mutation of mutations) |
+ { |
+ types.add(mutation.type); |
+ |
+ // There are only 3 types of mutations: "attributes", "characterData", and |
+ // "childList". |
+ if (types.size == 3) |
+ break; |
+ } |
+ |
+ return types; |
+} |
+ |
+function filterPatterns(patterns, {stylesheets, mutations}) |
+{ |
+ if (!stylesheets && !mutations) |
+ return patterns.slice(); |
+ |
+ let mutationTypes = mutations ? extractMutationTypes(mutations) : null; |
+ |
+ return patterns.filter( |
+ pattern => (stylesheets && patternDependsOnStyles(pattern)) || |
+ (mutations && patternDependsOnDOM(pattern) && |
+ patternMatchesMutationTypes(pattern, mutationTypes)) |
+ ); |
+} |
+ |
+function shouldObserveAttributes(patterns) |
+{ |
+ return patterns.some(patternMaybeDependsOnAttributes); |
+} |
+ |
function shouldObserveCharacterData(patterns) |
{ |
- // Observe changes to character data only if there's a contains selector in |
- // one of the patterns. |
- return patterns.some( |
- pattern => pattern.selectors.some( |
- selector => selector.dependsOnCharacterData |
- ) |
- ); |
+ return patterns.some(patternDependsOnCharacterData); |
} |
function ElemHideEmulation(addSelectorsFunc, hideElemsFunc) |
{ |
this.document = document; |
this.addSelectorsFunc = addSelectorsFunc; |
this.hideElemsFunc = hideElemsFunc; |
this.observer = new MutationObserver(this.observe.bind(this)); |