simplify saveStyle, invalidateCache
This commit is contained in:
		
							parent
							
								
									4bc27db3fc
								
							
						
					
					
						commit
						8f784a19d4
					
				|  | @ -1,4 +1,4 @@ | ||||||
| /* global getDatabase, getStyles, saveStyle, reportError, invalidateCache */ | /* global getDatabase, getStyles, saveStyle, reportError */ | ||||||
| 'use strict'; | 'use strict'; | ||||||
| 
 | 
 | ||||||
| chrome.webNavigation.onBeforeNavigate.addListener(data => { | chrome.webNavigation.onBeforeNavigate.addListener(data => { | ||||||
|  | @ -60,10 +60,6 @@ function onRuntimeMessage(request, sender, sendResponse) { | ||||||
|       saveStyle(request).then(sendResponse); |       saveStyle(request).then(sendResponse); | ||||||
|       return KEEP_CHANNEL_OPEN; |       return KEEP_CHANNEL_OPEN; | ||||||
| 
 | 
 | ||||||
|     case 'invalidateCache': |  | ||||||
|       invalidateCache(false, request); |  | ||||||
|       break; |  | ||||||
| 
 |  | ||||||
|     case 'healthCheck': |     case 'healthCheck': | ||||||
|       getDatabase( |       getDatabase( | ||||||
|         () => sendResponse(true), |         () => sendResponse(true), | ||||||
|  |  | ||||||
							
								
								
									
										128
									
								
								storage.js
									
									
									
									
									
								
							
							
						
						
									
										128
									
								
								storage.js
									
									
									
									
									
								
							|  | @ -10,15 +10,15 @@ const SLOPPY_REGEXP_PREFIX = '\0'; | ||||||
| // Note, only 'var'-declared variables are visible from another extension page
 | // Note, only 'var'-declared variables are visible from another extension page
 | ||||||
| // eslint-disable-next-line no-var
 | // eslint-disable-next-line no-var
 | ||||||
| var cachedStyles = { | var cachedStyles = { | ||||||
|   list: null, |   list: null,            // array of all styles
 | ||||||
|   byId: new Map(), |   byId: new Map(),       // all styles indexed by id
 | ||||||
|   filters: new Map(), |   filters: new Map(),    // filterStyles() parameters mapped to the returned results, 10k max
 | ||||||
|   regexps: new Map(), |   regexps: new Map(),    // compiled style regexps
 | ||||||
|   urlDomains: new Map(), |   urlDomains: new Map(), // getDomain() results for 100 last checked urls
 | ||||||
|   emptyCode: new Map(), // entire code is comments/whitespace/@namespace
 |   emptyCode: new Map(),  // entire code is comments/whitespace/@namespace
 | ||||||
|   mutex: { |   mutex: { | ||||||
|     inProgress: false, |     inProgress: false,   // while getStyles() is reading IndexedDB all subsequent calls
 | ||||||
|     onDone: [], |     onDone: [],          // to getStyles() are queued and resolved when the first one finishes
 | ||||||
|   }, |   }, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -56,7 +56,6 @@ function getStyles(options, callback) { | ||||||
|   } |   } | ||||||
|   cachedStyles.mutex.inProgress = true; |   cachedStyles.mutex.inProgress = true; | ||||||
| 
 | 
 | ||||||
|   //const t0 = performance.now();
 |  | ||||||
|   getDatabase(db => { |   getDatabase(db => { | ||||||
|     const tx = db.transaction(['styles'], 'readonly'); |     const tx = db.transaction(['styles'], 'readonly'); | ||||||
|     const os = tx.objectStore('styles'); |     const os = tx.objectStore('styles'); | ||||||
|  | @ -67,7 +66,6 @@ function getStyles(options, callback) { | ||||||
|         cachedStyles.byId.set(style.id, style); |         cachedStyles.byId.set(style.id, style); | ||||||
|         compileStyleRegExps({style}); |         compileStyleRegExps({style}); | ||||||
|       } |       } | ||||||
|       //console.debug('%s getStyles %s, invoking cached callbacks: %o', (performance.now() - t0).toFixed(1), JSON.stringify(options), cachedStyles.mutex.onDone.map(e => JSON.stringify(e.options))); // eslint-disable-line max-len
 |  | ||||||
|       callback(filterStyles(options)); |       callback(filterStyles(options)); | ||||||
| 
 | 
 | ||||||
|       cachedStyles.mutex.inProgress = false; |       cachedStyles.mutex.inProgress = false; | ||||||
|  | @ -88,7 +86,6 @@ function filterStyles({ | ||||||
|   asHash = null, |   asHash = null, | ||||||
|   strictRegexp = true, // used by the popup to detect bad regexps
 |   strictRegexp = true, // used by the popup to detect bad regexps
 | ||||||
| } = {}) { | } = {}) { | ||||||
|   //const t0 = performance.now();
 |  | ||||||
|   enabled = fixBoolean(enabled); |   enabled = fixBoolean(enabled); | ||||||
|   id = id === null ? null : Number(id); |   id = id === null ? null : Number(id); | ||||||
| 
 | 
 | ||||||
|  | @ -97,11 +94,8 @@ function filterStyles({ | ||||||
|   && id === null |   && id === null | ||||||
|   && matchUrl === null |   && matchUrl === null | ||||||
|   && asHash != true) { |   && asHash != true) { | ||||||
|     //console.debug('%c%s filterStyles SKIPPED LOOP %s', 'color:gray', (performance.now() - t0).toFixed(1), enabled, id, asHash, strictRegexp, matchUrl); // eslint-disable-line max-len
 |  | ||||||
|     return cachedStyles.list; |     return cachedStyles.list; | ||||||
|   } |   } | ||||||
|   // silence the inapplicable warning for async code
 |  | ||||||
|   // eslint-disable-next-line no-use-before-define
 |  | ||||||
|   const disableAll = asHash && prefs.get('disableAll', false); |   const disableAll = asHash && prefs.get('disableAll', false); | ||||||
| 
 | 
 | ||||||
|   if (matchUrl && matchUrl.startsWith(URLS.chromeWebStore)) { |   if (matchUrl && matchUrl.startsWith(URLS.chromeWebStore)) { | ||||||
|  | @ -114,7 +108,6 @@ function filterStyles({ | ||||||
|   const cacheKey = ' ' + enabled + url + '\t' + id + matchUrl + '\t' + asHash + strictRegexp; |   const cacheKey = ' ' + enabled + url + '\t' + id + matchUrl + '\t' + asHash + strictRegexp; | ||||||
|   const cached = cachedStyles.filters.get(cacheKey); |   const cached = cachedStyles.filters.get(cacheKey); | ||||||
|   if (cached) { |   if (cached) { | ||||||
|     //console.debug('%c%s filterStyles REUSED RESPONSE %s', 'color:gray', (performance.now() - t0).toFixed(1), enabled, id, asHash, strictRegexp, matchUrl); // eslint-disable-line max-len
 |  | ||||||
|     cached.hits++; |     cached.hits++; | ||||||
|     cached.lastHit = Date.now(); |     cached.lastHit = Date.now(); | ||||||
| 
 | 
 | ||||||
|  | @ -144,8 +137,8 @@ function filterStyles({ | ||||||
| 
 | 
 | ||||||
|   for (let i = 0, style; (style = styles[i]); i++) { |   for (let i = 0, style; (style = styles[i]); i++) { | ||||||
|     if ((enabled === null || style.enabled == enabled) |     if ((enabled === null || style.enabled == enabled) | ||||||
|       && (url === null || style.url == url) |     && (url === null || style.url == url) | ||||||
|       && (id === null || style.id == id)) { |     && (id === null || style.id == id)) { | ||||||
|       const sections = needSections && |       const sections = needSections && | ||||||
|         getApplicableSections({style, matchUrl, strictRegexp, stopOnFirst: !asHash}); |         getApplicableSections({style, matchUrl, strictRegexp, stopOnFirst: !asHash}); | ||||||
|       if (asHash) { |       if (asHash) { | ||||||
|  | @ -157,7 +150,6 @@ function filterStyles({ | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   //console.debug('%s filterStyles %s', (performance.now() - t0).toFixed(1), enabled, id, asHash, strictRegexp, matchUrl); // eslint-disable-line max-len
 |  | ||||||
|   cachedStyles.filters.set(cacheKey, { |   cachedStyles.filters.set(cacheKey, { | ||||||
|     styles: filtered, |     styles: filtered, | ||||||
|     lastHit: Date.now(), |     lastHit: Date.now(), | ||||||
|  | @ -188,52 +180,50 @@ function saveStyle(style) { | ||||||
|         delete style.name; |         delete style.name; | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       // Update
 |  | ||||||
|       if (id !== null) { |       if (id !== null) { | ||||||
|  |         // Update or create
 | ||||||
|         style.id = id; |         style.id = id; | ||||||
|         os.get(id).onsuccess = eventGet => { |         os.get(id).onsuccess = eventGet => { | ||||||
|           const existed = Boolean(eventGet.target.result); |           const existed = Boolean(eventGet.target.result); | ||||||
|           const oldStyle = Object.assign({}, eventGet.target.result); |           const oldStyle = Object.assign({}, eventGet.target.result); | ||||||
|           const codeIsUpdated = 'sections' in style && !styleSectionsEqual(style, oldStyle); |           const codeIsUpdated = 'sections' in style && !styleSectionsEqual(style, oldStyle); | ||||||
|           style = Object.assign(oldStyle, style); |           write(Object.assign(oldStyle, style), {existed, codeIsUpdated}); | ||||||
|           addMissingStyleTargets(style); |  | ||||||
|           os.put(style).onsuccess = eventPut => { |  | ||||||
|             style.id = style.id || eventPut.target.result; |  | ||||||
|             invalidateCache(notify, existed ? {updated: style} : {added: style}); |  | ||||||
|             compileStyleRegExps({style}); |  | ||||||
|             if (notify) { |  | ||||||
|               notifyAllTabs({ |  | ||||||
|                 method: existed ? 'styleUpdated' : 'styleAdded', |  | ||||||
|                 style, codeIsUpdated, reason, |  | ||||||
|               }); |  | ||||||
|             } |  | ||||||
|             resolve(style); |  | ||||||
|           }; |  | ||||||
|         }; |         }; | ||||||
|         return; |       } else { | ||||||
|  |         // Create
 | ||||||
|  |         delete style.id; | ||||||
|  |         write(Object.assign({ | ||||||
|  |           // Set optional things if they're undefined
 | ||||||
|  |           enabled: true, | ||||||
|  |           updateUrl: null, | ||||||
|  |           md5Url: null, | ||||||
|  |           url: null, | ||||||
|  |           originalMd5: null, | ||||||
|  |         }, style)); | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       // Create
 |       function write(style, {existed, codeIsUpdated} = {}) { | ||||||
|       delete style.id; |         style.sections = (style.sections || []).map(section => | ||||||
|       style = Object.assign({ |           Object.assign({ | ||||||
|         // Set optional things if they're undefined
 |             urls: [], | ||||||
|         enabled: true, |             urlPrefixes: [], | ||||||
|         updateUrl: null, |             domains: [], | ||||||
|         md5Url: null, |             regexps: [], | ||||||
|         url: null, |           }, section) | ||||||
|         originalMd5: null, |         ); | ||||||
|       }, style); |         os.put(style).onsuccess = event => { | ||||||
|       addMissingStyleTargets(style); |           style.id = style.id || event.target.result; | ||||||
|       os.add(style).onsuccess = event => { |           invalidateCache(existed ? {updated: style} : {added: style}); | ||||||
|         // Give it the ID that was generated
 |           compileStyleRegExps({style}); | ||||||
|         style.id = event.target.result; |           if (notify) { | ||||||
|         invalidateCache(notify, {added: style}); |             notifyAllTabs({ | ||||||
|         compileStyleRegExps({style}); |               method: existed ? 'styleUpdated' : 'styleAdded', | ||||||
|         if (notify) { |               style, codeIsUpdated, reason, | ||||||
|           notifyAllTabs({method: 'styleAdded', style, reason}); |             }); | ||||||
|         } |           } | ||||||
|         resolve(style); |           resolve(style); | ||||||
|       }; |         }; | ||||||
|  |       } | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
| } | } | ||||||
|  | @ -245,7 +235,7 @@ function deleteStyle({id, notify = true}) { | ||||||
|       const tx = db.transaction(['styles'], 'readwrite'); |       const tx = db.transaction(['styles'], 'readwrite'); | ||||||
|       const os = tx.objectStore('styles'); |       const os = tx.objectStore('styles'); | ||||||
|       os.delete(Number(id)).onsuccess = () => { |       os.delete(Number(id)).onsuccess = () => { | ||||||
|         invalidateCache(notify, {deletedId: id}); |         invalidateCache({deletedId: id}); | ||||||
|         if (notify) { |         if (notify) { | ||||||
|           notifyAllTabs({method: 'styleDeleted', id}); |           notifyAllTabs({method: 'styleDeleted', id}); | ||||||
|         } |         } | ||||||
|  | @ -429,15 +419,12 @@ function compileStyleRegExps({style, compileAll}) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| function invalidateCache(andNotify, {added, updated, deletedId} = {}) { | function invalidateCache({added, updated, deletedId} = {}) { | ||||||
|   // prevent double-add on echoed invalidation
 |   // prevent double-add on echoed invalidation
 | ||||||
|   const cached = added && cachedStyles.byId.get(added.id); |   const cached = added && cachedStyles.byId.get(added.id); | ||||||
|   if (cached) { |   if (cached) { | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|   if (andNotify) { |  | ||||||
|     chrome.runtime.sendMessage({method: 'invalidateCache', added, updated, deletedId}); |  | ||||||
|   } |  | ||||||
|   if (!cachedStyles.list) { |   if (!cachedStyles.list) { | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|  | @ -445,7 +432,6 @@ function invalidateCache(andNotify, {added, updated, deletedId} = {}) { | ||||||
|     const cached = cachedStyles.byId.get(updated.id); |     const cached = cachedStyles.byId.get(updated.id); | ||||||
|     if (cached) { |     if (cached) { | ||||||
|       Object.assign(cached, updated); |       Object.assign(cached, updated); | ||||||
|       //console.debug('cache: updated', updated);
 |  | ||||||
|     } |     } | ||||||
|     cachedStyles.filters.clear(); |     cachedStyles.filters.clear(); | ||||||
|     return; |     return; | ||||||
|  | @ -453,7 +439,6 @@ function invalidateCache(andNotify, {added, updated, deletedId} = {}) { | ||||||
|   if (added) { |   if (added) { | ||||||
|     cachedStyles.list.push(added); |     cachedStyles.list.push(added); | ||||||
|     cachedStyles.byId.set(added.id, added); |     cachedStyles.byId.set(added.id, added); | ||||||
|     //console.debug('cache: added', added);
 |  | ||||||
|     cachedStyles.filters.clear(); |     cachedStyles.filters.clear(); | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|  | @ -463,22 +448,18 @@ function invalidateCache(andNotify, {added, updated, deletedId} = {}) { | ||||||
|       const cachedIndex = cachedStyles.list.indexOf(deletedStyle); |       const cachedIndex = cachedStyles.list.indexOf(deletedStyle); | ||||||
|       cachedStyles.list.splice(cachedIndex, 1); |       cachedStyles.list.splice(cachedIndex, 1); | ||||||
|       cachedStyles.byId.delete(deletedId); |       cachedStyles.byId.delete(deletedId); | ||||||
|       //console.debug('cache: deleted', deletedStyle);
 |  | ||||||
|       cachedStyles.filters.clear(); |       cachedStyles.filters.clear(); | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   cachedStyles.list = null; |   cachedStyles.list = null; | ||||||
|   //console.debug('cache cleared');
 |  | ||||||
|   cachedStyles.filters.clear(); |   cachedStyles.filters.clear(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| function cleanupCachedFilters({force = false} = {}) { | function cleanupCachedFilters({force = false} = {}) { | ||||||
|   if (!force) { |   if (!force) { | ||||||
|     // sliding timer for 1 second
 |     debounce(cleanupCachedFilters, 1000, {force: true}); | ||||||
|     clearTimeout(cleanupCachedFilters.timeout); |  | ||||||
|     cleanupCachedFilters.timeout = setTimeout(cleanupCachedFilters, 1000, {force: true}); |  | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|   const size = cachedStyles.filters.size; |   const size = cachedStyles.filters.size; | ||||||
|  | @ -500,19 +481,6 @@ function cleanupCachedFilters({force = false} = {}) { | ||||||
|     .sort((a, b) => a.weight - b.weight) |     .sort((a, b) => a.weight - b.weight) | ||||||
|     .slice(0, size / 10 + 1) |     .slice(0, size / 10 + 1) | ||||||
|     .forEach(({id}) => cachedStyles.filters.delete(id)); |     .forEach(({id}) => cachedStyles.filters.delete(id)); | ||||||
|   cleanupCachedFilters.timeout = 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| function addMissingStyleTargets(style) { |  | ||||||
|   style.sections = (style.sections || []).map(section => |  | ||||||
|     Object.assign({ |  | ||||||
|       urls: [], |  | ||||||
|       urlPrefixes: [], |  | ||||||
|       domains: [], |  | ||||||
|       regexps: [], |  | ||||||
|     }, section) |  | ||||||
|   ); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user