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()}`;
}
}
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) {
const nodes = this.qsa(node);
if ( nodes === undefined ) { return; }
const nodes = this.nth
? PSelectorSpathTask.qsa(node, this.spath)
: node.querySelectorAll(this.spath);
for ( const node of nodes ) {
output.push(node);
}
@ -394,12 +379,10 @@ class PSelector {
prime(input) {
const root = input || document;
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));
}
const elems = root.querySelectorAll(selector);
return Array.from(elems);
return Array.from(root.querySelectorAll(this.selector));
}
exec(input) {
let nodes = this.prime(input);

View File

@ -104,22 +104,33 @@ const PSelectorMinTextLengthTask = class {
const PSelectorSpathTask = class {
constructor(task) {
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) {
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;
if ( parent === null ) { return; }
if ( parent === null ) { return []; }
let pos = 1;
for (;;) {
node = node.previousElementSibling;
if ( node === null ) { break; }
pos += 1;
}
const nodes = parent.querySelectorAll(
`:scope > :nth-child(${pos})${this.spath}`
return parent.querySelectorAll(
`:scope > :nth-child(${pos})${selector}`
);
for ( const node of nodes ) {
output.push(node);
}
}
};
@ -198,6 +209,9 @@ const PSelector = class {
prime(input) {
const root = input || docRegister;
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));
}
exec(input) {