Browse Source

fix: explicitly clear preinject cache when DB changes

tophf 5 years ago
parent
commit
bde0c94902
3 changed files with 22 additions and 6 deletions
  1. 6 3
      src/background/index.js
  2. 12 2
      src/background/utils/preinject.js
  3. 4 1
      src/common/cache.js

+ 6 - 3
src/background/index.js

@@ -9,7 +9,7 @@ import { getData, checkRemove } from './utils/db';
 import { setBadge } from './utils/icon';
 import { setBadge } from './utils/icon';
 import { initialize } from './utils/init';
 import { initialize } from './utils/init';
 import { getOption, hookOptions } from './utils/options';
 import { getOption, hookOptions } from './utils/options';
-import { getInjectedScripts } from './utils/preinject';
+import { clearPreinjectData, getInjectedScripts } from './utils/preinject';
 import { SCRIPT_TEMPLATE, resetScriptTemplate } from './utils/template-hook';
 import { SCRIPT_TEMPLATE, resetScriptTemplate } from './utils/template-hook';
 import { resetValueOpener, addValueOpener } from './utils/values';
 import { resetValueOpener, addValueOpener } from './utils/values';
 import './utils/clipboard';
 import './utils/clipboard';
@@ -124,10 +124,13 @@ const commandsToSyncIfTruthy = [
 async function handleCommandMessage(req, src) {
 async function handleCommandMessage(req, src) {
   const { cmd } = req;
   const { cmd } = req;
   const res = await commands[cmd]?.(req.data, src);
   const res = await commands[cmd]?.(req.data, src);
-  if (commandsToSync.includes(cmd)
-  || res && commandsToSyncIfTruthy.includes(cmd)) {
+  const maybeChanged = commandsToSync.includes(cmd);
+  if (maybeChanged || res && commandsToSyncIfTruthy.includes(cmd)) {
     sync.sync();
     sync.sync();
   }
   }
+  if (maybeChanged) {
+    clearPreinjectData();
+  }
   // `undefined` is not transferable, but `null` is
   // `undefined` is not transferable, but `null` is
   return res ?? null;
   return res ?? null;
 }
 }

+ 12 - 2
src/background/utils/preinject.js

@@ -1,7 +1,7 @@
 import { getUniqId } from '#/common';
 import { getUniqId } from '#/common';
 import { INJECT_CONTENT, INJECTABLE_TAB_URL_RE, METABLOCK_RE } from '#/common/consts';
 import { INJECT_CONTENT, INJECTABLE_TAB_URL_RE, METABLOCK_RE } from '#/common/consts';
+import initCache from '#/common/cache';
 import ua from '#/common/ua';
 import ua from '#/common/ua';
-import cache from './cache';
 import { getScriptsByURL } from './db';
 import { getScriptsByURL } from './db';
 import { extensionRoot, postInitialize } from './init';
 import { extensionRoot, postInitialize } from './init';
 import { getOption, hookOptions } from './options';
 import { getOption, hookOptions } from './options';
@@ -14,6 +14,7 @@ const API_CONFIG = {
 const TIME_AFTER_SEND = 10e3; // longer as establishing connection to sites may take time
 const TIME_AFTER_SEND = 10e3; // longer as establishing connection to sites may take time
 const TIME_AFTER_RECEIVE = 1e3; // shorter as response body will be coming very soon
 const TIME_AFTER_RECEIVE = 1e3; // shorter as response body will be coming very soon
 const TIME_KEEP_DATA = 60e3; // 100ms should be enough but the tab may hang or get paused in debugger
 const TIME_KEEP_DATA = 60e3; // 100ms should be enough but the tab may hang or get paused in debugger
+const cache = initCache({ lifetime: TIME_KEEP_DATA });
 let injectInto;
 let injectInto;
 hookOptions(changes => {
 hookOptions(changes => {
   injectInto = changes.defaultInjectInto ?? injectInto;
   injectInto = changes.defaultInjectInto ?? injectInto;
@@ -24,13 +25,22 @@ postInitialize.push(() => {
   togglePreinject(getOption('isApplied'));
   togglePreinject(getOption('isApplied'));
 });
 });
 
 
+export function clearPreinjectData() {
+  if (ua.isFirefox) {
+    for (const data of cache.getValues()) {
+      data.registration?.then(r => r.unregister());
+    }
+  }
+  cache.destroy();
+}
+
 /** @return {Promise<Object>} */
 /** @return {Promise<Object>} */
 export function getInjectedScripts(url, tabId, frameId) {
 export function getInjectedScripts(url, tabId, frameId) {
   return cache.pop(getKey(url, !frameId)) || prepare(url, tabId, frameId, true);
   return cache.pop(getKey(url, !frameId)) || prepare(url, tabId, frameId, true);
 }
 }
 
 
 function getKey(url, isTop) {
 function getKey(url, isTop) {
-  return `preinject${+isTop}:${url}`;
+  return isTop ? url : `-${url}`;
 }
 }
 
 
 function togglePreinject(enable) {
 function togglePreinject(enable) {

+ 4 - 1
src/common/cache.js

@@ -17,7 +17,7 @@ export default function initCache({
   // eslint-disable-next-line no-return-assign
   // eslint-disable-next-line no-return-assign
   const getNow = () => batchStarted && batchStartTime || (batchStartTime = performance.now());
   const getNow = () => batchStarted && batchStartTime || (batchStartTime = performance.now());
   return {
   return {
-    batch, get, pop, put, del, has, hit, destroy,
+    batch, get, getValues, pop, put, del, has, hit, destroy,
   };
   };
   function batch(enable) {
   function batch(enable) {
     batchStarted = enable;
     batchStarted = enable;
@@ -27,6 +27,9 @@ export default function initCache({
     const item = cache[key];
     const item = cache[key];
     return item ? item.value : def;
     return item ? item.value : def;
   }
   }
+  function getValues() {
+    return Object.values(cache).map(item => item.value);
+  }
   function pop(key, def) {
   function pop(key, def) {
     const value = get(key, def);
     const value = get(key, def);
     del(key);
     del(key);