Skip to content

Commit

Permalink
Properly serialize CSS combinators according to position in selector
Browse files Browse the repository at this point in the history
Related issue:
uBlockOrigin/uBlock-issues#2778

Regression from:
bb41d95

The regression occurred because the modified code made the assumption
that a leading combinator would never be preceded by whitespace, while
the parser didn't prevent this.

The parser has been fixed to ensure there is never a leading
whitespace in a selector.
  • Loading branch information
gorhill committed Aug 15, 2023
1 parent 79cf5f5 commit fbc7a0e
Showing 1 changed file with 30 additions and 3 deletions.
33 changes: 30 additions & 3 deletions src/js/static-filtering-parser.js
Expand Up @@ -3364,7 +3364,7 @@ class ExtSelectorCompiler {
out.push(`.${data.name}`);
break;
case 'Combinator':
out.push(data.name === ' ' ? ' ' : ` ${data.name} `);
out.push(data.name);
break;
case 'Identifier':
if ( this.reInvalidIdentifier.test(data.name) ) { return; }
Expand Down Expand Up @@ -3436,14 +3436,35 @@ class ExtSelectorCompiler {
return out.join('');
}

astAppendPart(part, out) {
const { data } = part;
switch ( data.type ) {
case 'Combinator': {
const s = this.astSerializePart(part);
if ( s === undefined ) { return false; }
if ( out.length === 0 ) {
if ( s !== ' ' ) {
out.push(s, ' ');
}
} else {
out.push(' ');
if ( s !== ' ' ) {
out.push(s, ' ');
}
}
break;
}
}
return true;
}

astSerialize(parts, plainCSS = true) {
const out = [];
for ( const part of parts ) {
const { data } = part;
switch ( data.type ) {
case 'AttributeSelector':
case 'ClassSelector':
case 'Combinator':
case 'Identifier':
case 'IdSelector':
case 'Nth':
Expand All @@ -3455,6 +3476,9 @@ class ExtSelectorCompiler {
out.push(s);
break;
}
case 'Combinator':
if ( this.astAppendPart(part, out) === false ) { return; }
break;
case 'Raw':
if ( plainCSS ) { return; }
out.push(this.astSerializePart(part));
Expand Down Expand Up @@ -3499,7 +3523,6 @@ class ExtSelectorCompiler {
}
case 'AttributeSelector':
case 'ClassSelector':
case 'Combinator':
case 'IdSelector':
case 'PseudoClassSelector':
case 'PseudoElementSelector':
Expand All @@ -3509,6 +3532,10 @@ class ExtSelectorCompiler {
prelude.push(component);
break;
}
case 'Combinator': {
if ( this.astAppendPart(part, prelude) === false ) { return; }
break;
}
case 'ProceduralSelector': {
if ( prelude.length !== 0 ) {
let spath = prelude.join('');
Expand Down

0 comments on commit fbc7a0e

Please sign in to comment.