diff options
Diffstat (limited to 'devtools/client/memory/test/browser/browser_memory_refresh_does_not_leak.js')
-rw-r--r-- | devtools/client/memory/test/browser/browser_memory_refresh_does_not_leak.js | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/devtools/client/memory/test/browser/browser_memory_refresh_does_not_leak.js b/devtools/client/memory/test/browser/browser_memory_refresh_does_not_leak.js new file mode 100644 index 000000000..7ab768b01 --- /dev/null +++ b/devtools/client/memory/test/browser/browser_memory_refresh_does_not_leak.js @@ -0,0 +1,108 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test that refreshing the page with devtools open does not leak the old +// windows from previous navigations. +// +// IF THIS TEST STARTS FAILING, YOU ARE LEAKING EVERY WINDOW EVER NAVIGATED TO +// WHILE DEVTOOLS ARE OPEN! THIS IS NOT SPECIFIC TO THE MEMORY TOOL ONLY! + +"use strict"; + +const HeapSnapshotFileUtils = require("devtools/shared/heapsnapshot/HeapSnapshotFileUtils"); +const { getLabelAndShallowSize } = require("devtools/shared/heapsnapshot/DominatorTreeNode"); + +const TEST_URL = "http://example.com/browser/devtools/client/memory/test/browser/doc_empty.html"; + +function* getWindowsInSnapshot(front) { + dumpn("Taking snapshot."); + const path = yield front.saveHeapSnapshot(); + dumpn("Took snapshot with path = " + path); + const snapshot = ChromeUtils.readHeapSnapshot(path); + dumpn("Read snapshot into memory, taking census."); + const report = snapshot.takeCensus({ + breakdown: { + by: "objectClass", + then: { by: "bucket" }, + other: { by: "count", count: true, bytes: false }, + } + }); + dumpn("Took census, window count = " + report.Window.count); + return report.Window; +} + +const DESCRIPTION = { + by: "coarseType", + objects: { + by: "objectClass", + then: { by: "count", count: true, bytes: false }, + other: { by: "count", count: true, bytes: false }, + }, + strings: { by: "count", count: true, bytes: false }, + scripts: { + by: "internalType", + then: { by: "count", count: true, bytes: false }, + }, + other: { + by: "internalType", + then: { by: "count", count: true, bytes: false }, + } +}; + +this.test = makeMemoryTest(TEST_URL, function* ({ tab, panel }) { + const heapWorker = panel.panelWin.gHeapAnalysesClient; + const front = panel.panelWin.gFront; + const store = panel.panelWin.gStore; + const { getState, dispatch } = store; + const doc = panel.panelWin.document; + + const startWindows = yield getWindowsInSnapshot(front); + dumpn("Initial windows found = " + startWindows.map(w => "0x" + w.toString(16)).join(", ")); + is(startWindows.length, 1); + + yield refreshTab(tab); + + const endWindows = yield getWindowsInSnapshot(front); + is(endWindows.length, 1); + + if (endWindows.length === 1) { + return; + } + + dumpn("Test failed, diagnosing leaking windows."); + dumpn("(This may fail if a moving GC has relocated the initial Window objects.)"); + + dumpn("Taking full runtime snapshot."); + const path = yield front.saveHeapSnapshot({ boundaries: { runtime: true } }); + dumpn("Full runtime's snapshot path = " + path); + + dumpn("Reading full runtime heap snapshot."); + const snapshot = ChromeUtils.readHeapSnapshot(path); + dumpn("Done reading full runtime heap snapshot."); + + const dominatorTree = snapshot.computeDominatorTree(); + const paths = snapshot.computeShortestPaths(dominatorTree.root, startWindows, 50); + + for (let i = 0; i < startWindows.length; i++) { + dumpn("Shortest retaining paths for leaking Window 0x" + startWindows[i].toString(16) + " ========================="); + let j = 0; + for (let retainingPath of paths.get(startWindows[i])) { + if (retainingPath.find(part => part.predecessor === startWindows[i])) { + // Skip paths that loop out from the target window and back to it again. + continue; + } + + dumpn(" Path #" + (++j) + ": --------------------------------------------------------------------"); + for (let part of retainingPath) { + const { label } = getLabelAndShallowSize(part.predecessor, snapshot, DESCRIPTION); + dumpn(" 0x" + part.predecessor.toString(16) + + " (" + label.join(" > ") + ")"); + dumpn(" |"); + dumpn(" " + part.edge); + dumpn(" |"); + dumpn(" V"); + } + dumpn(" 0x" + startWindows[i].toString(16) + " (objects > Window)"); + } + } +}); |