Bug 972243 - Use Cu.cloneInto() and/or shallow copies to clone state objects r=billm a=sylvestre
authorTim Taubert <ttaubert@mozilla.com>
Wed, 26 Feb 2014 11:34:32 +0100
changeset 234606 d3a94932b8007b98033152e198a0b4fbc334df2d
parent 234605 860e76ec9fe57cc83757089e5946a24fc6456bc3
child 234607 308d6ccf89ea8cce7466aa11bad05aa606822df3
push id208
push userryanvm@gmail.com
push dateMon, 23 Feb 2015 15:44:39 +0000
treeherdermozilla-b2g37_v2_2@09dafeb43234 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm, sylvestre
bugs972243
milestone28.0
Bug 972243 - Use Cu.cloneInto() and/or shallow copies to clone state objects r=billm a=sylvestre
browser/components/sessionstore/src/SessionStore.jsm
browser/components/sessionstore/src/TabState.jsm
browser/components/sessionstore/src/Utils.jsm
--- a/browser/components/sessionstore/src/SessionStore.jsm
+++ b/browser/components/sessionstore/src/SessionStore.jsm
@@ -3451,22 +3451,18 @@ let SessionStoreInternal = {
    * to restore the previous session (publicly exposed as restoreLastSession).
    *
    * @param state
    *        The state, presumably from nsISessionStartup.state
    * @returns [defaultState, state]
    */
   _prepDataForDeferredRestore: function ssi_prepDataForDeferredRestore(state) {
     // Make sure that we don't modify the global state as provided by
-    // nsSessionStartup.state. Converting the object to a JSON string and
-    // parsing it again is the easiest way to do that, although not the most
-    // efficient one. Deferred sessions that don't have automatic session
-    // restore enabled tend to be a lot smaller though so that this shouldn't
-    // be a big perf hit.
-    state = JSON.parse(JSON.stringify(state));
+    // nsSessionStartup.state.
+    state = Cu.cloneInto(state, {});
 
     let defaultState = { windows: [], selectedWindow: 1 };
 
     state.selectedWindow = state.selectedWindow || 1;
 
     // Look at each window, remove pinned tabs, adjust selectedindex,
     // remove window if necessary.
     for (let wIndex = 0; wIndex < state.windows.length;) {
--- a/browser/components/sessionstore/src/TabState.jsm
+++ b/browser/components/sessionstore/src/TabState.jsm
@@ -439,17 +439,17 @@ let TabStateInternal = {
     if (!browser || !browser.currentURI) {
       // can happen when calling this function right after .addTab()
       return tabData;
     }
     if (browser.__SS_data) {
       // Use the data to be restored when the tab hasn't been
       // completely loaded. We clone the data, since we're updating it
       // here and the caller may update it further.
-      tabData = JSON.parse(JSON.stringify(browser.__SS_data));
+      tabData = Utils.shallowCopy(browser.__SS_data);
       if (tab.pinned)
         tabData.pinned = true;
       else
         delete tabData.pinned;
       tabData.hidden = tab.hidden;
 
       // If __SS_extdata is set then we'll use that since it might be newer.
       if (tab.__SS_extdata)
--- a/browser/components/sessionstore/src/Utils.jsm
+++ b/browser/components/sessionstore/src/Utils.jsm
@@ -38,16 +38,26 @@ this.Utils = Object.freeze({
     if (host == domain)
       return true;
 
     let prevChar = host[index - 1];
     return (index == (host.length - domain.length)) &&
            (prevChar == "." || prevChar == "/");
   },
 
+  shallowCopy: function (obj) {
+    let retval = {};
+
+    for (let key of Object.keys(obj)) {
+      retval[key] = obj[key];
+    }
+
+    return retval;
+  },
+
   swapMapEntries: function (map, key, otherKey) {
     // Make sure that one or the other of these has an entry in the map,
     // and let it be |key|.
     if (!map.has(key)) {
       [key, otherKey] = [otherKey, key];
       if (!map.has(key)) {
         return;
       }