browser_memory_allocations_01.js (3532B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 add_task(async function () { 7 const target = await addTabTarget("data:text/html;charset=utf-8,test-doc"); 8 const memory = await target.getFront("memory"); 9 10 await memory.attach(); 11 12 await memory.startRecordingAllocations(); 13 ok(true, "Can start recording allocations"); 14 15 // Allocate some objects. 16 const [line1, line2, line3] = await SpecialPowers.spawn( 17 gBrowser.selectedBrowser, 18 [], 19 function () { 20 // Use eval to ensure allocating the object in the page's compartment 21 return content.eval( 22 "(" + 23 function () { 24 let alloc1, alloc2, alloc3; 25 26 /* eslint-disable max-nested-callbacks */ 27 (function outer() { 28 (function middle() { 29 (function inner() { 30 alloc1 = {}; 31 alloc1.line = Error().lineNumber; 32 alloc2 = []; 33 alloc2.line = Error().lineNumber; 34 // eslint-disable-next-line new-parens 35 alloc3 = new (function () {})(); 36 alloc3.line = Error().lineNumber; 37 })(); 38 })(); 39 })(); 40 /* eslint-enable max-nested-callbacks */ 41 42 return [alloc1.line, alloc2.line, alloc3.line]; 43 } + 44 ")()" 45 ); 46 } 47 ); 48 49 const response = await memory.getAllocations(); 50 51 await memory.stopRecordingAllocations(); 52 ok(true, "Can stop recording allocations"); 53 54 // Filter out allocations by library and test code, and get only the 55 // allocations that occurred in our test case above. 56 57 function isTestAllocation(alloc) { 58 const frame = response.frames[alloc]; 59 return ( 60 frame && 61 frame.functionDisplayName === "inner" && 62 (frame.line === line1 || frame.line === line2 || frame.line === line3) 63 ); 64 } 65 66 const testAllocations = response.allocations.filter(isTestAllocation); 67 Assert.greaterOrEqual( 68 testAllocations.length, 69 3, 70 "Should find our 3 test allocations (plus some allocations for the error " + 71 "objects used to get line numbers)" 72 ); 73 74 // For each of the test case's allocations, ensure that the parent frame 75 // indices are correct. Also test that we did get an allocation at each 76 // line we expected (rather than a bunch on the first line and none on the 77 // others, etc). 78 79 const expectedLines = new Set([line1, line2, line3]); 80 is(expectedLines.size, 3, "We are expecting 3 allocations"); 81 82 for (const alloc of testAllocations) { 83 const innerFrame = response.frames[alloc]; 84 ok(innerFrame, "Should get the inner frame"); 85 is(innerFrame.functionDisplayName, "inner"); 86 expectedLines.delete(innerFrame.line); 87 88 const middleFrame = response.frames[innerFrame.parent]; 89 ok(middleFrame, "Should get the middle frame"); 90 is(middleFrame.functionDisplayName, "middle"); 91 92 const outerFrame = response.frames[middleFrame.parent]; 93 ok(outerFrame, "Should get the outer frame"); 94 is(outerFrame.functionDisplayName, "outer"); 95 96 // Not going to test the rest of the frames because they are Task.jsm 97 // and promise frames and it gets gross. Plus, I wouldn't want this test 98 // to start failing if they changed their implementations in a way that 99 // added or removed stack frames here. 100 } 101 102 is(expectedLines.size, 0, "Should have found all the expected lines"); 103 104 await memory.detach(); 105 106 await target.destroy(); 107 });