Give precedence to negated types in case of ambiguity

Related feedback:
- https://github.com/uBlockOrigin/uAssets/issues/7639#issuecomment-933525018
This commit is contained in:
Raymond Hill 2021-10-06 09:44:15 -04:00
parent ebe173d273
commit 6464002088
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
2 changed files with 32 additions and 11 deletions

View File

@ -288,7 +288,7 @@ describe('SNFE', () => {
assert(engine.isBlockImportant()); assert(engine.isBlockImportant());
}); });
it('should block all except stylesheets', async () => { it('should block all except stylesheets #1', async () => {
await engine.useLists([ await engine.useLists([
{ name: 'test', raw: '||example.com^$~stylesheet,all' }, { name: 'test', raw: '||example.com^$~stylesheet,all' },
]); ]);
@ -299,6 +299,18 @@ describe('SNFE', () => {
}); });
assert.strictEqual(r, 0); assert.strictEqual(r, 0);
}); });
it('should block all except stylesheets #2', async () => {
await engine.useLists([
{ name: 'test', raw: '||example.com^$all,~stylesheet' },
]);
const r = engine.matchRequest({
originURL: 'https://www.example.com/',
type: 'stylesheet',
url: 'https://www.example.com/',
});
assert.strictEqual(r, 0);
});
}); });
}); });
} }

View File

@ -2955,15 +2955,20 @@ class FilterCompiler {
// Be ready to handle multiple negated types // Be ready to handle multiple negated types
processTypeOption(id, not) { processTypeOption(id, not) {
const typeBit = id !== -1 if ( id !== -1 ) {
? this.tokenIdToNormalizedType.get(id) const typeBit = this.tokenIdToNormalizedType.get(id);
: allTypesBits; if ( not ) {
this.notTypeBits |= typeBit;
} else {
this.typeBits |= typeBit;
}
return;
}
// `all` option
if ( not ) { if ( not ) {
this.notTypeBits |= typeBit; this.notTypeBits |= allTypesBits;
this.typeBits &= ~typeBit;
} else { } else {
this.typeBits |= typeBit; this.typeBits |= allTypesBits;
this.notTypeBits &= ~typeBit;
} }
} }
@ -3140,7 +3145,11 @@ class FilterCompiler {
// - no network type is present -- i.e. all network types are // - no network type is present -- i.e. all network types are
// implicitly toggled on // implicitly toggled on
if ( this.notTypeBits !== 0 ) { if ( this.notTypeBits !== 0 ) {
this.typeBits &= ~this.notTypeBits; if ( (this.typeBits && allNetworkTypesBits) === allNetworkTypesBits ) {
this.typeBits &= ~this.notTypeBits | allNetworkTypesBits;
} else {
this.typeBits &= ~this.notTypeBits;
}
this.optionUnitBits |= this.NOT_TYPE_BIT; this.optionUnitBits |= this.NOT_TYPE_BIT;
} }
@ -3546,7 +3555,7 @@ class FilterCompiler {
compileToAtomicFilter(fdata, writer) { compileToAtomicFilter(fdata, writer) {
const catBits = this.action | this.party; const catBits = this.action | this.party;
let { notTypeBits, typeBits } = this; let { typeBits } = this;
// Typeless // Typeless
if ( typeBits === 0 ) { if ( typeBits === 0 ) {
@ -3556,7 +3565,7 @@ class FilterCompiler {
// If all network types are set, create a typeless filter. Excluded // If all network types are set, create a typeless filter. Excluded
// network types are tested at match time, se we act as if they are // network types are tested at match time, se we act as if they are
// set. // set.
if ( ((typeBits | notTypeBits) & allNetworkTypesBits) === allNetworkTypesBits ) { if ( (typeBits & allNetworkTypesBits) === allNetworkTypesBits ) {
writer.push([ catBits, this.tokenHash, fdata ]); writer.push([ catBits, this.tokenHash, fdata ]);
typeBits &= ~allNetworkTypesBits; typeBits &= ~allNetworkTypesBits;
if ( typeBits === 0 ) { return; } if ( typeBits === 0 ) { return; }