Browse Source

fix: only skip sending the last known value

tophf 5 years ago
parent
commit
b9db23e57c
1 changed files with 18 additions and 16 deletions
  1. 18 16
      src/background/utils/values.js

+ 18 - 16
src/background/utils/values.js

@@ -1,5 +1,5 @@
 import { isEmpty, sendTabCmd } from '#/common';
-import { forEachEntry, objectSet } from '#/common/object';
+import { forEachEntry, objectPick, objectSet } from '#/common/object';
 import { getValueStoresByIds, dumpValueStores, dumpValueStore } from './db';
 import { commands } from './message';
 
@@ -20,13 +20,11 @@ Object.assign(commands, {
     if (store) broadcastUpdates(store);
   },
   /** @return {Promise<void>} */
-  UpdateValue({ id, update: { key, value } }, src) {
+  UpdateValue({ id, update: { key, value = null } }, src) {
     // Value will be updated to store later.
     updateLater();
-    cache = objectSet(cache, [id, [key]], {
-      value: value || null,
-      src: `${src.tab.id}:${src.frameId}`,
-    });
+    cache = objectSet(cache, [id, key, 'last'], value);
+    objectSet(cache, [id, key, src.tab.id, src.frameId], value);
   },
 });
 
@@ -67,9 +65,9 @@ async function doUpdate() {
     ids.forEach((id) => {
       const valueStore = valueStores[id] || (valueStores[id] = {});
       const updates = currentCache[id] || {};
-      updates::forEachEntry(([key, history]) => {
-        if (!history) delete valueStore[key];
-        else valueStore[key] = history[history.length - 1].value;
+      updates::forEachEntry(([key, { last }]) => {
+        if (!last) delete valueStore[key];
+        else valueStore[key] = last;
       });
     });
     await dumpValueStores(valueStores);
@@ -101,16 +99,20 @@ function broadcastUpdates(updates, oldCache = {}) {
 }
 
 function avoidInitiator(data, history, tabId, frameId) {
-  let clone;
   if (history) {
-    const src = `${tabId}:${frameId}`;
-    data::forEachEntry(([key, value]) => {
-      if (history[key]?.some(h => h.value === value && h.src === src)) {
-        if (!clone) clone = { ...data };
-        delete clone[key];
+    let toPick;
+    Object.keys(data).forEach((key, i, allKeys) => {
+      // Not sending `key` to this frame if its last recorded value is identical
+      const frameValue = history[key]?.[tabId]?.[frameId];
+      if (frameValue !== undefined && frameValue === data[key]) {
+        // ...sending the preceding different keys
+        if (!toPick) toPick = allKeys.slice(0, i);
+      } else {
+        // ...sending the subsequent different keys
+        if (toPick) toPick.push(key);
       }
     });
-    if (clone) data = clone;
+    if (toPick) data = objectPick(data, toPick);
   }
   return !isEmpty(data) ? data : undefined; // undef will remove the key in objectSet
 }