Browse Source

refactor: flatten object methods

Gerald 8 years ago
parent
commit
e4395a1f68

+ 3 - 2
src/background/app.js

@@ -1,6 +1,7 @@
 import 'src/common/polyfills';
 import 'src/common/browser';
-import { i18n, defaultImage, object } from 'src/common';
+import { i18n, defaultImage } from 'src/common';
+import { objectGet } from 'src/common/object';
 import * as sync from './sync';
 import {
   cache,
@@ -41,7 +42,7 @@ function checkUpdateAll() {
   setOption('lastUpdate', Date.now());
   getScripts()
   .then(scripts => {
-    const toUpdate = scripts.filter(item => object.get(item, 'config.shouldUpdate'));
+    const toUpdate = scripts.filter(item => objectGet(item, 'config.shouldUpdate'));
     return Promise.all(toUpdate.map(checkUpdate));
   })
   .then(updatedList => {

+ 3 - 2
src/background/sync/base.js

@@ -1,4 +1,5 @@
-import { debounce, normalizeKeys, request, noop, object } from 'src/common';
+import { debounce, normalizeKeys, request, noop } from 'src/common';
+import { objectPurify } from 'src/common/object';
 import { getEventEmitter, getOption, setOption, hookOptions } from '../utils';
 import { getScripts, getScriptCode, parseScript, removeScript, normalizePosition } from '../utils/db';
 
@@ -366,7 +367,7 @@ export const BaseService = serviceFactory({
                 data.code = obj.code;
                 if (obj.more) {
                   data.custom = obj.more.custom;
-                  data.config = object.purify({
+                  data.config = objectPurify({
                     enabled: obj.more.enabled,
                     shouldUpdate: obj.more.update,
                   });

+ 3 - 2
src/background/sync/onedrive.js

@@ -1,5 +1,6 @@
 // Reference: https://dev.onedrive.com/README.htm
-import { object, noop } from 'src/common';
+import { noop } from 'src/common';
+import { objectGet } from 'src/common/object';
 import { dumpQuery } from '../utils';
 import { BaseService, isScriptFile, register, getURI } from './base';
 
@@ -36,7 +37,7 @@ const OneDrive = BaseService.extend({
       throw res;
     })
     .catch(res => {
-      if (res.status === 400 && object.get(res, ['data', 'error']) === 'invalid_grant') {
+      if (res.status === 400 && objectGet(res, ['data', 'error']) === 'invalid_grant') {
         return Promise.reject({
           type: 'unauthorized',
         });

+ 17 - 16
src/background/utils/db.js

@@ -1,4 +1,5 @@
-import { i18n, request, buffer2string, getFullUrl, object } from 'src/common';
+import { i18n, request, buffer2string, getFullUrl } from 'src/common';
+import { objectGet, objectSet } from 'src/common/object';
 import { getNameURI, isRemote, parseMeta, newScript } from './script';
 import { testScript, testBlacklist } from './tester';
 import { register } from './init';
@@ -274,12 +275,12 @@ function initialize() {
         //   config: { enabled, shouldUpdate },
         // }
         scripts.push(value);
-        storeInfo.id = Math.max(storeInfo.id, getInt(object.get(value, 'props.id')));
-        storeInfo.position = Math.max(storeInfo.position, getInt(object.get(value, 'props.position')));
+        storeInfo.id = Math.max(storeInfo.id, getInt(objectGet(value, 'props.id')));
+        storeInfo.position = Math.max(storeInfo.position, getInt(objectGet(value, 'props.position')));
       }
     });
     scripts.sort((a, b) => {
-      const [pos1, pos2] = [a, b].map(item => getInt(object.get(item, 'props.position')));
+      const [pos1, pos2] = [a, b].map(item => getInt(objectGet(item, 'props.position')));
       return Math.sign(pos1 - pos2);
     });
     Object.assign(store, {
@@ -305,8 +306,8 @@ export function normalizePosition() {
   const updates = [];
   store.scripts.forEach((item, index) => {
     const position = index + 1;
-    if (object.get(item, 'props.position') !== position) {
-      object.set(item, 'props.position', position);
+    if (objectGet(item, 'props.position') !== position) {
+      objectSet(item, 'props.position', position);
       updates.push(item);
     }
     // XXX patch v2.8.0
@@ -331,7 +332,7 @@ export function getScript(where) {
     script = store.scriptMap[where.id];
   } else {
     const uri = where.uri || getNameURI({ meta: where.meta, id: '@@should-have-name' });
-    const predicate = item => uri === object.get(item, 'props.uri');
+    const predicate = item => uri === objectGet(item, 'props.uri');
     script = store.scripts.find(predicate);
   }
   return Promise.resolve(script);
@@ -353,7 +354,7 @@ export function getScriptCode(id) {
 export function setValues(where, values) {
   return (where.id
     ? Promise.resolve(where.id)
-    : getScript(where).then(script => object.get(script, 'props.id')))
+    : getScript(where).then(script => objectGet(script, 'props.id')))
   .then(id => {
     if (id) return storage.value.dump(id, values).then(() => ({ id, values }));
   });
@@ -390,7 +391,7 @@ export function getScriptsByURL(url) {
   };
   const scriptsWithValue = enabledScripts
   .filter(script => {
-    const grant = object.get(script, 'meta.grant');
+    const grant = objectGet(script, 'meta.grant');
     return grant && grant.some(gm => gmValues[gm]);
   });
   return Promise.all([
@@ -415,7 +416,7 @@ export function getData() {
   const cacheKeys = {};
   const { scripts } = store;
   scripts.forEach(script => {
-    const icon = object.get(script, 'meta.icon');
+    const icon = objectGet(script, 'meta.icon');
     if (isRemote(icon)) cacheKeys[icon] = 1;
   });
   return storage.cache.getMulti(Object.keys(cacheKeys))
@@ -441,7 +442,7 @@ export function checkRemove() {
 }
 
 export function removeScript(id) {
-  const i = store.scripts.findIndex(item => id === object.get(item, 'props.id'));
+  const i = store.scripts.findIndex(item => id === objectGet(item, 'props.id'));
   if (i >= 0) {
     store.scripts.splice(i, 1);
     storage.script.remove(id);
@@ -455,7 +456,7 @@ export function removeScript(id) {
 }
 
 export function moveScript(id, offset) {
-  const index = store.scripts.findIndex(item => id === object.get(item, 'props.id'));
+  const index = store.scripts.findIndex(item => id === objectGet(item, 'props.id'));
   const step = offset > 0 ? 1 : -1;
   const indexStart = index;
   const indexEnd = index + offset;
@@ -576,9 +577,9 @@ export function parseScript(data) {
       script.custom.homepageURL = data.from;
     }
     if (isRemote(data.url)) script.custom.lastInstallURL = data.url;
-    object.set(script, 'props.lastModified', data.modified || Date.now());
+    objectSet(script, 'props.lastModified', data.modified || Date.now());
     const position = +data.position;
-    if (position) object.set(script, 'props.position', position);
+    if (position) objectSet(script, 'props.position', position);
     buildPathMap(script);
     return saveScript(script, code).then(() => script);
   })
@@ -613,7 +614,7 @@ function fetchScriptResources(script, cache) {
   // @require
   meta.require.forEach(key => {
     const fullUrl = pathMap[key] || key;
-    const cached = object.get(cache, ['require', fullUrl]);
+    const cached = objectGet(cache, ['require', fullUrl]);
     if (cached) {
       storage.require.dump(fullUrl, cached);
     } else {
@@ -623,7 +624,7 @@ function fetchScriptResources(script, cache) {
   // @resource
   Object.values(meta.resources).forEach(url => {
     const fullUrl = pathMap[url] || url;
-    const cached = object.get(cache, ['resources', fullUrl]);
+    const cached = objectGet(cache, ['resources', fullUrl]);
     if (cached) {
       storage.cache.dump(fullUrl, cached);
     } else {

+ 5 - 4
src/background/utils/options.js

@@ -1,4 +1,5 @@
-import { initHooks, debounce, normalizeKeys, object } from 'src/common';
+import { initHooks, debounce, normalizeKeys } from 'src/common';
+import { objectGet, objectSet } from 'src/common/object';
 import { register } from './init';
 
 const defaults = {
@@ -31,7 +32,7 @@ const init = browser.storage.local.get('options')
   if (process.env.DEBUG) {
     console.log('options:', options); // eslint-disable-line no-console
   }
-  if (!object.get(options, 'version')) {
+  if (!objectGet(options, 'version')) {
     // v2.8.0+ stores options in browser.storage.local
     // Upgrade from v2.7.x
     if (process.env.DEBUG) {
@@ -81,7 +82,7 @@ export function getOption(key, def) {
   let value = options[mainKey];
   if (value == null) value = defaults[mainKey];
   if (value == null) value = def;
-  return keys.length > 1 ? object.get(value, keys.slice(1), def) : value;
+  return keys.length > 1 ? objectGet(value, keys.slice(1), def) : value;
 }
 
 export function setOption(key, value) {
@@ -91,7 +92,7 @@ export function setOption(key, value) {
   const mainKey = keys[0];
   if (mainKey in defaults) {
     if (keys.length > 1) {
-      optionValue = object.set(getOption(mainKey), keys.slice(1), value);
+      optionValue = objectSet(getOption(mainKey), keys.slice(1), value);
     }
     options[mainKey] = optionValue;
     browser.storage.local.set({ options });

+ 0 - 50
src/common/index.js

@@ -9,56 +9,6 @@ export function normalizeKeys(key) {
   return keys;
 }
 
-export const object = {
-  get(obj, rawKey, def) {
-    const keys = normalizeKeys(rawKey);
-    let res = obj;
-    keys.some((key) => {
-      if (res && typeof res === 'object' && (key in res)) {
-        res = res[key];
-      } else {
-        res = def;
-        return true;
-      }
-    });
-    return res;
-  },
-  set(obj, rawKey, val) {
-    const keys = normalizeKeys(rawKey);
-    if (!keys.length) return val;
-    const root = obj || {};
-    let sub = root;
-    const lastKey = keys.pop();
-    keys.forEach((key) => {
-      let child = sub[key];
-      if (!child) {
-        child = {};
-        sub[key] = child;
-      }
-      sub = child;
-    });
-    if (typeof val === 'undefined') {
-      delete sub[lastKey];
-    } else {
-      sub[lastKey] = val;
-    }
-    return root;
-  },
-  purify(obj) {
-    // Remove keys with undefined values
-    if (Array.isArray(obj)) {
-      obj.forEach(object.purify);
-    } else if (obj && typeof obj === 'object') {
-      Object.keys(obj).forEach(key => {
-        const type = typeof obj[key];
-        if (type === 'undefined') delete obj[key];
-        else object.purify(obj[key]);
-      });
-    }
-    return obj;
-  },
-};
-
 export function initHooks() {
   const hooks = [];
 

+ 51 - 0
src/common/object.js

@@ -0,0 +1,51 @@
+import { normalizeKeys } from '.';
+
+export function objectGet(obj, rawKey, def) {
+  const keys = normalizeKeys(rawKey);
+  let res = obj;
+  keys.some((key) => {
+    if (res && typeof res === 'object' && (key in res)) {
+      res = res[key];
+    } else {
+      res = def;
+      return true;
+    }
+  });
+  return res;
+}
+
+export function objectSet(obj, rawKey, val) {
+  const keys = normalizeKeys(rawKey);
+  if (!keys.length) return val;
+  const root = obj || {};
+  let sub = root;
+  const lastKey = keys.pop();
+  keys.forEach((key) => {
+    let child = sub[key];
+    if (!child) {
+      child = {};
+      sub[key] = child;
+    }
+    sub = child;
+  });
+  if (typeof val === 'undefined') {
+    delete sub[lastKey];
+  } else {
+    sub[lastKey] = val;
+  }
+  return root;
+}
+
+export function objectPurify(obj) {
+  // Remove keys with undefined values
+  if (Array.isArray(obj)) {
+    obj.forEach(objectPurify);
+  } else if (obj && typeof obj === 'object') {
+    Object.keys(obj).forEach(key => {
+      const type = typeof obj[key];
+      if (type === 'undefined') delete obj[key];
+      else objectPurify(obj[key]);
+    });
+  }
+  return obj;
+}

+ 4 - 3
src/common/options.js

@@ -1,4 +1,5 @@
-import { initHooks, sendMessage, object, normalizeKeys } from '.';
+import { initHooks, sendMessage, normalizeKeys } from '.';
+import { objectGet, objectSet } from './object';
 
 let options = {};
 const hooks = initHooks();
@@ -10,7 +11,7 @@ const ready = sendMessage({ cmd: 'GetAllOptions' })
 
 function getOption(key, def) {
   const keys = normalizeKeys(key);
-  return object.get(options, keys, def);
+  return objectGet(options, keys, def);
 }
 
 function setOption(key, value) {
@@ -22,7 +23,7 @@ function setOption(key, value) {
 
 function updateOptions(data) {
   Object.keys(data).forEach((key) => {
-    object.set(options, key, data[key]);
+    objectSet(options, key, data[key]);
   });
   hooks.fire(data);
 }

+ 5 - 4
src/options/views/edit/index.vue

@@ -33,7 +33,8 @@
 </template>
 
 <script>
-import { i18n, sendMessage, noop, object } from 'src/common';
+import { i18n, sendMessage, noop } from 'src/common';
+import { objectGet } from 'src/common/object';
 import VmCode from 'src/common/ui/code';
 import { showMessage } from '../../utils';
 import VmSettings from './settings';
@@ -81,7 +82,7 @@ export default {
     this.script = this.initial;
   },
   mounted() {
-    const id = object.get(this.script, 'props.id');
+    const id = objectGet(this.script, 'props.id');
     (id ? sendMessage({
       cmd: 'GetScriptCode',
       data: id,
@@ -145,7 +146,7 @@ export default {
         exclude: toList(rawCustom.exclude),
         excludeMatch: toList(rawCustom.excludeMatch),
       });
-      const id = object.get(this.script, 'props.id');
+      const id = objectGet(this.script, 'props.id');
       return sendMessage({
         cmd: 'ParseScript',
         data: {
@@ -162,7 +163,7 @@ export default {
       })
       .then(res => {
         this.canSave = false;
-        if (object.get(res, 'where.id')) this.script = res.update;
+        if (objectGet(res, 'where.id')) this.script = res.update;
       }, err => {
         showMessage({ text: err });
       });

+ 6 - 5
src/options/views/edit/settings.vue

@@ -87,7 +87,8 @@
 </template>
 
 <script>
-import { i18n, object } from 'src/common';
+import { i18n } from 'src/common';
+import { objectGet } from 'src/common/object';
 import Tooltip from 'src/common/ui/tooltip';
 
 export default {
@@ -105,10 +106,10 @@ export default {
     placeholders() {
       const { value } = this;
       return {
-        name: object.get(value, 'meta.name'),
-        homepageURL: object.get(value, 'meta.homepageURL'),
-        updateURL: object.get(value, 'meta.updateURL') || i18n('hintUseDownloadURL'),
-        downloadURL: object.get(value, 'meta.downloadURL') || value.lastInstallURL,
+        name: objectGet(value, 'meta.name'),
+        homepageURL: objectGet(value, 'meta.homepageURL'),
+        updateURL: objectGet(value, 'meta.updateURL') || i18n('hintUseDownloadURL'),
+        downloadURL: objectGet(value, 'meta.downloadURL') || value.lastInstallURL,
       };
     },
   },

+ 4 - 5
src/options/views/feature.vue

@@ -7,7 +7,7 @@
 <script>
 import Vue from 'vue';
 import options from 'src/common/options';
-import { object } from 'src/common';
+import { objectGet } from 'src/common/object';
 import { store } from '../utils';
 
 const FEATURES_KEY = 'features';
@@ -19,10 +19,9 @@ options.hook(data => {
   }
 });
 options.ready(() => reset('sync'));
-window.store = store;
 
 function reset(version) {
-  if (object.get(store, 'features.version') !== version) {
+  if (objectGet(store, 'features.version') !== version) {
     options.set(FEATURES_KEY, {
       version,
       data: {},
@@ -46,13 +45,13 @@ export default {
   },
   computed: {
     featured() {
-      return this.store.features && !object.get(this.store, ['features', 'data', this.name]);
+      return this.store.features && !objectGet(this.store, ['features', 'data', this.name]);
     },
   },
   methods: {
     onClick() {
       const { features } = this.store;
-      if (object.get(features, 'version')) {
+      if (objectGet(features, 'version')) {
         features.data[this.name] = 1;
         options.set(FEATURES_KEY, features);
       }