browser_object.js (4306B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 // Test the ObjectCommand 7 8 add_task(async function testObjectRelease() { 9 const tab = await addTab("data:text/html;charset=utf-8,Test page<script>var foo = { bar: 42 };</script>"); 10 11 const commands = await CommandsFactory.forTab(tab); 12 await commands.targetCommand.startListening(); 13 14 const evaluationResponse = await commands.scriptCommand.execute( 15 "window.foo" 16 ); 17 18 // Execute a second time so that the WebConsoleActor set this._lastConsoleInputEvaluation to another value 19 // and so we prevent freeing `window.foo` 20 await commands.scriptCommand.execute(""); 21 22 await SpecialPowers.spawn(gBrowser.selectedBrowser, [], function () { 23 is(content.wrappedJSObject.foo.bar, 42); 24 const weakRef = Cu.getWeakReference(content.wrappedJSObject.foo); 25 26 // Hold off the weak reference on SpecialPowsers so that it can be accessed in the next SpecialPowers.spawn 27 SpecialPowers.weakRef = weakRef; 28 29 // Nullify this variable so that it should be freed 30 // unless the DevTools inspection still hold it in memory 31 content.wrappedJSObject.foo = null; 32 33 Cu.forceGC(); 34 Cu.forceCC(); 35 36 ok(SpecialPowers.weakRef.get(), "The 'foo' object can't be freed because of DevTools keeping a reference on it"); 37 }); 38 39 info("Release the server side actors which are keeping the object in memory"); 40 const objectFront = evaluationResponse.result; 41 await commands.objectCommand.releaseObjects([objectFront]); 42 43 ok(objectFront.isDestroyed(), "The passed object front has been destroyed"); 44 45 await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () { 46 await ContentTaskUtils.waitForCondition(() => { 47 Cu.forceGC(); 48 Cu.forceCC(); 49 return !SpecialPowers.weakRef.get(); 50 }, "Wait for JS object to be freed", 500); 51 52 ok(!SpecialPowers.weakRef.get(), "The 'foo' object has been freed"); 53 }); 54 55 await commands.destroy(); 56 BrowserTestUtils.removeTab(tab); 57 }); 58 59 add_task(async function testMultiTargetObjectRelease() { 60 const tab = await addTab(`data:text/html;charset=utf-8,Test page<iframe src="data:text/html,bar">/iframe>`); 61 62 const commands = await CommandsFactory.forTab(tab); 63 await commands.targetCommand.startListening(); 64 65 const [,iframeTarget] = commands.targetCommand.getAllTargets(commands.targetCommand.ALL_TYPES); 66 is(iframeTarget.url, "data:text/html,bar"); 67 68 const evaluationResponse1 = await commands.scriptCommand.execute( 69 "window" 70 ); 71 const evaluationResponse2 = await commands.scriptCommand.execute( 72 "window", { 73 selectedTargetFront: iframeTarget, 74 } 75 ); 76 const object1 = evaluationResponse1.result; 77 const object2 = evaluationResponse2.result; 78 isnot(object1, object2, "The two window object fronts are different"); 79 isnot(object1.targetFront, object2.targetFront, "The two window object fronts relates to two distinct targets"); 80 is(object2.targetFront, iframeTarget, "The second object relates to the iframe target"); 81 82 await commands.objectCommand.releaseObjects([object1, object2]); 83 ok(object1.isDestroyed(), "The first object front is destroyed"); 84 ok(object2.isDestroyed(), "The second object front is destroyed"); 85 86 await commands.destroy(); 87 BrowserTestUtils.removeTab(tab); 88 }); 89 90 add_task(async function testWorkerObjectRelease() { 91 const workerUrl = `data:text/javascript,const foo = {}`; 92 const tab = await addTab(`data:text/html;charset=utf-8,Test page<script>const worker = new Worker("${workerUrl}")</script>`); 93 94 const commands = await CommandsFactory.forTab(tab); 95 commands.targetCommand.listenForWorkers = true; 96 await commands.targetCommand.startListening(); 97 98 const [,workerTarget] = commands.targetCommand.getAllTargets(commands.targetCommand.ALL_TYPES); 99 is(workerTarget.url, workerUrl); 100 101 const evaluationResponse = await commands.scriptCommand.execute( 102 "foo", { 103 selectedTargetFront: workerTarget, 104 } 105 ); 106 const object = evaluationResponse.result; 107 is(object.targetFront, workerTarget, "The 'foo' object relates to the worker target"); 108 109 await commands.objectCommand.releaseObjects([object]); 110 ok(object.isDestroyed(), "The object front is destroyed"); 111 112 await commands.destroy(); 113 BrowserTestUtils.removeTab(tab); 114 });