mirror of
https://github.com/gorhill/uBlock.git
synced 2024-11-01 16:33:06 +01:00
Fallback procedural :has() operator when argument is not a valid plain CSS selector
Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/2228
This commit is contained in:
parent
95661c5f49
commit
8f39a457b8
@ -1384,6 +1384,7 @@ Parser.prototype.SelectorCompiler = class {
|
|||||||
this.reDropScope = /^\s*:scope\s*(?=[+>~])/;
|
this.reDropScope = /^\s*:scope\s*(?=[+>~])/;
|
||||||
this.reIsDanglingSelector = /[+>~\s]\s*$/;
|
this.reIsDanglingSelector = /[+>~\s]\s*$/;
|
||||||
this.reIsCombinator = /^\s*[+>~]/;
|
this.reIsCombinator = /^\s*[+>~]/;
|
||||||
|
this.reForgivingOps = /:has\(/;
|
||||||
this.regexToRawValue = new Map();
|
this.regexToRawValue = new Map();
|
||||||
// https://github.com/gorhill/uBlock/issues/2793
|
// https://github.com/gorhill/uBlock/issues/2793
|
||||||
this.normalizedOperators = new Map([
|
this.normalizedOperators = new Map([
|
||||||
@ -1416,7 +1417,15 @@ Parser.prototype.SelectorCompiler = class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Can be used in a declarative CSS rule?
|
// Can be used in a declarative CSS rule?
|
||||||
if ( asProcedural === false && this.sheetSelectable(raw) ) {
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/2228
|
||||||
|
// Some operators are forgiving, so we need to exclude them for now
|
||||||
|
// as potentially declarative selectors until we validate that their
|
||||||
|
// arguments are themselves valid plain CSS selector.
|
||||||
|
if (
|
||||||
|
asProcedural === false &&
|
||||||
|
this.reForgivingOps.test(raw) === false &&
|
||||||
|
this.sheetSelectable(raw)
|
||||||
|
) {
|
||||||
out.compiled = raw;
|
out.compiled = raw;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1792,20 +1801,27 @@ Parser.prototype.SelectorCompiler = class {
|
|||||||
// Unbalanced parenthesis? An unbalanced parenthesis is fine
|
// Unbalanced parenthesis? An unbalanced parenthesis is fine
|
||||||
// as long as the last character is a closing parenthesis.
|
// as long as the last character is a closing parenthesis.
|
||||||
if ( pcnt !== 0 && c !== 0x29 ) { return; }
|
if ( pcnt !== 0 && c !== 0x29 ) { return; }
|
||||||
|
// Extract and remember operator/argument details.
|
||||||
|
const opname = raw.slice(opNameBeg, opNameEnd);
|
||||||
|
const oparg = raw.slice(opNameEnd + 1, i - 1);
|
||||||
|
const operator = this.normalizedOperators.get(opname) || opname;
|
||||||
// https://github.com/uBlockOrigin/uBlock-issues/issues/341#issuecomment-447603588
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/341#issuecomment-447603588
|
||||||
// Maybe that one operator is a valid CSS selector and if so,
|
// Maybe that one operator is a valid CSS selector and if so,
|
||||||
// then consider it to be part of the prefix.
|
// then consider it to be part of the prefix.
|
||||||
if ( this.querySelectable(raw.slice(opNameBeg, i)) ) { continue; }
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/2228
|
||||||
// Extract and remember operator details.
|
// Maybe an operator is a valid CSS selector, but if it is
|
||||||
let operator = raw.slice(opNameBeg, opNameEnd);
|
// "forgiving", we also need to validate that the argument itself
|
||||||
operator = this.normalizedOperators.get(operator) || operator;
|
// is also a valid CSS selector.
|
||||||
|
if (
|
||||||
|
this.querySelectable(raw.slice(opNameBeg, i)) &&
|
||||||
|
this.querySelectable(oparg)
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// Action operator can only be used as trailing operator in the
|
// Action operator can only be used as trailing operator in the
|
||||||
// root task list.
|
// root task list.
|
||||||
// Per-operator arguments validation
|
// Per-operator arguments validation
|
||||||
const args = this.compileArgument(
|
const args = this.compileArgument(operator, oparg);
|
||||||
operator,
|
|
||||||
raw.slice(opNameEnd + 1, i - 1)
|
|
||||||
);
|
|
||||||
if ( args === undefined ) { return; }
|
if ( args === undefined ) { return; }
|
||||||
if ( opPrefixBeg === 0 ) {
|
if ( opPrefixBeg === 0 ) {
|
||||||
prefix = raw.slice(0, opNameBeg);
|
prefix = raw.slice(0, opNameBeg);
|
||||||
|
Loading…
Reference in New Issue
Block a user