1
0
mirror of https://github.com/gorhill/uBlock.git synced 2024-09-04 01:59:38 +02:00

Fine tune latest changes for performance

Related commits:
- 157cef6034
- 1e2eb037e5
This commit is contained in:
Raymond Hill 2020-11-04 07:50:51 -05:00
parent 04b02f8044
commit 19331f1ab5
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2

View File

@ -1666,23 +1666,26 @@ const FilterCompositeAll = class extends FilterCollection {
return true;
}
// IMPORTANT: the modifier filter unit is assumed to be ALWAYS the
// first unit in the sequence. This requirement ensures that we do
// not have to traverse the sequence to find the modifier filter
// unit.
matchAndFetchModifiers(env) {
if ( this.match() !== true ) { return false; }
this.forEach(iunit => {
const f = filterUnits[iunit];
if ( f.matchAndFetchModifiers instanceof Function ) {
f.matchAndFetchModifiers(env);
}
});
const f = filterUnits[filterSequences[this.i]];
if (
f.matchAndFetchModifiers instanceof Function &&
f.type === env.modifier &&
this.match()
) {
f.matchAndFetchModifiers(env);
}
}
get modifier() {
return this.forEach(iunit => {
const f = filterUnits[iunit];
if ( f.matchAndFetchModifiers instanceof Function ) {
return f.modifier;
}
});
const f = filterUnits[filterSequences[this.i]];
if ( f.matchAndFetchModifiers instanceof Function ) {
return f.modifier;
}
}
// FilterPatternPlain is assumed to be first filter in sequence. This can
@ -1985,11 +1988,14 @@ const FilterBucket = class extends FilterCollection {
}
matchAndFetchModifiers(env) {
const sequences = filterSequences;
const units = filterUnits;
this.forEach(iunit => {
env.iunit = iunit;
units[iunit].matchAndFetchModifiers(env);
});
let i = this.i;
while ( i !== 0 ) {
env.iunit = sequences[i+0];
units[env.iunit].matchAndFetchModifiers(env);
i = sequences[i+1];
}
}
logData(details) {
@ -2401,6 +2407,7 @@ const FilterParser = class {
this.modifyValue = 'noopmp4-1s';
break;
case parser.OPTTokenQueryprune:
// TODO: validate value
case parser.OPTTokenRedirect:
case parser.OPTTokenRedirectRule:
if ( this.modifyType !== undefined ) { return false; }
@ -3083,8 +3090,11 @@ FilterContainer.prototype.compile = function(parser, writer) {
}
// Modifier
//
// IMPORTANT: the modifier unit MUST always appear first in a sequence.
//
// Reminder: A block filter is implicit with `redirect=` modifier.
if ( parsed.modifyType !== undefined ) {
// A block filter is implicit with `redirect=` modifier
if (
parsed.modifyType === parser.OPTTokenRedirect &&
(parsed.action & ActionBitsMask) !== AllowAction
@ -3096,7 +3106,7 @@ FilterContainer.prototype.compile = function(parser, writer) {
);
parsed.modifyType = parser.OPTTokenRedirectRule;
}
units.push(FilterModifier.compile(parsed));
units.unshift(FilterModifier.compile(parsed));
parsed.action = ModifyAction;
parsed.important = 0;
}
@ -3202,13 +3212,13 @@ FilterContainer.prototype.matchAndFetchModifiers = function(
? this.categories.get(catBits11)
: undefined;
const modifierResults = [];
const results = [];
const env = {
modifier: vAPI.StaticFilteringParser.netOptionTokenIds.get(modifierType) || 0,
bits: 0,
th: 0,
iunit: 0,
results: modifierResults,
results,
};
const units = filterUnits;
@ -3250,36 +3260,60 @@ FilterContainer.prototype.matchAndFetchModifiers = function(
i += 2;
}
if ( modifierResults.length === 0 ) { return; }
if ( results.length === 0 ) { return; }
// One single result is expected to be a common occurrence, and in such
// case there is no need to process exception vs. block, block important
// occurrences.
if ( results.length === 1 ) {
const result = results[0];
if ( (result.bits & ActionBitsMask) === AllowAction ) { return; }
return [ result ];
}
const toAddImportant = new Map();
const toAdd = new Map();
const toRemove = new Map();
for ( const modifierResult of modifierResults ) {
const actionBits = modifierResult.bits & ActionBitsMask;
const modifyValue = modifierResult.modifier.value;
for ( const result of results ) {
const actionBits = result.bits & ActionBitsMask;
const modifyValue = result.modifier.value;
if ( actionBits === BlockImportant ) {
toAddImportant.set(modifyValue, modifierResult);
toAddImportant.set(modifyValue, result);
} else if ( actionBits === BlockAction ) {
toAdd.set(modifyValue, modifierResult);
toAdd.set(modifyValue, result);
} else {
toRemove.set(modifyValue, modifierResult);
toRemove.set(modifyValue, result);
}
}
if ( toAddImportant.size === 0 && toAdd.size === 0 ) { return; }
// Remove entries overriden by important block filters.
for ( const key of toAddImportant.keys() ) {
toAdd.delete(key);
toRemove.delete(key);
if ( toAddImportant.size !== 0 ) {
for ( const key of toAddImportant.keys() ) {
toAdd.delete(key);
toRemove.delete(key);
}
}
// Exception filters
//
// Remove excepted block filters and unused exception filters.
//
// Special case, except-all:
// - Except-all applies only if there is at least one normal block filters.
// - Except-all does not apply to important block filters.
if ( toRemove.has('') ) {
if ( toAdd.size !== 0 ) {
if ( toRemove.size !== 0 ) {
if ( toRemove.has('') === false ) {
for ( const key of toRemove.keys() ) {
if ( toAdd.has(key) ) {
toAdd.delete(key);
} else {
toRemove.delete(key);
}
}
}
else if ( toAdd.size !== 0 ) {
toAdd.clear();
if ( toRemove.size !== 1 ) {
const entry = toRemove.get('');
@ -3290,16 +3324,6 @@ FilterContainer.prototype.matchAndFetchModifiers = function(
toRemove.clear();
}
}
// Remove excepted block filters and unused exception filters.
else {
for ( const key of toRemove.keys() ) {
if ( toAdd.has(key) ) {
toAdd.delete(key);
} else {
toRemove.delete(key);
}
}
}
if (
toAdd.size === 0 &&
@ -3525,7 +3549,25 @@ FilterContainer.prototype.matchString = function(fctxt, modifiers = 0) {
FilterContainer.prototype.redirectRequest = function(fctxt) {
const directives = this.matchAndFetchModifiers(fctxt, 'redirect-rule');
// No directive is the most common occurrence.
if ( directives === undefined ) { return; }
// A single directive should be the next most common occurrence.
if ( directives.length === 1 ) {
const directive = directives[0];
if ( (directive.bits & ActionBitsMask) === AllowAction ) {
return directive;
}
const modifier = directive.modifier;
if ( modifier.cache === undefined ) {
modifier.cache = this.parseRedirectRequestValue(modifier.value);
}
fctxt.redirectURL = µb.redirectEngine.tokenToURL(
fctxt,
modifier.cache.token
);
return directive;
}
// Multiple directives mean more work to do.
let winningDirective;
let winningPriority = 0;
for ( const directive of directives ) {
@ -3536,15 +3578,7 @@ FilterContainer.prototype.redirectRequest = function(fctxt) {
break;
}
if ( modifier.cache === undefined ) {
const rawToken = modifier.value;
let token = rawToken;
let priority = 0;
const match = /:(\d+)$/.exec(rawToken);
if ( match !== null ) {
token = rawToken.slice(0, match.index);
priority = parseInt(match[1], 10);
}
modifier.cache = { token, priority };
modifier.cache = this.parseRedirectRequestValue(modifier.value);
}
if (
winningDirective === undefined ||
@ -3564,9 +3598,15 @@ FilterContainer.prototype.redirectRequest = function(fctxt) {
return winningDirective;
};
FilterContainer.prototype.hasQuery = function(fctxt) {
urlTokenizer.setURL(fctxt.url);
return urlTokenizer.hasQuery();
FilterContainer.prototype.parseRedirectRequestValue = function(rawValue) {
let token = rawValue;
let priority = 0;
const match = /:(\d+)$/.exec(rawValue);
if ( match !== null ) {
token = rawValue.slice(0, match.index);
priority = parseInt(match[1], 10);
}
return { token, priority };
};
/******************************************************************************/
@ -3587,10 +3627,7 @@ FilterContainer.prototype.filterQuery = function(fctxt) {
break;
}
if ( modifier.cache === undefined ) {
let retext = modifier.value;
if ( retext.startsWith('|') ) { retext = `^${retext.slice(1)}`; }
if ( retext.endsWith('|') ) { retext = `${retext.slice(0,-1)}$`; }
modifier.cache = new RegExp(retext);
modifier.cache = this.parseFilterPruneValue(modifier.value);
}
const re = modifier.cache;
let filtered = false;
@ -3615,6 +3652,19 @@ FilterContainer.prototype.filterQuery = function(fctxt) {
return out;
};
FilterContainer.prototype.parseFilterPruneValue = function(rawValue) {
let retext = rawValue;
if ( retext.startsWith('|') ) { retext = `^${retext.slice(1)}`; }
if ( retext.endsWith('|') ) { retext = `${retext.slice(0,-1)}$`; }
try {
return new RegExp(retext);
} catch(ex) {
}
return /.^/;
};
/******************************************************************************/
FilterContainer.prototype.hasQuery = function(fctxt) {
urlTokenizer.setURL(fctxt.url);
return urlTokenizer.hasQuery();