diff --git a/browser/components/sessionstore/SessionStore.jsm b/browser/components/sessionstore/SessionStore.jsm index 4a4a60e5979f..171ebb789005 100644 --- a/browser/components/sessionstore/SessionStore.jsm +++ b/browser/components/sessionstore/SessionStore.jsm @@ -3570,7 +3570,9 @@ var SessionStoreInternal = { // Update the persistent tab state cache with |tabData| information. TabStateCache.update(browser, { - history: {entries: tabData.entries, index: tabData.index}, + // NOTE: Copy the entries array shallowly, so as to not screw with the + // original tabData's history when getting history updates. + history: {entries: [...tabData.entries], index: tabData.index}, scroll: tabData.scroll || null, storage: tabData.storage || null, formdata: tabData.formdata || null, diff --git a/browser/components/sessionstore/TabState.jsm b/browser/components/sessionstore/TabState.jsm index f22c52fe3387..f79e2086070b 100644 --- a/browser/components/sessionstore/TabState.jsm +++ b/browser/components/sessionstore/TabState.jsm @@ -179,7 +179,10 @@ var TabStateInternal = { } if (key === "history") { - tabData.entries = value.entries; + // Make a shallow copy of the entries array. We (currently) don't update + // entries in place, so we don't have to worry about performing a deep + // copy. + tabData.entries = [...value.entries]; if (value.hasOwnProperty("userContextId")) { tabData.userContextId = value.userContextId; diff --git a/browser/components/sessionstore/test/browser.ini b/browser/components/sessionstore/test/browser.ini index 4566f3a0c605..def87cef5de2 100644 --- a/browser/components/sessionstore/test/browser.ini +++ b/browser/components/sessionstore/test/browser.ini @@ -243,3 +243,4 @@ skip-if = !e10s # GroupedSHistory is e10s-only [browser_closed_objects_changed_notifications_tabs.js] [browser_closed_objects_changed_notifications_windows.js] +[browser_duplicate_history.js] diff --git a/browser/components/sessionstore/test/browser_duplicate_history.js b/browser/components/sessionstore/test/browser_duplicate_history.js new file mode 100644 index 000000000000..1c04eda1134b --- /dev/null +++ b/browser/components/sessionstore/test/browser_duplicate_history.js @@ -0,0 +1,22 @@ +XPCOMUtils.defineLazyModuleGetter(this, "SessionStore", + "resource:///modules/sessionstore/SessionStore.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "TabStateCache", + "resource:///modules/sessionstore/TabStateCache.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "TabStateFlusher", + "resource:///modules/sessionstore/TabStateFlusher.jsm"); + +add_task(function* () { + yield BrowserTestUtils.withNewTab("http://example.com", function* (aBrowser) { + let tab = gBrowser.getTabForBrowser(aBrowser); + yield TabStateFlusher.flush(aBrowser); + let before = TabStateCache.get(aBrowser); + + let newTab = SessionStore.duplicateTab(window, tab); + yield BrowserTestUtils.browserLoaded(newTab.linkedBrowser); + let after = TabStateCache.get(newTab.linkedBrowser); + + isnot(before.history.entries, after.history.entries, + "The entry objects should not be shared"); + yield BrowserTestUtils.removeTab(newTab); + }); +});