fune/js/xpconnect/tests/browser/browser_exception_leak.js
Kris Maglione 0b1a146519 Bug 1596918: Part 4c - Fix callers which depend on document lifecycle changes. r=mccr8
ContentTask tasks have a different lifetime than SpecialPowers tasks, with the
former being tied to the lifetime of a message manager and the latter tied to
the lifetime of a window global. That means that existing ContentTask callers
which expect to be able to register load listeners before the creation of a
window global, or which expect to persist after a page has navigated, won't
work as SpecialPowers tasks.

Since those sorts of tasks are not really resilient in the face of Fission,
they should really be written to work differently, but this patch mostly just
reverts them to using ContentTask for the time being.

Differential Revision: https://phabricator.services.mozilla.com/D53744

--HG--
extra : moz-landing-system : lando
2019-12-13 20:36:36 +00:00

73 lines
2.5 KiB
JavaScript

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// For bug 1471989, test that an exception saved by chrome code can't leak the page.
add_task(async function test() {
const url =
"http://mochi.test:8888/browser/js/xpconnect/tests/browser/browser_consoleStack.html";
let newTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
let browser = gBrowser.selectedBrowser;
let innerWindowId = browser.innerWindowID;
let stackTraceEmpty = await ContentTask.spawn(
browser,
{ innerWindowId },
async function(args) {
let { TestUtils } = ChromeUtils.import(
"resource://testing-common/TestUtils.jsm"
);
let { Assert } = ChromeUtils.import(
"resource://testing-common/Assert.jsm"
);
const ConsoleAPIStorage = Cc[
"@mozilla.org/consoleAPI-storage;1"
].getService(Ci.nsIConsoleAPIStorage);
let consoleEvents = ConsoleAPIStorage.getEvents(args.innerWindowId);
Assert.equal(
consoleEvents.length,
1,
"Should only be one console event for the window"
);
// Intentionally hold a reference to the console event.
let leakedConsoleEvent = consoleEvents[0];
let doc = content.document;
let promise = TestUtils.topicObserved(
"inner-window-nuked",
(subject, data) => {
let id = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
return id == args.innerWindowId;
}
);
content.location = "http://mochi.test:8888/";
await promise;
// This string should be empty. For that to happen, two things
// need to be true:
//
// a) ConsoleCallData::mStack is not null. This means that the
// stack trace was not reified before the page was nuked. If it
// was, then the correct |filename| value would be stored on the
// object. (This is not a problem, except that it stops us from
// testing the next condition.)
//
// b) ConsoleData::mStack.mStack is null. This means that the
// JSStackFrame is keeping alive the JS object in the page after
// the page was nuked, which leaks the page.
return leakedConsoleEvent.stacktrace[0].filename;
}
);
is(
stackTraceEmpty,
"",
"JSStackFrame shouldn't leak mStack after window nuking"
);
BrowserTestUtils.removeTab(newTab);
});