1
0
mirror of https://github.com/gorhill/uBlock.git synced 2024-09-15 15:32:28 +02:00

Fix broken :has() operator in HTML filtering

Related feedback:
- https://github.com/uBlockOrigin/uBlock-issues/issues/2228#issuecomment-1273119017
This commit is contained in:
Raymond Hill 2022-10-10 08:38:40 -04:00
parent 849937aae6
commit 5659194932
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
2 changed files with 25 additions and 28 deletions

View File

@ -232,25 +232,10 @@ class PSelectorSpathTask extends PSelectorTask {
this.spath = `:scope ${this.spath.trim()}`; this.spath = `:scope ${this.spath.trim()}`;
} }
} }
qsa(node) {
if ( this.nth === false ) {
return node.querySelectorAll(this.spath);
}
const parent = node.parentElement;
if ( parent === null ) { return; }
let pos = 1;
for (;;) {
node = node.previousElementSibling;
if ( node === null ) { break; }
pos += 1;
}
return parent.querySelectorAll(
`:scope > :nth-child(${pos})${this.spath}`
);
}
transpose(node, output) { transpose(node, output) {
const nodes = this.qsa(node); const nodes = this.nth
if ( nodes === undefined ) { return; } ? PSelectorSpathTask.qsa(node, this.spath)
: node.querySelectorAll(this.spath);
for ( const node of nodes ) { for ( const node of nodes ) {
output.push(node); output.push(node);
} }
@ -394,12 +379,10 @@ class PSelector {
prime(input) { prime(input) {
const root = input || document; const root = input || document;
if ( this.selector === '' ) { return [ root ]; } if ( this.selector === '' ) { return [ root ]; }
let selector = this.selector; if ( input !== document && /^ ?[>+~]/.test(this.selector) ) {
if ( input !== document && /^ [>+~]/.test(this.selector) ) {
return Array.from(PSelectorSpathTask.qsa(input, this.selector)); return Array.from(PSelectorSpathTask.qsa(input, this.selector));
} }
const elems = root.querySelectorAll(selector); return Array.from(root.querySelectorAll(this.selector));
return Array.from(elems);
} }
exec(input) { exec(input) {
let nodes = this.prime(input); let nodes = this.prime(input);

View File

@ -104,22 +104,33 @@ const PSelectorMinTextLengthTask = class {
const PSelectorSpathTask = class { const PSelectorSpathTask = class {
constructor(task) { constructor(task) {
this.spath = task[1]; this.spath = task[1];
this.nth = /^(?:\s*[+~]|:)/.test(this.spath);
if ( this.nth ) { return; }
if ( /^\s*>/.test(this.spath) ) {
this.spath = `:scope ${this.spath.trim()}`;
}
} }
transpose(node, output) { transpose(node, output) {
const nodes = this.nth
? PSelectorSpathTask.qsa(node, this.spath)
: node.querySelectorAll(this.spath);
for ( const node of nodes ) {
output.push(node);
}
}
// Helper method for other operators.
static qsa(node, selector) {
const parent = node.parentElement; const parent = node.parentElement;
if ( parent === null ) { return; } if ( parent === null ) { return []; }
let pos = 1; let pos = 1;
for (;;) { for (;;) {
node = node.previousElementSibling; node = node.previousElementSibling;
if ( node === null ) { break; } if ( node === null ) { break; }
pos += 1; pos += 1;
} }
const nodes = parent.querySelectorAll( return parent.querySelectorAll(
`:scope > :nth-child(${pos})${this.spath}` `:scope > :nth-child(${pos})${selector}`
); );
for ( const node of nodes ) {
output.push(node);
}
} }
}; };
@ -198,6 +209,9 @@ const PSelector = class {
prime(input) { prime(input) {
const root = input || docRegister; const root = input || docRegister;
if ( this.selector === '' ) { return [ root ]; } if ( this.selector === '' ) { return [ root ]; }
if ( input !== docRegister && /^ ?[>+~]/.test(this.selector) ) {
return Array.from(PSelectorSpathTask.qsa(input, this.selector));
}
return Array.from(root.querySelectorAll(this.selector)); return Array.from(root.querySelectorAll(this.selector));
} }
exec(input) { exec(input) {