--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -176,50 +176,43 @@ ServoRestyleManager::ClearRestyleStateFr
* need to track during the post-traversal.
*
* This is currently used to properly compute change hints when the parent
* element of this node is a display: contents node, and also to avoid computing
* the style for text children more than once per element.
*/
struct ServoRestyleManager::TextPostTraversalState
{
- nsStyleContext& mParentContext;
- ServoStyleSet& mStyleSet;
- RefPtr<nsStyleContext> mStyle;
- bool mShouldPostHints;
- bool mShouldComputeHints;
- nsChangeHint mComputedHint;
- nsChangeHint mHintsHandled;
-
+public:
TextPostTraversalState(nsStyleContext& aParentContext,
- ServoStyleSet& aStyleSet,
bool aDisplayContentsParentStyleChanged,
- nsChangeHint aHintsHandled)
+ ServoRestyleState& aParentRestyleState)
: mParentContext(aParentContext)
- , mStyleSet(aStyleSet)
+ , mParentRestyleState(aParentRestyleState)
, mStyle(nullptr)
, mShouldPostHints(aDisplayContentsParentStyleChanged)
, mShouldComputeHints(aDisplayContentsParentStyleChanged)
, mComputedHint(nsChangeHint_Empty)
- , mHintsHandled(aHintsHandled)
{}
+ nsStyleChangeList& ChangeList() { return mParentRestyleState.ChangeList(); }
+
nsStyleContext& ComputeStyle(nsIContent* aTextNode)
{
if (!mStyle) {
- mStyle = mStyleSet.ResolveStyleForText(aTextNode, &mParentContext);
+ mStyle = mParentRestyleState.StyleSet().ResolveStyleForText(
+ aTextNode, &mParentContext);
}
MOZ_ASSERT(mStyle);
return *mStyle;
}
void ComputeHintIfNeeded(nsIContent* aContent,
nsIFrame* aTextFrame,
- nsStyleContext& aNewContext,
- nsStyleChangeList& aChangeList)
+ nsStyleContext& aNewContext)
{
MOZ_ASSERT(aTextFrame);
MOZ_ASSERT(aNewContext.GetPseudo() == nsCSSAnonBoxes::mozText);
if (MOZ_LIKELY(!mShouldPostHints)) {
return;
}
@@ -233,46 +226,53 @@ struct ServoRestyleManager::TextPostTrav
// we'll cross that bridge when we support those in stylo.
if (mShouldComputeHints) {
mShouldComputeHints = false;
uint32_t equalStructs, samePointerStructs;
mComputedHint =
oldContext->CalcStyleDifference(&aNewContext,
&equalStructs,
&samePointerStructs);
- mComputedHint = NS_RemoveSubsumedHints(mComputedHint, mHintsHandled);
+ mComputedHint = NS_RemoveSubsumedHints(
+ mComputedHint, mParentRestyleState.ChangesHandled());
}
if (mComputedHint) {
- aChangeList.AppendChange(aTextFrame, aContent, mComputedHint);
+ mParentRestyleState.ChangeList().AppendChange(
+ aTextFrame, aContent, mComputedHint);
}
}
+
+private:
+ nsStyleContext& mParentContext;
+ ServoRestyleState& mParentRestyleState;
+ RefPtr<nsStyleContext> mStyle;
+ bool mShouldPostHints;
+ bool mShouldComputeHints;
+ nsChangeHint mComputedHint;
};
static void
UpdateBlockFramePseudoElements(nsBlockFrame* aFrame,
- ServoStyleSet& aStyleSet,
- nsStyleChangeList& aChangeList)
+ ServoRestyleState& aRestyleState)
{
if (nsBulletFrame* bullet = aFrame->GetBullet()) {
RefPtr<nsStyleContext> newContext =
- aStyleSet.ResolvePseudoElementStyle(
- aFrame->GetContent()->AsElement(),
- bullet->StyleContext()->GetPseudoType(),
- aFrame->StyleContext(),
- /* aPseudoElement = */ nullptr);
+ aRestyleState.StyleSet().ResolvePseudoElementStyle(
+ aFrame->GetContent()->AsElement(),
+ bullet->StyleContext()->GetPseudoType(),
+ aFrame->StyleContext(),
+ /* aPseudoElement = */ nullptr);
- aFrame->UpdateStyleOfOwnedChildFrame(bullet, newContext, aChangeList);
+ aFrame->UpdateStyleOfOwnedChildFrame(bullet, newContext, aRestyleState);
}
}
static void
-UpdateBackdropIfNeeded(nsIFrame* aFrame,
- ServoStyleSet& aStyleSet,
- nsStyleChangeList& aChangeList)
+UpdateBackdropIfNeeded(nsIFrame* aFrame, ServoRestyleState& aRestyleState)
{
const nsStyleDisplay* display = aFrame->StyleContext()->StyleDisplay();
if (display->mTopLayer != NS_STYLE_TOP_LAYER_TOP) {
return;
}
// Elements in the top layer are guaranteed to have absolute or fixed
// position per https://fullscreen.spec.whatwg.org/#new-stacking-layer.
@@ -287,71 +287,66 @@ UpdateBackdropIfNeeded(nsIFrame* aFrame,
MOZ_ASSERT(backdropPlaceholder->IsPlaceholderFrame());
nsIFrame* backdropFrame =
nsPlaceholderFrame::GetRealFrameForPlaceholder(backdropPlaceholder);
MOZ_ASSERT(backdropFrame->IsBackdropFrame());
MOZ_ASSERT(backdropFrame->StyleContext()->GetPseudoType() ==
CSSPseudoElementType::backdrop);
RefPtr<nsStyleContext> newContext =
- aStyleSet.ResolvePseudoElementStyle(
- aFrame->GetContent()->AsElement(),
- CSSPseudoElementType::backdrop,
- aFrame->StyleContext(),
- /* aPseudoElement = */ nullptr);
+ aRestyleState.StyleSet().ResolvePseudoElementStyle(
+ aFrame->GetContent()->AsElement(),
+ CSSPseudoElementType::backdrop,
+ aFrame->StyleContext(),
+ /* aPseudoElement = */ nullptr);
- aFrame->UpdateStyleOfOwnedChildFrame(backdropFrame,
- newContext,
- aChangeList);
+ aFrame->UpdateStyleOfOwnedChildFrame(
+ backdropFrame, newContext, aRestyleState);
}
static void
UpdateFramePseudoElementStyles(nsIFrame* aFrame,
- ServoStyleSet& aStyleSet,
- nsStyleChangeList& aChangeList)
+ ServoRestyleState& aRestyleState)
{
if (aFrame->IsFrameOfType(nsIFrame::eBlockFrame)) {
UpdateBlockFramePseudoElements(static_cast<nsBlockFrame*>(aFrame),
- aStyleSet,
- aChangeList);
+ aRestyleState);
}
- UpdateBackdropIfNeeded(aFrame, aStyleSet, aChangeList);
+ UpdateBackdropIfNeeded(aFrame, aRestyleState);
}
bool
ServoRestyleManager::ProcessPostTraversal(Element* aElement,
nsStyleContext* aParentContext,
- ServoStyleSet* aStyleSet,
- nsStyleChangeList& aChangeList,
- nsChangeHint aChangesHandled)
+ ServoRestyleState& aRestyleState)
{
nsIFrame* styleFrame = nsLayoutUtils::GetStyleFrame(aElement);
// Grab the change hint from Servo.
nsChangeHint changeHint = Servo_TakeChangeHint(aElement);
- changeHint = NS_RemoveSubsumedHints(changeHint, aChangesHandled);
- aChangesHandled |= changeHint;
+ changeHint =
+ NS_RemoveSubsumedHints(changeHint, aRestyleState.ChangesHandled());
// 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(!styleFrame || styleFrame->IsImageFrame());
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) {
- aChangeList.AppendChange(styleFrame, aElement, changeHint);
+ aRestyleState.ChangeList().AppendChange(styleFrame, aElement, changeHint);
}
// If our change hint is reconstruct, we delegate to the frame constructor,
// which consumes the new style and expects the old style to be on the frame.
//
// XXXbholley: We should teach the frame constructor how to clear the dirty
// descendants bit to avoid the traversal here.
if (changeHint & nsChangeHint_ReconstructFrame) {
@@ -376,45 +371,43 @@ ServoRestyleManager::ProcessPostTraversa
displayContentsNode =
PresContext()->FrameConstructor()->GetDisplayContentsNodeFor(aElement);
if (displayContentsNode) {
oldStyleContext = displayContentsNode->mStyle;
}
}
RefPtr<ServoComputedValues> computedValues =
- aStyleSet->ResolveServoStyle(aElement);
+ aRestyleState.StyleSet().ResolveServoStyle(aElement);
// Note that we rely in the fact that we don't cascade pseudo-element styles
// separately right now (that is, if a pseudo style changes, the normal style
// changes too).
//
// Otherwise we should probably encode that information somehow to avoid
// expensive checks in the common case.
//
// Also, we're going to need to check for pseudos of display: contents
// elements, though that is buggy right now even in non-stylo mode, see
// bug 1251799.
const bool recreateContext = oldStyleContext &&
oldStyleContext->ComputedValues() != computedValues;
+ ServoRestyleState childrenRestyleState(aRestyleState, changeHint);
+
RefPtr<nsStyleContext> newContext = nullptr;
if (recreateContext) {
MOZ_ASSERT(styleFrame || displayContentsNode);
auto pseudo = aElement->GetPseudoElementType();
nsIAtom* pseudoTag = pseudo == CSSPseudoElementType::NotPseudo
? nullptr : nsCSSPseudoElements::GetPseudoAtom(pseudo);
- newContext =
- aStyleSet->GetContext(computedValues.forget(),
- aParentContext,
- pseudoTag,
- pseudo,
- aElement);
+ newContext = aRestyleState.StyleSet().GetContext(
+ computedValues.forget(), aParentContext, pseudoTag, pseudo, aElement);
newContext->EnsureSameStructsCached(oldStyleContext);
// 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
@@ -425,99 +418,95 @@ ServoRestyleManager::ProcessPostTraversa
}
if (MOZ_UNLIKELY(displayContentsNode)) {
MOZ_ASSERT(!styleFrame);
displayContentsNode->mStyle = newContext;
}
if (styleFrame) {
- styleFrame->UpdateStyleOfOwnedAnonBoxes(*aStyleSet, aChangeList, changeHint);
- UpdateFramePseudoElementStyles(styleFrame, *aStyleSet, aChangeList);
+ styleFrame->UpdateStyleOfOwnedAnonBoxes(childrenRestyleState);
+ UpdateFramePseudoElementStyles(styleFrame, childrenRestyleState);
}
if (!aElement->GetParent()) {
// This is the root. Update styles on the viewport as needed.
ViewportFrame* viewport =
do_QueryFrame(mPresContext->PresShell()->GetRootFrame());
if (viewport) {
- viewport->UpdateStyle(*aStyleSet, aChangeList);
+ viewport->UpdateStyle(childrenRestyleState);
}
}
// Some changes to animations don't affect the computed style and yet still
// require the layer to be updated. For example, pausing an animation via
// the Web Animations API won't affect an element's style but still
// requires to update the animation on the layer.
//
// We can sometimes reach this when the animated style is being removed.
// Since AddLayerChangesForAnimation checks if |styleFrame| has a transform
// style or not, we need to call it *after* setting |newContext| to
// |styleFrame| to ensure the animated transform has been removed first.
- AddLayerChangesForAnimation(styleFrame, aElement, aChangeList);
+ AddLayerChangesForAnimation(
+ styleFrame, aElement, aRestyleState.ChangeList());
}
const bool descendantsNeedFrames =
aElement->HasFlag(NODE_DESCENDANTS_NEED_FRAMES);
const bool traverseElementChildren =
aElement->HasDirtyDescendantsForServo() ||
aElement->HasAnimationOnlyDirtyDescendantsForServo() ||
descendantsNeedFrames;
const bool traverseTextChildren = recreateContext || descendantsNeedFrames;
bool recreatedAnyContext = recreateContext;
if (traverseElementChildren || traverseTextChildren) {
nsStyleContext* upToDateContext =
recreateContext ? newContext : oldStyleContext;
StyleChildrenIterator it(aElement);
- TextPostTraversalState textState(
- *upToDateContext,
- *aStyleSet,
- displayContentsNode && recreateContext,
- aChangesHandled);
+ TextPostTraversalState textState(*upToDateContext,
+ displayContentsNode && recreateContext,
+ childrenRestyleState);
for (nsIContent* n = it.GetNextChild(); n; n = it.GetNextChild()) {
if (traverseElementChildren && n->IsElement()) {
- recreatedAnyContext |=
- ProcessPostTraversal(n->AsElement(), upToDateContext,
- aStyleSet, aChangeList, aChangesHandled);
+ recreatedAnyContext |= ProcessPostTraversal(
+ n->AsElement(), upToDateContext, childrenRestyleState);
} else if (traverseTextChildren && n->IsNodeOfType(nsINode::eTEXT)) {
- recreatedAnyContext |=
- ProcessPostTraversalForText(n, aChangeList, textState);
+ recreatedAnyContext |= ProcessPostTraversalForText(n, textState);
}
}
}
aElement->UnsetHasDirtyDescendantsForServo();
aElement->UnsetHasAnimationOnlyDirtyDescendantsForServo();
aElement->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES);
return recreatedAnyContext;
}
bool
ServoRestyleManager::ProcessPostTraversalForText(
nsIContent* aTextNode,
- nsStyleChangeList& aChangeList,
TextPostTraversalState& aPostTraversalState)
{
// Handle lazy frame construction.
if (aTextNode->HasFlag(NODE_NEEDS_FRAME)) {
- aChangeList.AppendChange(nullptr, aTextNode, nsChangeHint_ReconstructFrame);
+ aPostTraversalState.ChangeList().AppendChange(
+ nullptr, aTextNode, nsChangeHint_ReconstructFrame);
return true;
}
// Handle restyle.
nsIFrame* primaryFrame = aTextNode->GetPrimaryFrame();
if (!primaryFrame) {
return false;
}
RefPtr<nsStyleContext> oldStyleContext = primaryFrame->StyleContext();
nsStyleContext& newContext = aPostTraversalState.ComputeStyle(aTextNode);
- aPostTraversalState.ComputeHintIfNeeded(
- aTextNode, primaryFrame, newContext, aChangeList);
+ aPostTraversalState.ComputeHintIfNeeded(aTextNode, primaryFrame, newContext);
for (nsIFrame* f = primaryFrame; f;
f = GetNextContinuationWithSameStyle(f, oldStyleContext)) {
f->SetStyleContext(&newContext);
}
return true;
}
@@ -637,19 +626,18 @@ ServoRestyleManager::DoProcessPendingRes
}
// Recreate style contexts, and queue up change hints (which also handle
// lazy frame construction).
nsStyleChangeList currentChanges(StyleBackendType::Servo);
DocumentStyleRootIterator iter(doc);
bool anyStyleChanged = false;
while (Element* root = iter.GetNextStyleRoot()) {
- anyStyleChanged |=
- ProcessPostTraversal(
- root, nullptr, styleSet, currentChanges, nsChangeHint(0));
+ ServoRestyleState state(*styleSet, currentChanges);
+ anyStyleChanged |= ProcessPostTraversal(root, nullptr, state);
}
// Process the change hints.
//
// Unfortunately, the frame constructor can generate new change hints while
// processing existing ones. We redirect those into a secondary queue and
// iterate until there's nothing left.
ReentrantChangeList newChanges;
--- a/layout/base/ServoRestyleManager.h
+++ b/layout/base/ServoRestyleManager.h
@@ -23,16 +23,46 @@ class nsAttrValue;
class nsIAtom;
class nsIContent;
class nsIFrame;
class nsStyleChangeList;
namespace mozilla {
/**
+ * A stack class used to pass some common restyle state in a slightly more
+ * comfortable way than a bunch of individual arguments.
+ */
+class ServoRestyleState
+{
+public:
+ ServoRestyleState(ServoStyleSet& aStyleSet, nsStyleChangeList& aChangeList)
+ : mStyleSet(aStyleSet)
+ , mChangeList(aChangeList)
+ , mChangesHandled(nsChangeHint(0))
+ {}
+
+ ServoRestyleState(ServoRestyleState& aParentState,
+ nsChangeHint aHintForThisFrame)
+ : mStyleSet(aParentState.mStyleSet)
+ , mChangeList(aParentState.mChangeList)
+ , mChangesHandled(aParentState.mChangesHandled | aHintForThisFrame)
+ {}
+
+ nsChangeHint ChangesHandled() const { return mChangesHandled; }
+ nsStyleChangeList& ChangeList() { return mChangeList; }
+ ServoStyleSet& StyleSet() { return mStyleSet; }
+
+private:
+ ServoStyleSet& mStyleSet;
+ nsStyleChangeList& mChangeList;
+ const nsChangeHint mChangesHandled;
+};
+
+/**
* Restyle manager for a Servo-backed style system.
*/
class ServoRestyleManager : public RestyleManager
{
friend class ServoStyleSet;
public:
typedef ServoElementSnapshotTable SnapshotTable;
@@ -122,23 +152,20 @@ private:
*
* Returns whether any style did actually change. There may be cases where we
* didn't need to change any style after all, for example, when a content
* attribute changes that happens not to have any effect on the style of that
* element or any descendant or sibling.
*/
bool ProcessPostTraversal(Element* aElement,
nsStyleContext* aParentContext,
- ServoStyleSet* aStyleSet,
- nsStyleChangeList& aChangeList,
- nsChangeHint aChangesHandledForDescendants);
+ ServoRestyleState& aRestyleState);
struct TextPostTraversalState;
bool ProcessPostTraversalForText(nsIContent* aTextNode,
- nsStyleChangeList& aChangeList,
TextPostTraversalState& aState);
inline ServoStyleSet* StyleSet() const
{
MOZ_ASSERT(PresContext()->StyleSet()->IsServo(),
"ServoRestyleManager should only be used with a Servo-flavored "
"style backend");
return PresContext()->StyleSet()->AsServo();
--- a/layout/generic/ViewportFrame.cpp
+++ b/layout/generic/ViewportFrame.cpp
@@ -5,16 +5,17 @@
/*
* rendering object that is the root of the frame tree, which contains
* the document's scrollbars and contains fixed-positioned elements
*/
#include "mozilla/ViewportFrame.h"
+#include "mozilla/ServoRestyleManager.h"
#include "nsGkAtoms.h"
#include "nsIScrollableFrame.h"
#include "nsSubDocumentFrame.h"
#include "nsCanvasFrame.h"
#include "nsAbsoluteContainingBlock.h"
#include "GeckoProfiler.h"
#include "nsIMozBrowserFrame.h"
#include "nsPlaceholderFrame.h"
@@ -411,34 +412,33 @@ ViewportFrame::ComputeCustomOverflow(nsO
if (rootScrollFrame && !rootScrollFrame->IsIgnoringViewportClipping()) {
return false;
}
return nsContainerFrame::ComputeCustomOverflow(aOverflowAreas);
}
void
-ViewportFrame::UpdateStyle(ServoStyleSet& aStyleSet,
- nsStyleChangeList& aChangeList)
+ViewportFrame::UpdateStyle(ServoRestyleState& aRestyleState)
{
nsStyleContext* oldContext = StyleContext();
nsIAtom* pseudo = oldContext->GetPseudo();
RefPtr<nsStyleContext> newContext =
- aStyleSet.ResolveInheritingAnonymousBoxStyle(pseudo, nullptr);
+ aRestyleState.StyleSet().ResolveInheritingAnonymousBoxStyle(pseudo, nullptr);
// We're special because we have a null GetContent(), so don't call things
// like UpdateStyleOfOwnedChildFrame that try to append changes for the
// content to the change list. Nor do we computed a changehint, since we have
// no way to apply it anyway.
newContext->EnsureSameStructsCached(oldContext);
MOZ_ASSERT(!GetNextContinuation(), "Viewport has continuations?");
SetStyleContext(newContext);
- UpdateStyleOfOwnedAnonBoxes(aStyleSet, aChangeList, nsChangeHint_Empty);
+ UpdateStyleOfOwnedAnonBoxes(aRestyleState);
}
void
ViewportFrame::AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult)
{
if (mFrames.NotEmpty()) {
aResult.AppendElement(mFrames.FirstChild());
}
--- a/layout/generic/ViewportFrame.h
+++ b/layout/generic/ViewportFrame.h
@@ -13,16 +13,18 @@
#include "mozilla/Attributes.h"
#include "nsContainerFrame.h"
class nsPresContext;
namespace mozilla {
+class ServoRestyleState;
+
/**
* ViewportFrame is the parent of a single child - the doc root frame or a scroll frame
* containing the doc root frame. ViewportFrame stores this child in its primary child
* list.
*/
class ViewportFrame : public nsContainerFrame {
public:
NS_DECL_QUERYFRAME
@@ -71,17 +73,17 @@ public:
* @return the rect to use as containing block rect
*/
nsRect AdjustReflowInputAsContainingBlock(ReflowInput* aReflowInput) const;
/**
* Update our style (and recursively the styles of any anonymous boxes we
* might own)
*/
- void UpdateStyle(ServoStyleSet& aStyleSet, nsStyleChangeList& aChangeList);
+ void UpdateStyle(ServoRestyleState& aStyleSet);
/**
* Return our single anonymous box child.
*/
void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) override;
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override;
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -10197,19 +10197,17 @@ nsFrame::BoxMetrics() const
{
nsBoxLayoutMetrics* metrics = GetProperty(BoxMetricsProperty());
NS_ASSERTION(metrics, "A box layout method was called but InitBoxMetrics was never called");
return metrics;
}
void
nsIFrame::UpdateStyleOfChildAnonBox(nsIFrame* aChildFrame,
- ServoStyleSet& aStyleSet,
- nsStyleChangeList& aChangeList,
- nsChangeHint aHintForThisFrame)
+ ServoRestyleState& aRestyleState)
{
MOZ_ASSERT(aChildFrame->GetParent() == this,
"This should only be used for children!");
MOZ_ASSERT((!GetContent() && IsViewportFrame()) ||
aChildFrame->GetContent() == GetContent(),
"What content node is it a frame for?");
MOZ_ASSERT(!aChildFrame->GetPrevContinuation(),
"Only first continuations should end up here");
@@ -10218,53 +10216,58 @@ nsIFrame::UpdateStyleOfChildAnonBox(nsIF
// statically... But this API is a bit nicer.
nsIAtom* pseudo = aChildFrame->StyleContext()->GetPseudo();
MOZ_ASSERT(nsCSSAnonBoxes::IsAnonBox(pseudo), "Child is not an anon box?");
MOZ_ASSERT(!nsCSSAnonBoxes::IsNonInheritingAnonBox(pseudo),
"Why did the caller bother calling us?");
// Anon boxes inherit from their parent; that's us.
RefPtr<nsStyleContext> newContext =
- aStyleSet.ResolveInheritingAnonymousBoxStyle(pseudo, StyleContext());
+ aRestyleState.StyleSet().ResolveInheritingAnonymousBoxStyle(pseudo,
+ StyleContext());
nsChangeHint childHint =
- UpdateStyleOfOwnedChildFrame(aChildFrame, newContext, aChangeList);
+ UpdateStyleOfOwnedChildFrame(aChildFrame, newContext, aRestyleState);
// Now that we've updated the style on aChildFrame, check whether it itself
// has anon boxes to deal with.
- aChildFrame->UpdateStyleOfOwnedAnonBoxes(aStyleSet, aChangeList, childHint);
+ ServoRestyleState childrenState(aRestyleState, childHint);
+ aChildFrame->UpdateStyleOfOwnedAnonBoxes(childrenState);
}
nsChangeHint
nsIFrame::UpdateStyleOfOwnedChildFrame(nsIFrame* aChildFrame,
nsStyleContext* aNewStyleContext,
- nsStyleChangeList& aChangeList)
+ ServoRestyleState& aRestyleState)
{
// Figure out whether we have an actual change. It's important that we do
// this, for several reasons:
//
// 1) Even if all the child's changes are due to properties it inherits from
// us, it's possible that no one ever asked us for those style structs and
// hence changes to them aren't reflected in aHintForThisFrame at all.
//
// 2) Content can change stylesheets that change the styles of pseudos, and
// extensions can add/remove stylesheets that change the styles of
// anonymous boxes directly.
uint32_t equalStructs, samePointerStructs; // Not used, actually.
nsChangeHint childHint = aChildFrame->StyleContext()->CalcStyleDifference(
aNewStyleContext,
&equalStructs,
&samePointerStructs);
+ childHint = NS_RemoveSubsumedHints(childHint, aRestyleState.ChangesHandled());
if (childHint) {
if (childHint & nsChangeHint_ReconstructFrame) {
// If we generate a reconstruct here, remove any non-reconstruct hints we
// may have already generated for this content.
- aChangeList.PopChangesForContent(aChildFrame->GetContent());
- }
- aChangeList.AppendChange(aChildFrame, aChildFrame->GetContent(), childHint);
+ aRestyleState.ChangeList().PopChangesForContent(
+ aChildFrame->GetContent());
+ }
+ aRestyleState.ChangeList().AppendChange(
+ aChildFrame, aChildFrame->GetContent(), childHint);
}
for (nsIFrame* kid = aChildFrame; kid; kid = kid->GetNextContinuation()) {
kid->SetStyleContext(aNewStyleContext);
}
return childHint;
}
@@ -10556,49 +10559,44 @@ nsIFrame::UpdateWidgetProperties()
}
if (nsCOMPtr<nsIWidget> widget = GetWindowWidget(presContext)) {
widget->SetWindowOpacity(StyleUIReset()->mWindowOpacity);
widget->SetWindowTransform(ComputeWidgetTransform());
}
}
void
-nsIFrame::DoUpdateStyleOfOwnedAnonBoxes(ServoStyleSet& aStyleSet,
- nsStyleChangeList& aChangeList,
- nsChangeHint aHintForThisFrame)
+nsIFrame::DoUpdateStyleOfOwnedAnonBoxes(ServoRestyleState& aRestyleState)
{
// As a special case, we check for {ib}-split block frames here, rather
// than have an nsInlineFrame::AppendDirectlyOwnedAnonBoxes implementation
// that returns them.
//
// (If we did handle them in AppendDirectlyOwnedAnonBoxes, we would have to
// return *all* of the in-flow {ib}-split block frames, not just the first
// one. For restyling, we really just need the first in flow, and the other
// user of the AppendOwnedAnonBoxes API, AllChildIterator, doesn't need to
// know about them at all, since these block frames never create NAC. So we
// avoid any unncessary hashtable lookups for the {ib}-split frames by calling
// UpdateStyleOfOwnedAnonBoxesForIBSplit directly here.)
if (IsInlineFrame()) {
if ((GetStateBits() & NS_FRAME_PART_OF_IBSPLIT)) {
- static_cast<nsInlineFrame*>(this)->
- UpdateStyleOfOwnedAnonBoxesForIBSplit(aStyleSet, aChangeList,
- aHintForThisFrame);
+ static_cast<nsInlineFrame*>(this)->UpdateStyleOfOwnedAnonBoxesForIBSplit(
+ aRestyleState);
}
return;
}
AutoTArray<OwnedAnonBox,4> frames;
AppendDirectlyOwnedAnonBoxes(frames);
for (OwnedAnonBox& box : frames) {
if (box.mUpdateStyleFn) {
- box.mUpdateStyleFn(this, box.mAnonBoxFrame,
- aStyleSet, aChangeList, aHintForThisFrame);
+ box.mUpdateStyleFn(this, box.mAnonBoxFrame, aRestyleState);
} else {
- UpdateStyleOfChildAnonBox(box.mAnonBoxFrame,
- aStyleSet, aChangeList, aHintForThisFrame);
+ UpdateStyleOfChildAnonBox(box.mAnonBoxFrame, aRestyleState);
}
}
}
/* virtual */ void
nsIFrame::AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult)
{
MOZ_ASSERT(!(GetStateBits() & NS_FRAME_OWNS_ANON_BOXES));
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -94,17 +94,17 @@ struct nsMargin;
struct CharacterDataChangeInfo;
namespace mozilla {
enum class CSSPseudoElementType : uint8_t;
class EventStates;
struct ReflowInput;
class ReflowOutput;
-class ServoStyleSet;
+class ServoRestyleState;
class DisplayItemData;
class EffectSet;
namespace layers {
class Layer;
} // namespace layers
namespace gfx {
@@ -3286,69 +3286,65 @@ public:
* @return The style context that should be the parent of this frame's
* style context. Null is permitted, and means that this frame's
* style context should be the root of the style context tree.
*/
virtual nsStyleContext* GetParentStyleContext(nsIFrame** aProviderFrame) const = 0;
/**
* Called by ServoRestyleManager to update the style contexts of anonymous
- * boxes directly associtated with this frame. The passed-in ServoStyleSet
- * can be used to create new style contexts as needed.
+ * boxes directly associtated with this frame.
+ *
+ * The passed-in ServoRestyleState can be used to create new style contexts
+ * as needed, as well as posting changes to the change list.
+ *
+ * It's guaranteed to already have a change in it for this frame and this
+ * frame's content.
*
* This function will be called after this frame's style context has already
* been updated. This function will only be called on frames which have the
* NS_FRAME_OWNS_ANON_BOXES bit set.
- *
- * The nsStyleChangeList can be used to append additional changes. It's
- * guaranteed to already have a change in it for this frame and this frame's
- * content and a change hint of aHintForThisFrame.
- */
- void UpdateStyleOfOwnedAnonBoxes(mozilla::ServoStyleSet& aStyleSet,
- nsStyleChangeList& aChangeList,
- nsChangeHint aHintForThisFrame) {
+ */
+ void UpdateStyleOfOwnedAnonBoxes(mozilla::ServoRestyleState& aRestyleState)
+ {
if (GetStateBits() & NS_FRAME_OWNS_ANON_BOXES) {
- DoUpdateStyleOfOwnedAnonBoxes(aStyleSet, aChangeList, aHintForThisFrame);
+ DoUpdateStyleOfOwnedAnonBoxes(aRestyleState);
}
}
protected:
// This does the actual work of UpdateStyleOfOwnedAnonBoxes. It calls
// AppendDirectlyOwnedAnonBoxes to find all of the anonymous boxes
// owned by this frame, and then updates styles on each of them.
- void DoUpdateStyleOfOwnedAnonBoxes(mozilla::ServoStyleSet& aStyleSet,
- nsStyleChangeList& aChangeList,
- nsChangeHint aHintForThisFrame);
+ void DoUpdateStyleOfOwnedAnonBoxes(mozilla::ServoRestyleState& aRestyleState);
// A helper for DoUpdateStyleOfOwnedAnonBoxes for the specific case
// of the owned anon box being a child of this frame.
void UpdateStyleOfChildAnonBox(nsIFrame* aChildFrame,
- mozilla::ServoStyleSet& aStyleSet,
- nsStyleChangeList& aChangeList,
- nsChangeHint aHintForThisFrame);
+ mozilla::ServoRestyleState& aRestyleState);
public:
// A helper both for UpdateStyleOfChildAnonBox, and to update frame-backed
// pseudo-elements in ServoRestyleManager.
//
// This gets a style context that will be the new style context for
// `aChildFrame`, and takes care of updating it, calling CalcStyleDifference,
// and adding to the change list as appropriate.
//
// Returns the generated change hint for the frame.
nsChangeHint UpdateStyleOfOwnedChildFrame(
- nsIFrame* aChildFrame,
- nsStyleContext* aNewStyleContext,
- nsStyleChangeList& aChangeList);
+ nsIFrame* aChildFrame,
+ nsStyleContext* aNewStyleContext,
+ mozilla::ServoRestyleState& aRestyleState);
struct OwnedAnonBox
{
- typedef void (*UpdateStyleFn)(nsIFrame* aOwningFrame, nsIFrame* aAnonBox,
- mozilla::ServoStyleSet&,
- nsStyleChangeList&, nsChangeHint);
+ typedef void (*UpdateStyleFn)(nsIFrame* aOwningFrame,
+ nsIFrame* aAnonBox,
+ mozilla::ServoRestyleState& aRestyleState);
explicit OwnedAnonBox(nsIFrame* aAnonBoxFrame,
UpdateStyleFn aUpdateStyleFn = nullptr)
: mAnonBoxFrame(aAnonBoxFrame)
, mUpdateStyleFn(aUpdateStyleFn)
{}
nsIFrame* mAnonBoxFrame;
--- a/layout/generic/nsInlineFrame.cpp
+++ b/layout/generic/nsInlineFrame.cpp
@@ -1010,19 +1010,17 @@ nsInlineFrame::AccessibleType()
return a11y::eHyperTextType;
return a11y::eNoType;
}
#endif
void
nsInlineFrame::UpdateStyleOfOwnedAnonBoxesForIBSplit(
- ServoStyleSet& aStyleSet,
- nsStyleChangeList& aChangeList,
- nsChangeHint aHintForThisFrame)
+ ServoRestyleState& aRestyleState)
{
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,
@@ -1032,23 +1030,23 @@ nsInlineFrame::UpdateStyleOfOwnedAnonBox
"We should be the primary frame for our element");
nsIFrame* blockFrame = GetProperty(nsIFrame::IBSplitSibling());
MOZ_ASSERT(blockFrame, "Why did we have an IB split?");
// The anonymous block's style inherits from ours, and we already have our new
// style context.
RefPtr<nsStyleContext> newContext =
- aStyleSet.ResolveInheritingAnonymousBoxStyle(
+ aRestyleState.StyleSet().ResolveInheritingAnonymousBoxStyle(
nsCSSAnonBoxes::mozBlockInsideInlineWrapper, 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
+ // changehint being 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");
MOZ_ASSERT(blockFrame->StyleContext()->GetPseudo() ==
nsCSSAnonBoxes::mozBlockInsideInlineWrapper,
--- a/layout/generic/nsInlineFrame.h
+++ b/layout/generic/nsInlineFrame.h
@@ -112,19 +112,17 @@ public:
return (GetStateBits() & NS_INLINE_FRAME_BIDI_VISUAL_STATE_IS_SET)
? !!(GetStateBits() & NS_INLINE_FRAME_BIDI_VISUAL_IS_LAST)
: (!GetNextInFlow());
}
// Restyles the block wrappers around our non-inline-outside kids.
// This will only be called when such wrappers in fact exist.
void UpdateStyleOfOwnedAnonBoxesForIBSplit(
- mozilla::ServoStyleSet& aStyleSet,
- nsStyleChangeList& aChangeList,
- nsChangeHint aHintForThisFrame);
+ mozilla::ServoRestyleState& aRestyleState);
protected:
// Additional reflow state used during our reflow methods
struct InlineReflowInput {
nsIFrame* mPrevFrame;
nsInlineFrame* mNextInFlow;
nsIFrame* mLineContainer;
nsLineLayout* mLineLayout;
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -34,16 +34,17 @@
#include "nsCSSAnonBoxes.h"
#include "nsIPresShell.h"
#include "nsIDOMElement.h"
#include "nsIDOMHTMLElement.h"
#include "nsIScriptError.h"
#include "nsFrameManager.h"
#include "nsError.h"
#include "nsCSSFrameConstructor.h"
+#include "mozilla/ServoRestyleManager.h"
#include "mozilla/ServoStyleSet.h"
#include "mozilla/StyleSetHandle.h"
#include "mozilla/StyleSetHandleInlines.h"
#include "nsDisplayList.h"
#include "nsIScrollableFrame.h"
#include "nsCSSProps.h"
#include "RestyleTracker.h"
#include "nsStyleChangeList.h"
@@ -8008,43 +8009,43 @@ nsTableFrame::AppendDirectlyOwnedAnonBox
nsCSSAnonBoxes::tableWrapper,
"What happened to our parent?");
aResult.AppendElement(
OwnedAnonBox(wrapper, &UpdateStyleOfOwnedAnonBoxesForTableWrapper));
}
/* static */ void
nsTableFrame::UpdateStyleOfOwnedAnonBoxesForTableWrapper(
- nsIFrame* aOwningFrame,
- nsIFrame* aWrapperFrame,
- ServoStyleSet& aStyleSet,
- nsStyleChangeList& aChangeList,
- nsChangeHint aHintForThisFrame)
+ nsIFrame* aOwningFrame,
+ nsIFrame* aWrapperFrame,
+ ServoRestyleState& aRestyleState)
{
MOZ_ASSERT(aWrapperFrame->StyleContext()->GetPseudo() ==
nsCSSAnonBoxes::tableWrapper,
"What happened to our parent?");
RefPtr<nsStyleContext> newContext =
- aStyleSet.ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::tableWrapper,
- aOwningFrame->StyleContext());
+ aRestyleState.StyleSet().ResolveInheritingAnonymousBoxStyle(
+ nsCSSAnonBoxes::tableWrapper, aOwningFrame->StyleContext());
// Figure out whether we have an actual change. It's important that we do
// this, even though all the wrapper's changes are due to properties it
// inherits from us, because it's possible that no one ever asked us for those
// style structs and hence changes to them aren't reflected in
// aHintForThisFrame at all.
uint32_t equalStructs, samePointerStructs; // Not used, actually.
nsChangeHint wrapperHint = aWrapperFrame->StyleContext()->CalcStyleDifference(
newContext,
&equalStructs,
&samePointerStructs);
+ wrapperHint =
+ NS_RemoveSubsumedHints(wrapperHint, aRestyleState.ChangesHandled());
if (wrapperHint) {
- aChangeList.AppendChange(aWrapperFrame, aWrapperFrame->GetContent(),
- wrapperHint);
+ aRestyleState.ChangeList().AppendChange(
+ aWrapperFrame, aWrapperFrame->GetContent(), wrapperHint);
}
for (nsIFrame* cur = aWrapperFrame; cur; cur = cur->GetNextContinuation()) {
cur->SetStyleContext(newContext);
}
MOZ_ASSERT(!(aWrapperFrame->GetStateBits() & NS_FRAME_OWNS_ANON_BOXES),
"Wrapper frame doesn't have any anon boxes of its own!");
--- a/layout/tables/nsTableFrame.h
+++ b/layout/tables/nsTableFrame.h
@@ -593,21 +593,19 @@ public:
virtual bool ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas) override;
// Return our wrapper frame.
void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) override;
protected:
static void UpdateStyleOfOwnedAnonBoxesForTableWrapper(
- nsIFrame* aOwningFrame,
- nsIFrame* aWrapperFrame,
- mozilla::ServoStyleSet& aStyleSet,
- nsStyleChangeList& aChangeList,
- nsChangeHint aHintForThisFrame);
+ nsIFrame* aOwningFrame,
+ nsIFrame* aWrapperFrame,
+ mozilla::ServoRestyleState& aRestyleState);
/** protected constructor.
* @see NewFrame
*/
explicit nsTableFrame(nsStyleContext* aContext, ClassID aID = kClassID);
/** destructor, responsible for mColumnLayoutData */
virtual ~nsTableFrame();