Bug 1307884 - Limit for messages in the store; r=bgrins draft
authorJan Odvarko <odvarko@gmail.com>
Mon, 22 May 2017 19:19:56 +0200
changeset 582478 baebb8c6aeed8ff15fc9e81f9470dfad3371118c
parent 582447 8f4d2d35cb317235f30f4e3738ad3df16d2f9f3f
child 582479 8daa22c4645c15a04af636a02315a9246211dcb0
push id60109
push userjodvarko@mozilla.com
push dateMon, 22 May 2017 18:06:18 +0000
reviewersbgrins
bugs1307884
milestone55.0a1
Bug 1307884 - Limit for messages in the store; r=bgrins MozReview-Commit-ID: 3NLMvJFPbls
devtools/client/webconsole/new-console-output/reducers/messages.js
--- a/devtools/client/webconsole/new-console-output/reducers/messages.js
+++ b/devtools/client/webconsole/new-console-output/reducers/messages.js
@@ -3,16 +3,19 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 const Immutable = require("devtools/client/shared/vendor/immutable");
 const constants = require("devtools/client/webconsole/new-console-output/constants");
 const {isGroupType} = require("devtools/client/webconsole/new-console-output/utils/messages");
+const Services = require("Services");
+
+const logLimit = Math.max(Services.prefs.getIntPref("devtools.hud.loglimit"), 1);
 
 const MessageState = Immutable.Record({
   // List of all the messages added to the console.
   messagesById: Immutable.List(),
   // List of the message ids which are opened.
   messagesUiById: Immutable.List(),
   // Map of the form {messageId : tableData}, which represent the data passed
   // as an argument in console.table calls.
@@ -77,16 +80,26 @@ function messages(state = new MessageSta
             )
           );
 
           if (newMessage.type === constants.MESSAGE_TYPE.START_GROUP) {
             // We want the group to be open by default.
             record.set("messagesUiById", messagesUiById.push(newMessage.id));
           }
         }
+
+        // Remove top level message if the total count of top level messages
+        // exceeds the current limit.
+        let topLevelCount = getToplevelMessageCount(record);
+        while (topLevelCount > logLimit) {
+          let removedMessage = removeFirstMessage(record);
+          if (!removedMessage.groupId) {
+            topLevelCount--;
+          }
+        }
       });
     case constants.MESSAGES_CLEAR:
       return state.withMutations(function (record) {
         record.set("messagesById", Immutable.List());
         record.set("messagesUiById", Immutable.List());
         record.set("groupsById", Immutable.Map());
         record.set("currentGroup", null);
       });
@@ -132,9 +145,53 @@ function getParentGroups(currentGroup, g
     if (Array.isArray(parentGroups) && parentGroups.length > 0) {
       groups = groups.concat(parentGroups);
     }
   }
 
   return groups;
 }
 
+/**
+ * Returns total count of top level messages (those which are not
+ * within a group).
+ */
+function getToplevelMessageCount(record) {
+  return [...record.messagesById].filter(message => !message.groupId).length;
+}
+
+/**
+ * Remove first (the oldest) message from the store. The methods removes
+ * also all its references and children from the store.
+ */
+function removeFirstMessage(record) {
+  let firstMessage = record.messagesById.first();
+  record.set("messagesById", record.messagesById.shift());
+
+  // Remove from list of opened groups.
+  let uiIndex = record.messagesUiById.indexOf(firstMessage);
+  if (uiIndex >= 0) {
+    record.set("messagesUiById", record.messagesUiById.delete(uiIndex));
+  }
+
+  // Remove from list of tables.
+  if (record.messagesTableDataById.has(firstMessage.id)) {
+    record.set("messagesTableDataById", record.messagesTableDataById.delete(firstMessage.id));
+  }
+
+  // Remove from list of parent groups.
+  if (record.groupsById.has(firstMessage.id)) {
+    record.set("groupsById", record.groupsById.delete(firstMessage.id));
+  }
+
+  // Remove all children. This loop assumes that children of removed
+  // group immediately follows the group. We use recursion since
+  // there might be inner groups.
+  let message = record.messagesById.first();
+  while (message.groupId == firstMessage.id) {
+    removeFirstMessage(record);
+    message = record.messagesById.first();
+  }
+
+  return firstMessage;
+}
+
 exports.messages = messages;