diff --git a/src/js/cosmetic-filtering.js b/src/js/cosmetic-filtering.js index d8534c49b..f9c1a79a1 100644 --- a/src/js/cosmetic-filtering.js +++ b/src/js/cosmetic-filtering.js @@ -204,6 +204,9 @@ const FilterContainer = function() { // specific filters this.specificFilters = new µb.staticExtFilteringEngine.HostnameBasedDB(2); + // temporary filters + this.sessionFilterDB = new µb.staticExtFilteringEngine.SessionDB(); + // low generic cosmetic filters, organized by id/class then simple/complex. this.lowlyGeneric = Object.create(null); this.lowlyGeneric.id = { @@ -827,7 +830,7 @@ FilterContainer.prototype.randomAlphaToken = function() { /******************************************************************************/ FilterContainer.prototype.getSession = function() { - return this.specificFilters.session; + return this.sessionFilterDB; }; /******************************************************************************/ @@ -997,7 +1000,9 @@ FilterContainer.prototype.retrieveSpecificSelectors = function( } // Retrieve temporary filters - this.specificFilters.session.retrieve([ dummySet, exceptionSet ]); + if ( this.sessionFilterDB.isNotEmpty ) { + this.sessionFilterDB.retrieve([ null, exceptionSet ]); + } // Retrieve filters with a non-empty hostname this.specificFilters.retrieve( diff --git a/src/js/html-filtering.js b/src/js/html-filtering.js index 9d7c8c19d..338d5e18d 100644 --- a/src/js/html-filtering.js +++ b/src/js/html-filtering.js @@ -28,10 +28,11 @@ const pselectors = new Map(); const duplicates = new Set(); - let filterDB = new µb.staticExtFilteringEngine.HostnameBasedDB(2), - acceptedCount = 0, - discardedCount = 0, - docRegister; + const filterDB = new µb.staticExtFilteringEngine.HostnameBasedDB(2); + const sessionFilterDB = new µb.staticExtFilteringEngine.SessionDB(); + let acceptedCount = 0; + let discardedCount = 0; + let docRegister; const api = { get acceptedCount() { @@ -335,7 +336,7 @@ }; api.getSession = function() { - return filterDB.session; + return sessionFilterDB; }; api.retrieve = function(details) { @@ -354,7 +355,9 @@ const procedurals = new Set(); const exceptions = new Set(); - filterDB.session.retrieve([ new Set(), exceptions ]); + if ( sessionFilterDB.isNotEmpty ) { + sessionFilterDB.retrieve([ null, exceptions ]); + } filterDB.retrieve( hostname, [ plains, exceptions, procedurals, exceptions ] @@ -415,7 +418,7 @@ }; api.fromSelfie = function(selfie) { - filterDB = new µb.staticExtFilteringEngine.HostnameBasedDB(2, selfie); + filterDB.fromSelfie(selfie); pselectors.clear(); }; diff --git a/src/js/logger-ui.js b/src/js/logger-ui.js index 400883189..6736de2ed 100644 --- a/src/js/logger-ui.js +++ b/src/js/logger-ui.js @@ -1451,14 +1451,11 @@ const reloadTab = function(ev) { span.className = 'filter'; span.textContent = selector; fragment.appendChild(span); - let isTemporaryException = false; - if ( match[0] === '#@#' ) { - isTemporaryException = await messaging.send('loggerUI', { - what: 'hasTemporaryException', - filter, - }); - receiver.classList.toggle('exceptored', isTemporaryException); - } + const isTemporaryException = await messaging.send('loggerUI', { + what: 'hasTemporaryException', + filter, + }); + receiver.classList.toggle('exceptored', isTemporaryException); if ( match[0] === '##' || isTemporaryException ) { receiver.children[2].style.visibility = ''; } diff --git a/src/js/scriptlet-filtering.js b/src/js/scriptlet-filtering.js index e83c44e90..29a630dc5 100644 --- a/src/js/scriptlet-filtering.js +++ b/src/js/scriptlet-filtering.js @@ -24,14 +24,15 @@ /******************************************************************************/ µBlock.scriptletFilteringEngine = (function() { - const µb = µBlock, - duplicates = new Set(), - scriptletCache = new µb.MRUCache(32), - reEscapeScriptArg = /[\\'"]/g; + const µb = µBlock; + const duplicates = new Set(); + const scriptletCache = new µb.MRUCache(32); + const reEscapeScriptArg = /[\\'"]/g; - let acceptedCount = 0, - discardedCount = 0, - scriptletDB = new µb.staticExtFilteringEngine.HostnameBasedDB(1); + const scriptletDB = new µb.staticExtFilteringEngine.HostnameBasedDB(1); + const sessionScriptletDB = new µb.staticExtFilteringEngine.SessionDB(); + let acceptedCount = 0; + let discardedCount = 0; const api = { get acceptedCount() { @@ -343,7 +344,7 @@ }; api.getSession = function() { - return scriptletDB.session; + return sessionScriptletDB; }; const scriptlets$ = new Set(); @@ -371,7 +372,9 @@ scriptlets$.clear(); exceptions$.clear(); - scriptletDB.session.retrieve([ scriptlets$, exceptions$ ]); + if ( sessionScriptletDB.isNotEmpty ) { + sessionScriptletDB.retrieve([ null, exceptions$ ]); + } scriptletDB.retrieve(hostname, [ scriptlets$, exceptions$ ]); if ( request.entity !== '' ) { scriptletDB.retrieve( @@ -464,7 +467,7 @@ }; api.fromSelfie = function(selfie) { - scriptletDB = new µb.staticExtFilteringEngine.HostnameBasedDB(1, selfie); + scriptletDB.fromSelfie(selfie); }; api.benchmark = async function() { diff --git a/src/js/static-ext-filtering.js b/src/js/static-ext-filtering.js index 53da1919d..087f2da07 100644 --- a/src/js/static-ext-filtering.js +++ b/src/js/static-ext-filtering.js @@ -511,7 +511,6 @@ //-------------------------------------------------------------------------- api.HostnameBasedDB = class { - constructor(nBits, selfie = undefined) { this.nBits = nBits; this.timer = undefined; @@ -524,41 +523,6 @@ // Array of strings (selectors and pseudo-selectors) this.strSlots = []; this.size = 0; - // Temporary set - this.session = { - collection: new Map(), - add: function(bits, s) { - const bucket = this.collection.get(bits); - if ( bucket === undefined ) { - this.collection.set(bits, new Set([ s ])); - } else { - bucket.add(s); - } - }, - remove: function(bits, s) { - const bucket = this.collection.get(bits); - if ( bucket === undefined ) { return; } - bucket.delete(s); - if ( bucket.size !== 0 ) { return; } - this.collection.delete(bits); - }, - retrieve(out) { - const mask = out.length - 1; - for ( const [ bits, bucket ] of this.collection ) { - for ( const s of bucket ) { - out[bits & mask].add(s); - } - } - }, - has(bits, s) { - const selectors = this.collection.get(bits); - return selectors !== undefined && selectors.has(s); - }, - clear() { - this.collection.clear(); - }, - }; - if ( selfie !== undefined ) { this.fromSelfie(selfie); } @@ -675,6 +639,47 @@ } }; + api.SessionDB = class { + constructor() { + this.db = new Map(); + } + add(bits, s) { + const bucket = this.db.get(bits); + if ( bucket === undefined ) { + this.db.set(bits, new Set([ s ])); + } else { + bucket.add(s); + } + } + remove(bits, s) { + const bucket = this.db.get(bits); + if ( bucket === undefined ) { return; } + bucket.delete(s); + if ( bucket.size !== 0 ) { return; } + this.db.delete(bits); + } + retrieve(out) { + const mask = out.length - 1; + for ( const [ bits, bucket ] of this.db ) { + const i = bits & mask; + if ( out[i] instanceof Object === false ) { continue; } + for ( const s of bucket ) { + out[i].add(s); + } + } + } + has(bits, s) { + const selectors = this.db.get(bits); + return selectors !== undefined && selectors.has(s); + } + clear() { + this.db.clear(); + } + get isNotEmpty() { + return this.db.size !== 0; + } + }; + //-------------------------------------------------------------------------- // Public methods //--------------------------------------------------------------------------