Bug 1340723 part 3. Fix stylo to properly update styles on the anonymous blocks we create in a block-inside-inline situation when the style of the inline changes. r=emilio

MozReview-Commit-ID: JYz6g1ZJInT

--HG--
extra : rebase_source : 356785e1de38745c9ca23a04ce58a1d53dce692b
This commit is contained in:
Boris Zbarsky 2017-03-03 15:45:40 -05:00
parent e8c584ebb8
commit 799bc86f7c
9 changed files with 143 additions and 0 deletions

View File

@ -235,6 +235,9 @@ ServoRestyleManager::RecreateStyleContexts(Element* aElement,
// XXX This could not always work as expected: there are kinds of content
// with the first split and the last sharing style, but others not. We
// should handle those properly.
// XXXbz I think the UpdateStyleOfOwnedAnonBoxes call below handles _that_
// right, but not other cases where we happen to have different styles on
// different continuations... (e.g. first-line).
for (nsIFrame* f = styleFrame; f;
f = GetNextContinuationWithSameStyle(f, oldStyleContext)) {
f->SetStyleContext(newContext);

View File

@ -12129,6 +12129,7 @@ nsCSSFrameConstructor::ConstructInline(nsFrameConstructorState& aState,
aFrameItems.AddChild(newFrame);
newFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
CreateIBSiblings(aState, newFrame, positioned, childItems, aFrameItems);
return newFrame;

View File

@ -19,8 +19,10 @@
#include "nsDisplayList.h"
#include "mozilla/Likely.h"
#include "SVGTextFrame.h"
#include "nsStyleChangeList.h"
#include "mozilla/StyleSetHandle.h"
#include "mozilla/StyleSetHandleInlines.h"
#include "mozilla/ServoStyleSet.h"
#ifdef DEBUG
#undef NOISY_PUSHING
@ -1021,6 +1023,65 @@ nsInlineFrame::AccessibleType()
}
#endif
void
nsInlineFrame::DoUpdateStyleOfOwnedAnonBoxes(ServoStyleSet& aStyleSet,
nsStyleChangeList& aChangeList,
nsChangeHint aHintForThisFrame)
{
MOZ_ASSERT(GetStateBits() & NS_FRAME_OWNS_ANON_BOXES,
"Why did we get called?");
MOZ_ASSERT(GetStateBits() & NS_FRAME_PART_OF_IBSPLIT,
"Why did we have the NS_FRAME_OWNS_ANON_BOXES bit set?");
// Note: this assert _looks_ expensive, but it's cheap in all the cases when
// it passes!
MOZ_ASSERT(nsLayoutUtils::FirstContinuationOrIBSplitSibling(this) == this,
"Only the primary frame of the inline in a block-inside-inline "
"split should have NS_FRAME_OWNS_ANON_BOXES");
MOZ_ASSERT(mContent->GetPrimaryFrame() == this,
"We should be the primary frame for our element");
nsPresContext* presContext = PresContext();
// Get the FramePropertyTable up front, since we are likely to need it
// multiple times. The other option would be to just call
// nsIFrame::Properties() every time we need to do a lookup, but that does
// more pointer-chasing.
FramePropertyTable* propTable = presContext->PropertyTable();
nsIFrame* blockFrame = propTable->Get(this, nsIFrame::IBSplitSibling());
MOZ_ASSERT(blockFrame, "Why did we have an IB split?");
nsIAtom* pseudo = blockFrame->StyleContext()->GetPseudo();
MOZ_ASSERT(pseudo == nsCSSAnonBoxes::mozAnonymousBlock ||
pseudo == nsCSSAnonBoxes::mozAnonymousPositionedBlock,
"Unexpected kind of style context");
// The anonymous block's style inherits from ours, and we already have our new
// style context.
RefPtr<nsStyleContext> newContext =
aStyleSet.ResolveAnonymousBoxStyle(pseudo, StyleContext());
// We're guaranteed that newContext only differs from the old style context on
// the block in things they might inherit from us. And changehint processing
// guarantees walking the continuation and ib-sibling chains, so our existing
// changehint beign in aChangeList is good enough. So we don't need to touch
// aChangeList at all here.
while (blockFrame) {
MOZ_ASSERT(!blockFrame->GetPrevContinuation(),
"Must be first continuation");
// We _could_ just walk along using GetNextContinuationWithSameStyle here,
// but it would involve going back to the first continuation every so often,
// which is a bit silly when we can just keep track of our first
// continuations.
for (nsIFrame* cont = blockFrame; cont; cont = cont->GetNextContinuation()) {
cont->SetStyleContext(newContext);
}
nsIFrame* nextInline = propTable->Get(blockFrame, nsIFrame::IBSplitSibling());
MOZ_ASSERT(nextInline, "There is always a trailing inline in an IB split");
blockFrame = propTable->Get(nextInline, nsIFrame::IBSplitSibling());
}
}
//////////////////////////////////////////////////////////////////////
// nsLineFrame implementation

View File

@ -116,6 +116,13 @@ public:
: (!GetNextInFlow());
}
// Update the style on the block wrappers around our non-inline-outside kids.
// This will only be called when such wrappers in fact exist.
virtual void DoUpdateStyleOfOwnedAnonBoxes(
mozilla::ServoStyleSet& aStyleSet,
nsStyleChangeList& aChangeList,
nsChangeHint aHintForThisFrame) override;
protected:
// Additional reflow state used during our reflow methods
struct InlineReflowInput {

View File

@ -84,3 +84,5 @@ fails == float-inside-inline-between-blocks-1.html float-inside-inline-between-b
== append-to-empty-trailing-inline-1.html append-to-empty-trailing-inline-1.html
== append-to-nested-split-inline-1.html append-to-nested-split-inline-1.html
== append-to-nested-split-inline-1-ref.html append-to-nested-split-inline-1-ref.html
== relpos-inline-1a.html relpos-inline-1a.html
== relpos-inline-1b.html relpos-inline-1b.html

View File

@ -83,3 +83,5 @@
== append-to-empty-trailing-inline-1.html append-to-empty-trailing-inline-1-ref.html
== append-to-nested-split-inline-1.html append-to-nested-split-inline-1-ref.html
== append-to-nested-split-inline-1-ref.html append-to-nested-split-inline-1-noib-ref.html
== relpos-inline-1a.html relpos-inline-1-ref.html
== relpos-inline-1b.html relpos-inline-1-ref.html

View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<style>
span, div { position: relative; left: 200px }
html {
overflow: hidden;
}
</style>
</head>
<body>
<span>All text should be offset 200px.</span>
<div>Some more text</div>
</body>
</html>

View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<title>CSS 2.1 Test Suite: handling of blocks inside inlines</title>
<link rel="author" title="Boris Zbarsky" href="mailto:bzbarsky@mit.edu" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#anonymous-block-level"/>
<meta name="flags" content="" />
<style>
span { position: relative; left: 200px }
html {
overflow: hidden;
}
</style>
</head>
<body>
<span style="position: relative; left: 200px">
All text should be offset 200px.
<div>Some more text</div>
</span>
</body>
</html>

View File

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<title>CSS 2.1 Test Suite: handling of blocks inside inlines</title>
<link rel="author" title="Boris Zbarsky" href="mailto:bzbarsky@mit.edu" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#anonymous-block-level"/>
<meta name="flags" content="" />
<style>
span { position: relative }
html {
overflow: hidden;
}
</style>
</head>
<body>
<span style="position: relative; left: 100px">
All text should be offset 200px.
<div>Some more text</div>
</span>
<script>
onload = function() {
var s = document.querySelector("span");
s.offsetWidth; // flush layout
s.style.left = "200px";
document.documentElement.className = "";
}
</script>
</body>
</html>