diff options
Diffstat (limited to 'layout/base/tests/browser_bug1701027-1.js')
-rw-r--r-- | layout/base/tests/browser_bug1701027-1.js | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/layout/base/tests/browser_bug1701027-1.js b/layout/base/tests/browser_bug1701027-1.js new file mode 100644 index 0000000000..bf5a4ffaa3 --- /dev/null +++ b/layout/base/tests/browser_bug1701027-1.js @@ -0,0 +1,130 @@ +/* This test is based on + https://searchfox.org/mozilla-central/rev/e082df56bbfeaff0f388e7da9da401ff414df18f/gfx/layers/apz/test/mochitest/browser_test_select_zoom.js +*/ + +// In order for this test to test the original bug we need: +// 1) At least e10s enabled so that apz is enabled so we can create an +// nsDisplayAsyncZoom item +// (the insertion of this item without marking the required frame modified +// is what causes the bug in the retained display list merging) +// 2) a root content document, again so that we can create a nsDisplayAsyncZoom +// item +// 3) the root content document cannot have a display port to start +// (if it has a display port then it gets a nsDisplayAsyncZoom, but we need +// that to be created after the anonymous content we insert into the +// document) +// Point 3) requires the root content document to be in the parent process, +// since if it is in a content process it will get a displayport for being at +// the root of a process. +// Creating an in-process root content document I think is not possible in +// mochitest-plain. mochitest-chrome does not have e10s enabled. So this has to +// be a mochitest-browser-chrome test. + +// Outline of this test: +// Open a new tab with a pretty simple content file, that is not scrollable +// Use the anonymous content api to insert into that content doc +// Send a mouse click over the content doc +// The click hits fixed pos content. +// This sets a displayport on the root scroll frame of the content doc. +// (This is because we call GetAsyncScrollableAncestorFrame in +// PrepareForSetTargetAPZCNotification +// https://searchfox.org/mozilla-central/rev/e082df56bbfeaff0f388e7da9da401ff414df18f/gfx/layers/apz/util/APZCCallbackHelper.cpp#624 +// which passes the SCROLLABLE_FIXEDPOS_FINDS_ROOT flag +// https://searchfox.org/mozilla-central/rev/e082df56bbfeaff0f388e7da9da401ff414df18f/layout/base/nsLayoutUtils.cpp#2884 +// so starting from fixed pos content means we always find the root scroll +// frame, whereas if we started from non-fixed content we'd walk pass the root +// scroll frame becase it isn't scrollable.) +// Then we have to be careful not to do anything that causes a full display +// list rebuild. +// And finally we change the color of the fixed element which covers the whole +// viewport which causes us to do a partial display list update including the +// anonymous content, which hits the assert we are aiming to test. + +add_task(async function () { + function getChromeURL(filename) { + let chromeURL = getRootDirectory(gTestPath) + filename; + return chromeURL; + } + + // We need this otherwise there is a burst animation on the new tab when it + // loads and that somehow scrolls a scroll frame, which makes it active, + // which makes the scrolled frame an AGR, which means we have multiple AGRs + // (the display port makes the root scroll frame active and an AGR) so we hit + // this + // https://searchfox.org/mozilla-central/rev/e082df56bbfeaff0f388e7da9da401ff414df18f/layout/painting/RetainedDisplayListBuilder.cpp#1179 + // and are forced to do a full display list rebuild and that prevents us from + // testing the original bug. + await SpecialPowers.pushPrefEnv({ + set: [["ui.prefersReducedMotion", 1]], + }); + + const pageUrl = getChromeURL("helper_bug1701027-1.html"); + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl); + + const [theX, theY] = await SpecialPowers.spawn( + tab.linkedBrowser, + [], + async () => { + content.document.body.offsetWidth; + + await new Promise(r => content.window.requestAnimationFrame(r)); + + const rect = content.document + .getElementById("fd") + .getBoundingClientRect(); + const x = content.window.mozInnerScreenX + rect.left + rect.width / 2; + const y = content.window.mozInnerScreenY + rect.top + rect.height / 2; + + let doc = SpecialPowers.wrap(content.document); + var bq = doc.createElement("blockquote"); + bq.textContent = "This blockquote text."; + var div = doc.createElement("div"); + div.textContent = " This div text."; + bq.appendChild(div); + var ac = doc.insertAnonymousContent(bq); + content.document.body.offsetWidth; + + await new Promise(r => content.window.requestAnimationFrame(r)); + await new Promise(r => content.window.requestAnimationFrame(r)); + + return [x, y]; + } + ); + + EventUtils.synthesizeNativeMouseEvent({ + type: "click", + target: window.document.documentElement, + screenX: theX, + screenY: theY, + }); + + await new Promise(resolve => setTimeout(resolve, 0)); + await SpecialPowers.spawn(tab.linkedBrowser, [], async () => { + await new Promise(r => content.window.requestAnimationFrame(r)); + await new Promise(r => content.window.requestAnimationFrame(r)); + }); + + await SpecialPowers.spawn(tab.linkedBrowser, [], async () => { + content.document.getElementById("fd").style.backgroundColor = "blue"; + }); + + await new Promise(resolve => setTimeout(resolve, 0)); + await SpecialPowers.spawn(tab.linkedBrowser, [], async () => { + await new Promise(r => content.window.requestAnimationFrame(r)); + await new Promise(r => content.window.requestAnimationFrame(r)); + }); + + await SpecialPowers.spawn(tab.linkedBrowser, [], async () => { + content.document.getElementById("fd").style.backgroundColor = "red"; + }); + + await new Promise(resolve => setTimeout(resolve, 0)); + await SpecialPowers.spawn(tab.linkedBrowser, [], async () => { + await new Promise(r => content.window.requestAnimationFrame(r)); + await new Promise(r => content.window.requestAnimationFrame(r)); + }); + + BrowserTestUtils.removeTab(tab); + + ok(true, "didn't crash"); +}); |