improve slightly pre-parsing of `##script:...` filters

This commit is contained in:
Raymond Hill 2017-12-17 10:28:12 -05:00
parent 7afc78e866
commit 4a09c9f866
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
2 changed files with 38 additions and 25 deletions

View File

@ -120,7 +120,7 @@ var µBlock = (function() { // jshint ignore:line
// read-only // read-only
systemSettings: { systemSettings: {
compiledMagic: 'vrgorlgelgws', compiledMagic: 'pxpclstriajk',
selfieMagic: 'pxpclstriajk' selfieMagic: 'pxpclstriajk'
}, },

View File

@ -778,7 +778,6 @@ FilterContainer.prototype.compileSelector = (function() {
var reAfterBeforeSelector = /^(.+?)(::?after|::?before)$/, var reAfterBeforeSelector = /^(.+?)(::?after|::?before)$/,
reStyleSelector = /^(.+?):style\((.+?)\)$/, reStyleSelector = /^(.+?):style\((.+?)\)$/,
reStyleBad = /url\([^)]+\)/, reStyleBad = /url\([^)]+\)/,
reScriptSelector = /^script:(contains|inject)\((.+)\)$/,
reExtendedSyntax = /\[-(?:abp|ext)-[a-z-]+=(['"])(?:.+?)(?:\1)\]/, reExtendedSyntax = /\[-(?:abp|ext)-[a-z-]+=(['"])(?:.+?)(?:\1)\]/,
reExtendedSyntaxParser = /\[-(?:abp|ext)-([a-z-]+)=(['"])(.+?)\2\]/, reExtendedSyntaxParser = /\[-(?:abp|ext)-([a-z-]+)=(['"])(.+?)\2\]/,
div = document.createElement('div'); div = document.createElement('div');
@ -865,7 +864,7 @@ FilterContainer.prototype.compileSelector = (function() {
} }
// `script:` filter? // `script:` filter?
if ( (matches = reScriptSelector.exec(raw)) !== null ) { if ( (matches = this.reScriptSelector.exec(raw)) !== null ) {
// :inject // :inject
if ( matches[1] === 'inject' ) { if ( matches[1] === 'inject' ) {
return raw; return raw;
@ -1258,17 +1257,25 @@ FilterContainer.prototype.compileGenericHideSelector = function(parsed, writer)
/******************************************************************************/ /******************************************************************************/
FilterContainer.prototype.compileGenericUnhideSelector = function(parsed, writer) { FilterContainer.prototype.compileGenericUnhideSelector = function(parsed, writer) {
var selector = parsed.suffix; var selector = parsed.suffix,
compiled;
// script:contains(...) // script:contains(...)
// script:inject(...) // script:inject(...)
if ( this.reScriptSelector.test(selector) ) { if ( this.reScriptSelector.test(selector) ) {
writer.push([ 6 /* js */, '!', '', selector ]); compiled = [ 6 /* js */, 0, '!', '', '' ];
if ( selector.startsWith('script:inject') ) {
compiled[4] = selector.slice(14, -1).trim();
} else {
compiled[1] = 1;
compiled[4] = selector.slice(16, -1).trim();
}
writer.push(compiled);
return; return;
} }
// Procedural cosmetic filters are acceptable as generic exception filters. // Procedural cosmetic filters are acceptable as generic exception filters.
var compiled = this.compileSelector(selector); compiled = this.compileSelector(selector);
if ( compiled === undefined ) { return; } if ( compiled === undefined ) { return; }
// https://github.com/chrisaljoudi/uBlock/issues/497 // https://github.com/chrisaljoudi/uBlock/issues/497
@ -1294,7 +1301,8 @@ FilterContainer.prototype.compileHostnameSelector = function(hostname, parsed, w
var selector = parsed.suffix, var selector = parsed.suffix,
domain = this.µburi.domainFromHostname(hostname), domain = this.µburi.domainFromHostname(hostname),
hash; hash,
compiled;
// script:contains(...) // script:contains(...)
// script:inject(...) // script:inject(...)
@ -1303,11 +1311,18 @@ FilterContainer.prototype.compileHostnameSelector = function(hostname, parsed, w
if ( unhide ) { if ( unhide ) {
hash = '!' + hash; hash = '!' + hash;
} }
writer.push([ 6 /* js */, hash, hostname, selector ]); compiled = [ 6 /* js */, 0, hash, hostname, '' ];
if ( selector.startsWith('script:inject') ) {
compiled[4] = selector.slice(14, -1).trim();
} else {
compiled[1] = 1;
compiled[4] = selector.slice(16, -1).trim();
}
writer.push(compiled);
return; return;
} }
var compiled = this.compileSelector(selector); compiled = this.compileSelector(selector);
if ( compiled === undefined ) { return; } if ( compiled === undefined ) { return; }
// https://github.com/chrisaljoudi/uBlock/issues/188 // https://github.com/chrisaljoudi/uBlock/issues/188
@ -1411,7 +1426,7 @@ FilterContainer.prototype.fromCompiledContent = function(
// js, hash, example.com, script:contains(...) // js, hash, example.com, script:contains(...)
// js, hash, example.com, script:inject(...) // js, hash, example.com, script:inject(...)
case 6: case 6:
this.createScriptFilter(args[1], args[2], args[3]); this.createScriptFilter(args);
break; break;
// https://github.com/chrisaljoudi/uBlock/issues/497 // https://github.com/chrisaljoudi/uBlock/issues/497
@ -1465,7 +1480,7 @@ FilterContainer.prototype.skipGenericCompiledContent = function(reader) {
// js, hash, example.com, script:inject(...) // js, hash, example.com, script:inject(...)
case 6: case 6:
this.duplicateBuster.add(fingerprint); this.duplicateBuster.add(fingerprint);
this.createScriptFilter(args[1], args[2], args[3]); this.createScriptFilter(args);
break; break;
// https://github.com/chrisaljoudi/uBlock/issues/497 // https://github.com/chrisaljoudi/uBlock/issues/497
@ -1515,7 +1530,7 @@ FilterContainer.prototype.skipCompiledContent = function(reader) {
fingerprint = reader.fingerprint(); fingerprint = reader.fingerprint();
if ( this.duplicateBuster.has(fingerprint) === false ) { if ( this.duplicateBuster.has(fingerprint) === false ) {
this.duplicateBuster.add(fingerprint); this.duplicateBuster.add(fingerprint);
this.createScriptFilter(args[1], args[2], args[3]); this.createScriptFilter(args);
} }
continue; continue;
} }
@ -1526,12 +1541,12 @@ FilterContainer.prototype.skipCompiledContent = function(reader) {
/******************************************************************************/ /******************************************************************************/
FilterContainer.prototype.createScriptFilter = function(hash, hostname, selector) { FilterContainer.prototype.createScriptFilter = function(args) {
if ( selector.startsWith('script:contains') ) { if ( args[1] === 0 ) {
return this.createScriptTagFilter(hash, hostname, selector); return this.createUserScriptRule(args);
} }
if ( selector.startsWith('script:inject') ) { if ( args[1] === 1 ) {
return this.createUserScriptRule(hash, hostname, selector); return this.createScriptTagFilter(args);
} }
}; };
@ -1542,8 +1557,9 @@ FilterContainer.prototype.createScriptFilter = function(hash, hostname, selector
// ^ ^ // ^ ^
// 16 -1 // 16 -1
FilterContainer.prototype.createScriptTagFilter = function(hash, hostname, selector) { FilterContainer.prototype.createScriptTagFilter = function(args) {
var token = selector.slice(16, -1); var hostname = args[3],
token = args[4];
token = token.startsWith('/') && token.endsWith('/') token = token.startsWith('/') && token.endsWith('/')
? token.slice(1, -1) ? token.slice(1, -1)
: token.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); : token.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
@ -1603,12 +1619,9 @@ FilterContainer.prototype.retrieveScriptTagRegex = function(domain, hostname) {
// userScripts{hash} => FilterHostname | FilterBucket // userScripts{hash} => FilterHostname | FilterBucket
FilterContainer.prototype.createUserScriptRule = function( FilterContainer.prototype.createUserScriptRule = function(args) {
hash, var hash = args[2],
hostname, filter = new FilterHostname(args[4], args[3]);
selector
) {
var filter = new FilterHostname(selector.slice(14, -1).trim(), hostname);
var bucket = this.userScripts.get(hash); var bucket = this.userScripts.get(hash);
if ( bucket === undefined ) { if ( bucket === undefined ) {
this.userScripts.set(hash, filter); this.userScripts.set(hash, filter);