Re-arrange parsing of type options to be order-independent

Related commit:
- 1888033070

This removes the need to place `all` before any negated
type in the list of options.
This commit is contained in:
Raymond Hill 2019-05-21 14:04:21 -04:00
parent 5b47a06cbe
commit 32b04fa262
No known key found for this signature in database
GPG key ID: 25E1490B761470C2

View file

@ -1872,6 +1872,7 @@ FilterParser.prototype.reset = function() {
this.tokenHash = this.noTokenHash; this.tokenHash = this.noTokenHash;
this.tokenBeg = 0; this.tokenBeg = 0;
this.types = 0; this.types = 0;
this.notTypes = 0;
this.important = 0; this.important = 0;
this.wildcarded = false; this.wildcarded = false;
this.unsupported = false; this.unsupported = false;
@ -1894,26 +1895,11 @@ FilterParser.prototype.parseTypeOption = function(raw, not) {
? this.bitFromType(this.toNormalizedType[raw]) ? this.bitFromType(this.toNormalizedType[raw])
: allTypesBits; : allTypesBits;
if ( !not ) { if ( not ) {
this.notTypes |= typeBit;
} else {
this.types |= typeBit; this.types |= typeBit;
return;
} }
// Non-network types can only toggle themselves.
if ( (typeBit & allNetworkTypesBits) === 0 ) {
this.types &= ~typeBit;
return;
}
// Negated network type: the first negation imply all network types are
// toggled on.
if (
(typeBit & allNetworkTypesBits) !== 0 &&
(this.types & allNetworkTypesBits) === 0
) {
this.types |= allNetworkTypesBits;
}
this.types &= ~typeBit;
}; };
/******************************************************************************/ /******************************************************************************/
@ -1952,11 +1938,10 @@ FilterParser.prototype.parseDomainOption = function(s) {
FilterParser.prototype.parseOptions = function(s) { FilterParser.prototype.parseOptions = function(s) {
this.fopts = s; this.fopts = s;
var opts = s.split(','); const opts = s.split(',');
var opt, not;
for ( var i = 0; i < opts.length; i++ ) { for ( var i = 0; i < opts.length; i++ ) {
opt = opts[i]; let opt = opts[i];
not = opt.startsWith('~'); const not = opt.startsWith('~');
if ( not ) { if ( not ) {
opt = opt.slice(1); opt = opt.slice(1);
} }
@ -2034,6 +2019,32 @@ FilterParser.prototype.parseOptions = function(s) {
this.unsupported = true; this.unsupported = true;
break; break;
} }
// Negated network types? Toggle on all network type bits.
if ( (this.notTypes & allNetworkTypesBits) !== 0 ) {
this.types |= allNetworkTypesBits & ~this.notTypes;
if ( this.types === 0 ) {
this.unsupported = true;
}
}
// Negated non-network types can only toggle themselves.
if ( this.notTypes !== 0 ) {
this.types &= ~this.notTypes;
if ( this.types === 0 ) {
this.unsupported = true;
}
}
// https://github.com/gorhill/uBlock/issues/2283
// Abort if type is only for unsupported types, otherwise
// toggle off `unsupported` bit.
if ( this.types & unsupportedTypeBit ) {
this.types &= ~unsupportedTypeBit;
if ( this.types === 0 ) {
this.unsupported = true;
}
}
}; };
/******************************************************************************* /*******************************************************************************
@ -2094,16 +2105,7 @@ FilterParser.prototype.parse = function(raw) {
return this; return this;
} }
this.parseOptions(s.slice(pos + 1)); this.parseOptions(s.slice(pos + 1));
// https://github.com/gorhill/uBlock/issues/2283 if ( this.unsupported ) { return this; }
// Abort if type is only for unsupported types, otherwise
// toggle off `unsupported` bit.
if ( this.types & unsupportedTypeBit ) {
this.types &= ~unsupportedTypeBit;
if ( this.types === 0 ) {
this.unsupported = true;
return this;
}
}
s = s.slice(0, pos); s = s.slice(0, pos);
} }
} }
@ -2743,30 +2745,30 @@ FilterContainer.prototype.compileToAtomicFilter = function(
writer.select(0); writer.select(0);
} }
let descBits = parsed.action | parsed.important | parsed.party; const descBits = parsed.action | parsed.important | parsed.party;
let type = parsed.types; let typeBits = parsed.types;
// Typeless // Typeless
if ( type === 0 ) { if ( typeBits === 0 ) {
writer.push([ descBits, parsed.tokenHash, fdata ]); writer.push([ descBits, parsed.tokenHash, fdata ]);
return; return;
} }
// If all network types are set, just use `no_type`. // If all network types are set, create a typeless filter
if ( (type & allNetworkTypesBits) === allNetworkTypesBits ) { if ( (typeBits & allNetworkTypesBits) === allNetworkTypesBits ) {
writer.push([ descBits, parsed.tokenHash, fdata ]); writer.push([ descBits, parsed.tokenHash, fdata ]);
type &= ~allNetworkTypesBits; typeBits &= ~allNetworkTypesBits;
} }
// Specific type(s) // One filter per specific types
let bitOffset = 1; let bitOffset = 1;
do { do {
if ( type & 1 ) { if ( typeBits & 1 ) {
writer.push([ descBits | (bitOffset << 4), parsed.tokenHash, fdata ]); writer.push([ descBits | (bitOffset << 4), parsed.tokenHash, fdata ]);
} }
bitOffset += 1; bitOffset += 1;
type >>>= 1; typeBits >>>= 1;
} while ( type !== 0 ); } while ( typeBits !== 0 );
// Only static filter with an explicit type can be redirected. If we reach // Only static filter with an explicit type can be redirected. If we reach
// this point, it's because there is one or more explicit type. // this point, it's because there is one or more explicit type.