mirror of
https://github.com/gorhill/uBlock.git
synced 2024-11-07 03:12:33 +01:00
new content script code: perf work re. high-high generics
Now splitting high-high generics in two subgroups: one group for simple selectors, another group for complex selectors. Turns out the great majority of high-high generics are simple selectors, and simple selectors can be applied incrementally with DOM changes, as opposed to complex selectors. This brings in a significant perf. improvement in the processing of high-high generics (previously, all high-high generic selectors were processed as one big complex selector).
This commit is contained in:
parent
b65699aef2
commit
e99d993a4c
@ -1,7 +1,7 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
uBlock - a browser extension to block requests.
|
uBlock Origin - a browser extension to block requests.
|
||||||
Copyright (C) 2014-2015 Raymond Hill
|
Copyright (C) 2014-2016 Raymond Hill
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -19,7 +19,6 @@
|
|||||||
Home: https://github.com/gorhill/uBlock
|
Home: https://github.com/gorhill/uBlock
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global vAPI */
|
|
||||||
/* exported µBlock */
|
/* exported µBlock */
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
@ -92,8 +91,8 @@ return {
|
|||||||
|
|
||||||
// read-only
|
// read-only
|
||||||
systemSettings: {
|
systemSettings: {
|
||||||
compiledMagic: 'nytangedtvcz',
|
compiledMagic: 'splsmclwnvoj',
|
||||||
selfieMagic: 'emzolxctioww'
|
selfieMagic: 'splsmclwnvoj'
|
||||||
},
|
},
|
||||||
|
|
||||||
restoreBackupSettings: {
|
restoreBackupSettings: {
|
||||||
|
@ -38,6 +38,18 @@ if ( typeof vAPI !== 'object' || vAPI.contentscriptInjected ) {
|
|||||||
|
|
||||||
vAPI.contentscriptInjected = true;
|
vAPI.contentscriptInjected = true;
|
||||||
|
|
||||||
|
vAPI.matchesProp = (function() {
|
||||||
|
var docElem = document.documentElement;
|
||||||
|
if ( typeof docElem.matches !== 'function' ) {
|
||||||
|
if ( typeof docElem.mozMatchesSelector === 'function' ) {
|
||||||
|
return 'mozMatchesSelector';
|
||||||
|
} else if ( typeof docElem.webkitMatchesSelector === 'function' ) {
|
||||||
|
return 'webkitMatchesSelector';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 'matches';
|
||||||
|
})();
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@ -53,7 +65,7 @@ vAPI.domFilterer = {
|
|||||||
enabled: true,
|
enabled: true,
|
||||||
hiddenId: String.fromCharCode(Date.now() % 26 + 97) + Math.floor(Math.random() * 982451653 + 982451653).toString(36),
|
hiddenId: String.fromCharCode(Date.now() % 26 + 97) + Math.floor(Math.random() * 982451653 + 982451653).toString(36),
|
||||||
hiddenNodeCount: 0,
|
hiddenNodeCount: 0,
|
||||||
matchesProp: 'matches',
|
matchesProp: vAPI.matchesProp,
|
||||||
newDeclarativeSelectors: [],
|
newDeclarativeSelectors: [],
|
||||||
shadowId: String.fromCharCode(Date.now() % 26 + 97) + Math.floor(Math.random() * 982451653 + 982451653).toString(36),
|
shadowId: String.fromCharCode(Date.now() % 26 + 97) + Math.floor(Math.random() * 982451653 + 982451653).toString(36),
|
||||||
styleTags: [],
|
styleTags: [],
|
||||||
@ -410,14 +422,6 @@ vAPI.domFilterer = {
|
|||||||
var df = vAPI.domFilterer;
|
var df = vAPI.domFilterer;
|
||||||
df.cssNotHiddenId = ':not([' + df.hiddenId + '])';
|
df.cssNotHiddenId = ':not([' + df.hiddenId + '])';
|
||||||
df.xpathNotHiddenId = '[not(@' + df.hiddenId + ')]';
|
df.xpathNotHiddenId = '[not(@' + df.hiddenId + ')]';
|
||||||
var docElem = document.documentElement;
|
|
||||||
if ( typeof docElem.matches !== 'function' ) {
|
|
||||||
if ( typeof docElem.mozMatchesSelector === 'function' ) {
|
|
||||||
df.matchesProp = 'mozMatchesSelector';
|
|
||||||
} else if ( typeof docElem.webkitMatchesSelector === 'function' ) {
|
|
||||||
df.matchesProp = 'webkitMatchesSelector';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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. For browser with no
|
// Set() is used to implement this functionality. For browser with no
|
||||||
@ -835,12 +839,11 @@ if ( !vAPI.contentscriptInjected ) {
|
|||||||
domFilterer.checkStyleTags(false);
|
domFilterer.checkStyleTags(false);
|
||||||
domFilterer.commit();
|
domFilterer.commit();
|
||||||
|
|
||||||
var contextNodes = [ document.documentElement ];
|
var contextNodes = [ document.documentElement ],
|
||||||
var messaging = vAPI.messaging;
|
messaging = vAPI.messaging,
|
||||||
var highGenerics = null;
|
highGenerics = null,
|
||||||
var highHighGenericsInjected = false;
|
lowGenericSelectors = [],
|
||||||
var lowGenericSelectors = [];
|
queriedSelectors = Object.create(null);
|
||||||
var queriedSelectors = Object.create(null);
|
|
||||||
|
|
||||||
var responseHandler = function(response) {
|
var responseHandler = function(response) {
|
||||||
// https://github.com/gorhill/uMatrix/issues/144
|
// https://github.com/gorhill/uMatrix/issues/144
|
||||||
@ -859,6 +862,7 @@ if ( !vAPI.contentscriptInjected ) {
|
|||||||
highGenerics = result.highGenerics;
|
highGenerics = result.highGenerics;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( highGenerics ) {
|
if ( highGenerics ) {
|
||||||
if ( highGenerics.hideLowCount ) {
|
if ( highGenerics.hideLowCount ) {
|
||||||
processHighLowGenerics(highGenerics.hideLow);
|
processHighLowGenerics(highGenerics.hideLow);
|
||||||
@ -866,10 +870,11 @@ if ( !vAPI.contentscriptInjected ) {
|
|||||||
if ( highGenerics.hideMediumCount ) {
|
if ( highGenerics.hideMediumCount ) {
|
||||||
processHighMediumGenerics(highGenerics.hideMedium);
|
processHighMediumGenerics(highGenerics.hideMedium);
|
||||||
}
|
}
|
||||||
if ( highGenerics.hideHighCount ) {
|
if ( highGenerics.hideHighSimpleCount || highGenerics.hideHighComplexCount ) {
|
||||||
processHighHighGenericsAsync();
|
processHighHighGenerics();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
domFilterer.commit(contextNodes);
|
domFilterer.commit(contextNodes);
|
||||||
contextNodes = [];
|
contextNodes = [];
|
||||||
};
|
};
|
||||||
@ -886,10 +891,10 @@ if ( !vAPI.contentscriptInjected ) {
|
|||||||
},
|
},
|
||||||
responseHandler
|
responseHandler
|
||||||
);
|
);
|
||||||
|
lowGenericSelectors = [];
|
||||||
} else {
|
} else {
|
||||||
responseHandler(null);
|
responseHandler(null);
|
||||||
}
|
}
|
||||||
lowGenericSelectors = [];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Extract and return the staged nodes which (may) match the selectors.
|
// Extract and return the staged nodes which (may) match the selectors.
|
||||||
@ -1009,42 +1014,50 @@ if ( !vAPI.contentscriptInjected ) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// High-high generics are very costly to process, so we will coalesce
|
var highHighSimpleGenericsCost = 0,
|
||||||
// requests to process high-high generics into as few requests as possible.
|
highHighSimpleGenericsInjected = false,
|
||||||
// The gain is significant on bloated pages.
|
highHighComplexGenericsCost = 0,
|
||||||
|
highHighComplexGenericsInjected = false;
|
||||||
var processHighHighGenericsMisses = 8;
|
|
||||||
var processHighHighGenericsTimer = null;
|
|
||||||
|
|
||||||
var processHighHighGenerics = function() {
|
var processHighHighGenerics = function() {
|
||||||
processHighHighGenericsTimer = null;
|
var tstart;
|
||||||
if ( highGenerics.hideHigh === '' ) {
|
// Simple selectors.
|
||||||
return;
|
if (
|
||||||
|
highHighSimpleGenericsInjected === false &&
|
||||||
|
highHighSimpleGenericsCost < 50 &&
|
||||||
|
highGenerics.hideHighSimpleCount !== 0
|
||||||
|
) {
|
||||||
|
tstart = window.performance.now();
|
||||||
|
var matchesProp = vAPI.matchesProp,
|
||||||
|
nodes = contextNodes,
|
||||||
|
i = nodes.length, node;
|
||||||
|
while ( i-- ) {
|
||||||
|
node = nodes[i];
|
||||||
|
if (
|
||||||
|
node[matchesProp](highGenerics.hideHighSimple) ||
|
||||||
|
node.querySelector(highGenerics.hideHighSimple) !== null
|
||||||
|
) {
|
||||||
|
highHighSimpleGenericsInjected = true;
|
||||||
|
domFilterer.addSelectors(highGenerics.hideHighSimple.split(',\n'));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if ( highHighGenericsInjected ) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
// When there are too many misses for these highly generic CSS rules,
|
highHighSimpleGenericsCost += window.performance.now() - tstart;
|
||||||
// we will just give up on looking whether they need to be injected.
|
|
||||||
if ( document.querySelector(highGenerics.hideHigh) === null ) {
|
|
||||||
processHighHighGenericsMisses -= 1;
|
|
||||||
if ( processHighHighGenericsMisses === 0 ) {
|
|
||||||
highHighGenericsInjected = true;
|
|
||||||
}
|
}
|
||||||
return;
|
// Complex selectors.
|
||||||
}
|
if (
|
||||||
highHighGenericsInjected = true;
|
highHighComplexGenericsInjected === false &&
|
||||||
// We need to filter out possible exception cosmetic filters from
|
highHighComplexGenericsCost < 50 &&
|
||||||
// high-high generics selectors.
|
highGenerics.hideHighComplexCount !== 0
|
||||||
domFilterer.addSelectors(highGenerics.hideHigh.split(',\n'));
|
) {
|
||||||
|
tstart = window.performance.now();
|
||||||
|
if ( document.querySelector(highGenerics.hideHighComplex) !== null ) {
|
||||||
|
highHighComplexGenericsInjected = true;
|
||||||
|
domFilterer.addSelectors(highGenerics.hideHighComplex.split(',\n'));
|
||||||
domFilterer.commit();
|
domFilterer.commit();
|
||||||
};
|
|
||||||
|
|
||||||
var processHighHighGenericsAsync = function() {
|
|
||||||
if ( processHighHighGenericsTimer !== null ) {
|
|
||||||
clearTimeout(processHighHighGenericsTimer);
|
|
||||||
}
|
}
|
||||||
processHighHighGenericsTimer = vAPI.setTimeout(processHighHighGenerics, 300);
|
highHighComplexGenericsCost += window.performance.now() - tstart;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Extract all classes/ids: these will be passed to the cosmetic filtering
|
// Extract all classes/ids: these will be passed to the cosmetic filtering
|
||||||
@ -1225,9 +1238,6 @@ if ( !vAPI.contentscriptInjected ) {
|
|||||||
if ( removedNodeListsTimer !== null ) {
|
if ( removedNodeListsTimer !== null ) {
|
||||||
clearTimeout(removedNodeListsTimer);
|
clearTimeout(removedNodeListsTimer);
|
||||||
}
|
}
|
||||||
if ( processHighHighGenericsTimer !== null ) {
|
|
||||||
clearTimeout(processHighHighGenericsTimer);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
@ -672,10 +672,15 @@ FilterContainer.prototype.reset = function() {
|
|||||||
this.highMediumGenericHide = {};
|
this.highMediumGenericHide = {};
|
||||||
this.highMediumGenericHideCount = 0;
|
this.highMediumGenericHideCount = 0;
|
||||||
|
|
||||||
// everything else
|
// high-high-simple selectors
|
||||||
this.highHighGenericHideArray = [];
|
this.highHighSimpleGenericHideArray = [];
|
||||||
this.highHighGenericHide = '';
|
this.highHighSimpleGenericHide = '';
|
||||||
this.highHighGenericHideCount = 0;
|
this.highHighSimpleGenericHideCount = 0;
|
||||||
|
|
||||||
|
// high-high-complex selectors
|
||||||
|
this.highHighComplexGenericHideArray = [];
|
||||||
|
this.highHighComplexGenericHide = '';
|
||||||
|
this.highHighComplexGenericHideCount = 0;
|
||||||
|
|
||||||
// generic exception filters
|
// generic exception filters
|
||||||
this.genericDonthide = [];
|
this.genericDonthide = [];
|
||||||
@ -888,8 +893,13 @@ FilterContainer.prototype.compileGenericSelector = function(parsed, out) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// All else
|
// All else: high-high generics.
|
||||||
out.push('c\vhhg0\v' + selector);
|
// Distinguish simple vs complex selectors.
|
||||||
|
if ( selector.indexOf(' ') === -1 ) {
|
||||||
|
out.push('c\vhhsg0\v' + selector);
|
||||||
|
} else {
|
||||||
|
out.push('c\vhhcg0\v' + selector);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
FilterContainer.prototype.reClassOrIdSelector = /^[#.][\w-]+$/;
|
FilterContainer.prototype.reClassOrIdSelector = /^[#.][\w-]+$/;
|
||||||
@ -1048,9 +1058,15 @@ FilterContainer.prototype.fromCompiledContent = function(text, lineBeg, skip) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( fields[0] === 'hhg0' ) {
|
if ( fields[0] === 'hhsg0' ) {
|
||||||
this.highHighGenericHideArray.push(fields[1]);
|
this.highHighSimpleGenericHideArray.push(fields[1]);
|
||||||
this.highHighGenericHideCount += 1;
|
this.highHighSimpleGenericHideCount += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( fields[0] === 'hhcg0' ) {
|
||||||
|
this.highHighComplexGenericHideArray.push(fields[1]);
|
||||||
|
this.highHighComplexGenericHideCount += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1197,11 +1213,17 @@ FilterContainer.prototype.retrieveScriptTags = function(domain, hostname) {
|
|||||||
FilterContainer.prototype.freeze = function() {
|
FilterContainer.prototype.freeze = function() {
|
||||||
this.duplicateBuster = {};
|
this.duplicateBuster = {};
|
||||||
|
|
||||||
if ( this.highHighGenericHide !== '' ) {
|
if ( this.highHighSimpleGenericHide !== '' ) {
|
||||||
this.highHighGenericHideArray.unshift(this.highHighGenericHide);
|
this.highHighSimpleGenericHideArray.unshift(this.highHighSimpleGenericHide);
|
||||||
}
|
}
|
||||||
this.highHighGenericHide = this.highHighGenericHideArray.join(',\n');
|
this.highHighSimpleGenericHide = this.highHighSimpleGenericHideArray.join(',\n');
|
||||||
this.highHighGenericHideArray = [];
|
this.highHighSimpleGenericHideArray = [];
|
||||||
|
|
||||||
|
if ( this.highHighComplexGenericHide !== '' ) {
|
||||||
|
this.highHighComplexGenericHideArray.unshift(this.highHighComplexGenericHide);
|
||||||
|
}
|
||||||
|
this.highHighComplexGenericHide = this.highHighComplexGenericHideArray.join(',\n');
|
||||||
|
this.highHighComplexGenericHideArray = [];
|
||||||
|
|
||||||
this.parser.reset();
|
this.parser.reset();
|
||||||
this.frozen = true;
|
this.frozen = true;
|
||||||
@ -1245,8 +1267,10 @@ FilterContainer.prototype.toSelfie = function() {
|
|||||||
highLowGenericHideCount: this.highLowGenericHideCount,
|
highLowGenericHideCount: this.highLowGenericHideCount,
|
||||||
highMediumGenericHide: this.highMediumGenericHide,
|
highMediumGenericHide: this.highMediumGenericHide,
|
||||||
highMediumGenericHideCount: this.highMediumGenericHideCount,
|
highMediumGenericHideCount: this.highMediumGenericHideCount,
|
||||||
highHighGenericHide: this.highHighGenericHide,
|
highHighSimpleGenericHide: this.highHighSimpleGenericHide,
|
||||||
highHighGenericHideCount: this.highHighGenericHideCount,
|
highHighSimpleGenericHideCount: this.highHighSimpleGenericHideCount,
|
||||||
|
highHighComplexGenericHide: this.highHighComplexGenericHide,
|
||||||
|
highHighComplexGenericHideCount: this.highHighComplexGenericHideCount,
|
||||||
genericDonthide: this.genericDonthide,
|
genericDonthide: this.genericDonthide,
|
||||||
scriptTagFilters: this.scriptTagFilters,
|
scriptTagFilters: this.scriptTagFilters,
|
||||||
scriptTagFilterCount: this.scriptTagFilterCount,
|
scriptTagFilterCount: this.scriptTagFilterCount,
|
||||||
@ -1309,8 +1333,10 @@ FilterContainer.prototype.fromSelfie = function(selfie) {
|
|||||||
this.highLowGenericHideCount = selfie.highLowGenericHideCount;
|
this.highLowGenericHideCount = selfie.highLowGenericHideCount;
|
||||||
this.highMediumGenericHide = selfie.highMediumGenericHide;
|
this.highMediumGenericHide = selfie.highMediumGenericHide;
|
||||||
this.highMediumGenericHideCount = selfie.highMediumGenericHideCount;
|
this.highMediumGenericHideCount = selfie.highMediumGenericHideCount;
|
||||||
this.highHighGenericHide = selfie.highHighGenericHide;
|
this.highHighSimpleGenericHide = selfie.highHighSimpleGenericHide;
|
||||||
this.highHighGenericHideCount = selfie.highHighGenericHideCount;
|
this.highHighSimpleGenericHideCount = selfie.highHighSimpleGenericHideCount;
|
||||||
|
this.highHighComplexGenericHide = selfie.highHighComplexGenericHide;
|
||||||
|
this.highHighComplexGenericHideCount = selfie.highHighComplexGenericHideCount;
|
||||||
this.genericDonthide = selfie.genericDonthide;
|
this.genericDonthide = selfie.genericDonthide;
|
||||||
this.scriptTagFilters = selfie.scriptTagFilters;
|
this.scriptTagFilters = selfie.scriptTagFilters;
|
||||||
this.scriptTagFilterCount = selfie.scriptTagFilterCount;
|
this.scriptTagFilterCount = selfie.scriptTagFilterCount;
|
||||||
@ -1441,8 +1467,10 @@ FilterContainer.prototype.retrieveGenericSelectors = function(request) {
|
|||||||
hideLowCount: this.highLowGenericHideCount,
|
hideLowCount: this.highLowGenericHideCount,
|
||||||
hideMedium: this.highMediumGenericHide,
|
hideMedium: this.highMediumGenericHide,
|
||||||
hideMediumCount: this.highMediumGenericHideCount,
|
hideMediumCount: this.highMediumGenericHideCount,
|
||||||
hideHigh: this.highHighGenericHide,
|
hideHighSimple: this.highHighSimpleGenericHide,
|
||||||
hideHighCount: this.highHighGenericHideCount
|
hideHighSimpleCount: this.highHighSimpleGenericHideCount,
|
||||||
|
hideHighComplex: this.highHighComplexGenericHide,
|
||||||
|
hideHighComplexCount: this.highHighComplexGenericHideCount
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,8 +125,10 @@ var fromCosmeticFilter = function(details) {
|
|||||||
reStr.push('c', 'hlg0', reEscape(filter));
|
reStr.push('c', 'hlg0', reEscape(filter));
|
||||||
} else if ( reHighMedium.test(filter) ) { // [href^="..."]
|
} else if ( reHighMedium.test(filter) ) { // [href^="..."]
|
||||||
reStr.push('c', 'hmg0', '[^"]{8}', '[a-z]*' + reEscape(filter));
|
reStr.push('c', 'hmg0', '[^"]{8}', '[a-z]*' + reEscape(filter));
|
||||||
} else { // all else
|
} else if ( filter.indexOf(' ') === -1 ) { // high-high-simple selector
|
||||||
reStr.push('c', 'hhg0', reEscape(filter));
|
reStr.push('c', 'hhsg0', reEscape(filter));
|
||||||
|
} else { // high-high-complex selector
|
||||||
|
reStr.push('c', 'hhcg0', reEscape(filter));
|
||||||
}
|
}
|
||||||
candidates[details.rawFilter] = new RegExp(reStr.join('\\v') + '(?:\\n|$)');
|
candidates[details.rawFilter] = new RegExp(reStr.join('\\v') + '(?:\\n|$)');
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user