performance improvement re. high-high generics

This commit is contained in:
gorhill 2014-09-16 19:16:18 -04:00
parent 19c6155787
commit af95ef5c1a
2 changed files with 81 additions and 26 deletions

View file

@ -247,30 +247,39 @@ var uBlockMessaging = (function(name){
processHighMediumGenerics(highGenerics.hideMedium, hideSelectors);
}
if ( highGenerics.hideHighCount ) {
processHighHighGenerics(highGenerics.hideHigh, hideSelectors);
processHighHighGenericsAsync();
}
}
if ( hideSelectors.length ) {
hideElements(hideSelectors);
var style = document.createElement('style');
style.setAttribute('class', 'ublock-postload-1ae7a5f130fc79b4fdb8a4272d9426b5');
// The linefeed before the style block is very important: do no remove!
style.appendChild(document.createTextNode(hideSelectors.join(',\n') + '\n{display:none !important;}'));
var parent = document.body || document.documentElement;
if ( parent ) {
parent.appendChild(style);
}
messaging.tell({
what: 'injectedSelectors',
type: 'cosmetic',
hostname: window.location.hostname,
selectors: hideSelectors
});
//console.debug('µBlock> generic cosmetic filters: injecting %d CSS rules:', hideSelectors.length, text);
addStyleTag(hideSelectors);
}
contextNodes.length = 0;
};
// Ensure elements matching a set of selectors are visually removed
// from the page, by:
// - Modifying the style property on the elements themselves
// - Injecting a style tag
var addStyleTag = function(selectors) {
hideElements(selectors);
var style = document.createElement('style');
style.setAttribute('class', 'ublock-postload-1ae7a5f130fc79b4fdb8a4272d9426b5');
// The linefeed before the style block is very important: do no remove!
style.appendChild(document.createTextNode(selectors.join(',\n') + '\n{display:none !important;}'));
var parent = document.body || document.documentElement;
if ( parent ) {
parent.appendChild(style);
}
messaging.tell({
what: 'injectedSelectors',
type: 'cosmetic',
hostname: window.location.hostname,
selectors: selectors
});
//console.debug('µBlock> generic cosmetic filters: injecting %d CSS rules:', selectors.length, text);
};
var hideElements = function(selectors) {
// https://github.com/gorhill/uBlock/issues/207
// Do not call querySelectorAll() using invalid CSS selectors
@ -289,6 +298,8 @@ var uBlockMessaging = (function(name){
}
};
// Extract and return the staged nodes which (may) match the selectors.
var selectNodes = function(selector) {
var targetNodes = [];
var i = contextNodes.length;
@ -309,6 +320,10 @@ var uBlockMessaging = (function(name){
return targetNodes;
};
// Low generics:
// - [id]
// - [class]
var processLowGenerics = function(generics, out) {
var i = generics.length;
var selector;
@ -322,6 +337,10 @@ var uBlockMessaging = (function(name){
}
};
// High-low generics:
// - [alt="..."]
// - [title="..."]
var processHighLowGenerics = function(generics, out) {
var attrs = ['title', 'alt'];
var attr, attrValue, nodeList, iNode, node;
@ -351,6 +370,9 @@ var uBlockMessaging = (function(name){
}
};
// High-medium generics:
// - [href^="http"]
var processHighMediumGenerics = function(generics, out) {
var nodeList = selectNodes('a[href^="http"]');
var iNode = nodeList.length;
@ -376,22 +398,45 @@ var uBlockMessaging = (function(name){
}
};
var processHighHighGenerics = function(generics, out) {
// High-high generics are *very costly* to process, so we will coalesce
// requests to process high-high generics into as few requests as possible.
// The gain is *significant* on bloated pages.
var processHighHighGenericsTimer = null;
var processHighHighGenerics = function() {
processHighHighGenericsTimer = null;
if ( injectedSelectors['{{highHighGenerics}}'] !== undefined ) { return; }
if ( document.querySelector(generics) === null ) { return; }
if ( document.querySelector(highGenerics.hideHigh) === null ) { return; }
injectedSelectors['{{highHighGenerics}}'] = true;
var selectors = generics.split(',\n');
var iSelector = selectors.length;
// We need to filter out possible exception cosmetic filters from
// high-high generics selectors.
var selectors = highGenerics.hideHigh.split(',\n');
var i = selectors.length;
var selector;
while ( iSelector-- ) {
selector = selectors[iSelector];
if ( injectedSelectors[selector] === undefined ) {
while ( i-- ) {
selector = selectors[i];
if ( injectedSelectors.hasOwnProperty(selector) ) {
selectors.splice(i, 1);
} else {
injectedSelectors[selector] = true;
out.push(selector);
}
}
if ( selectors.length !== 0 ) {
addStyleTag(selectors);
}
};
var processHighHighGenericsAsync = function() {
if ( processHighHighGenericsTimer !== null ) {
clearTimeout(processHighHighGenericsTimer);
}
processHighHighGenericsTimer = setTimeout(processHighHighGenerics, 300);
};
// Extract all ids: these will be passed to the cosmetic filtering
// engine, and in return we will obtain only the relevant CSS selectors.
var idsFromNodeList = function(nodes) {
if ( !nodes || !nodes.length ) {
return;
@ -418,6 +463,9 @@ var uBlockMessaging = (function(name){
}
};
// Extract all classes: these will be passed to the cosmetic filtering
// engine, and in return we will obtain only the relevant CSS selectors.
var classesFromNodeList = function(nodes) {
if ( !nodes || !nodes.length ) {
return;
@ -460,8 +508,14 @@ var uBlockMessaging = (function(name){
}
};
// Start cosmetic filtering.
domLoaded();
// Below this point is the code which takes care to observe changes in
// the page and to add if needed relevant CSS rules as a result of the
// changes.
// Observe changes in the DOM only if...
// - there is a document.body
// - there is at least one `script` tag

View file

@ -385,9 +385,10 @@ PageStore.prototype.getNetFilteringSwitch = function() {
PageStore.prototype.filterRequest = function(context, requestType, requestURL) {
var result = this.netFilteringCache.lookup(requestURL);
if ( result !== undefined ) {
//console.debug(' cache HIT: PageStore.filterRequest("%s")', requestURL);
return result.slice(result.indexOf('\t') + 1);
}
//console.debug('µBlock> PageStore.filterRequest(): "%s" not in cache', requestURL);
//console.debug('cache MISS: PageStore.filterRequest("%s")', requestURL);
result = µb.netFilteringEngine.matchString(context, requestURL, requestType);
if ( collapsibleRequestTypes.indexOf(requestType) !== -1 || µb.userSettings.logRequests ) {
this.netFilteringCache.add(requestURL, requestType + '\t' + result);