Index: include.preload.js |
diff --git a/include.preload.js b/include.preload.js |
index 86e52c32afceb894f6591a84b0eca3b1842383ce..eb5610ca33cf8402ebea7c23f6d65f68c95c1b6c 100644 |
--- a/include.preload.js |
+++ b/include.preload.js |
@@ -192,64 +192,88 @@ function getContentDocument(element) |
} |
} |
-function ElementHidingTracer(selectors) |
+function ElementHidingTracer() |
{ |
- this.selectors = selectors; |
+ this.filters = new Map(); |
this.changedNodes = []; |
this.timeout = null; |
+ this.started = false; |
this.observer = new MutationObserver(this.observe.bind(this)); |
this.trace = this.trace.bind(this); |
- |
- if (document.readyState == "loading") |
- document.addEventListener("DOMContentLoaded", this.trace); |
- else |
- this.trace(); |
} |
ElementHidingTracer.prototype = { |
- checkNodes: function(nodes) |
+ start: function() |
+ { |
+ let _start = () => { |
+ this.trace(); |
+ this.started = true; |
+ }; |
+ |
+ if (document.readyState == "loading") |
+ document.addEventListener("DOMContentLoaded", _start); |
+ else |
+ _start(); |
+ }, |
+ |
+ addFilters: function(filters) |
{ |
- var matchedSelectors = []; |
+ if (this.started) |
+ window.setTimeout(() => { |
+ this.checkNodes([document], filters); |
+ }, 0); |
- // Find all selectors that match any hidden element inside the given nodes. |
- for (var i = 0; i < this.selectors.length; i++) |
+ for (let [key, value] of filters) |
{ |
- var selector = this.selectors[i]; |
+ if (!this.filters.has(key)) |
+ this.filters.set(key, []); |
+ Array.prototype.push.apply(this.filters.get(key), value); |
+ } |
+ }, |
- for (var j = 0; j < nodes.length; j++) |
- { |
- var elements = nodes[j].querySelectorAll(selector); |
- var matched = false; |
+ checkNodes: function(nodes, filters) |
+ { |
+ let matchedFilters = []; |
- for (var k = 0; k < elements.length; k++) |
+ for (let [filter, selectors] of filters) |
+ { |
+ for (let i = 0; i < selectors.length; i++) |
+ { |
+ for (var j = 0; j < nodes.length; j++) |
{ |
- // Only consider selectors that actually have an effect on the |
- // computed styles, and aren't overridden by rules with higher |
- // priority, or haven't been circumvented in a different way. |
- if (getComputedStyle(elements[k]).display == "none") |
+ var elements = nodes[j].querySelectorAll(selectors[i]); |
+ var matched = false; |
+ |
+ for (var k = 0; k < elements.length; k++) |
{ |
- matchedSelectors.push(selector); |
- matched = true; |
- break; |
+ // Only consider selectors that actually have an effect on the |
+ // computed styles, and aren't overridden by rules with higher |
+ // priority, or haven't been circumvented in a different way. |
+ if (getComputedStyle(elements[k]).display == "none") |
+ { |
+ matchedFilters.push(filter.replace(/^.*?##/, "")); |
+ matched = true; |
+ break; |
+ } |
} |
- } |
- if (matched) |
- break; |
+ if (matched) |
+ break; |
+ } |
} |
} |
- if (matchedSelectors.length > 0) |
+ if (matchedFilters.length > 0) |
ext.backgroundPage.sendMessage({ |
type: "devtools.traceElemHide", |
- selectors: matchedSelectors |
+ selectors: matchedFilters |
}); |
}, |
onTimeout: function() |
{ |
- this.checkNodes(this.changedNodes); |
+ this.checkNodes(this.changedNodes, this.filters); |
this.changedNodes = []; |
this.timeout = null; |
}, |
@@ -312,7 +336,7 @@ ElementHidingTracer.prototype = { |
trace: function() |
{ |
- this.checkNodes([document]); |
+ this.checkNodes([document], this.filters); |
this.observer.observe( |
document, |
@@ -490,11 +514,21 @@ ElemHide.prototype = { |
return shadow; |
}, |
- addSelectors: function(selectors) |
+ addSelectors: function(filters) |
{ |
- if (selectors.length == 0) |
+ if (!filters) |
return; |
+ if (this.tracer) |
+ this.tracer.addFilters(filters); |
+ |
+ let selectors = []; |
+ for (let filterSelectors of filters.values()) |
+ { |
+ for (let i = 0; i < filterSelectors.length; i++) |
+ selectors.push(filterSelectors[i]); |
+ } |
+ |
if (!this.style) |
{ |
// Create <style> element lazily, only if we add styles. Add it to |
@@ -544,38 +578,37 @@ ElemHide.prototype = { |
apply: function() |
{ |
var selectors = null; |
- var elemHideEmulationLoaded = false; |
var checkLoaded = function() |
{ |
- if (!selectors || !elemHideEmulationLoaded) |
- return; |
- |
if (this.tracer) |
this.tracer.disconnect(); |
this.tracer = null; |
+ if (selectors.trace) |
+ this.tracer = new ElementHidingTracer(); |
+ |
if (this.style && this.style.parentElement) |
this.style.parentElement.removeChild(this.style); |
this.style = null; |
- this.addSelectors(selectors.selectors); |
+ if (selectors.selectors) |
+ { |
+ let filters = new Map(); |
+ for (let i = 0; i < selectors.selectors.length; i++) |
+ filters.set(selectors.selectors[i], [selectors.selectors[i]]); |
+ this.addSelectors(filters); |
+ } |
this.elemHideEmulation.apply(); |
- if (selectors.trace) |
- this.tracer = new ElementHidingTracer(selectors.selectors); |
+ if (this.tracer) |
+ this.tracer.start(); |
}.bind(this); |
- ext.backgroundPage.sendMessage({type: "get-selectors"}, function(response) |
+ ext.backgroundPage.sendMessage({type: "get-selectors"}, response => |
{ |
selectors = response; |
- checkLoaded(); |
- }); |
- |
- this.elemHideEmulation.load(function() |
- { |
- elemHideEmulationLoaded = true; |
- checkLoaded(); |
+ this.elemHideEmulation.load(checkLoaded); |
}); |
} |
}; |