mirror of
https://github.com/gorhill/uBlock.git
synced 2024-11-07 03:12:33 +01:00
this fixes #438
This commit is contained in:
parent
e42fbb0612
commit
c0b9e634b3
@ -21,12 +21,12 @@
|
|||||||
|
|
||||||
/* jshint bitwise: false */
|
/* jshint bitwise: false */
|
||||||
/* global µBlock */
|
/* global µBlock */
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
µBlock.cosmeticFilteringEngine = (function(){
|
µBlock.cosmeticFilteringEngine = (function(){
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
@ -294,14 +294,46 @@ FilterParser.prototype.parse = function(s) {
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var SelectorCacheEntry = function() {
|
var SelectorCacheEntry = function() {
|
||||||
|
this.reset();
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
SelectorCacheEntry.junkyard = [];
|
||||||
|
|
||||||
|
SelectorCacheEntry.factory = function() {
|
||||||
|
var entry = SelectorCacheEntry.junkyard.pop();
|
||||||
|
if ( entry ) {
|
||||||
|
return entry.reset();
|
||||||
|
}
|
||||||
|
return new SelectorCacheEntry();
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
SelectorCacheEntry.prototype.netLowWaterMark = 20;
|
||||||
|
SelectorCacheEntry.prototype.netHighWaterMark = 30;
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
SelectorCacheEntry.prototype.reset = function() {
|
||||||
this.cosmetic = {};
|
this.cosmetic = {};
|
||||||
this.net = {};
|
this.net = {};
|
||||||
this.netCount = 0;
|
this.netCount = 0;
|
||||||
this.lastAccessTime = Date.now();
|
this.lastAccessTime = Date.now();
|
||||||
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
SelectorCacheEntry.prototype.netLowWaterMark = 20;
|
/******************************************************************************/
|
||||||
SelectorCacheEntry.prototype.netHighWaterMark = 30;
|
|
||||||
|
SelectorCacheEntry.prototype.dispose = function() {
|
||||||
|
this.cosmetic = this.net = null;
|
||||||
|
if ( SelectorCacheEntry.junkyard.length < 25 ) {
|
||||||
|
SelectorCacheEntry.junkyard.push(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
SelectorCacheEntry.prototype.addCosmetic = function(selectors) {
|
SelectorCacheEntry.prototype.addCosmetic = function(selectors) {
|
||||||
var dict = this.cosmetic;
|
var dict = this.cosmetic;
|
||||||
@ -311,6 +343,8 @@ SelectorCacheEntry.prototype.addCosmetic = function(selectors) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
SelectorCacheEntry.prototype.addNet = function(selectors) {
|
SelectorCacheEntry.prototype.addNet = function(selectors) {
|
||||||
if ( typeof selectors === 'string' ) {
|
if ( typeof selectors === 'string' ) {
|
||||||
this.addNetOne(selectors, Date.now());
|
this.addNetOne(selectors, Date.now());
|
||||||
@ -333,6 +367,8 @@ SelectorCacheEntry.prototype.addNet = function(selectors) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
SelectorCacheEntry.prototype.addNetOne = function(selector, now) {
|
SelectorCacheEntry.prototype.addNetOne = function(selector, now) {
|
||||||
var dict = this.net;
|
var dict = this.net;
|
||||||
if ( dict[selector] === undefined ) {
|
if ( dict[selector] === undefined ) {
|
||||||
@ -341,6 +377,8 @@ SelectorCacheEntry.prototype.addNetOne = function(selector, now) {
|
|||||||
dict[selector] = now;
|
dict[selector] = now;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
SelectorCacheEntry.prototype.addNetMany = function(selectors, now) {
|
SelectorCacheEntry.prototype.addNetMany = function(selectors, now) {
|
||||||
var dict = this.net;
|
var dict = this.net;
|
||||||
var i = selectors.length || 0;
|
var i = selectors.length || 0;
|
||||||
@ -354,6 +392,8 @@ SelectorCacheEntry.prototype.addNetMany = function(selectors, now) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
SelectorCacheEntry.prototype.add = function(selectors, type) {
|
SelectorCacheEntry.prototype.add = function(selectors, type) {
|
||||||
this.lastAccessTime = Date.now();
|
this.lastAccessTime = Date.now();
|
||||||
if ( type === 'cosmetic' ) {
|
if ( type === 'cosmetic' ) {
|
||||||
@ -363,6 +403,8 @@ SelectorCacheEntry.prototype.add = function(selectors, type) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/420
|
// https://github.com/gorhill/uBlock/issues/420
|
||||||
SelectorCacheEntry.prototype.remove = function(type) {
|
SelectorCacheEntry.prototype.remove = function(type) {
|
||||||
this.lastAccessTime = Date.now();
|
this.lastAccessTime = Date.now();
|
||||||
@ -374,6 +416,8 @@ SelectorCacheEntry.prototype.remove = function(type) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
SelectorCacheEntry.prototype.retrieve = function(type, out) {
|
SelectorCacheEntry.prototype.retrieve = function(type, out) {
|
||||||
this.lastAccessTime = Date.now();
|
this.lastAccessTime = Date.now();
|
||||||
var dict = type === 'cosmetic' ? this.cosmetic : this.net;
|
var dict = type === 'cosmetic' ? this.cosmetic : this.net;
|
||||||
@ -463,6 +507,10 @@ var FilterContainer = function() {
|
|||||||
this.type0NoDomainHash = 'type0NoDomain';
|
this.type0NoDomainHash = 'type0NoDomain';
|
||||||
this.type1NoDomainHash = 'type1NoDomain';
|
this.type1NoDomainHash = 'type1NoDomain';
|
||||||
this.parser = new FilterParser();
|
this.parser = new FilterParser();
|
||||||
|
this.selectorCachePruneDelay = 5 * 60 * 1000; // 5 minutes
|
||||||
|
this.selectorCacheAgeMax = 20 * 60 * 1000; // 20 minutes
|
||||||
|
this.selectorCacheCountMin = 10;
|
||||||
|
this.selectorCacheTimer = null;
|
||||||
this.reset();
|
this.reset();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -478,8 +526,6 @@ FilterContainer.prototype.reset = function() {
|
|||||||
|
|
||||||
this.selectorCache = {};
|
this.selectorCache = {};
|
||||||
this.selectorCacheCount = 0;
|
this.selectorCacheCount = 0;
|
||||||
this.selectorCacheLowWaterMark = 75;
|
|
||||||
this.selectorCacheHighWaterMark = 100;
|
|
||||||
|
|
||||||
// temporary (at parse time)
|
// temporary (at parse time)
|
||||||
this.lowGenericHide = {};
|
this.lowGenericHide = {};
|
||||||
@ -907,6 +953,23 @@ FilterContainer.prototype.fromSelfie = function(selfie) {
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
FilterContainer.prototype.triggerSelectorCachePruner = function() {
|
||||||
|
if ( this.selectorCacheTimer !== null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( this.selectorCacheCount <= this.selectorCacheCountMin ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Of interest: http://fitzgeraldnick.com/weblog/40/
|
||||||
|
// http://googlecode.blogspot.ca/2009/07/gmail-for-mobile-html5-series-using.html
|
||||||
|
this.selectorCacheTimer = setTimeout(
|
||||||
|
this.pruneSelectorCacheAsync.bind(this),
|
||||||
|
this.selectorCachePruneDelay
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterContainer.prototype.addToSelectorCache = function(details) {
|
FilterContainer.prototype.addToSelectorCache = function(details) {
|
||||||
var hostname = details.hostname;
|
var hostname = details.hostname;
|
||||||
if ( typeof hostname !== 'string' || hostname === '' ) {
|
if ( typeof hostname !== 'string' || hostname === '' ) {
|
||||||
@ -918,11 +981,9 @@ FilterContainer.prototype.addToSelectorCache = function(details) {
|
|||||||
}
|
}
|
||||||
var entry = this.selectorCache[hostname];
|
var entry = this.selectorCache[hostname];
|
||||||
if ( entry === undefined ) {
|
if ( entry === undefined ) {
|
||||||
entry = this.selectorCache[hostname] = new SelectorCacheEntry();
|
entry = this.selectorCache[hostname] = SelectorCacheEntry.factory();
|
||||||
this.selectorCacheCount += 1;
|
this.selectorCacheCount += 1;
|
||||||
if ( this.selectorCacheCount > this.selectorCacheHighWaterMark ) {
|
this.triggerSelectorCachePruner();
|
||||||
this.pruneSelectorCache();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
entry.add(selectors, details.type);
|
entry.add(selectors, details.type);
|
||||||
};
|
};
|
||||||
@ -953,17 +1014,33 @@ FilterContainer.prototype.retrieveFromSelectorCache = function(hostname, type, o
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterContainer.prototype.pruneSelectorCache = function() {
|
FilterContainer.prototype.pruneSelectorCacheAsync = function() {
|
||||||
var cache = this.selectorCache;
|
this.selectorCacheTimer = null;
|
||||||
var hostnames = Object.keys(cache).sort(function(a ,b) {
|
if ( this.selectorCacheCount <= this.selectorCacheCountMin ) {
|
||||||
return cache[b].lastAccessTime - cache[a].lastAccessTime;
|
return;
|
||||||
});
|
|
||||||
var toRemove = hostnames.slice(this.selectorCacheLowWaterMark);
|
|
||||||
var i = toRemove.length;
|
|
||||||
while ( i-- ) {
|
|
||||||
delete cache[toRemove[i]];
|
|
||||||
}
|
}
|
||||||
this.selectorCacheCount -= toRemove.length;
|
var cache = this.selectorCache;
|
||||||
|
// Sorted from most-recently-used to least-recently-used, because
|
||||||
|
// we loop beginning at the end below.
|
||||||
|
// We can't avoid sorting because we have to keep a minimum number of
|
||||||
|
// entries, and these entries should always be the most-recently-used.
|
||||||
|
var hostnames = Object.keys(cache)
|
||||||
|
.sort(function(a, b) { return cache[b].lastAccessTime - cache[a].lastAccessTime; })
|
||||||
|
.slice(this.selectorCacheCountMin);
|
||||||
|
var obsolete = Date.now() - this.selectorCacheAgeMax;
|
||||||
|
var hostname, entry;
|
||||||
|
var i = hostnames.length;
|
||||||
|
while ( i-- ) {
|
||||||
|
hostname = hostnames[i];
|
||||||
|
entry = cache[hostname];
|
||||||
|
if ( entry.lastAccessTime > obsolete ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// console.debug('pruneSelectorCacheAsync: flushing "%s"', hostname);
|
||||||
|
entry.dispose();
|
||||||
|
delete cache[hostname];
|
||||||
|
}
|
||||||
|
this.triggerSelectorCachePruner();
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
Loading…
Reference in New Issue
Block a user