1
0
mirror of https://github.com/gorhill/uBlock.git synced 2024-11-07 03:12:33 +01:00
This commit is contained in:
gorhill 2016-10-30 15:19:58 -04:00
parent efdf43f1d5
commit 3f8c7b915c

View File

@ -595,8 +595,10 @@ var FilterContainer = function() {
this.selectorCacheTimer = null; this.selectorCacheTimer = null;
this.reHasUnicode = /[^\x00-\x7F]/; this.reHasUnicode = /[^\x00-\x7F]/;
this.reClassOrIdSelector = /^[#.][\w-]+$/; this.reClassOrIdSelector = /^[#.][\w-]+$/;
this.rePlainSelector = /^[#.][\w-]+/; this.rePlainSelector = /^[#.][\w\\-]+/;
this.rePlainSelectorEscaped = /^[#.](?:\\[0-9A-Fa-f]+ |\\.|\w|-)+/;
this.rePlainSelectorEx = /^[^#.\[(]+([#.][\w-]+)/; this.rePlainSelectorEx = /^[^#.\[(]+([#.][\w-]+)/;
this.reEscapeSequence = /\\([0-9A-Fa-f]+ |.)/g;
this.reHighLow = /^[a-z]*\[(?:alt|title)="[^"]+"\]$/; this.reHighLow = /^[a-z]*\[(?:alt|title)="[^"]+"\]$/;
this.reHighMedium = /^\[href\^="https?:\/\/([^"]{8})[^"]*"\]$/; this.reHighMedium = /^\[href\^="https?:\/\/([^"]{8})[^"]*"\]$/;
this.reScriptSelector = /^script:(contains|inject)\((.+)\)$/; this.reScriptSelector = /^script:(contains|inject)\((.+)\)$/;
@ -786,6 +788,40 @@ FilterContainer.prototype.isValidSelector = (function() {
/******************************************************************************/ /******************************************************************************/
// https://github.com/gorhill/uBlock/issues/1668
// The key must be literal: unescape escaped CSS before extracting key.
// It's an uncommon case, so it's best to unescape only when needed.
FilterContainer.prototype.keyFromSelector = function(selector) {
var matches = this.rePlainSelector.exec(selector);
if ( matches === null ) { return; }
var key = matches[0];
if ( key.indexOf('\\') === -1 ) {
return key;
}
key = '';
matches = this.rePlainSelectorEscaped.exec(selector);
if ( matches === null ) { return; }
var escaped = matches[0],
beg = 0;
this.reEscapeSequence.lastIndex = 0;
for (;;) {
matches = this.reEscapeSequence.exec(escaped);
if ( matches === null ) {
return key + escaped.slice(beg);
}
key += escaped.slice(beg, matches.index);
beg = this.reEscapeSequence.lastIndex;
if ( matches[1].length === 1 ) {
key += matches[1];
} else {
key += String.fromCharCode(parseInt(matches[1], 16));
}
}
};
/******************************************************************************/
FilterContainer.prototype.compile = function(s, out) { FilterContainer.prototype.compile = function(s, out) {
var parsed = this.parser.parse(s); var parsed = this.parser.parse(s);
if ( parsed.cosmetic === false ) { if ( parsed.cosmetic === false ) {
@ -846,23 +882,21 @@ FilterContainer.prototype.compileGenericSelector = function(parsed, out) {
FilterContainer.prototype.compileGenericHideSelector = function(parsed, out) { FilterContainer.prototype.compileGenericHideSelector = function(parsed, out) {
var selector = parsed.suffix, var selector = parsed.suffix,
type = selector.charAt(0), type = selector.charAt(0),
matches; key, matches;
if ( type === '#' || type === '.' ) { if ( type === '#' || type === '.' ) {
matches = this.rePlainSelector.exec(selector); key = this.keyFromSelector(selector);
if ( matches === null ) { if ( key === undefined ) { return; }
return;
}
// Single-CSS rule: no need to test for whether the selector // Single-CSS rule: no need to test for whether the selector
// is valid, the regex took care of this. Most generic selector falls // is valid, the regex took care of this. Most generic selector falls
// into that category. // into that category.
if ( matches[0] === selector ) { if ( key === selector ) {
out.push('c\vlg\v' + matches[0]); out.push('c\vlg\v' + key);
return; return;
} }
// Many-CSS rules // Composite CSS rule.
if ( this.isValidSelector(selector) ) { if ( this.isValidSelector(selector) ) {
out.push('c\vlg+\v' + matches[0] + '\v' + selector); out.push('c\vlg+\v' + key + '\v' + selector);
} }
return; return;
} }