diff --git a/platform/common/vapi-background.js b/platform/common/vapi-background.js index 20e8e29e0..6e3aa86c5 100644 --- a/platform/common/vapi-background.js +++ b/platform/common/vapi-background.js @@ -919,6 +919,9 @@ vAPI.messaging = { this.onPortDisconnect(port); } } + if ( this.defaultHandler ) { + this.defaultHandler(message, null, ( ) => { }); + } }, onFrameworkMessage: function(request, port, callback) { diff --git a/src/css/logger-ui.css b/src/css/logger-ui.css index 44c8bffe4..ec1712065 100644 --- a/src/css/logger-ui.css +++ b/src/css/logger-ui.css @@ -678,6 +678,9 @@ body[dir="rtl"] #netFilteringDialog > .panes > .details > div > span:nth-of-type background-color: rgb(var(--primary-50) / 50%); } #netFilteringDialog > .panes > .details .exceptor::before { + content: '@@'; + } +#netFilteringDialog.extendedRealm > .panes > .details .exceptor::before { content: '#@#'; } #netFilteringDialog > div.panes > .dynamic > .toolbar { diff --git a/src/js/background.js b/src/js/background.js index a381fac6c..b91a2fb69 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -211,6 +211,9 @@ const µBlock = { // jshint ignore:line availableFilterLists: {}, badLists: new Map(), + inMemoryFilters: [], + inMemoryFiltersCompiled: '', + // https://github.com/uBlockOrigin/uBlock-issues/issues/974 // This can be used to defer filtering decision-making. readyToFilter: false, diff --git a/src/js/cosmetic-filtering.js b/src/js/cosmetic-filtering.js index d473371db..c4dfd3992 100644 --- a/src/js/cosmetic-filtering.js +++ b/src/js/cosmetic-filtering.js @@ -27,10 +27,7 @@ import './utils.js'; import logger from './logger.js'; import µb from './background.js'; -import { - StaticExtFilteringHostnameDB, - StaticExtFilteringSessionDB, -} from './static-ext-filtering-db.js'; +import { StaticExtFilteringHostnameDB } from './static-ext-filtering-db.js'; /******************************************************************************/ /******************************************************************************/ @@ -236,10 +233,7 @@ const FilterContainer = function() { // specific filters this.specificFilters = new StaticExtFilteringHostnameDB(2); - // temporary filters - this.sessionFilterDB = new StaticExtFilteringSessionDB(); - - // low generic cosmetic filters: map of hash => array of selectors + // low generic cosmetic filters: map of hash => stringified selector list this.lowlyGeneric = new Map(); // highly generic selectors sets @@ -478,15 +472,6 @@ FilterContainer.prototype.compileSpecificSelector = function( /******************************************************************************/ -FilterContainer.prototype.compileTemporary = function(parser) { - return { - session: this.sessionFilterDB, - selector: parser.result.compiled, - }; -}; - -/******************************************************************************/ - FilterContainer.prototype.fromCompiledContent = function(reader, options) { if ( options.skipCosmetic ) { this.skipCompiledContent(reader, 'SPECIFIC'); @@ -697,12 +682,6 @@ FilterContainer.prototype.disableSurveyor = function(details) { /******************************************************************************/ -FilterContainer.prototype.getSession = function() { - return this.sessionFilterDB; -}; - -/******************************************************************************/ - FilterContainer.prototype.cssRuleFromProcedural = function(json) { const pfilter = JSON.parse(json); if ( pfilter.cssable !== true ) { return; } @@ -831,11 +810,6 @@ FilterContainer.prototype.retrieveSpecificSelectors = function( } } - // Retrieve temporary filters - if ( this.sessionFilterDB.isNotEmpty ) { - this.sessionFilterDB.retrieve([ null, exceptionSet ]); - } - // Retrieve filters with a non-empty hostname this.specificFilters.retrieve( hostname, diff --git a/src/js/html-filtering.js b/src/js/html-filtering.js index c9dc8a8f0..9867d1842 100644 --- a/src/js/html-filtering.js +++ b/src/js/html-filtering.js @@ -27,10 +27,7 @@ import logger from './logger.js'; import µb from './background.js'; import { sessionFirewall } from './filtering-engines.js'; -import { - StaticExtFilteringHostnameDB, - StaticExtFilteringSessionDB, -} from './static-ext-filtering-db.js'; +import { StaticExtFilteringHostnameDB } from './static-ext-filtering-db.js'; /******************************************************************************/ @@ -38,7 +35,6 @@ const pselectors = new Map(); const duplicates = new Set(); const filterDB = new StaticExtFilteringHostnameDB(2); -const sessionFilterDB = new StaticExtFilteringSessionDB(); let acceptedCount = 0; let discardedCount = 0; @@ -347,13 +343,6 @@ htmlFilteringEngine.compile = function(parser, writer) { } }; -htmlFilteringEngine.compileTemporary = function(parser) { - return { - session: sessionFilterDB, - selector: parser.result.compiled, - }; -}; - htmlFilteringEngine.fromCompiledContent = function(reader) { // Don't bother loading filters if stream filtering is not supported. if ( µb.canFilterResponseData === false ) { return; } @@ -373,10 +362,6 @@ htmlFilteringEngine.fromCompiledContent = function(reader) { } }; -htmlFilteringEngine.getSession = function() { - return sessionFilterDB; -}; - htmlFilteringEngine.retrieve = function(details) { const hostname = details.hostname; @@ -384,9 +369,6 @@ htmlFilteringEngine.retrieve = function(details) { const procedurals = new Set(); const exceptions = new Set(); - if ( sessionFilterDB.isNotEmpty ) { - sessionFilterDB.retrieve([ null, exceptions ]); - } filterDB.retrieve( hostname, [ plains, exceptions, procedurals, exceptions ] diff --git a/src/js/httpheader-filtering.js b/src/js/httpheader-filtering.js index c959e565e..53d10217e 100644 --- a/src/js/httpheader-filtering.js +++ b/src/js/httpheader-filtering.js @@ -28,16 +28,12 @@ import µb from './background.js'; import { entityFromDomain } from './uri-utils.js'; import { sessionFirewall } from './filtering-engines.js'; -import { - StaticExtFilteringHostnameDB, - StaticExtFilteringSessionDB, -} from './static-ext-filtering-db.js'; +import { StaticExtFilteringHostnameDB } from './static-ext-filtering-db.js'; /******************************************************************************/ const duplicates = new Set(); const filterDB = new StaticExtFilteringHostnameDB(1); -const sessionFilterDB = new StaticExtFilteringSessionDB(); const $headers = new Set(); const $exceptions = new Set(); @@ -123,13 +119,6 @@ httpheaderFilteringEngine.compile = function(parser, writer) { } }; -httpheaderFilteringEngine.compileTemporary = function(parser) { - return { - session: sessionFilterDB, - selector: parser.result.compiled.slice(15, -1), - }; -}; - // 01234567890123456789 // responseheader(name) // ^ ^ @@ -152,10 +141,6 @@ httpheaderFilteringEngine.fromCompiledContent = function(reader) { } }; -httpheaderFilteringEngine.getSession = function() { - return sessionFilterDB; -}; - httpheaderFilteringEngine.apply = function(fctxt, headers) { if ( filterDB.size === 0 ) { return; } @@ -173,9 +158,6 @@ httpheaderFilteringEngine.apply = function(fctxt, headers) { $headers.clear(); $exceptions.clear(); - if ( sessionFilterDB.isNotEmpty ) { - sessionFilterDB.retrieve([ null, $exceptions ]); - } filterDB.retrieve(hostname, [ $headers, $exceptions ]); filterDB.retrieve(entity, [ $headers, $exceptions ], 1); if ( $headers.size === 0 ) { return; } diff --git a/src/js/logger-ui.js b/src/js/logger-ui.js index aa0feb127..87f2e1167 100644 --- a/src/js/logger-ui.js +++ b/src/js/logger-ui.js @@ -1246,9 +1246,13 @@ const reloadTab = function(ev) { // Toggle temporary exception filter if ( tcl.contains('exceptor') ) { ev.stopPropagation(); + const filter = filterFromTargetRow(); + const exceptedFilter = dom.cl.has(targetRow, 'extendedRealm') + ? `#@#${filter.replace(/^.*?#@?#/, '')}` + : `@@${filter.replace(/^@@/, '')}`; const status = await messaging.send('loggerUI', { - what: 'toggleTemporaryException', - filter: filterFromTargetRow(), + what: 'toggleInMemoryFilter', + filter: exceptedFilter, }); const row = target.closest('div'); dom.cl.toggle(row, 'exceptored', status); @@ -1477,26 +1481,16 @@ const reloadTab = function(ev) { const toSummaryPaneFilterNode = async function(receiver, filter) { receiver.children[1].textContent = filter; if ( filterAuthorMode !== true ) { return; } - const match = /#@?#/.exec(filter); - if ( match === null ) { return; } - const fragment = document.createDocumentFragment(); - const pos = match.index + match[0].length; - fragment.appendChild(document.createTextNode(filter.slice(0, pos))); - const selector = filter.slice(pos); - const span = document.createElement('span'); - span.className = 'filter'; - span.textContent = selector; - fragment.appendChild(span); + if ( dom.cl.has(targetRow, 'canLookup') === false ) { return; } + const exceptedFilter = dom.cl.has(targetRow, 'extendedRealm') + ? `#@#${filter.replace(/^.*?#@?#/, '')}` + : `@@${filter.replace(/^@@/, '')}`; const isTemporaryException = await messaging.send('loggerUI', { - what: 'hasTemporaryException', - filter, + what: 'hasInMemoryFilter', + filter: exceptedFilter, }); dom.cl.toggle(receiver, 'exceptored', isTemporaryException); - if ( match[0] === '##' || isTemporaryException ) { - receiver.children[2].style.visibility = ''; - } - receiver.children[1].textContent = ''; - receiver.children[1].appendChild(fragment); + receiver.children[2].style.visibility = ''; }; const fillSummaryPaneFilterList = async function(rows) { diff --git a/src/js/logger.js b/src/js/logger.js index 9abf6a588..9318621b2 100644 --- a/src/js/logger.js +++ b/src/js/logger.js @@ -32,19 +32,15 @@ let writePtr = 0; const logBufferObsoleteAfter = 30 * 1000; const janitor = ( ) => { - if ( - buffer !== null && - lastReadTime < (Date.now() - logBufferObsoleteAfter) - ) { - logger.enabled = false; - buffer = null; - writePtr = 0; - logger.ownerId = undefined; - vAPI.messaging.broadcast({ what: 'loggerDisabled' }); - } - if ( buffer !== null ) { - vAPI.setTimeout(janitor, logBufferObsoleteAfter); + if ( buffer === null ) { return; } + if ( lastReadTime >= (Date.now() - logBufferObsoleteAfter) ) { + return vAPI.setTimeout(janitor, logBufferObsoleteAfter); } + logger.enabled = false; + buffer = null; + writePtr = 0; + logger.ownerId = undefined; + vAPI.messaging.broadcast({ what: 'loggerDisabled' }); }; const boxEntry = function(details) { diff --git a/src/js/messaging.js b/src/js/messaging.js index 1fd1c511e..bdc90ddd9 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -35,7 +35,6 @@ import logger from './logger.js'; import lz4Codec from './lz4.js'; import io from './assets.js'; import scriptletFilteringEngine from './scriptlet-filtering.js'; -import staticExtFilteringEngine from './static-ext-filtering.js'; import staticFilteringReverseLookup from './reverselookup.js'; import staticNetFilteringEngine from './static-net-filtering.js'; import µb from './background.js'; @@ -305,6 +304,10 @@ const onMessage = function(request, sender, callback) { µb.elementPickerExec(request.tabId, 0, request.targetURL, request.zap); break; + case 'loggerDisabled': + µb.clearInMemoryFilters(); + break; + case 'gotoURL': µb.openNewTab(request.details); break; @@ -1680,42 +1683,11 @@ const getURLFilteringData = function(details) { return response; }; -const compileTemporaryException = function(filter) { - const parser = new StaticFilteringParser({ - nativeCssHas: vAPI.webextFlavor.env.includes('native_css_has'), - }); - parser.analyze(filter); - if ( parser.shouldDiscard() ) { return; } - return staticExtFilteringEngine.compileTemporary(parser); -}; - -const toggleTemporaryException = function(details) { - const result = compileTemporaryException(details.filter); - if ( result === undefined ) { return false; } - const { session, selector } = result; - if ( session.has(1, selector) ) { - session.remove(1, selector); - return false; - } - session.add(1, selector); - return true; -}; - -const hasTemporaryException = function(details) { - const result = compileTemporaryException(details.filter); - if ( result === undefined ) { return false; } - const { session, selector } = result; - return session && session.has(1, selector); -}; - const onMessage = function(request, sender, callback) { // Async switch ( request.what ) { case 'readAll': - if ( - logger.ownerId !== undefined && - logger.ownerId !== request.ownerId - ) { + if ( logger.ownerId !== undefined && logger.ownerId !== request.ownerId ) { return callback({ unavailable: true }); } vAPI.tabs.getCurrent().then(tab => { @@ -1723,6 +1695,13 @@ const onMessage = function(request, sender, callback) { }); return; + case 'toggleInMemoryFilter': { + const promise = µb.hasInMemoryFilter(request.filter) + ? µb.removeInMemoryFilter(request.filter) + : µb.addInMemoryFilter(request.filter); + promise.then(status => { callback(status); }); + return; + } default: break; } @@ -1731,14 +1710,14 @@ const onMessage = function(request, sender, callback) { let response; switch ( request.what ) { - case 'hasTemporaryException': - response = hasTemporaryException(request); + case 'hasInMemoryFilter': + response = µb.hasInMemoryFilter(request.filter); break; case 'releaseView': - if ( request.ownerId === logger.ownerId ) { - logger.ownerId = undefined; - } + if ( request.ownerId !== logger.ownerId ) { break; } + logger.ownerId = undefined; + µb.clearInMemoryFilters(); break; case 'saveURLFilteringRules': @@ -1761,10 +1740,6 @@ const onMessage = function(request, sender, callback) { response = getURLFilteringData(request); break; - case 'toggleTemporaryException': - response = toggleTemporaryException(request); - break; - default: return vAPI.messaging.UNHANDLED; } diff --git a/src/js/scriptlet-filtering.js b/src/js/scriptlet-filtering.js index 6a8e7178e..b8a2c8f36 100644 --- a/src/js/scriptlet-filtering.js +++ b/src/js/scriptlet-filtering.js @@ -28,10 +28,7 @@ import µb from './background.js'; import { redirectEngine } from './redirect-engine.js'; import { sessionFirewall } from './filtering-engines.js'; -import { - StaticExtFilteringHostnameDB, - StaticExtFilteringSessionDB, -} from './static-ext-filtering-db.js'; +import { StaticExtFilteringHostnameDB } from './static-ext-filtering-db.js'; import { domainFromHostname, @@ -46,7 +43,6 @@ const scriptletCache = new µb.MRUCache(32); const reEscapeScriptArg = /[\\'"]/g; const scriptletDB = new StaticExtFilteringHostnameDB(1); -const sessionScriptletDB = new StaticExtFilteringSessionDB(); let acceptedCount = 0; let discardedCount = 0; @@ -262,13 +258,6 @@ scriptletFilteringEngine.compile = function(parser, writer) { } }; -scriptletFilteringEngine.compileTemporary = function(parser) { - return { - session: sessionScriptletDB, - selector: parser.result.compiled, - }; -}; - // 01234567890123456789 // +js(token[, arg[, ...]]) // ^ ^ @@ -291,10 +280,6 @@ scriptletFilteringEngine.fromCompiledContent = function(reader) { } }; -scriptletFilteringEngine.getSession = function() { - return sessionScriptletDB; -}; - const $scriptlets = new Set(); const $exceptions = new Set(); const $scriptletToCodeMap = new Map(); @@ -307,9 +292,6 @@ scriptletFilteringEngine.retrieve = function(request, options = {}) { $scriptlets.clear(); $exceptions.clear(); - if ( sessionScriptletDB.isNotEmpty ) { - sessionScriptletDB.retrieve([ null, $exceptions ]); - } scriptletDB.retrieve(hostname, [ $scriptlets, $exceptions ]); const entity = request.entity !== '' ? `${hostname.slice(0, -request.domain.length)}${request.entity}` diff --git a/src/js/static-ext-filtering-db.js b/src/js/static-ext-filtering-db.js index a118485b6..8669e4e9e 100644 --- a/src/js/static-ext-filtering-db.js +++ b/src/js/static-ext-filtering-db.js @@ -170,55 +170,8 @@ const StaticExtFilteringHostnameDB = class { /******************************************************************************/ -const StaticExtFilteringSessionDB = class { - constructor() { - this.db = new Map(); - } - compile(s) { - return s; - } - 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; - } -}; - -/******************************************************************************/ - export { StaticExtFilteringHostnameDB, - StaticExtFilteringSessionDB, }; /******************************************************************************/ diff --git a/src/js/static-ext-filtering.js b/src/js/static-ext-filtering.js index d6bc851b2..4c776cfda 100644 --- a/src/js/static-ext-filtering.js +++ b/src/js/static-ext-filtering.js @@ -132,19 +132,6 @@ staticExtFilteringEngine.compile = function(parser, writer) { return true; }; -staticExtFilteringEngine.compileTemporary = function(parser) { - if ( (parser.flavorBits & parser.BITFlavorExtScriptlet) !== 0 ) { - return scriptletFilteringEngine.compileTemporary(parser); - } - if ( (parser.flavorBits & parser.BITFlavorExtResponseHeader) !== 0 ) { - return httpheaderFilteringEngine.compileTemporary(parser); - } - if ( (parser.flavorBits & parser.BITFlavorExtHTML) !== 0 ) { - return htmlFilteringEngine.compileTemporary(parser); - } - return cosmeticFilteringEngine.compileTemporary(parser); -}; - staticExtFilteringEngine.fromCompiledContent = function(reader, options) { cosmeticFilteringEngine.fromCompiledContent(reader, options); scriptletFilteringEngine.fromCompiledContent(reader, options); diff --git a/src/js/storage.js b/src/js/storage.js index 9682e4d68..47c9339ce 100644 --- a/src/js/storage.js +++ b/src/js/storage.js @@ -618,6 +618,36 @@ self.addEventListener('hiddenSettingsChanged', ( ) => { /******************************************************************************/ +µb.hasInMemoryFilter = function(raw) { + return this.inMemoryFilters.includes(raw); +}; + +µb.addInMemoryFilter = async function(raw) { + if ( this.inMemoryFilters.includes(raw) ){ return true; } + this.inMemoryFilters.push(raw); + this.inMemoryFiltersCompiled = ''; + await this.loadFilterLists(); + return true; +}; + +µb.removeInMemoryFilter = async function(raw) { + const pos = this.inMemoryFilters.indexOf(raw); + if ( pos === -1 ) { return false; } + this.inMemoryFilters.splice(pos, 1); + this.inMemoryFiltersCompiled = ''; + await this.loadFilterLists(); + return false; +}; + +µb.clearInMemoryFilters = async function() { + if ( this.inMemoryFilters.length === 0 ) { return; } + this.inMemoryFilters = []; + this.inMemoryFiltersCompiled = ''; + await this.loadFilterLists(); +}; + +/******************************************************************************/ + µb.getAvailableLists = async function() { let oldAvailableLists = {}, newAvailableLists = {}; @@ -760,12 +790,12 @@ self.addEventListener('hiddenSettingsChanged', ( ) => { /******************************************************************************/ -µb.loadFilterLists = (( ) => { +{ const loadedListKeys = []; let loadingPromise; let t0 = 0; - const onDone = function() { + const onDone = ( ) => { ubolog(`loadFilterLists() took ${Date.now()-t0} ms`); staticNetFilteringEngine.freeze(); @@ -773,30 +803,30 @@ self.addEventListener('hiddenSettingsChanged', ( ) => { redirectEngine.freeze(); vAPI.net.unsuspend(); - vAPI.storage.set({ 'availableFilterLists': this.availableFilterLists }); + vAPI.storage.set({ 'availableFilterLists': µb.availableFilterLists }); vAPI.messaging.broadcast({ what: 'staticFilteringDataChanged', - parseCosmeticFilters: this.userSettings.parseAllABPHideFilters, - ignoreGenericCosmeticFilters: this.userSettings.ignoreGenericCosmeticFilters, + parseCosmeticFilters: µb.userSettings.parseAllABPHideFilters, + ignoreGenericCosmeticFilters: µb.userSettings.ignoreGenericCosmeticFilters, listKeys: loadedListKeys }); - this.selfieManager.destroy(); + µb.selfieManager.destroy(); lz4Codec.relinquish(); - this.compiledFormatChanged = false; + µb.compiledFormatChanged = false; loadingPromise = undefined; }; - const applyCompiledFilters = function(assetKey, compiled) { + const applyCompiledFilters = (assetKey, compiled) => { const snfe = staticNetFilteringEngine; const sxfe = staticExtFilteringEngine; - let acceptedCount = snfe.acceptedCount + sxfe.acceptedCount, - discardedCount = snfe.discardedCount + sxfe.discardedCount; - this.applyCompiledFilters(compiled, assetKey === this.userFiltersPath); - if ( this.availableFilterLists.hasOwnProperty(assetKey) ) { - const entry = this.availableFilterLists[assetKey]; + let acceptedCount = snfe.acceptedCount + sxfe.acceptedCount; + let discardedCount = snfe.discardedCount + sxfe.discardedCount; + µb.applyCompiledFilters(compiled, assetKey === µb.userFiltersPath); + if ( µb.availableFilterLists.hasOwnProperty(assetKey) ) { + const entry = µb.availableFilterLists[assetKey]; entry.entryCount = snfe.acceptedCount + sxfe.acceptedCount - acceptedCount; entry.entryUsedCount = entry.entryCount - @@ -805,8 +835,8 @@ self.addEventListener('hiddenSettingsChanged', ( ) => { loadedListKeys.push(assetKey); }; - const onFilterListsReady = function(lists) { - this.availableFilterLists = lists; + const onFilterListsReady = lists => { + µb.availableFilterLists = lists; if ( vAPI.Net.canSuspend() ) { vAPI.net.suspend(); @@ -814,7 +844,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => { redirectEngine.reset(); staticExtFilteringEngine.reset(); staticNetFilteringEngine.reset(); - this.selfieManager.destroy(); + µb.selfieManager.destroy(); staticFilteringReverseLookup.resetLists(); // We need to build a complete list of assets to pull first: this is @@ -825,37 +855,44 @@ self.addEventListener('hiddenSettingsChanged', ( ) => { for ( const assetKey in lists ) { if ( lists.hasOwnProperty(assetKey) === false ) { continue; } if ( lists[assetKey].off ) { continue; } - toLoad.push( - this.getCompiledFilterList(assetKey).then(details => { - applyCompiledFilters.call( - this, - details.assetKey, - details.content - ); + µb.getCompiledFilterList(assetKey).then(details => { + applyCompiledFilters(details.assetKey, details.content); }) ); } + if ( µb.inMemoryFilters.length !== 0 ) { + if ( µb.inMemoryFiltersCompiled === '' ) { + µb.inMemoryFiltersCompiled = + µb.compileFilters( + µb.inMemoryFilters.join('\n'), + { assetKey: 'in-memory'} + ); + } + if ( µb.inMemoryFiltersCompiled !== '' ) { + toLoad.push( + µb.applyCompiledFilters(µb.inMemoryFiltersCompiled, true) + ); + } + } + return Promise.all(toLoad); }; - return function() { - if ( loadingPromise instanceof Promise === false ) { - t0 = Date.now(); - loadedListKeys.length = 0; - loadingPromise = Promise.all([ - this.getAvailableLists().then(lists => - onFilterListsReady.call(this, lists) - ), - this.loadRedirectResources(), - ]).then(( ) => { - onDone.call(this); - }); - } + µb.loadFilterLists = function() { + if ( loadingPromise instanceof Promise ) { return loadingPromise; } + t0 = Date.now(); + loadedListKeys.length = 0; + loadingPromise = Promise.all([ + this.getAvailableLists().then(lists => onFilterListsReady(lists)), + this.loadRedirectResources(), + ]).then(( ) => { + onDone(); + }); return loadingPromise; }; -})(); +} /******************************************************************************/ @@ -1158,6 +1195,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => { // memory usage at selfie-load time. For some reasons. const create = async function() { + if ( µb.inMemoryFilters.length !== 0 ) { return; } await Promise.all([ io.put( 'selfie/main',