cosmetic filtering: stop surveying and/or filtering after too many consecutive misses

This commit is contained in:
gorhill 2016-07-12 13:29:30 -04:00
parent 58beeaacc1
commit 9e7fbb857b
2 changed files with 67 additions and 25 deletions

View File

@ -121,6 +121,7 @@ var reParserEx = /^(.*?(:has\(.+?\)|:xpath\(.+?\))?)(:style\(.+?\))?$/;
var allExceptions = Object.create(null); var allExceptions = Object.create(null);
var allSelectors = Object.create(null); var allSelectors = Object.create(null);
var stagedNodes = [];
// Complex selectors, due to their nature may need to be "de-committed". A // Complex selectors, due to their nature may need to be "de-committed". A
// Set() is used to implement this functionality. // Set() is used to implement this functionality.
@ -143,6 +144,7 @@ var cosmeticFiltersActivated = function() {
/******************************************************************************/ /******************************************************************************/
var domFilterer = { var domFilterer = {
commitMissCount: 0,
disabledId: vAPI.randomToken(), disabledId: vAPI.randomToken(),
enabled: true, enabled: true,
hiddenId: vAPI.randomToken(), hiddenId: vAPI.randomToken(),
@ -202,7 +204,6 @@ var domFilterer = {
return this; return this;
} }
if ( sel1.lastIndexOf(':xpath',0) === 0 ) { if ( sel1.lastIndexOf(':xpath',0) === 0 ) {
if ( sel0 !== sel1 ) { return this; }
this.jobQueue.push({ t: 'xpath-hide', raw: s, _0: sel1.slice(7, -1) }); this.jobQueue.push({ t: 'xpath-hide', raw: s, _0: sel1.slice(7, -1) });
return this; return this;
} }
@ -267,14 +268,9 @@ var domFilterer = {
} }
}, },
commit: function(stagedNodes) { commit_: function() {
var beforeHiddenNodeCount = this.hiddenNodeCount; var beforeHiddenNodeCount = this.hiddenNodeCount,
styleText = '', i, n;
if ( stagedNodes === undefined ) {
stagedNodes = [ document.documentElement ];
}
var styleText = '', i, n;
// Stock job 0 = css rules/hide // Stock job 0 = css rules/hide
if ( this.job0._0.length ) { if ( this.job0._0.length ) {
@ -305,6 +301,7 @@ var domFilterer = {
this.runSimpleSelectorJob(this.job2, stagedNodes[i], hideNode); this.runSimpleSelectorJob(this.job2, stagedNodes[i], hideNode);
} }
} }
stagedNodes = [];
// Complex selectors: non-incremental. // Complex selectors: non-incremental.
complexSelectorsOldResultSet = complexSelectorsCurrentResultSet; complexSelectorsOldResultSet = complexSelectorsCurrentResultSet;
@ -323,6 +320,13 @@ var domFilterer = {
this.runJob(this.jobQueue[i], complexHideNode); this.runJob(this.jobQueue[i], complexHideNode);
} }
var commitHit = this.hiddenNodeCount !== beforeHiddenNodeCount;
if ( commitHit ) {
this.commitMissCount = 0;
} else {
this.commitMissCount += 1;
}
// Un-hide nodes previously hidden. // Un-hide nodes previously hidden.
i = complexSelectorsOldResultSet.size; i = complexSelectorsOldResultSet.size;
if ( i !== 0 ) { if ( i !== 0 ) {
@ -334,10 +338,7 @@ var domFilterer = {
} }
// If DOM nodes have been affected, lazily notify core process. // If DOM nodes have been affected, lazily notify core process.
if ( if ( commitHit && cosmeticFiltersActivatedTimer === null ) {
this.hiddenNodeCount !== beforeHiddenNodeCount &&
cosmeticFiltersActivatedTimer === null
) {
cosmeticFiltersActivatedTimer = vAPI.setTimeout( cosmeticFiltersActivatedTimer = vAPI.setTimeout(
cosmeticFiltersActivated, cosmeticFiltersActivated,
503 503
@ -345,20 +346,35 @@ var domFilterer = {
} }
}, },
commit: function(nodes) {
if ( stagedNodes.length === 0 ) {
window.requestAnimationFrame(this.commit_.bind(this));
}
if ( nodes === undefined ) {
stagedNodes = [ document.documentElement ];
} else if ( stagedNodes[0] !== document.documentElement ) {
stagedNodes = stagedNodes.concat(nodes);
}
},
hideNode: function(node) { hideNode: function(node) {
if ( node[this.hiddenId] ) { if ( node[this.hiddenId] !== undefined ) {
return; return;
} }
node.setAttribute(this.hiddenId, ''); node.setAttribute(this.hiddenId, '');
node[this.hiddenId] = true;
this.hiddenNodeCount += 1; this.hiddenNodeCount += 1;
node.hidden = true; node.hidden = true;
// TODO: conditionally make use of `display: none !important;` style. node[this.hiddenId] = null;
// - is node.style.display !== ''? var style = window.getComputedStyle(node),
// - if yes, is node.hasAttribute('style') true? display = style.getPropertyValue('display');
// - if yes: node.setAttribute('style', node.getAttribute('style') + if ( display !== '' && display !== 'none' ) {
// ';display: none !important' var styleAttr = node.getAttribute('style') || '';
// - remember this was done node[this.hiddenId] = node.hasAttribute('style') && styleAttr;
if ( styleAttr !== '' ) {
styleAttr += '; ';
}
node.setAttribute('style', styleAttr + 'display: none !important;');
}
if ( shadowId === undefined ) { if ( shadowId === undefined ) {
return; return;
} }
@ -452,6 +468,12 @@ var domFilterer = {
showNode: function(node) { showNode: function(node) {
node.hidden = false; node.hidden = false;
var styleAttr = node[this.hiddenId];
if ( styleAttr === false ) {
node.removeAttribute('style');
} else if ( typeof styleAttr === 'string' ) {
node.setAttribute('style', node[this.hiddenId]);
}
var shadow = node.shadowRoot; var shadow = node.shadowRoot;
if ( shadow && shadow[shadowId] ) { if ( shadow && shadow[shadowId] ) {
if ( shadow.firstElementChild !== null ) { if ( shadow.firstElementChild !== null ) {
@ -470,7 +492,7 @@ var domFilterer = {
}, },
unhideNode: function(node) { unhideNode: function(node) {
if ( node[this.hiddenId] ) { if ( node[this.hiddenId] !== undefined ) {
this.hiddenNodeCount--; this.hiddenNodeCount--;
} }
node.removeAttribute(this.hiddenId); node.removeAttribute(this.hiddenId);
@ -487,6 +509,12 @@ var domFilterer = {
unshowNode: function(node) { unshowNode: function(node) {
node.hidden = true; node.hidden = true;
var styleAttr = node[this.hiddenId];
if ( styleAttr === false ) {
node.setAttribute('style', 'display: none !important;');
} else if ( typeof styleAttr === 'string' ) {
node.setAttribute('style', node[this.hiddenId] + '; display: none !important;');
}
var shadow = node.shadowRoot; var shadow = node.shadowRoot;
if ( shadow && shadow[shadowId] && shadow.firstElementChild !== null ) { if ( shadow && shadow[shadowId] && shadow.firstElementChild !== null ) {
shadow.removeChild(shadow.firstElementChild); shadow.removeChild(shadow.firstElementChild);
@ -921,9 +949,10 @@ skip-survey=false: survey-phase-1 => survey-phase-2 => survey-phase-3 => commit
return; return;
} }
var queriedSelectors = Object.create(null), var cosmeticSurveyingMissCount = 0,
highGenerics = null, highGenerics = null,
lowGenericSelectors = []; lowGenericSelectors = [],
queriedSelectors = Object.create(null);
// Handle main process' response. // Handle main process' response.
@ -974,6 +1003,16 @@ skip-survey=false: survey-phase-1 => survey-phase-2 => survey-phase-3 => commit
); );
} }
// Shutdown surveyor if too many consecutive empty resultsets.
if ( domFilterer.job0._0.length === 0 ) {
cosmeticSurveyingMissCount += 1;
if ( cosmeticSurveyingMissCount > 255 ) {
domSurveyor = undefined;
}
} else {
cosmeticSurveyingMissCount = 0;
}
domFilterer.commit(contextNodes); domFilterer.commit(contextNodes);
contextNodes = []; contextNodes = [];
@ -1280,6 +1319,9 @@ skip-survey=false: survey-phase-1 => survey-phase-2 => survey-phase-3 => commit
} else { } else {
domFilterer.commit(contextNodes); domFilterer.commit(contextNodes);
contextNodes = []; contextNodes = [];
if ( domFilterer.commitMissCount > 255 ) {
domLayoutObserver.disconnect();
}
} }
} }

View File

@ -49,7 +49,7 @@ var isBadRegex = function(s) {
return false; return false;
}; };
var cosmeticSurveyingMissCountMax = parseInt(vAPI.localStorage.getItem('cosmeticSurveyingMissCountMax'), 10) || 10; var cosmeticSurveyingMissCountMax = parseInt(vAPI.localStorage.getItem('cosmeticSurveyingMissCountMax'), 10) || 15;
/******************************************************************************/ /******************************************************************************/
/* /*