mirror of
https://github.com/gorhill/uBlock.git
synced 2024-10-04 16:47:15 +02:00
Add ability to report exception cosmetic filters in the logger
Related issue: - https://github.com/gorhill/uBlock/issues/127 Additionally, the extended exception filters in the logger will be rendered with a line-through to more easily distinguish them from non-exception ones. Also, opportunistically converted revisited code to ES6 syntax.
This commit is contained in:
parent
2114c857a4
commit
3573b6b32c
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
if ( typeof vAPI === 'object' ) {
|
if ( typeof vAPI === 'object' ) {
|
||||||
vAPI.supportsUserStylesheets =
|
vAPI.supportsUserStylesheets =
|
||||||
/\bChrom(?:e|ium)\/(?:6[6789]|[789]|1\d\d)/.test(navigator.userAgent);
|
/\bChrom(?:e|ium)\/(?:5\d|6[012345])\b/.test(navigator.userAgent) === false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,10 +40,10 @@ vAPI.userStylesheet = {
|
|||||||
inject: function() {
|
inject: function() {
|
||||||
this.style = document.createElement('style');
|
this.style = document.createElement('style');
|
||||||
this.style.disabled = this.disabled;
|
this.style.disabled = this.disabled;
|
||||||
var parent = document.head || document.documentElement;
|
const parent = document.head || document.documentElement;
|
||||||
if ( parent === null ) { return; }
|
if ( parent === null ) { return; }
|
||||||
parent.appendChild(this.style);
|
parent.appendChild(this.style);
|
||||||
var observer = new MutationObserver(function() {
|
const observer = new MutationObserver(function() {
|
||||||
if ( this.style === null ) { return; }
|
if ( this.style === null ) { return; }
|
||||||
if ( this.style.sheet !== null ) { return; }
|
if ( this.style.sheet !== null ) { return; }
|
||||||
this.styleFixCount += 1;
|
this.styleFixCount += 1;
|
||||||
@ -58,31 +58,31 @@ vAPI.userStylesheet = {
|
|||||||
add: function(cssText) {
|
add: function(cssText) {
|
||||||
if ( cssText === '' || this.css.has(cssText) ) { return; }
|
if ( cssText === '' || this.css.has(cssText) ) { return; }
|
||||||
if ( this.style === null ) { this.inject(); }
|
if ( this.style === null ) { this.inject(); }
|
||||||
var sheet = this.style.sheet;
|
const sheet = this.style.sheet;
|
||||||
if ( !sheet ) { return; }
|
if ( !sheet ) { return; }
|
||||||
var i = sheet.cssRules.length;
|
const i = sheet.cssRules.length;
|
||||||
sheet.insertRule(cssText, i);
|
sheet.insertRule(cssText, i);
|
||||||
this.css.set(cssText, sheet.cssRules[i]);
|
this.css.set(cssText, sheet.cssRules[i]);
|
||||||
},
|
},
|
||||||
remove: function(cssText) {
|
remove: function(cssText) {
|
||||||
if ( cssText === '' ) { return; }
|
if ( cssText === '' ) { return; }
|
||||||
var cssRule = this.css.get(cssText);
|
const cssRule = this.css.get(cssText);
|
||||||
if ( cssRule === undefined ) { return; }
|
if ( cssRule === undefined ) { return; }
|
||||||
this.css.delete(cssText);
|
this.css.delete(cssText);
|
||||||
if ( this.style === null ) { return; }
|
if ( this.style === null ) { return; }
|
||||||
var sheet = this.style.sheet;
|
const sheet = this.style.sheet;
|
||||||
if ( !sheet ) { return; }
|
if ( !sheet ) { return; }
|
||||||
var rules = sheet.cssRules,
|
const rules = sheet.cssRules;
|
||||||
i = rules.length;
|
let i = rules.length;
|
||||||
while ( i-- ) {
|
while ( i-- ) {
|
||||||
if ( rules[i] !== cssRule ) { continue; }
|
if ( rules[i] !== cssRule ) { continue; }
|
||||||
sheet.deleteRule(i);
|
sheet.deleteRule(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ( rules.length !== 0 ) { return; }
|
if ( rules.length !== 0 ) { return; }
|
||||||
var style = this.style;
|
const style = this.style;
|
||||||
this.style = null;
|
this.style = null;
|
||||||
var parent = style.parentNode;
|
const parent = style.parentNode;
|
||||||
if ( parent !== null ) {
|
if ( parent !== null ) {
|
||||||
parent.removeChild(style);
|
parent.removeChild(style);
|
||||||
}
|
}
|
||||||
@ -99,55 +99,54 @@ vAPI.userStylesheet = {
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
vAPI.DOMFilterer = function() {
|
vAPI.DOMFilterer = class {
|
||||||
this.commitTimer = new vAPI.SafeAnimationFrame(this.commitNow.bind(this));
|
constructor() {
|
||||||
this.domIsReady = document.readyState !== 'loading';
|
this.commitTimer = new vAPI.SafeAnimationFrame(this.commitNow.bind(this));
|
||||||
this.listeners = [];
|
this.domIsReady = document.readyState !== 'loading';
|
||||||
this.excludedNodeSet = new WeakSet();
|
this.listeners = [];
|
||||||
this.addedNodes = new Set();
|
this.excludedNodeSet = new WeakSet();
|
||||||
this.removedNodes = false;
|
this.addedNodes = new Set();
|
||||||
|
this.removedNodes = false;
|
||||||
|
|
||||||
this.specificSimpleHide = new Set();
|
this.specificSimpleHide = new Set();
|
||||||
this.specificSimpleHideAggregated = undefined;
|
this.specificSimpleHideAggregated = undefined;
|
||||||
this.addedSpecificSimpleHide = [];
|
this.addedSpecificSimpleHide = [];
|
||||||
this.specificComplexHide = new Set();
|
this.specificComplexHide = new Set();
|
||||||
this.specificComplexHideAggregated = undefined;
|
this.specificComplexHideAggregated = undefined;
|
||||||
this.addedSpecificComplexHide = [];
|
this.addedSpecificComplexHide = [];
|
||||||
this.specificOthers = [];
|
this.specificOthers = [];
|
||||||
this.genericSimpleHide = new Set();
|
this.genericSimpleHide = new Set();
|
||||||
this.genericComplexHide = new Set();
|
this.genericComplexHide = new Set();
|
||||||
|
this.exceptedCSSRules = [];
|
||||||
|
|
||||||
this.hideNodeExpando = undefined;
|
this.hideNodeExpando = undefined;
|
||||||
this.hideNodeBatchProcessTimer = undefined;
|
this.hideNodeBatchProcessTimer = undefined;
|
||||||
this.hiddenNodeObserver = undefined;
|
this.hiddenNodeObserver = undefined;
|
||||||
this.hiddenNodesetToProcess = new Set();
|
this.hiddenNodesetToProcess = new Set();
|
||||||
this.hiddenNodeset = new WeakSet();
|
this.hiddenNodeset = new WeakSet();
|
||||||
|
|
||||||
if ( vAPI.domWatcher instanceof Object ) {
|
if ( vAPI.domWatcher instanceof Object ) {
|
||||||
vAPI.domWatcher.addListener(this);
|
vAPI.domWatcher.addListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://www.w3.org/community/webed/wiki/CSS/Selectors#Combinators
|
||||||
|
this.reCSSCombinators = /[ >+~]/;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
vAPI.DOMFilterer.prototype = {
|
commitNow() {
|
||||||
// https://www.w3.org/community/webed/wiki/CSS/Selectors#Combinators
|
|
||||||
reCSSCombinators: /[ >+~]/,
|
|
||||||
|
|
||||||
commitNow: function() {
|
|
||||||
this.commitTimer.clear();
|
this.commitTimer.clear();
|
||||||
|
|
||||||
if ( this.domIsReady !== true || vAPI.userStylesheet.disabled ) {
|
if ( this.domIsReady !== true || vAPI.userStylesheet.disabled ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var nodes, node;
|
|
||||||
|
|
||||||
// Filterset changed.
|
// Filterset changed.
|
||||||
|
|
||||||
if ( this.addedSpecificSimpleHide.length !== 0 ) {
|
if ( this.addedSpecificSimpleHide.length !== 0 ) {
|
||||||
//console.time('specific simple filterset changed');
|
//console.time('specific simple filterset changed');
|
||||||
//console.log('added %d specific simple selectors', this.addedSpecificSimpleHide.length);
|
//console.log('added %d specific simple selectors', this.addedSpecificSimpleHide.length);
|
||||||
nodes = document.querySelectorAll(this.addedSpecificSimpleHide.join(','));
|
const nodes = document.querySelectorAll(this.addedSpecificSimpleHide.join(','));
|
||||||
for ( node of nodes ) {
|
for ( const node of nodes ) {
|
||||||
this.hideNode(node);
|
this.hideNode(node);
|
||||||
}
|
}
|
||||||
this.addedSpecificSimpleHide = [];
|
this.addedSpecificSimpleHide = [];
|
||||||
@ -158,8 +157,8 @@ vAPI.DOMFilterer.prototype = {
|
|||||||
if ( this.addedSpecificComplexHide.length !== 0 ) {
|
if ( this.addedSpecificComplexHide.length !== 0 ) {
|
||||||
//console.time('specific complex filterset changed');
|
//console.time('specific complex filterset changed');
|
||||||
//console.log('added %d specific complex selectors', this.addedSpecificComplexHide.length);
|
//console.log('added %d specific complex selectors', this.addedSpecificComplexHide.length);
|
||||||
nodes = document.querySelectorAll(this.addedSpecificComplexHide.join(','));
|
const nodes = document.querySelectorAll(this.addedSpecificComplexHide.join(','));
|
||||||
for ( node of nodes ) {
|
for ( const node of nodes ) {
|
||||||
this.hideNode(node);
|
this.hideNode(node);
|
||||||
}
|
}
|
||||||
this.addedSpecificComplexHide = [];
|
this.addedSpecificComplexHide = [];
|
||||||
@ -169,8 +168,8 @@ vAPI.DOMFilterer.prototype = {
|
|||||||
|
|
||||||
// DOM layout changed.
|
// DOM layout changed.
|
||||||
|
|
||||||
var domNodesAdded = this.addedNodes.size !== 0,
|
const domNodesAdded = this.addedNodes.size !== 0;
|
||||||
domLayoutChanged = domNodesAdded || this.removedNodes;
|
const domLayoutChanged = domNodesAdded || this.removedNodes;
|
||||||
|
|
||||||
if ( domNodesAdded === false || domLayoutChanged === false ) {
|
if ( domNodesAdded === false || domLayoutChanged === false ) {
|
||||||
return;
|
return;
|
||||||
@ -184,12 +183,12 @@ vAPI.DOMFilterer.prototype = {
|
|||||||
this.specificSimpleHideAggregated =
|
this.specificSimpleHideAggregated =
|
||||||
Array.from(this.specificSimpleHide).join(',\n');
|
Array.from(this.specificSimpleHide).join(',\n');
|
||||||
}
|
}
|
||||||
for ( node of this.addedNodes ) {
|
for ( const node of this.addedNodes ) {
|
||||||
if ( node[vAPI.matchesProp](this.specificSimpleHideAggregated) ) {
|
if ( node[vAPI.matchesProp](this.specificSimpleHideAggregated) ) {
|
||||||
this.hideNode(node);
|
this.hideNode(node);
|
||||||
}
|
}
|
||||||
nodes = node.querySelectorAll(this.specificSimpleHideAggregated);
|
const nodes = node.querySelectorAll(this.specificSimpleHideAggregated);
|
||||||
for ( node of nodes ) {
|
for ( const node of nodes ) {
|
||||||
this.hideNode(node);
|
this.hideNode(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -202,8 +201,8 @@ vAPI.DOMFilterer.prototype = {
|
|||||||
this.specificComplexHideAggregated =
|
this.specificComplexHideAggregated =
|
||||||
Array.from(this.specificComplexHide).join(',\n');
|
Array.from(this.specificComplexHide).join(',\n');
|
||||||
}
|
}
|
||||||
nodes = document.querySelectorAll(this.specificComplexHideAggregated);
|
const nodes = document.querySelectorAll(this.specificComplexHideAggregated);
|
||||||
for ( node of nodes ) {
|
for ( const node of nodes ) {
|
||||||
this.hideNode(node);
|
this.hideNode(node);
|
||||||
}
|
}
|
||||||
//console.timeEnd('dom layout changed/specific complex selectors');
|
//console.timeEnd('dom layout changed/specific complex selectors');
|
||||||
@ -211,23 +210,23 @@ vAPI.DOMFilterer.prototype = {
|
|||||||
|
|
||||||
this.addedNodes.clear();
|
this.addedNodes.clear();
|
||||||
this.removedNodes = false;
|
this.removedNodes = false;
|
||||||
},
|
}
|
||||||
|
|
||||||
commit: function(now) {
|
commit(now) {
|
||||||
if ( now ) {
|
if ( now ) {
|
||||||
this.commitTimer.clear();
|
this.commitTimer.clear();
|
||||||
this.commitNow();
|
this.commitNow();
|
||||||
} else {
|
} else {
|
||||||
this.commitTimer.start();
|
this.commitTimer.start();
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
addCSSRule: function(selectors, declarations, details) {
|
addCSSRule(selectors, declarations, details) {
|
||||||
if ( selectors === undefined ) { return; }
|
if ( selectors === undefined ) { return; }
|
||||||
|
|
||||||
if ( details === undefined ) { details = {}; }
|
if ( details === undefined ) { details = {}; }
|
||||||
|
|
||||||
var selectorsStr = Array.isArray(selectors) ?
|
const selectorsStr = Array.isArray(selectors) ?
|
||||||
selectors.join(',\n') :
|
selectors.join(',\n') :
|
||||||
selectors;
|
selectors;
|
||||||
if ( selectorsStr.length === 0 ) { return; }
|
if ( selectorsStr.length === 0 ) { return; }
|
||||||
@ -251,10 +250,9 @@ vAPI.DOMFilterer.prototype = {
|
|||||||
// Do not strongly enforce internal CSS rules.
|
// Do not strongly enforce internal CSS rules.
|
||||||
if ( details.internal ) { return; }
|
if ( details.internal ) { return; }
|
||||||
|
|
||||||
var isGeneric= details.lazy === true,
|
const isGeneric= details.lazy === true;
|
||||||
isSimple = details.type === 'simple',
|
const isSimple = details.type === 'simple';
|
||||||
isComplex = details.type === 'complex',
|
const isComplex = details.type === 'complex';
|
||||||
selector;
|
|
||||||
|
|
||||||
if ( isGeneric ) {
|
if ( isGeneric ) {
|
||||||
if ( isSimple ) {
|
if ( isSimple ) {
|
||||||
@ -267,12 +265,12 @@ vAPI.DOMFilterer.prototype = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var selectorsArr = Array.isArray(selectors) ?
|
const selectorsArr = Array.isArray(selectors) ?
|
||||||
selectors :
|
selectors :
|
||||||
selectors.split(',\n');
|
selectors.split(',\n');
|
||||||
|
|
||||||
if ( isGeneric ) {
|
if ( isGeneric ) {
|
||||||
for ( selector of selectorsArr ) {
|
for ( const selector of selectorsArr ) {
|
||||||
if ( this.reCSSCombinators.test(selector) ) {
|
if ( this.reCSSCombinators.test(selector) ) {
|
||||||
this.genericComplexHide.add(selector);
|
this.genericComplexHide.add(selector);
|
||||||
} else {
|
} else {
|
||||||
@ -283,7 +281,7 @@ vAPI.DOMFilterer.prototype = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Specific cosmetic filters.
|
// Specific cosmetic filters.
|
||||||
for ( selector of selectorsArr ) {
|
for ( const selector of selectorsArr ) {
|
||||||
if (
|
if (
|
||||||
isComplex ||
|
isComplex ||
|
||||||
isSimple === false && this.reCSSCombinators.test(selector)
|
isSimple === false && this.reCSSCombinators.test(selector)
|
||||||
@ -297,44 +295,51 @@ vAPI.DOMFilterer.prototype = {
|
|||||||
this.addedSpecificSimpleHide.push(selector);
|
this.addedSpecificSimpleHide.push(selector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
onDOMCreated: function() {
|
exceptCSSRules(exceptions) {
|
||||||
|
if ( exceptions.length === 0 ) { return; }
|
||||||
|
this.exceptedCSSRules.push(...exceptions);
|
||||||
|
if ( this.hasListeners() ) {
|
||||||
|
this.triggerListeners({ exceptions });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onDOMCreated() {
|
||||||
this.domIsReady = true;
|
this.domIsReady = true;
|
||||||
this.addedNodes.clear();
|
this.addedNodes.clear();
|
||||||
this.removedNodes = false;
|
this.removedNodes = false;
|
||||||
this.commit();
|
this.commit();
|
||||||
},
|
}
|
||||||
|
|
||||||
onDOMChanged: function(addedNodes, removedNodes) {
|
onDOMChanged(addedNodes, removedNodes) {
|
||||||
for ( var node of addedNodes ) {
|
for ( const node of addedNodes ) {
|
||||||
this.addedNodes.add(node);
|
this.addedNodes.add(node);
|
||||||
}
|
}
|
||||||
this.removedNodes = this.removedNodes || removedNodes;
|
this.removedNodes = this.removedNodes || removedNodes;
|
||||||
this.commit();
|
this.commit();
|
||||||
},
|
}
|
||||||
|
|
||||||
addListener: function(listener) {
|
addListener(listener) {
|
||||||
if ( this.listeners.indexOf(listener) !== -1 ) { return; }
|
if ( this.listeners.indexOf(listener) !== -1 ) { return; }
|
||||||
this.listeners.push(listener);
|
this.listeners.push(listener);
|
||||||
},
|
}
|
||||||
|
|
||||||
removeListener: function(listener) {
|
removeListener(listener) {
|
||||||
var pos = this.listeners.indexOf(listener);
|
const pos = this.listeners.indexOf(listener);
|
||||||
if ( pos === -1 ) { return; }
|
if ( pos === -1 ) { return; }
|
||||||
this.listeners.splice(pos, 1);
|
this.listeners.splice(pos, 1);
|
||||||
},
|
}
|
||||||
|
|
||||||
hasListeners: function() {
|
hasListeners() {
|
||||||
return this.listeners.length !== 0;
|
return this.listeners.length !== 0;
|
||||||
},
|
}
|
||||||
|
|
||||||
triggerListeners: function(changes) {
|
triggerListeners(changes) {
|
||||||
var i = this.listeners.length;
|
for ( const listener of this.listeners ) {
|
||||||
while ( i-- ) {
|
listener.onFiltersetChanged(changes);
|
||||||
this.listeners[i].onFiltersetChanged(changes);
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
// https://jsperf.com/clientheight-and-clientwidth-vs-getcomputedstyle
|
// https://jsperf.com/clientheight-and-clientwidth-vs-getcomputedstyle
|
||||||
// Avoid getComputedStyle(), detecting whether a node is visible can be
|
// Avoid getComputedStyle(), detecting whether a node is visible can be
|
||||||
@ -351,10 +356,10 @@ vAPI.DOMFilterer.prototype = {
|
|||||||
// However, toggling off/on cosmetic filtering repeatedly is not
|
// However, toggling off/on cosmetic filtering repeatedly is not
|
||||||
// a real use case, but this shows this will help performance
|
// a real use case, but this shows this will help performance
|
||||||
// on sites which try to use inline styles to bypass blockers.
|
// on sites which try to use inline styles to bypass blockers.
|
||||||
hideNodeBatchProcess: function() {
|
hideNodeBatchProcess() {
|
||||||
this.hideNodeBatchProcessTimer.clear();
|
this.hideNodeBatchProcessTimer.clear();
|
||||||
var expando = this.hideNodeExpando;
|
const expando = this.hideNodeExpando;
|
||||||
for ( var node of this.hiddenNodesetToProcess ) {
|
for ( const node of this.hiddenNodesetToProcess ) {
|
||||||
if (
|
if (
|
||||||
this.hiddenNodeset.has(node) === false ||
|
this.hiddenNodeset.has(node) === false ||
|
||||||
node[expando] === undefined ||
|
node[expando] === undefined ||
|
||||||
@ -362,7 +367,7 @@ vAPI.DOMFilterer.prototype = {
|
|||||||
) {
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var attr = node.getAttribute('style');
|
let attr = node.getAttribute('style');
|
||||||
if ( attr === null ) {
|
if ( attr === null ) {
|
||||||
attr = '';
|
attr = '';
|
||||||
} else if (
|
} else if (
|
||||||
@ -374,24 +379,18 @@ vAPI.DOMFilterer.prototype = {
|
|||||||
node.setAttribute('style', attr + 'display:none!important;');
|
node.setAttribute('style', attr + 'display:none!important;');
|
||||||
}
|
}
|
||||||
this.hiddenNodesetToProcess.clear();
|
this.hiddenNodesetToProcess.clear();
|
||||||
},
|
}
|
||||||
|
|
||||||
hideNodeObserverHandler: function(mutations) {
|
hideNodeObserverHandler(mutations) {
|
||||||
if ( vAPI.userStylesheet.disabled ) { return; }
|
if ( vAPI.userStylesheet.disabled ) { return; }
|
||||||
var i = mutations.length,
|
const stagedNodes = this.hiddenNodesetToProcess;
|
||||||
stagedNodes = this.hiddenNodesetToProcess;
|
for ( const mutation of mutations ) {
|
||||||
while ( i-- ) {
|
stagedNodes.add(mutation.target);
|
||||||
stagedNodes.add(mutations[i].target);
|
|
||||||
}
|
}
|
||||||
this.hideNodeBatchProcessTimer.start();
|
this.hideNodeBatchProcessTimer.start();
|
||||||
},
|
}
|
||||||
|
|
||||||
hiddenNodeObserverOptions: {
|
hideNodeInit() {
|
||||||
attributes: true,
|
|
||||||
attributeFilter: [ 'style' ]
|
|
||||||
},
|
|
||||||
|
|
||||||
hideNodeInit: function() {
|
|
||||||
this.hideNodeExpando = vAPI.randomToken();
|
this.hideNodeExpando = vAPI.randomToken();
|
||||||
this.hideNodeBatchProcessTimer =
|
this.hideNodeBatchProcessTimer =
|
||||||
new vAPI.SafeAnimationFrame(this.hideNodeBatchProcess.bind(this));
|
new vAPI.SafeAnimationFrame(this.hideNodeBatchProcess.bind(this));
|
||||||
@ -400,21 +399,21 @@ vAPI.DOMFilterer.prototype = {
|
|||||||
if ( this.hideNodeStyleSheetInjected === false ) {
|
if ( this.hideNodeStyleSheetInjected === false ) {
|
||||||
this.hideNodeStyleSheetInjected = true;
|
this.hideNodeStyleSheetInjected = true;
|
||||||
vAPI.userStylesheet.add(
|
vAPI.userStylesheet.add(
|
||||||
'[' + this.hideNodeAttr + ']\n{display:none!important;}'
|
`[${this.hideNodeAttr}]\n{display:none!important;}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
excludeNode: function(node) {
|
excludeNode(node) {
|
||||||
this.excludedNodeSet.add(node);
|
this.excludedNodeSet.add(node);
|
||||||
this.unhideNode(node);
|
this.unhideNode(node);
|
||||||
},
|
}
|
||||||
|
|
||||||
unexcludeNode: function(node) {
|
unexcludeNode(node) {
|
||||||
this.excludedNodeSet.delete(node);
|
this.excludedNodeSet.delete(node);
|
||||||
},
|
}
|
||||||
|
|
||||||
hideNode: function(node) {
|
hideNode(node) {
|
||||||
if ( this.excludedNodeSet.has(node) ) { return; }
|
if ( this.excludedNodeSet.has(node) ) { return; }
|
||||||
if ( this.hideNodeAttr === undefined ) { return; }
|
if ( this.hideNodeAttr === undefined ) { return; }
|
||||||
if ( this.hiddenNodeset.has(node) ) { return; }
|
if ( this.hiddenNodeset.has(node) ) { return; }
|
||||||
@ -430,15 +429,15 @@ vAPI.DOMFilterer.prototype = {
|
|||||||
this.hiddenNodesetToProcess.add(node);
|
this.hiddenNodesetToProcess.add(node);
|
||||||
this.hideNodeBatchProcessTimer.start();
|
this.hideNodeBatchProcessTimer.start();
|
||||||
this.hiddenNodeObserver.observe(node, this.hiddenNodeObserverOptions);
|
this.hiddenNodeObserver.observe(node, this.hiddenNodeObserverOptions);
|
||||||
},
|
}
|
||||||
|
|
||||||
unhideNode: function(node) {
|
unhideNode(node) {
|
||||||
if ( this.hiddenNodeset.has(node) === false ) { return; }
|
if ( this.hiddenNodeset.has(node) === false ) { return; }
|
||||||
node.hidden = false;
|
node.hidden = false;
|
||||||
node.removeAttribute(this.hideNodeAttr);
|
node.removeAttribute(this.hideNodeAttr);
|
||||||
this.hiddenNodesetToProcess.delete(node);
|
this.hiddenNodesetToProcess.delete(node);
|
||||||
if ( this.hideNodeExpando === undefined ) { return; }
|
if ( this.hideNodeExpando === undefined ) { return; }
|
||||||
var attr = node[this.hideNodeExpando];
|
const attr = node[this.hideNodeExpando];
|
||||||
if ( attr === false ) {
|
if ( attr === false ) {
|
||||||
node.removeAttribute('style');
|
node.removeAttribute('style');
|
||||||
} else if ( typeof attr === 'string' ) {
|
} else if ( typeof attr === 'string' ) {
|
||||||
@ -446,28 +445,28 @@ vAPI.DOMFilterer.prototype = {
|
|||||||
}
|
}
|
||||||
node[this.hideNodeExpando] = undefined;
|
node[this.hideNodeExpando] = undefined;
|
||||||
this.hiddenNodeset.delete(node);
|
this.hiddenNodeset.delete(node);
|
||||||
},
|
}
|
||||||
|
|
||||||
showNode: function(node) {
|
showNode(node) {
|
||||||
node.hidden = false;
|
node.hidden = false;
|
||||||
var attr = node[this.hideNodeExpando];
|
const attr = node[this.hideNodeExpando];
|
||||||
if ( attr === false ) {
|
if ( attr === false ) {
|
||||||
node.removeAttribute('style');
|
node.removeAttribute('style');
|
||||||
} else if ( typeof attr === 'string' ) {
|
} else if ( typeof attr === 'string' ) {
|
||||||
node.setAttribute('style', attr);
|
node.setAttribute('style', attr);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
unshowNode: function(node) {
|
unshowNode(node) {
|
||||||
node.hidden = true;
|
node.hidden = true;
|
||||||
this.hiddenNodesetToProcess.add(node);
|
this.hiddenNodesetToProcess.add(node);
|
||||||
},
|
}
|
||||||
|
|
||||||
toggle: function(state, callback) {
|
toggle(state, callback) {
|
||||||
vAPI.userStylesheet.toggle(state);
|
vAPI.userStylesheet.toggle(state);
|
||||||
var disabled = vAPI.userStylesheet.disabled,
|
const disabled = vAPI.userStylesheet.disabled;
|
||||||
nodes = document.querySelectorAll('[' + this.hideNodeAttr + ']');
|
const nodes = document.querySelectorAll(`[${this.hideNodeAttr}]`);
|
||||||
for ( var node of nodes ) {
|
for ( const node of nodes ) {
|
||||||
if ( disabled ) {
|
if ( disabled ) {
|
||||||
this.showNode(node);
|
this.showNode(node);
|
||||||
} else {
|
} else {
|
||||||
@ -480,11 +479,12 @@ vAPI.DOMFilterer.prototype = {
|
|||||||
if ( typeof callback === 'function' ) {
|
if ( typeof callback === 'function' ) {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
getAllSelectors_: function(all) {
|
getAllSelectors_(all) {
|
||||||
var out = {
|
const out = {
|
||||||
declarative: []
|
declarative: [],
|
||||||
|
exceptions: this.exceptedCSSRules,
|
||||||
};
|
};
|
||||||
if ( this.specificSimpleHide.size !== 0 ) {
|
if ( this.specificSimpleHide.size !== 0 ) {
|
||||||
out.declarative.push([
|
out.declarative.push([
|
||||||
@ -516,28 +516,30 @@ vAPI.DOMFilterer.prototype = {
|
|||||||
'display:none!important;'
|
'display:none!important;'
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
for ( var entry of this.specificOthers ) {
|
for ( const entry of this.specificOthers ) {
|
||||||
out.declarative.push([ entry.selectors, entry.declarations ]);
|
out.declarative.push([ entry.selectors, entry.declarations ]);
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
},
|
}
|
||||||
|
|
||||||
getFilteredElementCount: function() {
|
getFilteredElementCount() {
|
||||||
var details = this.getAllSelectors_(true);
|
const details = this.getAllSelectors_(true);
|
||||||
if ( Array.isArray(details.declarative) === false ) { return 0; }
|
if ( Array.isArray(details.declarative) === false ) { return 0; }
|
||||||
var selectors = details.declarative.reduce(function(acc, entry) {
|
const selectors = details.declarative.map(entry => entry[0]);
|
||||||
acc.push(entry[0]);
|
|
||||||
return acc;
|
|
||||||
}, []);
|
|
||||||
if ( selectors.length === 0 ) { return 0; }
|
if ( selectors.length === 0 ) { return 0; }
|
||||||
return document.querySelectorAll(selectors.join(',\n')).length;
|
return document.querySelectorAll(selectors.join(',\n')).length;
|
||||||
},
|
}
|
||||||
|
|
||||||
getAllSelectors: function() {
|
getAllSelectors() {
|
||||||
return this.getAllSelectors_(false);
|
return this.getAllSelectors_(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
vAPI.DOMFilterer.prototype.hiddenNodeObserverOptions = {
|
||||||
|
attributes: true,
|
||||||
|
attributeFilter: [ 'style' ]
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
@ -57,31 +57,31 @@ vAPI.userStylesheet = {
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
vAPI.DOMFilterer = function() {
|
vAPI.DOMFilterer = class {
|
||||||
this.commitTimer = new vAPI.SafeAnimationFrame(this.commitNow.bind(this));
|
constructor() {
|
||||||
this.domIsReady = document.readyState !== 'loading';
|
this.commitTimer = new vAPI.SafeAnimationFrame(( ) => this.commitNow);
|
||||||
this.disabled = false;
|
this.domIsReady = document.readyState !== 'loading';
|
||||||
this.listeners = [];
|
this.disabled = false;
|
||||||
this.filterset = new Set();
|
this.listeners = [];
|
||||||
this.excludedNodeSet = new WeakSet();
|
this.filterset = new Set();
|
||||||
this.addedCSSRules = new Set();
|
this.excludedNodeSet = new WeakSet();
|
||||||
|
this.addedCSSRules = new Set();
|
||||||
|
this.exceptedCSSRules = [];
|
||||||
|
this.reOnlySelectors = /\n\{[^\n]+/g;
|
||||||
|
|
||||||
// https://github.com/uBlockOrigin/uBlock-issues/issues/167
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/167
|
||||||
// By the time the DOMContentLoaded is fired, the content script might
|
// By the time the DOMContentLoaded is fired, the content script might
|
||||||
// have been disconnected from the background page. Unclear why this
|
// have been disconnected from the background page. Unclear why this
|
||||||
// would happen, so far seems to be a Chromium-specific behavior at
|
// would happen, so far seems to be a Chromium-specific behavior at
|
||||||
// launch time.
|
// launch time.
|
||||||
if ( this.domIsReady !== true ) {
|
if ( this.domIsReady !== true ) {
|
||||||
document.addEventListener('DOMContentLoaded', ( ) => {
|
document.addEventListener('DOMContentLoaded', ( ) => {
|
||||||
if ( vAPI instanceof Object === false ) { return; }
|
if ( vAPI instanceof Object === false ) { return; }
|
||||||
this.domIsReady = true;
|
this.domIsReady = true;
|
||||||
this.commit();
|
this.commit();
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
vAPI.DOMFilterer.prototype = {
|
|
||||||
reOnlySelectors: /\n\{[^\n]+/g,
|
|
||||||
|
|
||||||
// Here we will deal with:
|
// Here we will deal with:
|
||||||
// - Injecting low priority user styles;
|
// - Injecting low priority user styles;
|
||||||
@ -92,11 +92,11 @@ vAPI.DOMFilterer.prototype = {
|
|||||||
// process. Another approach would be to have vAPI.SafeAnimationFrame
|
// process. Another approach would be to have vAPI.SafeAnimationFrame
|
||||||
// register a shutdown job: to evaluate. For now I will keep the fix
|
// register a shutdown job: to evaluate. For now I will keep the fix
|
||||||
// trivial.
|
// trivial.
|
||||||
commitNow: function() {
|
commitNow() {
|
||||||
this.commitTimer.clear();
|
this.commitTimer.clear();
|
||||||
if ( vAPI instanceof Object === false ) { return; }
|
if ( vAPI instanceof Object === false ) { return; }
|
||||||
let userStylesheet = vAPI.userStylesheet;
|
const userStylesheet = vAPI.userStylesheet;
|
||||||
for ( let entry of this.addedCSSRules ) {
|
for ( const entry of this.addedCSSRules ) {
|
||||||
if (
|
if (
|
||||||
this.disabled === false &&
|
this.disabled === false &&
|
||||||
entry.lazy &&
|
entry.lazy &&
|
||||||
@ -109,25 +109,25 @@ vAPI.DOMFilterer.prototype = {
|
|||||||
}
|
}
|
||||||
this.addedCSSRules.clear();
|
this.addedCSSRules.clear();
|
||||||
userStylesheet.apply();
|
userStylesheet.apply();
|
||||||
},
|
}
|
||||||
|
|
||||||
commit: function(commitNow) {
|
commit(commitNow) {
|
||||||
if ( commitNow ) {
|
if ( commitNow ) {
|
||||||
this.commitTimer.clear();
|
this.commitTimer.clear();
|
||||||
this.commitNow();
|
this.commitNow();
|
||||||
} else {
|
} else {
|
||||||
this.commitTimer.start();
|
this.commitTimer.start();
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
addCSSRule: function(selectors, declarations, details) {
|
addCSSRule(selectors, declarations, details) {
|
||||||
if ( selectors === undefined ) { return; }
|
if ( selectors === undefined ) { return; }
|
||||||
var selectorsStr = Array.isArray(selectors)
|
const selectorsStr = Array.isArray(selectors)
|
||||||
? selectors.join(',\n')
|
? selectors.join(',\n')
|
||||||
: selectors;
|
: selectors;
|
||||||
if ( selectorsStr.length === 0 ) { return; }
|
if ( selectorsStr.length === 0 ) { return; }
|
||||||
if ( details === undefined ) { details = {}; }
|
if ( details === undefined ) { details = {}; }
|
||||||
var entry = {
|
const entry = {
|
||||||
selectors: selectorsStr,
|
selectors: selectorsStr,
|
||||||
declarations,
|
declarations,
|
||||||
lazy: details.lazy === true,
|
lazy: details.lazy === true,
|
||||||
@ -148,64 +148,71 @@ vAPI.DOMFilterer.prototype = {
|
|||||||
declarative: [ [ selectorsStr, declarations ] ]
|
declarative: [ [ selectorsStr, declarations ] ]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
addListener: function(listener) {
|
exceptCSSRules(exceptions) {
|
||||||
|
if ( exceptions.length === 0 ) { return; }
|
||||||
|
this.exceptedCSSRules.push(...exceptions);
|
||||||
|
if ( this.hasListeners() ) {
|
||||||
|
this.triggerListeners({ exceptions });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addListener(listener) {
|
||||||
if ( this.listeners.indexOf(listener) !== -1 ) { return; }
|
if ( this.listeners.indexOf(listener) !== -1 ) { return; }
|
||||||
this.listeners.push(listener);
|
this.listeners.push(listener);
|
||||||
},
|
}
|
||||||
|
|
||||||
removeListener: function(listener) {
|
removeListener(listener) {
|
||||||
var pos = this.listeners.indexOf(listener);
|
const pos = this.listeners.indexOf(listener);
|
||||||
if ( pos === -1 ) { return; }
|
if ( pos === -1 ) { return; }
|
||||||
this.listeners.splice(pos, 1);
|
this.listeners.splice(pos, 1);
|
||||||
},
|
}
|
||||||
|
|
||||||
hasListeners: function() {
|
hasListeners() {
|
||||||
return this.listeners.length !== 0;
|
return this.listeners.length !== 0;
|
||||||
},
|
}
|
||||||
|
|
||||||
triggerListeners: function(changes) {
|
triggerListeners(changes) {
|
||||||
var i = this.listeners.length;
|
for ( const listener of this.listeners ) {
|
||||||
while ( i-- ) {
|
listener.onFiltersetChanged(changes);
|
||||||
this.listeners[i].onFiltersetChanged(changes);
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
excludeNode: function(node) {
|
excludeNode(node) {
|
||||||
this.excludedNodeSet.add(node);
|
this.excludedNodeSet.add(node);
|
||||||
this.unhideNode(node);
|
this.unhideNode(node);
|
||||||
},
|
}
|
||||||
|
|
||||||
unexcludeNode: function(node) {
|
unexcludeNode(node) {
|
||||||
this.excludedNodeSet.delete(node);
|
this.excludedNodeSet.delete(node);
|
||||||
},
|
}
|
||||||
|
|
||||||
hideNode: function(node) {
|
hideNode(node) {
|
||||||
if ( this.excludedNodeSet.has(node) ) { return; }
|
if ( this.excludedNodeSet.has(node) ) { return; }
|
||||||
if ( this.hideNodeAttr === undefined ) { return; }
|
if ( this.hideNodeAttr === undefined ) { return; }
|
||||||
node.setAttribute(this.hideNodeAttr, '');
|
node.setAttribute(this.hideNodeAttr, '');
|
||||||
if ( this.hideNodeStyleSheetInjected === false ) {
|
if ( this.hideNodeStyleSheetInjected === false ) {
|
||||||
this.hideNodeStyleSheetInjected = true;
|
this.hideNodeStyleSheetInjected = true;
|
||||||
this.addCSSRule(
|
this.addCSSRule(
|
||||||
'[' + this.hideNodeAttr + ']',
|
`[${this.hideNodeAttr}]`,
|
||||||
'display:none!important;'
|
'display:none!important;'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
unhideNode: function(node) {
|
unhideNode(node) {
|
||||||
if ( this.hideNodeAttr === undefined ) { return; }
|
if ( this.hideNodeAttr === undefined ) { return; }
|
||||||
node.removeAttribute(this.hideNodeAttr);
|
node.removeAttribute(this.hideNodeAttr);
|
||||||
},
|
}
|
||||||
|
|
||||||
toggle: function(state, callback) {
|
toggle(state, callback) {
|
||||||
if ( state === undefined ) { state = this.disabled; }
|
if ( state === undefined ) { state = this.disabled; }
|
||||||
if ( state !== this.disabled ) { return; }
|
if ( state !== this.disabled ) { return; }
|
||||||
this.disabled = !state;
|
this.disabled = !state;
|
||||||
var userStylesheet = vAPI.userStylesheet;
|
const userStylesheet = vAPI.userStylesheet;
|
||||||
for ( var entry of this.filterset ) {
|
for ( const entry of this.filterset ) {
|
||||||
var rule = entry.selectors + '\n{' + entry.declarations + '}';
|
const rule = `${entry.selectors}\n{${entry.declarations}}`;
|
||||||
if ( this.disabled ) {
|
if ( this.disabled ) {
|
||||||
userStylesheet.remove(rule);
|
userStylesheet.remove(rule);
|
||||||
} else {
|
} else {
|
||||||
@ -213,38 +220,35 @@ vAPI.DOMFilterer.prototype = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
userStylesheet.apply(callback);
|
userStylesheet.apply(callback);
|
||||||
},
|
}
|
||||||
|
|
||||||
getAllSelectors_: function(all) {
|
getAllSelectors_(all) {
|
||||||
var out = {
|
const out = {
|
||||||
declarative: []
|
declarative: [],
|
||||||
|
exceptions: this.exceptedCSSRules,
|
||||||
};
|
};
|
||||||
var selectors;
|
for ( const entry of this.filterset ) {
|
||||||
for ( var entry of this.filterset ) {
|
let selectors = entry.selectors;
|
||||||
selectors = entry.selectors;
|
|
||||||
if ( all !== true && this.hideNodeAttr !== undefined ) {
|
if ( all !== true && this.hideNodeAttr !== undefined ) {
|
||||||
selectors = selectors
|
selectors = selectors
|
||||||
.replace('[' + this.hideNodeAttr + ']', '')
|
.replace(`[${this.hideNodeAttr}]`, '')
|
||||||
.replace(/^,\n|,\n$/gm, '');
|
.replace(/^,\n|,\n$/gm, '');
|
||||||
if ( selectors === '' ) { continue; }
|
if ( selectors === '' ) { continue; }
|
||||||
}
|
}
|
||||||
out.declarative.push([ selectors, entry.declarations ]);
|
out.declarative.push([ selectors, entry.declarations ]);
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
},
|
}
|
||||||
|
|
||||||
getFilteredElementCount: function() {
|
getFilteredElementCount() {
|
||||||
let details = this.getAllSelectors_(true);
|
const details = this.getAllSelectors_(true);
|
||||||
if ( Array.isArray(details.declarative) === false ) { return 0; }
|
if ( Array.isArray(details.declarative) === false ) { return 0; }
|
||||||
let selectors = details.declarative.reduce(function(acc, entry) {
|
const selectors = details.declarative.map(entry => entry[0]);
|
||||||
acc.push(entry[0]);
|
|
||||||
return acc;
|
|
||||||
}, []);
|
|
||||||
if ( selectors.length === 0 ) { return 0; }
|
if ( selectors.length === 0 ) { return 0; }
|
||||||
return document.querySelectorAll(selectors.join(',\n')).length;
|
return document.querySelectorAll(selectors.join(',\n')).length;
|
||||||
},
|
}
|
||||||
|
|
||||||
getAllSelectors: function() {
|
getAllSelectors() {
|
||||||
return this.getAllSelectors_(false);
|
return this.getAllSelectors_(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -265,11 +265,11 @@ body.colorBlind #netFilteringDialog > .panes > .details > div[data-status="2"] {
|
|||||||
#vwRenderer .logEntry > div[data-tabid="-1"] {
|
#vwRenderer .logEntry > div[data-tabid="-1"] {
|
||||||
text-shadow: 0 0.2em 0.4em #aaa;
|
text-shadow: 0 0.2em 0.4em #aaa;
|
||||||
}
|
}
|
||||||
#vwRenderer .logEntry > div.cosmetic,
|
#vwRenderer .logEntry > div.cosmeticRealm,
|
||||||
#vwRenderer .logEntry > div.redirect {
|
#vwRenderer .logEntry > div.redirect {
|
||||||
background-color: rgba(255, 255, 0, 0.1);
|
background-color: rgba(255, 255, 0, 0.1);
|
||||||
}
|
}
|
||||||
body.colorBlind #vwRenderer .logEntry > div.cosmetic,
|
body.colorBlind #vwRenderer .logEntry > div.cosmeticRealm,
|
||||||
body.colorBlind #vwRenderer .logEntry > div.redirect {
|
body.colorBlind #vwRenderer .logEntry > div.redirect {
|
||||||
background-color: rgba(0, 19, 110, 0.1);
|
background-color: rgba(0, 19, 110, 0.1);
|
||||||
}
|
}
|
||||||
@ -326,6 +326,9 @@ body[dir="rtl"] #vwRenderer .logEntry > div > span:first-child {
|
|||||||
#vwRenderer .logEntry > div.messageRealm[data-type="tabLoad"] > span:nth-of-type(2) {
|
#vwRenderer .logEntry > div.messageRealm[data-type="tabLoad"] > span:nth-of-type(2) {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
#vwRenderer .logEntry > div.cosmeticRealm.isException > span:nth-of-type(2) {
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
#vwRenderer .logEntry > div > span:nth-of-type(3) {
|
#vwRenderer .logEntry > div > span:nth-of-type(3) {
|
||||||
font: 12px monospace;
|
font: 12px monospace;
|
||||||
padding-left: 0.3em;
|
padding-left: 0.3em;
|
||||||
|
@ -825,66 +825,60 @@ vAPI.DOMFilterer = (function() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const DOMFiltererBase = vAPI.DOMFilterer;
|
const DOMFilterer = class extends vAPI.DOMFilterer {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.exceptions = [];
|
||||||
|
this.proceduralFilterer = new DOMProceduralFilterer(this);
|
||||||
|
this.hideNodeAttr = undefined;
|
||||||
|
this.hideNodeStyleSheetInjected = false;
|
||||||
|
if ( vAPI.domWatcher instanceof Object ) {
|
||||||
|
vAPI.domWatcher.addListener(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const domFilterer = function() {
|
commitNow() {
|
||||||
DOMFiltererBase.call(this);
|
super.commitNow();
|
||||||
this.exceptions = [];
|
this.proceduralFilterer.commitNow();
|
||||||
this.proceduralFilterer = new DOMProceduralFilterer(this);
|
}
|
||||||
this.hideNodeAttr = undefined;
|
|
||||||
this.hideNodeStyleSheetInjected = false;
|
|
||||||
|
|
||||||
// May or may not exist: cache locally since this may be called often.
|
addProceduralSelectors(aa) {
|
||||||
this.baseOnDOMChanged = DOMFiltererBase.prototype.onDOMChanged;
|
this.proceduralFilterer.addProceduralSelectors(aa);
|
||||||
|
}
|
||||||
|
|
||||||
if ( vAPI.domWatcher instanceof Object ) {
|
createProceduralFilter(o) {
|
||||||
vAPI.domWatcher.addListener(this);
|
return this.proceduralFilterer.createProceduralFilter(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
getAllSelectors() {
|
||||||
|
const out = super.getAllSelectors();
|
||||||
|
out.procedural = Array.from(this.proceduralFilterer.selectors.values());
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
getAllExceptionSelectors() {
|
||||||
|
return this.exceptions.join(',\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
onDOMCreated() {
|
||||||
|
if ( super.onDOMCreated instanceof Function ) {
|
||||||
|
super.onDOMCreated();
|
||||||
|
}
|
||||||
|
this.proceduralFilterer.onDOMCreated();
|
||||||
|
}
|
||||||
|
|
||||||
|
onDOMChanged() {
|
||||||
|
if ( super.onDOMChanged instanceof Function ) {
|
||||||
|
super.onDOMChanged(arguments);
|
||||||
|
}
|
||||||
|
this.proceduralFilterer.onDOMChanged.apply(
|
||||||
|
this.proceduralFilterer,
|
||||||
|
arguments
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
domFilterer.prototype = Object.create(DOMFiltererBase.prototype);
|
|
||||||
domFilterer.prototype.constructor = domFilterer;
|
|
||||||
|
|
||||||
domFilterer.prototype.commitNow = function() {
|
return DOMFilterer;
|
||||||
DOMFiltererBase.prototype.commitNow.call(this);
|
|
||||||
this.proceduralFilterer.commitNow();
|
|
||||||
};
|
|
||||||
|
|
||||||
domFilterer.prototype.addProceduralSelectors = function(aa) {
|
|
||||||
this.proceduralFilterer.addProceduralSelectors(aa);
|
|
||||||
};
|
|
||||||
|
|
||||||
domFilterer.prototype.createProceduralFilter = function(o) {
|
|
||||||
return this.proceduralFilterer.createProceduralFilter(o);
|
|
||||||
};
|
|
||||||
|
|
||||||
domFilterer.prototype.getAllSelectors = function() {
|
|
||||||
const out = DOMFiltererBase.prototype.getAllSelectors.call(this);
|
|
||||||
out.procedural = Array.from(this.proceduralFilterer.selectors.values());
|
|
||||||
return out;
|
|
||||||
};
|
|
||||||
|
|
||||||
domFilterer.prototype.getAllExceptionSelectors = function() {
|
|
||||||
return this.exceptions.join(',\n');
|
|
||||||
};
|
|
||||||
|
|
||||||
domFilterer.prototype.onDOMCreated = function() {
|
|
||||||
if ( DOMFiltererBase.prototype.onDOMCreated !== undefined ) {
|
|
||||||
DOMFiltererBase.prototype.onDOMCreated.call(this);
|
|
||||||
}
|
|
||||||
this.proceduralFilterer.onDOMCreated();
|
|
||||||
};
|
|
||||||
|
|
||||||
domFilterer.prototype.onDOMChanged = function() {
|
|
||||||
if ( this.baseOnDOMChanged !== undefined ) {
|
|
||||||
this.baseOnDOMChanged.apply(this, arguments);
|
|
||||||
}
|
|
||||||
this.proceduralFilterer.onDOMChanged.apply(
|
|
||||||
this.proceduralFilterer,
|
|
||||||
arguments
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return domFilterer;
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
vAPI.domFilterer = new vAPI.DOMFilterer();
|
vAPI.domFilterer = new vAPI.DOMFilterer();
|
||||||
@ -1340,6 +1334,10 @@ vAPI.domSurveyor = (function() {
|
|||||||
);
|
);
|
||||||
mustCommit = true;
|
mustCommit = true;
|
||||||
}
|
}
|
||||||
|
selectors = result.excepted;
|
||||||
|
if ( Array.isArray(selectors) && selectors.length !== 0 ) {
|
||||||
|
domFilterer.exceptCSSRules(selectors);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( pendingNodes.stopped === false ) {
|
if ( pendingNodes.stopped === false ) {
|
||||||
@ -1524,6 +1522,7 @@ vAPI.bootstrap = (function() {
|
|||||||
{ injected: true }
|
{ injected: true }
|
||||||
);
|
);
|
||||||
domFilterer.addProceduralSelectors(cfeDetails.proceduralFilters);
|
domFilterer.addProceduralSelectors(cfeDetails.proceduralFilters);
|
||||||
|
domFilterer.exceptCSSRules(cfeDetails.exceptedFilters);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( cfeDetails.networkFilters.length !== 0 ) {
|
if ( cfeDetails.networkFilters.length !== 0 ) {
|
||||||
|
@ -843,22 +843,22 @@ FilterContainer.prototype.retrieveGenericSelectors = function(request) {
|
|||||||
|
|
||||||
//console.time('cosmeticFilteringEngine.retrieveGenericSelectors');
|
//console.time('cosmeticFilteringEngine.retrieveGenericSelectors');
|
||||||
|
|
||||||
let simpleSelectors = this.setRegister0,
|
const simpleSelectors = this.setRegister0;
|
||||||
complexSelectors = this.setRegister1;
|
const complexSelectors = this.setRegister1;
|
||||||
|
|
||||||
let cacheEntry = this.selectorCache.get(request.hostname),
|
const cacheEntry = this.selectorCache.get(request.hostname);
|
||||||
previousHits = cacheEntry && cacheEntry.cosmetic || this.setRegister2;
|
const previousHits = cacheEntry && cacheEntry.cosmetic || this.setRegister2;
|
||||||
|
|
||||||
for ( let type in this.lowlyGeneric ) {
|
for ( const type in this.lowlyGeneric ) {
|
||||||
let entry = this.lowlyGeneric[type];
|
const entry = this.lowlyGeneric[type];
|
||||||
let selectors = request[entry.canonical];
|
const selectors = request[entry.canonical];
|
||||||
if ( Array.isArray(selectors) === false ) { continue; }
|
if ( Array.isArray(selectors) === false ) { continue; }
|
||||||
for ( let selector of selectors ) {
|
for ( let selector of selectors ) {
|
||||||
if ( entry.simple.has(selector) === false ) { continue; }
|
if ( entry.simple.has(selector) === false ) { continue; }
|
||||||
let bucket = entry.complex.get(selector);
|
const bucket = entry.complex.get(selector);
|
||||||
if ( bucket !== undefined ) {
|
if ( bucket !== undefined ) {
|
||||||
if ( Array.isArray(bucket) ) {
|
if ( Array.isArray(bucket) ) {
|
||||||
for ( selector of bucket ) {
|
for ( const selector of bucket ) {
|
||||||
if ( previousHits.has(selector) === false ) {
|
if ( previousHits.has(selector) === false ) {
|
||||||
complexSelectors.add(selector);
|
complexSelectors.add(selector);
|
||||||
}
|
}
|
||||||
@ -877,26 +877,39 @@ FilterContainer.prototype.retrieveGenericSelectors = function(request) {
|
|||||||
|
|
||||||
// Apply exceptions: it is the responsibility of the caller to provide
|
// Apply exceptions: it is the responsibility of the caller to provide
|
||||||
// the exceptions to be applied.
|
// the exceptions to be applied.
|
||||||
|
const excepted = [];
|
||||||
if ( Array.isArray(request.exceptions) ) {
|
if ( Array.isArray(request.exceptions) ) {
|
||||||
for ( let exception of request.exceptions ) {
|
for ( const exception of request.exceptions ) {
|
||||||
simpleSelectors.delete(exception);
|
if (
|
||||||
complexSelectors.delete(exception);
|
simpleSelectors.delete(exception) ||
|
||||||
|
complexSelectors.delete(exception)
|
||||||
|
) {
|
||||||
|
excepted.push(exception);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( simpleSelectors.size === 0 && complexSelectors.size === 0 ) {
|
if (
|
||||||
|
simpleSelectors.size === 0 &&
|
||||||
|
complexSelectors.size === 0 &&
|
||||||
|
excepted.length === 0
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let out = {
|
const out = {
|
||||||
simple: Array.from(simpleSelectors),
|
simple: Array.from(simpleSelectors),
|
||||||
complex: Array.from(complexSelectors),
|
complex: Array.from(complexSelectors),
|
||||||
injected: ''
|
injected: '',
|
||||||
|
excepted,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Cache and inject (if user stylesheets supported) looked-up low generic
|
// Cache and inject (if user stylesheets supported) looked-up low generic
|
||||||
// cosmetic filters.
|
// cosmetic filters.
|
||||||
if ( typeof request.hostname === 'string' && request.hostname !== '' ) {
|
if (
|
||||||
|
(typeof request.hostname === 'string' && request.hostname !== '') &&
|
||||||
|
(out.simple.length !== 0 || out.complex.length !== 0)
|
||||||
|
) {
|
||||||
this.addToSelectorCache({
|
this.addToSelectorCache({
|
||||||
cost: request.surveyCost || 0,
|
cost: request.surveyCost || 0,
|
||||||
hostname: request.hostname,
|
hostname: request.hostname,
|
||||||
@ -913,7 +926,7 @@ FilterContainer.prototype.retrieveGenericSelectors = function(request) {
|
|||||||
request.tabId !== undefined &&
|
request.tabId !== undefined &&
|
||||||
request.frameId !== undefined
|
request.frameId !== undefined
|
||||||
) {
|
) {
|
||||||
let injected = [];
|
const injected = [];
|
||||||
if ( out.simple.length !== 0 ) {
|
if ( out.simple.length !== 0 ) {
|
||||||
injected.push(out.simple.join(',\n'));
|
injected.push(out.simple.join(',\n'));
|
||||||
out.simple = [];
|
out.simple = [];
|
||||||
@ -964,6 +977,7 @@ FilterContainer.prototype.retrieveSpecificSelectors = function(
|
|||||||
domain: request.domain,
|
domain: request.domain,
|
||||||
declarativeFilters: [],
|
declarativeFilters: [],
|
||||||
exceptionFilters: [],
|
exceptionFilters: [],
|
||||||
|
exceptedFilters: [],
|
||||||
hideNodeAttr: this.randomAlphaToken(),
|
hideNodeAttr: this.randomAlphaToken(),
|
||||||
hideNodeStyleSheetInjected: false,
|
hideNodeStyleSheetInjected: false,
|
||||||
highGenericHideSimple: '',
|
highGenericHideSimple: '',
|
||||||
@ -1008,8 +1022,13 @@ FilterContainer.prototype.retrieveSpecificSelectors = function(
|
|||||||
if ( exceptionSet.size !== 0 ) {
|
if ( exceptionSet.size !== 0 ) {
|
||||||
out.exceptionFilters = Array.from(exceptionSet);
|
out.exceptionFilters = Array.from(exceptionSet);
|
||||||
for ( const exception of exceptionSet ) {
|
for ( const exception of exceptionSet ) {
|
||||||
specificSet.delete(exception);
|
if (
|
||||||
proceduralSet.delete(exception);
|
specificSet.delete(exception) ||
|
||||||
|
proceduralSet.delete(exception)
|
||||||
|
) {
|
||||||
|
out.exceptedFilters.push(exception);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1034,7 +1053,7 @@ FilterContainer.prototype.retrieveSpecificSelectors = function(
|
|||||||
const entry = this.highlyGeneric[type];
|
const entry = this.highlyGeneric[type];
|
||||||
let str = entry.mru.lookup(exceptionHash);
|
let str = entry.mru.lookup(exceptionHash);
|
||||||
if ( str === undefined ) {
|
if ( str === undefined ) {
|
||||||
str = { s: entry.str };
|
str = { s: entry.str, excepted: [] };
|
||||||
let genericSet = entry.dict;
|
let genericSet = entry.dict;
|
||||||
let hit = false;
|
let hit = false;
|
||||||
for ( const exception of exceptionSet ) {
|
for ( const exception of exceptionSet ) {
|
||||||
@ -1042,14 +1061,20 @@ FilterContainer.prototype.retrieveSpecificSelectors = function(
|
|||||||
}
|
}
|
||||||
if ( hit ) {
|
if ( hit ) {
|
||||||
genericSet = new Set(entry.dict);
|
genericSet = new Set(entry.dict);
|
||||||
for ( let exception of exceptionSet ) {
|
for ( const exception of exceptionSet ) {
|
||||||
genericSet.delete(exception);
|
if ( genericSet.delete(exception) ) {
|
||||||
|
str.excepted.push(exception);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
str.s = Array.from(genericSet).join(',\n');
|
str.s = Array.from(genericSet).join(',\n');
|
||||||
}
|
}
|
||||||
entry.mru.add(exceptionHash, str);
|
entry.mru.add(exceptionHash, str);
|
||||||
}
|
}
|
||||||
out[entry.canonical] = str.s;
|
out[entry.canonical] = str.s;
|
||||||
|
if ( str.excepted.length !== 0 ) {
|
||||||
|
out.exceptedFilters.push(...str.excepted);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,13 +622,13 @@ const viewPort = (function() {
|
|||||||
if ( filter !== undefined ) {
|
if ( filter !== undefined ) {
|
||||||
if ( typeof filter.source === 'string' ) {
|
if ( typeof filter.source === 'string' ) {
|
||||||
filteringType = filter.source;
|
filteringType = filter.source;
|
||||||
divcl.add(filteringType);
|
|
||||||
}
|
}
|
||||||
if ( filteringType === 'static' ) {
|
if ( filteringType === 'static' ) {
|
||||||
divcl.add('canLookup');
|
divcl.add('canLookup');
|
||||||
div.setAttribute('data-filter', filter.compiled);
|
div.setAttribute('data-filter', filter.compiled);
|
||||||
} else if ( filteringType === 'cosmetic' ) {
|
} else if ( filteringType === 'cosmetic' ) {
|
||||||
divcl.add('canLookup');
|
divcl.add('canLookup');
|
||||||
|
divcl.toggle('isException', filter.raw.startsWith('#@#'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
span = div.children[1];
|
span = div.children[1];
|
||||||
@ -1503,7 +1503,7 @@ const reloadTab = function(ev) {
|
|||||||
text = trch[1].textContent;
|
text = trch[1].textContent;
|
||||||
if (
|
if (
|
||||||
(text !== '') &&
|
(text !== '') &&
|
||||||
(trcl.contains('cosmetic') || trcl.contains('static'))
|
(trcl.contains('cosmeticRealm') || trcl.contains('networkRealm'))
|
||||||
) {
|
) {
|
||||||
rows[0].children[1].textContent = text;
|
rows[0].children[1].textContent = text;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1352,7 +1352,7 @@ const logCosmeticFilters = function(tabId, details) {
|
|||||||
.setDocOriginFromURL(details.frameURL)
|
.setDocOriginFromURL(details.frameURL)
|
||||||
.setFilter(filter);
|
.setFilter(filter);
|
||||||
for ( const selector of details.matchedSelectors.sort() ) {
|
for ( const selector of details.matchedSelectors.sort() ) {
|
||||||
filter.raw = '##' + selector;
|
filter.raw = selector;
|
||||||
fctxt.toLogger();
|
fctxt.toLogger();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -186,6 +186,7 @@ const fromCosmeticFilter = function(details) {
|
|||||||
// Lowly generic cosmetic filters
|
// Lowly generic cosmetic filters
|
||||||
case 0: // simple id-based
|
case 0: // simple id-based
|
||||||
if (
|
if (
|
||||||
|
exception === false &&
|
||||||
fargs[1] === selector.slice(1) &&
|
fargs[1] === selector.slice(1) &&
|
||||||
selector.charAt(0) === '#'
|
selector.charAt(0) === '#'
|
||||||
) {
|
) {
|
||||||
@ -194,6 +195,7 @@ const fromCosmeticFilter = function(details) {
|
|||||||
break;
|
break;
|
||||||
case 2: // simple class-based
|
case 2: // simple class-based
|
||||||
if (
|
if (
|
||||||
|
exception === false &&
|
||||||
fargs[1] === selector.slice(1) &&
|
fargs[1] === selector.slice(1) &&
|
||||||
selector.charAt(0) === '.'
|
selector.charAt(0) === '.'
|
||||||
) {
|
) {
|
||||||
@ -202,7 +204,7 @@ const fromCosmeticFilter = function(details) {
|
|||||||
break;
|
break;
|
||||||
case 1: // complex id-based
|
case 1: // complex id-based
|
||||||
case 3: // complex class-based
|
case 3: // complex class-based
|
||||||
if ( fargs[2] === selector ) {
|
if ( exception === false && fargs[2] === selector ) {
|
||||||
found = prefix + selector;
|
found = prefix + selector;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -35,30 +35,34 @@ if (
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let reHasCSSCombinators = /[ >+~]/,
|
const reHasCSSCombinators = /[ >+~]/;
|
||||||
reHasPseudoClass = /:+(?:after|before)$/,
|
const reHasPseudoClass = /:+(?:after|before)$/;
|
||||||
sanitizedSelectors = new Map(),
|
const sanitizedSelectors = new Map();
|
||||||
simpleDeclarativeSet = new Set(),
|
const simpleDeclarativeSet = new Set();
|
||||||
simpleDeclarativeStr,
|
let simpleDeclarativeStr;
|
||||||
complexDeclarativeSet = new Set(),
|
const complexDeclarativeSet = new Set();
|
||||||
complexDeclarativeStr,
|
let complexDeclarativeStr;
|
||||||
proceduralDict = new Map(),
|
const proceduralDict = new Map();
|
||||||
nodesToProcess = new Set(),
|
const exceptionSet = new Set();
|
||||||
shouldProcessDeclarativeComplex = false,
|
let exceptionStr;
|
||||||
shouldProcessProcedural = false,
|
const nodesToProcess = new Set();
|
||||||
loggedSelectors = new Set();
|
let shouldProcessDeclarativeComplex = false;
|
||||||
|
let shouldProcessProcedural = false;
|
||||||
|
let shouldProcessExceptions = false;
|
||||||
|
const loggedSelectors = new Set();
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
let shouldProcess = function() {
|
const shouldProcess = function() {
|
||||||
return nodesToProcess.size !== 0 ||
|
return nodesToProcess.size !== 0 ||
|
||||||
shouldProcessDeclarativeComplex ||
|
shouldProcessDeclarativeComplex ||
|
||||||
shouldProcessProcedural;
|
shouldProcessProcedural ||
|
||||||
|
shouldProcessExceptions;
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
let processDeclarativeSimple = function(node, out) {
|
const processDeclarativeSimple = function(node, out) {
|
||||||
if ( simpleDeclarativeSet.size === 0 ) { return; }
|
if ( simpleDeclarativeSet.size === 0 ) { return; }
|
||||||
if ( simpleDeclarativeStr === undefined ) {
|
if ( simpleDeclarativeStr === undefined ) {
|
||||||
simpleDeclarativeStr = Array.from(simpleDeclarativeSet).join(',\n');
|
simpleDeclarativeStr = Array.from(simpleDeclarativeSet).join(',\n');
|
||||||
@ -69,14 +73,14 @@ let processDeclarativeSimple = function(node, out) {
|
|||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for ( let selector of simpleDeclarativeSet ) {
|
for ( const selector of simpleDeclarativeSet ) {
|
||||||
if (
|
if (
|
||||||
(node === document || node.matches(selector) === false) &&
|
(node === document || node.matches(selector) === false) &&
|
||||||
(node.querySelector(selector) === null)
|
(node.querySelector(selector) === null)
|
||||||
) {
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
out.push(sanitizedSelectors.get(selector) || selector);
|
out.push(`##${sanitizedSelectors.get(selector) || selector}`);
|
||||||
simpleDeclarativeSet.delete(selector);
|
simpleDeclarativeSet.delete(selector);
|
||||||
simpleDeclarativeStr = undefined;
|
simpleDeclarativeStr = undefined;
|
||||||
loggedSelectors.add(selector);
|
loggedSelectors.add(selector);
|
||||||
@ -86,15 +90,15 @@ let processDeclarativeSimple = function(node, out) {
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
let processDeclarativeComplex = function(out) {
|
const processDeclarativeComplex = function(out) {
|
||||||
if ( complexDeclarativeSet.size === 0 ) { return; }
|
if ( complexDeclarativeSet.size === 0 ) { return; }
|
||||||
if ( complexDeclarativeStr === undefined ) {
|
if ( complexDeclarativeStr === undefined ) {
|
||||||
complexDeclarativeStr = Array.from(complexDeclarativeSet).join(',\n');
|
complexDeclarativeStr = Array.from(complexDeclarativeSet).join(',\n');
|
||||||
}
|
}
|
||||||
if ( document.querySelector(complexDeclarativeStr) === null ) { return; }
|
if ( document.querySelector(complexDeclarativeStr) === null ) { return; }
|
||||||
for ( let selector of complexDeclarativeSet ) {
|
for ( const selector of complexDeclarativeSet ) {
|
||||||
if ( document.querySelector(selector) === null ) { continue; }
|
if ( document.querySelector(selector) === null ) { continue; }
|
||||||
out.push(sanitizedSelectors.get(selector) || selector);
|
out.push(`##${sanitizedSelectors.get(selector) || selector}`);
|
||||||
complexDeclarativeSet.delete(selector);
|
complexDeclarativeSet.delete(selector);
|
||||||
complexDeclarativeStr = undefined;
|
complexDeclarativeStr = undefined;
|
||||||
loggedSelectors.add(selector);
|
loggedSelectors.add(selector);
|
||||||
@ -104,11 +108,11 @@ let processDeclarativeComplex = function(out) {
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
let processProcedural = function(out) {
|
const processProcedural = function(out) {
|
||||||
if ( proceduralDict.size === 0 ) { return; }
|
if ( proceduralDict.size === 0 ) { return; }
|
||||||
for ( let entry of proceduralDict ) {
|
for ( const entry of proceduralDict ) {
|
||||||
if ( entry[1].test() === false ) { continue; }
|
if ( entry[1].test() === false ) { continue; }
|
||||||
out.push(entry[1].raw);
|
out.push(`##${entry[1].raw}`);
|
||||||
proceduralDict.delete(entry[0]);
|
proceduralDict.delete(entry[0]);
|
||||||
if ( proceduralDict.size === 0 ) { break; }
|
if ( proceduralDict.size === 0 ) { break; }
|
||||||
}
|
}
|
||||||
@ -116,16 +120,33 @@ let processProcedural = function(out) {
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
let processTimer = new vAPI.SafeAnimationFrame(() => {
|
const processExceptions = function(out) {
|
||||||
|
if ( exceptionSet.size === 0 ) { return; }
|
||||||
|
if ( exceptionStr === undefined ) {
|
||||||
|
exceptionStr = Array.from(exceptionSet).join(',\n');
|
||||||
|
}
|
||||||
|
if ( document.querySelector(exceptionStr) === null ) { return; }
|
||||||
|
for ( const selector of exceptionSet ) {
|
||||||
|
if ( document.querySelector(selector) === null ) { continue; }
|
||||||
|
out.push(`#@#${selector}`);
|
||||||
|
exceptionSet.delete(selector);
|
||||||
|
exceptionStr = undefined;
|
||||||
|
loggedSelectors.add(selector);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
const processTimer = new vAPI.SafeAnimationFrame(() => {
|
||||||
//console.time('dom logger/scanning for matches');
|
//console.time('dom logger/scanning for matches');
|
||||||
processTimer.clear();
|
processTimer.clear();
|
||||||
let toLog = [];
|
const toLog = [];
|
||||||
if ( nodesToProcess.size !== 0 && simpleDeclarativeSet.size !== 0 ) {
|
if ( nodesToProcess.size !== 0 && simpleDeclarativeSet.size !== 0 ) {
|
||||||
if ( nodesToProcess.size !== 1 && nodesToProcess.has(document) ) {
|
if ( nodesToProcess.size !== 1 && nodesToProcess.has(document) ) {
|
||||||
nodesToProcess.clear();
|
nodesToProcess.clear();
|
||||||
nodesToProcess.add(document);
|
nodesToProcess.add(document);
|
||||||
}
|
}
|
||||||
for ( let node of nodesToProcess ) {
|
for ( const node of nodesToProcess ) {
|
||||||
processDeclarativeSimple(node, toLog);
|
processDeclarativeSimple(node, toLog);
|
||||||
}
|
}
|
||||||
nodesToProcess.clear();
|
nodesToProcess.clear();
|
||||||
@ -138,6 +159,10 @@ let processTimer = new vAPI.SafeAnimationFrame(() => {
|
|||||||
processProcedural(toLog);
|
processProcedural(toLog);
|
||||||
shouldProcessProcedural = false;
|
shouldProcessProcedural = false;
|
||||||
}
|
}
|
||||||
|
if ( shouldProcessExceptions ) {
|
||||||
|
processExceptions(toLog);
|
||||||
|
shouldProcessExceptions = false;
|
||||||
|
}
|
||||||
if ( toLog.length === 0 ) { return; }
|
if ( toLog.length === 0 ) { return; }
|
||||||
vAPI.messaging.send(
|
vAPI.messaging.send(
|
||||||
'scriptlets',
|
'scriptlets',
|
||||||
@ -145,7 +170,7 @@ let processTimer = new vAPI.SafeAnimationFrame(() => {
|
|||||||
what: 'logCosmeticFilteringData',
|
what: 'logCosmeticFilteringData',
|
||||||
frameURL: window.location.href,
|
frameURL: window.location.href,
|
||||||
frameHostname: window.location.hostname,
|
frameHostname: window.location.hostname,
|
||||||
matchedSelectors: toLog
|
matchedSelectors: toLog,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
//console.timeEnd('dom logger/scanning for matches');
|
//console.timeEnd('dom logger/scanning for matches');
|
||||||
@ -153,10 +178,10 @@ let processTimer = new vAPI.SafeAnimationFrame(() => {
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
let attributeObserver = new MutationObserver(mutations => {
|
const attributeObserver = new MutationObserver(mutations => {
|
||||||
if ( simpleDeclarativeSet.size !== 0 ) {
|
if ( simpleDeclarativeSet.size !== 0 ) {
|
||||||
for ( let mutation of mutations ) {
|
for ( const mutation of mutations ) {
|
||||||
let node = mutation.target;
|
const node = mutation.target;
|
||||||
if ( node.nodeType !== 1 ) { continue; }
|
if ( node.nodeType !== 1 ) { continue; }
|
||||||
nodesToProcess.add(node);
|
nodesToProcess.add(node);
|
||||||
}
|
}
|
||||||
@ -174,20 +199,20 @@ let attributeObserver = new MutationObserver(mutations => {
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
let handlers = {
|
const handlers = {
|
||||||
onFiltersetChanged: function(changes) {
|
onFiltersetChanged: function(changes) {
|
||||||
//console.time('dom logger/filterset changed');
|
//console.time('dom logger/filterset changed');
|
||||||
let simpleSizeBefore = simpleDeclarativeSet.size,
|
const simpleSizeBefore = simpleDeclarativeSet.size,
|
||||||
complexSizeBefore = complexDeclarativeSet.size,
|
complexSizeBefore = complexDeclarativeSet.size,
|
||||||
logNow = [];
|
logNow = [];
|
||||||
for ( let entry of (changes.declarative || []) ) {
|
for ( const entry of (changes.declarative || []) ) {
|
||||||
for ( let selector of entry[0].split(',\n') ) {
|
for ( let selector of entry[0].split(',\n') ) {
|
||||||
if ( entry[1] !== 'display:none!important;' ) {
|
if ( entry[1] !== 'display:none!important;' ) {
|
||||||
logNow.push(selector + ':style(' + entry[1] + ')');
|
logNow.push(`##${selector}:style(${entry[1]})`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( reHasPseudoClass.test(selector) ) {
|
if ( reHasPseudoClass.test(selector) ) {
|
||||||
let sanitized = selector.replace(reHasPseudoClass, '');
|
const sanitized = selector.replace(reHasPseudoClass, '');
|
||||||
sanitizedSelectors.set(sanitized, selector);
|
sanitizedSelectors.set(sanitized, selector);
|
||||||
selector = sanitized;
|
selector = sanitized;
|
||||||
}
|
}
|
||||||
@ -222,11 +247,19 @@ let handlers = {
|
|||||||
Array.isArray(changes.procedural) &&
|
Array.isArray(changes.procedural) &&
|
||||||
changes.procedural.length !== 0
|
changes.procedural.length !== 0
|
||||||
) {
|
) {
|
||||||
for ( let selector of changes.procedural ) {
|
for ( const selector of changes.procedural ) {
|
||||||
proceduralDict.set(selector.raw, selector);
|
proceduralDict.set(selector.raw, selector);
|
||||||
}
|
}
|
||||||
shouldProcessProcedural = true;
|
shouldProcessProcedural = true;
|
||||||
}
|
}
|
||||||
|
if ( Array.isArray(changes.exceptions) ) {
|
||||||
|
for ( const selector of changes.exceptions ) {
|
||||||
|
if ( loggedSelectors.has(selector) ) { continue; }
|
||||||
|
exceptionSet.add(selector);
|
||||||
|
}
|
||||||
|
exceptionStr = undefined;
|
||||||
|
shouldProcessExceptions = true;
|
||||||
|
}
|
||||||
if ( shouldProcess() ) {
|
if ( shouldProcess() ) {
|
||||||
processTimer.start(1);
|
processTimer.start(1);
|
||||||
}
|
}
|
||||||
@ -246,7 +279,7 @@ let handlers = {
|
|||||||
// This is to guard against runaway job queue. I suspect this could
|
// This is to guard against runaway job queue. I suspect this could
|
||||||
// occur on slower devices.
|
// occur on slower devices.
|
||||||
if ( simpleDeclarativeSet.size !== 0 ) {
|
if ( simpleDeclarativeSet.size !== 0 ) {
|
||||||
for ( let node of addedNodes ) {
|
for ( const node of addedNodes ) {
|
||||||
if ( node.parentNode === null ) { continue; }
|
if ( node.parentNode === null ) { continue; }
|
||||||
nodesToProcess.add(node);
|
nodesToProcess.add(node);
|
||||||
}
|
}
|
||||||
@ -257,6 +290,9 @@ let handlers = {
|
|||||||
if ( proceduralDict.size !== 0 ) {
|
if ( proceduralDict.size !== 0 ) {
|
||||||
shouldProcessProcedural = true;
|
shouldProcessProcedural = true;
|
||||||
}
|
}
|
||||||
|
if ( exceptionSet.size !== 0 ) {
|
||||||
|
shouldProcessExceptions = true;
|
||||||
|
}
|
||||||
if ( shouldProcess() ) {
|
if ( shouldProcess() ) {
|
||||||
processTimer.start(100);
|
processTimer.start(100);
|
||||||
}
|
}
|
||||||
@ -265,7 +301,7 @@ let handlers = {
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
let onMessage = function(msg) {
|
const onMessage = function(msg) {
|
||||||
if ( msg.what === 'loggerDisabled' ) {
|
if ( msg.what === 'loggerDisabled' ) {
|
||||||
processTimer.clear();
|
processTimer.clear();
|
||||||
attributeObserver.disconnect();
|
attributeObserver.disconnect();
|
||||||
|
Loading…
Reference in New Issue
Block a user