mirror of https://github.com/gorhill/uBlock.git
code review: reuse last decomposed hostname (hit rate = 75%)
This commit is contained in:
parent
46c81ea691
commit
7766786b2c
|
@ -70,41 +70,9 @@ var nameToActionMap = {
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// For performance purpose, as simple tests as possible
|
// For performance purpose, as simple tests as possible
|
||||||
var reHostnameVeryCoarse = /[g-z_-]/;
|
|
||||||
var reIPv4VeryCoarse = /\.\d+$/;
|
|
||||||
var reBadHostname = /[^0-9a-z_.\[\]:%-]/;
|
var reBadHostname = /[^0-9a-z_.\[\]:%-]/;
|
||||||
var reNotASCII = /[^\x20-\x7F]/;
|
var reNotASCII = /[^\x20-\x7F]/;
|
||||||
|
|
||||||
// http://tools.ietf.org/html/rfc5952
|
|
||||||
// 4.3: "MUST be represented in lowercase"
|
|
||||||
// Also: http://en.wikipedia.org/wiki/IPv6_address#Literal_IPv6_addresses_in_network_resource_identifiers
|
|
||||||
|
|
||||||
var isIPAddress = function(hostname) {
|
|
||||||
if ( reHostnameVeryCoarse.test(hostname) ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( reIPv4VeryCoarse.test(hostname) ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return hostname.startsWith('[');
|
|
||||||
};
|
|
||||||
|
|
||||||
var toBroaderHostname = function(hostname) {
|
|
||||||
var pos = hostname.indexOf('.');
|
|
||||||
if ( pos !== -1 ) {
|
|
||||||
return hostname.slice(pos + 1);
|
|
||||||
}
|
|
||||||
return hostname !== '*' && hostname !== '' ? '*' : '';
|
|
||||||
};
|
|
||||||
|
|
||||||
var toBroaderIPAddress = function(ipaddress) {
|
|
||||||
return ipaddress !== '*' && ipaddress !== '' ? '*' : '';
|
|
||||||
};
|
|
||||||
|
|
||||||
var selectHostnameBroadener = function(hostname) {
|
|
||||||
return isIPAddress(hostname) ? toBroaderIPAddress : toBroaderHostname;
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
Matrix.prototype.reset = function() {
|
Matrix.prototype.reset = function() {
|
||||||
|
@ -114,6 +82,8 @@ Matrix.prototype.reset = function() {
|
||||||
this.z = '';
|
this.z = '';
|
||||||
this.rules = new Map();
|
this.rules = new Map();
|
||||||
this.changed = false;
|
this.changed = false;
|
||||||
|
this.decomposedSource = [];
|
||||||
|
this.decomposedDestination = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -291,14 +261,13 @@ var domainFromHostname = µBlock.URI.domainFromHostname;
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
Matrix.prototype.evaluateCellZ = function(srcHostname, desHostname, type, broadener) {
|
Matrix.prototype.evaluateCellZ = function(srcHostname, desHostname, type) {
|
||||||
|
µBlock.decomposeHostname(srcHostname, this.decomposedSource);
|
||||||
this.type = type;
|
this.type = type;
|
||||||
var bitOffset = typeBitOffsets[type];
|
let bitOffset = typeBitOffsets[type];
|
||||||
var s = srcHostname;
|
for ( let shn of this.decomposedSource ) {
|
||||||
var v;
|
this.z = shn;
|
||||||
for (;;) {
|
let v = this.rules.get(shn + ' ' + desHostname);
|
||||||
this.z = s;
|
|
||||||
v = this.rules.get(s + ' ' + desHostname);
|
|
||||||
if ( v !== undefined ) {
|
if ( v !== undefined ) {
|
||||||
v = v >>> bitOffset & 3;
|
v = v >>> bitOffset & 3;
|
||||||
if ( v !== 0 ) {
|
if ( v !== 0 ) {
|
||||||
|
@ -306,8 +275,6 @@ Matrix.prototype.evaluateCellZ = function(srcHostname, desHostname, type, broade
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s = broadener(s);
|
|
||||||
if ( s === '' ) { break; }
|
|
||||||
}
|
}
|
||||||
// srcHostname is '*' at this point
|
// srcHostname is '*' at this point
|
||||||
this.r = 0;
|
this.r = 0;
|
||||||
|
@ -318,29 +285,24 @@ Matrix.prototype.evaluateCellZ = function(srcHostname, desHostname, type, broade
|
||||||
|
|
||||||
Matrix.prototype.evaluateCellZY = function(srcHostname, desHostname, type) {
|
Matrix.prototype.evaluateCellZY = function(srcHostname, desHostname, type) {
|
||||||
// Pathological cases.
|
// Pathological cases.
|
||||||
var d = desHostname;
|
if ( desHostname === '' ) {
|
||||||
if ( d === '' ) {
|
|
||||||
this.r = 0;
|
this.r = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare broadening handlers -- depends on whether we are dealing with
|
|
||||||
// a hostname or IP address.
|
|
||||||
var broadenSource = selectHostnameBroadener(srcHostname),
|
|
||||||
broadenDestination = selectHostnameBroadener(desHostname);
|
|
||||||
|
|
||||||
// Precedence: from most specific to least specific
|
// Precedence: from most specific to least specific
|
||||||
|
|
||||||
// Specific-destination, any party, any type
|
// Specific-destination, any party, any type
|
||||||
while ( d !== '*' ) {
|
µBlock.decomposeHostname(desHostname, this.decomposedDestination);
|
||||||
this.y = d;
|
for ( let dhn of this.decomposedDestination ) {
|
||||||
if ( this.evaluateCellZ(srcHostname, d, '*', broadenSource) !== 0 ) {
|
if ( dhn === '*' ) { break; }
|
||||||
|
this.y = dhn;
|
||||||
|
if ( this.evaluateCellZ(srcHostname, dhn, '*') !== 0 ) {
|
||||||
return this.r;
|
return this.r;
|
||||||
}
|
}
|
||||||
d = broadenDestination(d);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var thirdParty = is3rdParty(srcHostname, desHostname);
|
let thirdParty = is3rdParty(srcHostname, desHostname);
|
||||||
|
|
||||||
// Any destination
|
// Any destination
|
||||||
this.y = '*';
|
this.y = '*';
|
||||||
|
@ -349,34 +311,34 @@ Matrix.prototype.evaluateCellZY = function(srcHostname, desHostname, type) {
|
||||||
if ( thirdParty ) {
|
if ( thirdParty ) {
|
||||||
// 3rd-party, specific type
|
// 3rd-party, specific type
|
||||||
if ( type === 'script' ) {
|
if ( type === 'script' ) {
|
||||||
if ( this.evaluateCellZ(srcHostname, '*', '3p-script', broadenSource) !== 0 ) {
|
if ( this.evaluateCellZ(srcHostname, '*', '3p-script') !== 0 ) {
|
||||||
return this.r;
|
return this.r;
|
||||||
}
|
}
|
||||||
} else if ( type === 'sub_frame' ) {
|
} else if ( type === 'sub_frame' ) {
|
||||||
if ( this.evaluateCellZ(srcHostname, '*', '3p-frame', broadenSource) !== 0 ) {
|
if ( this.evaluateCellZ(srcHostname, '*', '3p-frame') !== 0 ) {
|
||||||
return this.r;
|
return this.r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 3rd-party, any type
|
// 3rd-party, any type
|
||||||
if ( this.evaluateCellZ(srcHostname, '*', '3p', broadenSource) !== 0 ) {
|
if ( this.evaluateCellZ(srcHostname, '*', '3p') !== 0 ) {
|
||||||
return this.r;
|
return this.r;
|
||||||
}
|
}
|
||||||
} else if ( type === 'script' ) {
|
} else if ( type === 'script' ) {
|
||||||
// 1st party, specific type
|
// 1st party, specific type
|
||||||
if ( this.evaluateCellZ(srcHostname, '*', '1p-script', broadenSource) !== 0 ) {
|
if ( this.evaluateCellZ(srcHostname, '*', '1p-script') !== 0 ) {
|
||||||
return this.r;
|
return this.r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Any destination, any party, specific type
|
// Any destination, any party, specific type
|
||||||
if ( supportedDynamicTypes.hasOwnProperty(type) ) {
|
if ( supportedDynamicTypes.hasOwnProperty(type) ) {
|
||||||
if ( this.evaluateCellZ(srcHostname, '*', type, broadenSource) !== 0 ) {
|
if ( this.evaluateCellZ(srcHostname, '*', type) !== 0 ) {
|
||||||
return this.r;
|
return this.r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Any destination, any party, any type
|
// Any destination, any party, any type
|
||||||
if ( this.evaluateCellZ(srcHostname, '*', '*', broadenSource) !== 0 ) {
|
if ( this.evaluateCellZ(srcHostname, '*', '*') !== 0 ) {
|
||||||
return this.r;
|
return this.r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,40 +60,12 @@ var nameToSwitchStateMap = {
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// For performance purpose, as simple tests as possible
|
// For performance purpose, as simple tests as possible
|
||||||
var reHostnameVeryCoarse = /[g-z_-]/;
|
|
||||||
var reIPv4VeryCoarse = /\.\d+$/;
|
|
||||||
var reNotASCII = /[^\x20-\x7F]/;
|
var reNotASCII = /[^\x20-\x7F]/;
|
||||||
|
|
||||||
// http://tools.ietf.org/html/rfc5952
|
// http://tools.ietf.org/html/rfc5952
|
||||||
// 4.3: "MUST be represented in lowercase"
|
// 4.3: "MUST be represented in lowercase"
|
||||||
// Also: http://en.wikipedia.org/wiki/IPv6_address#Literal_IPv6_addresses_in_network_resource_identifiers
|
// Also: http://en.wikipedia.org/wiki/IPv6_address#Literal_IPv6_addresses_in_network_resource_identifiers
|
||||||
|
|
||||||
var isIPAddress = function(hostname) {
|
|
||||||
if ( reHostnameVeryCoarse.test(hostname) ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( reIPv4VeryCoarse.test(hostname) ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return hostname.startsWith('[');
|
|
||||||
};
|
|
||||||
|
|
||||||
var toBroaderHostname = function(hostname) {
|
|
||||||
var pos = hostname.indexOf('.');
|
|
||||||
if ( pos !== -1 ) {
|
|
||||||
return hostname.slice(pos + 1);
|
|
||||||
}
|
|
||||||
return hostname !== '*' && hostname !== '' ? '*' : '';
|
|
||||||
};
|
|
||||||
|
|
||||||
var toBroaderIPAddress = function(ipaddress) {
|
|
||||||
return ipaddress !== '*' && ipaddress !== '' ? '*' : '';
|
|
||||||
};
|
|
||||||
|
|
||||||
var selectHostnameBroadener = function(hostname) {
|
|
||||||
return isIPAddress(hostname) ? toBroaderIPAddress : toBroaderHostname;
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
HnSwitches.prototype.reset = function() {
|
HnSwitches.prototype.reset = function() {
|
||||||
|
@ -102,6 +74,7 @@ HnSwitches.prototype.reset = function() {
|
||||||
this.z = '';
|
this.z = '';
|
||||||
this.r = 0;
|
this.r = 0;
|
||||||
this.changed = true;
|
this.changed = true;
|
||||||
|
this.decomposedSource = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -220,21 +193,17 @@ HnSwitches.prototype.evaluateZ = function(switchName, hostname) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.n = switchName;
|
this.n = switchName;
|
||||||
var bits,
|
µBlock.decomposeHostname(hostname, this.decomposedSource);
|
||||||
hn = hostname,
|
for ( let shn of this.decomposedSource ) {
|
||||||
broadenSource = selectHostnameBroadener(hn);
|
let bits = this.switches.get(shn);
|
||||||
for (;;) {
|
|
||||||
bits = this.switches.get(hn);
|
|
||||||
if ( bits !== undefined ) {
|
if ( bits !== undefined ) {
|
||||||
bits = bits >>> bitOffset & 3;
|
bits = bits >>> bitOffset & 3;
|
||||||
if ( bits !== 0 ) {
|
if ( bits !== 0 ) {
|
||||||
this.z = hn;
|
this.z = shn;
|
||||||
this.r = bits;
|
this.r = bits;
|
||||||
return bits === 1;
|
return bits === 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hn = broadenSource(hn);
|
|
||||||
if ( hn === '' ) { break; }
|
|
||||||
}
|
}
|
||||||
this.r = 0;
|
this.r = 0;
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -137,6 +137,7 @@ URLNetFiltering.prototype.reset = function() {
|
||||||
this.type = '';
|
this.type = '';
|
||||||
this.r = 0;
|
this.r = 0;
|
||||||
this.changed = false;
|
this.changed = false;
|
||||||
|
this.decomposedSource = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -207,32 +208,31 @@ URLNetFiltering.prototype.evaluateZ = function(context, target, type) {
|
||||||
if ( this.rules.size === 0 ) {
|
if ( this.rules.size === 0 ) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
var entries, pos, i, entry;
|
µBlock.decomposeHostname(context, this.decomposedSource);
|
||||||
for (;;) {
|
for ( let shn of this.decomposedSource ) {
|
||||||
this.context = context;
|
this.context = shn;
|
||||||
if ( (entries = this.rules.get(context + ' ' + type)) ) {
|
let entries = this.rules.get(shn + ' ' + type);
|
||||||
i = indexOfMatch(entries, target);
|
if ( entries !== undefined ) {
|
||||||
|
let i = indexOfMatch(entries, target);
|
||||||
if ( i !== -1 ) {
|
if ( i !== -1 ) {
|
||||||
entry = entries[i];
|
let entry = entries[i];
|
||||||
this.url = entry.url;
|
this.url = entry.url;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.r = entry.action;
|
this.r = entry.action;
|
||||||
return this.r;
|
return this.r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( (entries = this.rules.get(context + ' *')) ) {
|
entries = this.rules.get(shn + ' *');
|
||||||
i = indexOfMatch(entries, target);
|
if ( entries !== undefined ) {
|
||||||
|
let i = indexOfMatch(entries, target);
|
||||||
if ( i !== -1 ) {
|
if ( i !== -1 ) {
|
||||||
entry = entries[i];
|
let entry = entries[i];
|
||||||
this.url = entry.url;
|
this.url = entry.url;
|
||||||
this.type = '*';
|
this.type = '*';
|
||||||
this.r = entry.action;
|
this.r = entry.action;
|
||||||
return this.r;
|
return this.r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( context === '*' ) { break; }
|
|
||||||
pos = context.indexOf('.');
|
|
||||||
context = pos !== -1 ? context.slice(pos + 1) : '*';
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -416,3 +416,48 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
µBlock.decomposeHostname = (function() {
|
||||||
|
// For performance purpose, as simple tests as possible
|
||||||
|
let reHostnameVeryCoarse = /[g-z_-]/;
|
||||||
|
let reIPv4VeryCoarse = /\.\d+$/;
|
||||||
|
|
||||||
|
let isIPAddress = function(hostname) {
|
||||||
|
if ( reHostnameVeryCoarse.test(hostname) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( reIPv4VeryCoarse.test(hostname) ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return hostname.startsWith('[');
|
||||||
|
};
|
||||||
|
|
||||||
|
let toBroaderHostname = function(hostname) {
|
||||||
|
let pos = hostname.indexOf('.');
|
||||||
|
if ( pos !== -1 ) {
|
||||||
|
return hostname.slice(pos + 1);
|
||||||
|
}
|
||||||
|
return hostname !== '*' && hostname !== '' ? '*' : '';
|
||||||
|
};
|
||||||
|
|
||||||
|
let toBroaderIPAddress = function(ipaddress) {
|
||||||
|
return ipaddress !== '*' && ipaddress !== '' ? '*' : '';
|
||||||
|
};
|
||||||
|
|
||||||
|
return function decomposeHostname(hostname, decomposed) {
|
||||||
|
if ( decomposed.length === 0 || decomposed[0] !== hostname ) {
|
||||||
|
let broaden = isIPAddress(hostname) ?
|
||||||
|
toBroaderIPAddress :
|
||||||
|
toBroaderHostname;
|
||||||
|
decomposed[0] = hostname;
|
||||||
|
let i = 1;
|
||||||
|
for (;;) {
|
||||||
|
hostname = broaden(hostname);
|
||||||
|
if ( hostname === '' ) { break; }
|
||||||
|
decomposed[i++] = hostname;
|
||||||
|
}
|
||||||
|
decomposed.length = i;
|
||||||
|
}
|
||||||
|
return decomposed;
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
Loading…
Reference in New Issue