fune/browser/base/content/test/performance/browser_windowopen_reflows.js
Mike Conley 4cdf0cab90 Bug 1354194 - Add utility method for more easily writing reflow tests. r=florian
This also consolidates the pre-existing style and layout flush regression tests
into the same performance folder.

MozReview-Commit-ID: IA3FqroG75O

--HG--
rename : browser/base/content/test/windows/.eslintrc.js => browser/base/content/test/performance/.eslintrc.js
rename : browser/base/content/test/general/browser_tabopen_reflows.js => browser/base/content/test/performance/browser_tabopen_reflows.js
rename : browser/base/content/test/windows/browser_toolbariconcolor_restyles.js => browser/base/content/test/performance/browser_toolbariconcolor_restyles.js
rename : browser/base/content/test/general/browser_windowopen_reflows.js => browser/base/content/test/performance/browser_windowopen_reflows.js
extra : rebase_source : b226a9aceecf118ffad2f23c2361f0be403d5aaf
2017-05-02 17:30:18 -04:00

117 lines
4.6 KiB
JavaScript

/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const EXPECTED_REFLOWS = [
// handleEvent flushes layout to get the tabstrip width after a resize.
"handleEvent@chrome://browser/content/tabbrowser.xml|",
// Loading a tab causes a reflow.
"loadTabs@chrome://browser/content/tabbrowser.xml|" +
"loadOneOrMoreURIs@chrome://browser/content/browser.js|" +
"_delayedStartup@chrome://browser/content/browser.js|",
// Selecting the address bar causes a reflow.
"select@chrome://global/content/bindings/textbox.xml|" +
"focusAndSelectUrlBar@chrome://browser/content/browser.js|" +
"_delayedStartup@chrome://browser/content/browser.js|",
// Focusing the content area causes a reflow.
"_delayedStartup@chrome://browser/content/browser.js|",
];
if (Services.appinfo.OS == "WINNT" || Services.appinfo.OS == "Darwin") {
// TabsInTitlebar._update causes a reflow on OS X and Windows trying to do calculations
// since layout info is already dirty. This doesn't seem to happen before
// MozAfterPaint on Linux.
EXPECTED_REFLOWS.push("rect@chrome://browser/content/browser-tabsintitlebar.js|" +
"_update@chrome://browser/content/browser-tabsintitlebar.js|" +
"updateAppearance@chrome://browser/content/browser-tabsintitlebar.js|" +
"handleEvent@chrome://browser/content/tabbrowser.xml|");
}
if (Services.appinfo.OS == "Darwin") {
// _onOverflow causes a reflow getting widths.
EXPECTED_REFLOWS.push("_onOverflow@resource:///modules/CustomizableUI.jsm|" +
"init@resource:///modules/CustomizableUI.jsm|" +
"observe@resource:///modules/CustomizableUI.jsm|" +
"_delayedStartup@chrome://browser/content/browser.js|");
// Same as above since in packaged builds there are no function names and the resource URI includes "app"
EXPECTED_REFLOWS.push("@resource://app/modules/CustomizableUI.jsm|" +
"@resource://app/modules/CustomizableUI.jsm|" +
"@resource://app/modules/CustomizableUI.jsm|" +
"_delayedStartup@chrome://browser/content/browser.js|");
}
/*
* This test ensures that there are no unexpected
* uninterruptible reflows when opening new windows.
*/
function test() {
waitForExplicitFinish();
// Add a reflow observer and open a new window
let win = OpenBrowserWindow();
let docShell = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
docShell.addWeakReflowObserver(observer);
// Wait until the mozafterpaint event occurs.
waitForMozAfterPaint(win, function paintListener() {
// Remove reflow observer and clean up.
docShell.removeWeakReflowObserver(observer);
win.close();
finish();
});
}
var observer = {
reflow(start, end) {
// Gather information about the current code path.
let stack = new Error().stack;
let path = stack.split("\n").slice(1).map(line => {
return line.replace(/:\d+:\d+$/, "");
}).join("|");
let pathWithLineNumbers = (new Error().stack).split("\n").slice(1).join("|");
// Stack trace is empty. Reflow was triggered by native code.
if (path === "") {
return;
}
// Check if this is an expected reflow.
for (let expectedStack of EXPECTED_REFLOWS) {
if (path.startsWith(expectedStack) ||
// Accept an empty function name for gBrowserInit._delayedStartup or TabsInTitlebar._update to workaround bug 906578.
path.startsWith(expectedStack.replace(/(^|\|)(gBrowserInit\._delayedStartup|TabsInTitlebar\._update)@/, "$1@"))) {
ok(true, "expected uninterruptible reflow '" + expectedStack + "'");
return;
}
}
ok(false, "unexpected uninterruptible reflow '" + pathWithLineNumbers + "'");
},
reflowInterruptible(start, end) {
// We're not interested in interruptible reflows.
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIReflowObserver,
Ci.nsISupportsWeakReference])
};
function waitForMozAfterPaint(win, callback) {
let dwu = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
let lastTransactionId = dwu.lastTransactionId;
win.addEventListener("MozAfterPaint", function onEnd(event) {
if (event.target != win || event.transactionId <= lastTransactionId)
return;
win.removeEventListener("MozAfterPaint", onEnd);
executeSoon(callback);
});
}