this fixes #41

This commit is contained in:
gorhill 2014-07-04 16:47:34 -04:00
parent b5e323e91e
commit d043f54a32
2 changed files with 105 additions and 13 deletions

View File

@ -251,7 +251,11 @@ var FilterContainer = function() {
this.processedCount = 0; this.processedCount = 0;
this.filters = {}; this.filters = {};
this.hideUnfiltered = []; this.hideUnfiltered = [];
this.hideLowGenerics = {};
this.hideHighGenerics = [];
this.donthideUnfiltered = []; this.donthideUnfiltered = [];
this.donthideLowGenerics = {};
this.donthideHighGenerics = [];
this.rejected = []; this.rejected = [];
}; };
@ -265,7 +269,11 @@ FilterContainer.prototype.reset = function() {
this.processedCount = 0; this.processedCount = 0;
this.filters = {}; this.filters = {};
this.hideUnfiltered = []; this.hideUnfiltered = [];
this.hideLowGenerics = {};
this.hideHighGenerics = [];
this.donthideUnfiltered = []; this.donthideUnfiltered = [];
this.donthideLowGenerics = {};
this.donthideHighGenerics = [];
this.rejected = []; this.rejected = [];
}; };
@ -316,7 +324,29 @@ FilterContainer.prototype.add = function(s) {
/******************************************************************************/ /******************************************************************************/
FilterContainer.prototype.chunkify = function(selectors) { FilterContainer.prototype.freezeGenerics = function(what) {
var selectors = this[what + 'Unfiltered'];
//console.log('%d highly generic selectors:\n', selectors.length, selectors.sort().join('\n'));
// ["title"] and ["alt"] will be sorted out manually, these are the most
// common generic selectors, aka "low generics". The rest will be put in
// the high genericity bin.
var lowGenerics = {};
var lowGenericCount = 0;
var re = /^(([a-z]*)\[(alt|title)="([^"]+)"\])$/;
var i = selectors.length;
var selector, matches;
while ( i-- ) {
selector = selectors[i];
matches = re.exec(selector);
if ( !matches ) {
continue;
}
lowGenerics[matches[1]] = true;
lowGenericCount++;
selectors.splice(i, 1);
}
// Chunksize is a compromise between number of selectors per chunk (the // Chunksize is a compromise between number of selectors per chunk (the
// number of selectors querySelector() will have to deal with), and the // number of selectors querySelector() will have to deal with), and the
// number of chunks (the number of times querySelector() will have to // number of chunks (the number of times querySelector() will have to
@ -334,14 +364,18 @@ FilterContainer.prototype.chunkify = function(selectors) {
} }
chunkified.push(chunk.join(',')); chunkified.push(chunk.join(','));
} }
return chunkified;
this[what + 'LowGenerics'] = lowGenerics;
this[what + 'LowGenericCount'] = lowGenericCount;
this[what + 'HighGenerics'] = chunkified;
this[what + 'Unfiltered'] = [];
}; };
/******************************************************************************/ /******************************************************************************/
FilterContainer.prototype.freeze = function() { FilterContainer.prototype.freeze = function() {
this.hideUnfiltered = this.chunkify(this.hideUnfiltered); this.freezeGenerics('hide');
this.donthideUnfiltered = this.chunkify(this.donthideUnfiltered); this.freezeGenerics('donthide');
this.filterParser.reset(); this.filterParser.reset();
@ -582,8 +616,12 @@ FilterContainer.prototype.retrieveGenericSelectors = function(tabHostname, reque
var r = { var r = {
hide: [], hide: [],
donthide: [], donthide: [],
hideUnfiltered: this.hideUnfiltered, hideLowGenerics: this.hideLowGenerics,
donthideUnfiltered: this.donthideUnfiltered hideLowGenericCount: this.hideLowGenericCount,
hideHighGenerics: this.hideHighGenerics,
donthideLowGenerics: this.donthideLowGenerics,
donthideLowGenericCount: this.donthideLowGenericCount,
donthideHighGenerics: this.donthideHighGenerics
}; };
var hash, bucket; var hash, bucket;

View File

@ -177,7 +177,8 @@ var cosmeticFiltering = (function() {
return; return;
} }
var styleText = []; var styleText = [];
filterUnfiltered(selectors.hideUnfiltered, selectors.hide); filterLowGenerics(selectors, 'hide');
filterHighGenerics(selectors, 'hide');
reduce(selectors.hide, injectedSelectors); reduce(selectors.hide, injectedSelectors);
if ( selectors.hide.length ) { if ( selectors.hide.length ) {
var hideStyleText = '{{hideSelectors}} {display:none !important;}' var hideStyleText = '{{hideSelectors}} {display:none !important;}'
@ -186,7 +187,8 @@ var cosmeticFiltering = (function() {
applyCSS(selectors.hide, 'display', 'none'); applyCSS(selectors.hide, 'display', 'none');
//console.debug('µBlock> generic cosmetic filters: injecting %d CSS rules:', selectors.hide.length, hideStyleText); //console.debug('µBlock> generic cosmetic filters: injecting %d CSS rules:', selectors.hide.length, hideStyleText);
} }
filterUnfiltered(selectors.donthideUnfiltered, selectors.donthide); filterLowGenerics(selectors, 'donthide');
filterHighGenerics(selectors, 'donthide');
reduce(selectors.donthide, injectedSelectors); reduce(selectors.donthide, injectedSelectors);
if ( selectors.donthide.length ) { if ( selectors.donthide.length ) {
var dontHideStyleText = '{{donthideSelectors}} {display:initial !important;}' var dontHideStyleText = '{{donthideSelectors}} {display:initial !important;}'
@ -216,16 +218,68 @@ var cosmeticFiltering = (function() {
} }
}; };
var filterUnfiltered = function(inSelectors, outSelectors) { var filterTitleGeneric = function(generics, root, out) {
var i = inSelectors.length; if ( !root.title.length ) {
return;
}
var selector = '[title="' + root.title + '"]';
if ( generics[selector] && !injectedSelectors[selector] ) {
out.push(selector);
}
selector = root.tagName + selector;
if ( generics[selector] && !injectedSelectors[selector] ) {
out.push(selector);
}
};
var filterAltGeneric = function(generics, root, out) {
var alt = root.getAttribute('alt');
if ( !alt || !alt.length ) {
return;
}
var selector = '[alt="' + root.title + '"]';
if ( generics[selector] && !injectedSelectors[selector] ) {
out.push(selector);
}
selector = root.tagName + selector;
if ( generics[selector] && !injectedSelectors[selector] ) {
out.push(selector);
}
};
var filterLowGenerics = function(selectors, what) {
if ( selectors[what + 'LowGenericCount'] === 0 ) {
return;
}
var out = selectors[what];
var generics = selectors[what + 'LowGenerics'];
var nodeList, iNode;
// Low generics: ["title"]
nodeList = document.querySelectorAll('[title]');
iNode = nodeList.length;
while ( iNode-- ) {
filterTitleGeneric(generics, nodeList[iNode], out);
}
// Low generics: ["alt"]
nodeList = document.querySelectorAll('[alt]');
iNode = nodeList.length;
while ( iNode-- ) {
filterAltGeneric(generics, nodeList[iNode], out);
}
};
var filterHighGenerics = function(selectors, what) {
var out = selectors[what];
var generics = selectors[what + 'HighGenerics'];
var iGeneric = generics.length;
var selector; var selector;
while ( i-- ) { while ( iGeneric-- ) {
selector = inSelectors[i]; selector = generics[iGeneric];
if ( injectedSelectors[selector] ) { if ( injectedSelectors[selector] ) {
continue; continue;
} }
if ( document.querySelector(selector) !== null ) { if ( document.querySelector(selector) !== null ) {
outSelectors.push(selector); out.push(selector);
} }
} }
}; };