Bug 1836801. If the order of top layer items changes make sure to mark the frame modified. r=gfx-reviewers,aosmond

The order of items in the mTopLayer array determines the order that we build display items, so if it changes we need to mark the frames as modified so that retained display list partial updates can properly merge.

Differential Revision: https://phabricator.services.mozilla.com/D201214
This commit is contained in:
Timothy Nikkel 2024-02-22 10:09:18 +00:00
parent 1405226c26
commit e393bfbb89
3 changed files with 74 additions and 0 deletions

View File

@ -14751,6 +14751,10 @@ void Document::TopLayerPush(Element& aElement) {
const bool modal = aElement.State().HasState(ElementState::MODAL);
TopLayerPop(aElement);
if (nsIFrame* f = aElement.GetPrimaryFrame()) {
f->MarkNeedsDisplayItemRebuild();
}
mTopLayer.AppendElement(do_GetWeakReference(&aElement));
NS_ASSERTION(GetTopLayerTop() == &aElement, "Should match");
@ -14804,6 +14808,9 @@ Element* Document::TopLayerPop(FunctionRef<bool(Element*)> aPredicate) {
nsCOMPtr<Element> element(do_QueryReferent(mTopLayer[i]));
if (element && aPredicate(element)) {
removedElement = element;
if (nsIFrame* f = element->GetPrimaryFrame()) {
f->MarkNeedsDisplayItemRebuild();
}
mTopLayer.RemoveElementAt(i);
break;
}
@ -14818,6 +14825,12 @@ Element* Document::TopLayerPop(FunctionRef<bool(Element*)> aPredicate) {
while (!mTopLayer.IsEmpty()) {
Element* element = GetTopLayerTop();
if (!element || element->GetComposedDoc() != this) {
if (element) {
if (nsIFrame* f = element->GetPrimaryFrame()) {
f->MarkNeedsDisplayItemRebuild();
}
}
mTopLayer.RemoveLastElement();
} else {
// The top element of the stack is now an in-doc element. Return here.

View File

@ -234,6 +234,8 @@ support-files = ["bug1448730.html"]
["test_bug1756118.html"]
["test_bug1836801.html"]
["test_caret_browsing_around_form_controls.html"]
skip-if = ["os == 'android'"]

View File

@ -0,0 +1,59 @@
<!DOCTYPE html>
<html>
<head>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<script>
// this is a crashtest, just getting to the end is a pass, fullscreen
// doesn't work in crashtests though not sure why -->
SimpleTest.waitForExplicitFinish();
SimpleTest.requestFlakyTimeout("crashtest sensitive to timing");
function begin() {
SimpleTest.waitForFocus(begin2);
}
function begin2() {
SpecialPowers.pushPrefEnv({
"set":[["full-screen-api.allow-trusted-requests-only", false]]
}, startTest);
}
window.addEventListener("load", begin);
const func_0 = async function(arg0) {
//SpecialPowers.wrap(document).notifyUserGestureActivation();
await arg0.originalTarget.requestFullscreen()
arg0.originalTarget.ariaValueText = "a"
}
async function startTest() {
let a = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas")
document.documentElement.appendChild(a)
document.addEventListener("DOMAttrModified", func_0, { })
let b = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas")
document.documentElement.appendChild(b)
b.setAttribute("class", "x")
//SpecialPowers.wrap(document).notifyUserGestureActivation();
await b.mozRequestFullScreen()
let c = document.createElementNS("http://www.w3.org/1999/xhtml", "slot")
document.documentElement.appendChild(c)
c.setAttribute("class", "x")
b.inert = true
setTimeout(async () => {
b.setAttribute("title", "a")
}, 200)
a.ariaSort = "descending"
setTimeout(finishup, 400);
}
async function finishup() {
await new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(resolve)));
await document.exitFullscreen();
SimpleTest.finish();
}
</script>
</html>