Bug 1258911. Correctly reframe an absolutely positioned frame that goes from having a transform to not having one and has an abs pos kid with a fixed-pos descendant. r=dbaron

Instead of skipping the absolute and fixed child lists, we walk all kids of the
frame.  But before recursing down into things that are absolute containing
blocks we ensure that we're only looking for fixed-pos placeholders, so we don't
reframe if we have a relatively positioned descendant with absolutely positioned
kids, for example.  Note that this part is pure optimization attempt, and it
might be cheaper to not do it: IsAbsoluteContainingBlock is not that cheap and
the situations where we avoid reframing due to this optimization are likely
fairly rare.
This commit is contained in:
Boris Zbarsky 2016-08-26 15:38:16 -04:00
parent 0e5b46b6d6
commit f795d19994
4 changed files with 46 additions and 16 deletions

View File

@ -661,26 +661,35 @@ static bool
FrameHasPositionedPlaceholderDescendants(nsIFrame* aFrame,
uint32_t aPositionMask)
{
const nsIFrame::ChildListIDs skip(nsIFrame::kAbsoluteList |
nsIFrame::kFixedList);
MOZ_ASSERT(aPositionMask & (1 << NS_STYLE_POSITION_FIXED));
for (nsIFrame::ChildListIterator lists(aFrame); !lists.IsDone(); lists.Next()) {
if (!skip.Contains(lists.CurrentID())) {
for (nsIFrame* f : lists.CurrentList()) {
if (f->GetType() == nsGkAtoms::placeholderFrame) {
nsIFrame* outOfFlow =
nsPlaceholderFrame::GetRealFrameForPlaceholder(f);
// If SVG text frames could appear here, they could confuse us since
// they ignore their position style ... but they can't.
NS_ASSERTION(!outOfFlow->IsSVGText(),
"SVG text frames can't be out of flow");
if (aPositionMask & (1 << outOfFlow->StyleDisplay()->mPosition)) {
return true;
}
}
if (FrameHasPositionedPlaceholderDescendants(f, aPositionMask)) {
for (nsIFrame* f : lists.CurrentList()) {
if (f->GetType() == nsGkAtoms::placeholderFrame) {
nsIFrame* outOfFlow =
nsPlaceholderFrame::GetRealFrameForPlaceholder(f);
// If SVG text frames could appear here, they could confuse us since
// they ignore their position style ... but they can't.
NS_ASSERTION(!outOfFlow->IsSVGText(),
"SVG text frames can't be out of flow");
if (aPositionMask & (1 << outOfFlow->StyleDisplay()->mPosition)) {
return true;
}
}
uint32_t positionMask = aPositionMask;
// Is it faster to check aPositionMask & (1 << NS_STYLE_POSITION_ABSOLUTE)
// before we check IsAbsPosContainingBlock? Not clear....
if (f->IsAbsPosContainingBlock()) {
if (f->IsFixedPosContainingBlock()) {
continue;
}
// We don't care about absolutely positioned things inside f, because
// they will still use f as their containing block.
positionMask = (1 << NS_STYLE_POSITION_FIXED);
}
if (FrameHasPositionedPlaceholderDescendants(f, positionMask)) {
return true;
}
}
}
return false;

View File

@ -0,0 +1,3 @@
<!DOCTYPE html>
<html style="background: green">
</html>

View File

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html style="background: red">
<div style="transform: translate3d(0, 0, 0); position: absolute;
top: 0; left: 0; width: 100px; height: 100px">
<div style="position: absolute">
<div style="position: fixed; width: 100%; height: 100%; top: 0; left: 0;
background: green">
</div>
</div>
</div>
<script>
onload = function() {
document.body.offsetWidth;
document.querySelector("div").style.transform = "none";
}
</script>
</html>

View File

@ -9,6 +9,7 @@
== dynamic-addremove-1a.html dynamic-addremove-1-ref.html
== dynamic-addremove-1b.html dynamic-addremove-1-ref.html
== dynamic-addremove-1c.html dynamic-addremove-1-ref.html
== dynamic-addremove-2.html dynamic-addremove-2-ref.html
# translatex should act like position: relative
skip-if(B2G||Mulet) == translatex-1a.html translatex-1-ref.html # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) == translatex-1b.html translatex-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop