Bug 1501337 - Fix a leak and uncleared listeners in places code relating to the edit bookmarks views. r=mak, a=RyanVM
authorMark Banner <standard8@mozilla.com>
Tue, 23 Oct 2018 17:58:43 +0000
changeset 500827 e89d63d1dd5fbde689fb49dd3fc8dcf9203c789c
parent 500826 154465d8a68413c82c8fdb3cfe15e704829dada3
child 500828 3cf4f972200ce2467776265331e0bded412ded40
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmak, RyanVM
bugs1501337
milestone64.0
Bug 1501337 - Fix a leak and uncleared listeners in places code relating to the edit bookmarks views. r=mak, a=RyanVM Differential Revision: https://phabricator.services.mozilla.com/D9546
browser/components/places/content/bookmarkProperties.js
browser/components/places/content/editBookmark.js
toolkit/components/places/PlacesUtils.jsm
--- a/browser/components/places/content/bookmarkProperties.js
+++ b/browser/components/places/content/bookmarkProperties.js
@@ -360,16 +360,18 @@ var BookmarkPropertiesPanel = {
     delete this._mutationObserver;
 
     window.removeEventListener("resize", this);
 
     // Calling removeEventListener with arguments which do not identify any
     // currently registered EventListener on the EventTarget has no effect.
     this._element("locationField")
         .removeEventListener("input", this);
+    this._element("keywordField")
+        .removeEventListener("input", this);
   },
 
   onDialogAccept() {
     // We must blur current focused element to save its changes correctly
     document.commandDispatcher.focusedElement.blur();
     // We have to uninit the panel first, otherwise late changes could force it
     // to commit more transactions.
     gEditItemOverlay.uninitPanel(true);
--- a/browser/components/places/content/editBookmark.js
+++ b/browser/components/places/content/editBookmark.js
@@ -435,16 +435,17 @@ var gEditItemOverlay = {
       // Hide the tag selector if it was previously visible.
       var tagsSelectorRow = this._element("tagsSelectorRow");
       if (!tagsSelectorRow.collapsed)
         this.toggleTagsSelector().catch(Cu.reportError);
     }
 
     if (this._observersAdded) {
       PlacesUtils.bookmarks.removeObserver(this);
+      window.removeEventListener("unload", this);
       this._observersAdded = false;
     }
 
     this._setPaneInfo(null);
     this._firstEditedField = "";
   },
 
   get selectedFolderGuid() {
--- a/toolkit/components/places/PlacesUtils.jsm
+++ b/toolkit/components/places/PlacesUtils.jsm
@@ -2001,26 +2001,30 @@ PlacesUtils.metadata = {
       if (row.getTypeOfIndex(0) == row.VALUE_TYPE_BLOB) {
         value = new Uint8Array(rawValue);
       } else if (typeof rawValue == "string" &&
                  rawValue.startsWith(this.jsonPrefix)) {
         try {
           value = JSON.parse(this._base64Decode(rawValue.substr(this.jsonPrefix.length)));
         } catch (ex) {
           if (defaultValue !== undefined) {
-            value = defaultValue;
+            // We must create a new array in the local scope to avoid a memory
+            // leak due to the array global object.
+            value = Cu.cloneInto(defaultValue, {});
           } else {
             throw ex;
           }
         }
       } else {
         value = rawValue;
       }
     } else if (defaultValue !== undefined) {
-      value = defaultValue;
+      // We must create a new array in the local scope to avoid a memory leak due
+      // to the array global object.
+      value = Cu.cloneInto(defaultValue, {});
     } else {
       throw new Error(`No data stored for key ${key}`);
     }
     this.cache.set(key, value);
     return value;
   },
 
   async setWithConnection(db, key, value) {