Browse Source

refactor: use hookOptionsInit

tophf 2 years ago
parent
commit
f1f510c91e

+ 3 - 4
src/background/sync/index.js

@@ -10,7 +10,7 @@ import './dropbox';
 import './onedrive';
 import './googledrive';
 import './webdav';
-import { addOwnCommands, hookOptions, init } from '../utils';
+import { addOwnCommands, hookOptionsInit } from '../utils';
 import { S_CODE_PRE, S_SCRIPT_PRE } from '../utils/storage';
 import { onStorageChanged } from '../utils/storage-cache';
 
@@ -20,9 +20,8 @@ const keysToSyncRe = new RegExp(`^(?:${[
 ].join('|')})`);
 let unwatch;
 
-init.then(reconfigure);
-hookOptions((data) => {
-  if ('sync.current' in data) reconfigure();
+hookOptionsInit((changes, firstRun) => {
+  if ('sync.current' in changes || firstRun) reconfigure();
 });
 
 addOwnCommands({

+ 1 - 2
src/background/utils/db.js

@@ -7,7 +7,7 @@ import { INFERRED, TIMEOUT_24HOURS, TIMEOUT_WEEK } from '@/common/consts';
 import { deepSize, forEachEntry, forEachKey, forEachValue } from '@/common/object';
 import pluginEvents from '../plugin/events';
 import { getDefaultCustom, getNameURI, inferScriptProps, newScript, parseMeta } from './script';
-import { resetBlacklist, testBlacklist, testerBatch, testScript } from './tester';
+import { testBlacklist, testerBatch, testScript } from './tester';
 import { addOwnCommands, addPublicCommands, commands, resolveInit } from './init';
 import patchDB from './patch-db';
 import { getOption, initOptions, setOption } from './options';
@@ -161,7 +161,6 @@ addOwnCommands({
   }
   sortScripts();
   vacuum(data);
-  resetBlacklist();
   checkRemove();
   setInterval(checkRemove, TIMEOUT_24HOURS);
   resolveInit();

+ 13 - 11
src/background/utils/options.js

@@ -1,20 +1,15 @@
 import { debounce, ensureArray, initHooks, normalizeKeys, sendCmd } from '@/common';
-import { deepCopy, deepEqual, mapEntry, objectGet, objectSet } from '@/common/object';
+import { deepCopy, deepEqual, objectGet, objectSet } from '@/common/object';
 import defaults from '@/common/options-defaults';
-import { addOwnCommands, commands, init } from './init';
+import { addOwnCommands, init } from './init';
 import storage from './storage';
 
 let changes;
-let options = {};
 
 addOwnCommands({
   /** @return {Object} */
   GetAllOptions() {
-    return commands.GetOptions(defaults);
-  },
-  /** @return {Object} */
-  GetOptions(data) {
-    return data::mapEntry((_, key) => getOption(key));
+    return Object.assign({}, defaults, options); // eslint-disable-line no-use-before-define
   },
   /**
    * @param {{key:string, value?:PlainJSONValue, reply?:boolean}|Array} data
@@ -28,6 +23,7 @@ addOwnCommands({
   },
 });
 
+const options = {};
 const STORAGE_KEY = 'options';
 const VERSION = 'version';
 const TPL_KEY = 'scriptTemplate';
@@ -43,14 +39,13 @@ const DELAY = 100;
 const hooks = initHooks();
 const callHooksLater = debounce(callHooks, DELAY);
 const writeOptionsLater = debounce(writeOptions, DELAY);
+const optProxy = new Proxy(defaults, { get: (_, key) => getOption(key) });
 export const hookOptions = hooks.hook;
-// TODO: add `keys` parameter to hookOptions
-// TODO: call hooks.fire in init.then (DANGER! check usages of hookOptions+getOption)
 hookOptions(changes => sendCmd('UpdateOptions', changes));
 
 export function initOptions(data) {
   data = data[STORAGE_KEY] || {};
-  if (isObject(data)) options = data;
+  Object.assign(options, data);
   if (process.env.DEBUG) console.info('options:', options);
   if (!options[VERSION]) {
     setOption(VERSION, 1);
@@ -84,6 +79,13 @@ function callHooks() {
   hooks.fire(tmp);
 }
 
+/** Hooks and calls the callback with a copy of all options when init is resolved */
+export function hookOptionsInit(cb) {
+  if (init) init.then(() => cb(optProxy, true));
+  else cb(optProxy, true);
+  return hookOptions(cb);
+}
+
 export function getOption(key) {
   let res = options[key];
   if (res != null) return res;

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

@@ -3,13 +3,13 @@ import {
   BLACKLIST, HOMEPAGE_URL, KNOWN_INJECT_INTO, META_STR, METABLOCK_RE, NEWLINE_END_RE,
 } from '@/common/consts';
 import initCache from '@/common/cache';
-import { forEachEntry, forEachKey, forEachValue, mapEntry, objectSet } from '@/common/object';
+import { forEachEntry, forEachValue, mapEntry, objectSet } from '@/common/object';
 import ua from '@/common/ua';
 import { CACHE_KEYS, getScriptsByURL, PROMISE, REQ_KEYS, VALUE_IDS } from './db';
 import { setBadge } from './icon';
-import { addOwnCommands, addPublicCommands, init } from './init';
+import { addOwnCommands, addPublicCommands } from './init';
 import { clearNotifications } from './notifications';
-import { getOption, hookOptions } from './options';
+import { hookOptionsInit } from './options';
 import { popupTabs } from './popup-tracker';
 import { clearRequestsByTabId, reifyRequests } from './requests';
 import {
@@ -211,12 +211,7 @@ addPublicCommands({
   },
 });
 
-hookOptions(onOptionChanged);
-init.then(() => {
-  OPT_HANDLERS::forEachKey(key => {
-    onOptionChanged({ [key]: getOption(key) });
-  });
-});
+hookOptionsInit(onOptionChanged);
 
 onStorageChanged((keys, data) => {
   const toClear = [];
@@ -262,13 +257,15 @@ function removeStaleCacheEntry(val, key) {
 }
 
 function onOptionChanged(changes) {
-  changes::forEachEntry(([key, value]) => {
-    if (OPT_HANDLERS[key]) {
-      OPT_HANDLERS[key](value);
-    } else if (key.includes('.')) { // used by `expose.url`
-      onOptionChanged(objectSet({}, key, value));
+  // DANGER! Must initialize in the specified order
+  for (const key in OPT_HANDLERS) {
+    if (key in changes) OPT_HANDLERS[key](changes[key]);
+  }
+  for (const key in changes) {
+    if (key.includes('.')) { // used by `expose.url`
+      onOptionChanged(objectSet({}, key, changes[key]));
     }
-  });
+  }
 }
 
 function toggleXhrInject(enable) {

+ 2 - 2
src/background/utils/tester.js

@@ -3,7 +3,7 @@ import { getScriptPrettyUrl } from '@/common';
 import { BLACKLIST, BLACKLIST_ERRORS } from '@/common/consts';
 import initCache from '@/common/cache';
 import { getPublicSuffix } from '@/common/tld';
-import { getOption, hookOptions } from './options';
+import { getOption, hookOptionsInit } from './options';
 import storage from './storage';
 
 const matchAlways = { test: () => 1 };
@@ -57,7 +57,7 @@ let urlResultsMat;
 let urlResultsInc;
 // Context end
 
-hookOptions((changes) => {
+hookOptionsInit((changes) => {
   if (BLACKLIST in changes) {
     const errors = resetBlacklist(changes[BLACKLIST] || []);
     const res = errors.length ? errors : null;

+ 1 - 1
src/options/views/tab-settings/vm-export.vue

@@ -86,7 +86,7 @@ function download(blob, fileName) {
    * v56 in Windows https://bugzil.la/1357486
    * v61 in MacOS https://bugzil.la/1385403
    * v63 in Linux https://bugzil.la/1357487 */
-  const FF = ua.firefox;
+  const FF = IS_FIREFOX;
   // eslint-disable-next-line no-nested-ternary
   if (FF && (ua.os === 'win' ? FF < 56 : ua.os === 'mac' ? FF < 61 : FF < 63)) {
     const reader = new FileReader();