Skip to content

Commit 3f8c7b9

Browse files
committed
1 parent efdf43f commit 3f8c7b9

1 file changed

Lines changed: 44 additions & 10 deletions

File tree

src/js/cosmetic-filtering.js

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -595,8 +595,10 @@ var FilterContainer = function() {
595595
this.selectorCacheTimer = null;
596596
this.reHasUnicode = /[^\x00-\x7F]/;
597597
this.reClassOrIdSelector = /^[#.][\w-]+$/;
598-
this.rePlainSelector = /^[#.][\w-]+/;
598+
this.rePlainSelector = /^[#.][\w\\-]+/;
599+
this.rePlainSelectorEscaped = /^[#.](?:\\[0-9A-Fa-f]+ |\\.|\w|-)+/;
599600
this.rePlainSelectorEx = /^[^#.\[(]+([#.][\w-]+)/;
601+
this.reEscapeSequence = /\\([0-9A-Fa-f]+ |.)/g;
600602
this.reHighLow = /^[a-z]*\[(?:alt|title)="[^"]+"\]$/;
601603
this.reHighMedium = /^\[href\^="https?:\/\/([^"]{8})[^"]*"\]$/;
602604
this.reScriptSelector = /^script:(contains|inject)\((.+)\)$/;
@@ -786,6 +788,40 @@ FilterContainer.prototype.isValidSelector = (function() {
786788

787789
/******************************************************************************/
788790

791+
// https://github.com/gorhill/uBlock/issues/1668
792+
// The key must be literal: unescape escaped CSS before extracting key.
793+
// It's an uncommon case, so it's best to unescape only when needed.
794+
795+
FilterContainer.prototype.keyFromSelector = function(selector) {
796+
var matches = this.rePlainSelector.exec(selector);
797+
if ( matches === null ) { return; }
798+
var key = matches[0];
799+
if ( key.indexOf('\\') === -1 ) {
800+
return key;
801+
}
802+
key = '';
803+
matches = this.rePlainSelectorEscaped.exec(selector);
804+
if ( matches === null ) { return; }
805+
var escaped = matches[0],
806+
beg = 0;
807+
this.reEscapeSequence.lastIndex = 0;
808+
for (;;) {
809+
matches = this.reEscapeSequence.exec(escaped);
810+
if ( matches === null ) {
811+
return key + escaped.slice(beg);
812+
}
813+
key += escaped.slice(beg, matches.index);
814+
beg = this.reEscapeSequence.lastIndex;
815+
if ( matches[1].length === 1 ) {
816+
key += matches[1];
817+
} else {
818+
key += String.fromCharCode(parseInt(matches[1], 16));
819+
}
820+
}
821+
};
822+
823+
/******************************************************************************/
824+
789825
FilterContainer.prototype.compile = function(s, out) {
790826
var parsed = this.parser.parse(s);
791827
if ( parsed.cosmetic === false ) {
@@ -846,23 +882,21 @@ FilterContainer.prototype.compileGenericSelector = function(parsed, out) {
846882
FilterContainer.prototype.compileGenericHideSelector = function(parsed, out) {
847883
var selector = parsed.suffix,
848884
type = selector.charAt(0),
849-
matches;
885+
key, matches;
850886

851887
if ( type === '#' || type === '.' ) {
852-
matches = this.rePlainSelector.exec(selector);
853-
if ( matches === null ) {
854-
return;
855-
}
888+
key = this.keyFromSelector(selector);
889+
if ( key === undefined ) { return; }
856890
// Single-CSS rule: no need to test for whether the selector
857891
// is valid, the regex took care of this. Most generic selector falls
858892
// into that category.
859-
if ( matches[0] === selector ) {
860-
out.push('c\vlg\v' + matches[0]);
893+
if ( key === selector ) {
894+
out.push('c\vlg\v' + key);
861895
return;
862896
}
863-
// Many-CSS rules
897+
// Composite CSS rule.
864898
if ( this.isValidSelector(selector) ) {
865-
out.push('c\vlg+\v' + matches[0] + '\v' + selector);
899+
out.push('c\vlg+\v' + key + '\v' + selector);
866900
}
867901
return;
868902
}

0 commit comments

Comments
 (0)