Bug 1338921 - Handle lazy frame construction in the regular post-servo pass. r=emilio

MozReview-Commit-ID: FSXKAiyZDzt
This commit is contained in:
Bobby Holley 2017-02-27 19:06:07 -08:00
parent c589f558a4
commit fa5229bbea
5 changed files with 60 additions and 43 deletions

View File

@ -1404,13 +1404,12 @@ RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
{
MOZ_ASSERT(aChangeList[i].mHint & nsChangeHint_ReconstructFrame);
MOZ_ASSERT(!aChangeList[i].mFrame);
MOZ_ASSERT(!aChangeList[i].mContent->GetPrimaryFrame());
++i;
}
if (i != lazyRangeStart) {
nsIContent* start = aChangeList[lazyRangeStart].mContent;
nsIContent* end = aChangeList[i-1].mContent->GetNextSibling();
nsIContent* container = start->GetFlattenedTreeParent();
nsIContent* container = start->GetParent();
MOZ_ASSERT(container);
if (!end) {
frameConstructor->ContentAppended(container, start, false);

View File

@ -127,23 +127,36 @@ ClearRestyleStateFromSubtree(Element* aElement)
Unused << Servo_TakeChangeHint(aElement);
aElement->UnsetHasDirtyDescendantsForServo();
aElement->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES);
}
void
ServoRestyleManager::RecreateStyleContexts(Element* aElement,
nsStyleContext* aParentContext,
ServoStyleSet* aStyleSet,
nsStyleChangeList& aChangeListToProcess)
ServoRestyleManager::ProcessPostTraversal(Element* aElement,
nsStyleContext* aParentContext,
ServoStyleSet* aStyleSet,
nsStyleChangeList& aChangeList)
{
nsIFrame* styleFrame = nsLayoutUtils::GetStyleFrame(aElement);
// Grab the change hint from Servo.
nsChangeHint changeHint = Servo_TakeChangeHint(aElement);
// Handle lazy frame construction by posting a reconstruct for any lazily-
// constructed roots.
if (aElement->HasFlag(NODE_NEEDS_FRAME)) {
changeHint |= nsChangeHint_ReconstructFrame;
// The only time the primary frame is non-null is when image maps do hacky
// SetPrimaryFrame calls.
MOZ_ASSERT_IF(styleFrame, styleFrame->GetType() == nsGkAtoms::imageFrame);
styleFrame = nullptr;
}
// Although we shouldn't generate non-ReconstructFrame hints for elements with
// no frames, we can still get them here if they were explicitly posted by
// PostRestyleEvent, such as a RepaintFrame hint when a :link changes to be
// :visited. Skip processing these hints if there is no frame.
if ((styleFrame || (changeHint & nsChangeHint_ReconstructFrame)) && changeHint) {
aChangeListToProcess.AppendChange(styleFrame, aElement, changeHint);
aChangeList.AppendChange(styleFrame, aElement, changeHint);
}
// If our change hint is reconstruct, we delegate to the frame constructor,
@ -219,8 +232,7 @@ ServoRestyleManager::RecreateStyleContexts(Element* aElement,
}
if (styleFrame) {
styleFrame->UpdateStyleOfOwnedAnonBoxes(*aStyleSet, aChangeListToProcess,
changeHint);
styleFrame->UpdateStyleOfOwnedAnonBoxes(*aStyleSet, aChangeList, changeHint);
}
// Update pseudo-elements state if appropriate.
@ -258,8 +270,10 @@ ServoRestyleManager::RecreateStyleContexts(Element* aElement,
}
}
bool traverseElementChildren = aElement->HasDirtyDescendantsForServo();
bool traverseTextChildren = recreateContext;
bool descendantsNeedFrames = aElement->HasFlag(NODE_DESCENDANTS_NEED_FRAMES);
bool traverseElementChildren =
aElement->HasDirtyDescendantsForServo() || descendantsNeedFrames;
bool traverseTextChildren = recreateContext || descendantsNeedFrames;
if (traverseElementChildren || traverseTextChildren) {
nsStyleContext* upToDateContext =
recreateContext ? newContext : oldStyleContext;
@ -267,22 +281,31 @@ ServoRestyleManager::RecreateStyleContexts(Element* aElement,
StyleChildrenIterator it(aElement);
for (nsIContent* n = it.GetNextChild(); n; n = it.GetNextChild()) {
if (traverseElementChildren && n->IsElement()) {
RecreateStyleContexts(n->AsElement(), upToDateContext,
aStyleSet, aChangeListToProcess);
ProcessPostTraversal(n->AsElement(), upToDateContext,
aStyleSet, aChangeList);
} else if (traverseTextChildren && n->IsNodeOfType(nsINode::eTEXT)) {
RecreateStyleContextsForText(n, upToDateContext, aStyleSet);
ProcessPostTraversalForText(n, upToDateContext, aStyleSet, aChangeList);
}
}
}
aElement->UnsetHasDirtyDescendantsForServo();
aElement->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES);
}
void
ServoRestyleManager::RecreateStyleContextsForText(nsIContent* aTextNode,
nsStyleContext* aParentContext,
ServoStyleSet* aStyleSet)
ServoRestyleManager::ProcessPostTraversalForText(nsIContent* aTextNode,
nsStyleContext* aParentContext,
ServoStyleSet* aStyleSet,
nsStyleChangeList& aChangeList)
{
// Handle lazy frame construction.
if (aTextNode->HasFlag(NODE_NEEDS_FRAME)) {
aChangeList.AppendChange(nullptr, aTextNode, nsChangeHint_ReconstructFrame);
return;
}
// Handle restyle.
nsIFrame* primaryFrame = aTextNode->GetPrimaryFrame();
if (primaryFrame) {
RefPtr<nsStyleContext> oldStyleContext = primaryFrame->StyleContext();
@ -360,24 +383,14 @@ ServoRestyleManager::ProcessPendingRestyles()
// uninstalling XBL bindings) can trigger additional style validations.
mInStyleRefresh = true;
while (styleSet->StyleDocument()) {
PresContext()->EffectCompositor()->ClearElementsToRestyle();
// First do any queued-up frame creation. (see bugs 827239 and 997506).
//
// XXXEmilio I'm calling this to avoid random behavior changes, since we
// delay frame construction after styling we should re-check once our
// model is more stable whether we can skip this call.
//
// Note this has to be *after* restyling, because otherwise frame
// construction will find unstyled nodes, and that's not funny.
PresContext()->FrameConstructor()->CreateNeededFrames();
// Recreate style contexts and queue up change hints.
// Recreate style contexts, and queue up change hints (which also handle
// lazy frame construction).
nsStyleChangeList currentChanges;
DocumentStyleRootIterator iter(doc);
while (Element* root = iter.GetNextStyleRoot()) {
RecreateStyleContexts(root, nullptr, styleSet, currentChanges);
ProcessPostTraversal(root, nullptr, styleSet, currentChanges);
}
// Process the change hints.

View File

@ -100,17 +100,17 @@ protected:
private:
/**
* Traverses a tree of content that Servo has just restyled, recreating style
* contexts for their frames with the new style data.
* Performs post-Servo-traversal processing on this element and its descendants.
*/
void RecreateStyleContexts(Element* aElement,
nsStyleContext* aParentContext,
ServoStyleSet* aStyleSet,
nsStyleChangeList& aChangeList);
void ProcessPostTraversal(Element* aElement,
nsStyleContext* aParentContext,
ServoStyleSet* aStyleSet,
nsStyleChangeList& aChangeList);
void RecreateStyleContextsForText(nsIContent* aTextNode,
nsStyleContext* aParentContext,
ServoStyleSet* aStyleSet);
void ProcessPostTraversalForText(nsIContent* aTextNode,
nsStyleContext* aParentContext,
ServoStyleSet* aStyleSet,
nsStyleChangeList& aChangeList);
inline ServoStyleSet* StyleSet() const
{

View File

@ -29,9 +29,14 @@ nsStyleChangeList::AppendChange(nsIFrame* aFrame, nsIContent* aContent, nsChange
// display:contents elements posts the changes for their children:
(aFrame && aContent->GetParent() &&
aFrame->PresContext()->FrameManager()->
GetDisplayContentsStyleFor(aContent->GetParent())),
GetDisplayContentsStyleFor(aContent->GetParent())) ||
(aContent->IsNodeOfType(nsINode::eTEXT) &&
aContent->IsStyledByServo() &&
aContent->HasFlag(NODE_NEEDS_FRAME) &&
aHint & nsChangeHint_ReconstructFrame),
"Shouldn't be trying to restyle non-elements directly, "
"except if it's a display:contents child");
"except if it's a display:contents child or a text node "
"doing lazy frame construction");
MOZ_ASSERT(!(aHint & nsChangeHint_AllReflowHints) ||
(aHint & nsChangeHint_NeedReflow),
"Reflow hint bits set without actually asking for a reflow");

View File

@ -38,10 +38,10 @@ Any line which doesn't follow the format above would be ignored like comment.
* test_all_shorthand.html: all shorthand servo/servo#15055 [*]
* Animation support:
* test_animations.html [277]
* test_animations_async_tests.html [3]
* test_animations_async_tests.html [2]
* test_animations_dynamic_changes.html [1]
* test_bug716226.html [1]
* test_flexbox_flex_grow_and_shrink.html [16]
* test_flexbox_flex_grow_and_shrink.html [8]
* OMTA
* test_animations_effect_timing_duration.html [1]
* test_animations_effect_timing_enddelay.html [1]