mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
Bug 1367553: Move dirty style tracking to the StyleSet. r=heycam
MozReview-Commit-ID: 2ut8SAwNGN2 --HG-- extra : rebase_source : d9f7d7f1da7b38e595021795ee902e63746c8161
This commit is contained in:
parent
0d2aa9ed3e
commit
d4ee389879
@ -52,7 +52,6 @@
|
||||
#include "nsIContentIterator.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/Event.h" // for Event::GetEventPopupControlState()
|
||||
#include "mozilla/dom/ShadowRoot.h"
|
||||
#include "mozilla/dom/PointerEvent.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsAnimationManager.h"
|
||||
@ -784,7 +783,6 @@ nsIPresShell::nsIPresShell()
|
||||
, mCanvasBackgroundColor(NS_RGBA(0,0,0,0))
|
||||
, mSelectionFlags(0)
|
||||
, mRenderFlags(0)
|
||||
, mStylesHaveChanged(false)
|
||||
, mDidInitialize(false)
|
||||
, mIsDestroying(false)
|
||||
, mIsReflowing(false)
|
||||
@ -1544,7 +1542,6 @@ PresShell::AddUserSheet(StyleSheet* aSheet)
|
||||
}
|
||||
|
||||
mStyleSet->EndUpdate();
|
||||
|
||||
RestyleForCSSRuleChanges();
|
||||
}
|
||||
|
||||
@ -2535,8 +2532,9 @@ PresShell::EndUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType)
|
||||
|
||||
if (aUpdateType & UPDATE_STYLE) {
|
||||
mStyleSet->EndUpdate();
|
||||
if (mStylesHaveChanged || !mChangedScopeStyleRoots.IsEmpty())
|
||||
if (mStyleSet->StyleSheetsHaveChanged()) {
|
||||
RestyleForCSSRuleChanges();
|
||||
}
|
||||
}
|
||||
|
||||
mFrameConstructor->EndUpdate();
|
||||
@ -4546,17 +4544,6 @@ PresShell::ReconstructFrames()
|
||||
void
|
||||
nsIPresShell::RestyleForCSSRuleChanges()
|
||||
{
|
||||
AutoTArray<RefPtr<mozilla::dom::Element>,1> scopeRoots;
|
||||
mChangedScopeStyleRoots.SwapElements(scopeRoots);
|
||||
|
||||
if (mStylesHaveChanged) {
|
||||
// If we need to restyle everything, no need to restyle individual
|
||||
// scoped style roots.
|
||||
scopeRoots.Clear();
|
||||
}
|
||||
|
||||
mStylesHaveChanged = false;
|
||||
|
||||
if (mIsDestroying) {
|
||||
// We don't want to mess with restyles at this point
|
||||
return;
|
||||
@ -4568,33 +4555,12 @@ nsIPresShell::RestyleForCSSRuleChanges()
|
||||
mPresContext->RebuildCounterStyles();
|
||||
}
|
||||
|
||||
Element* root = mDocument->GetRootElement();
|
||||
if (!mDidInitialize) {
|
||||
// Nothing to do here, since we have no frames yet
|
||||
return;
|
||||
}
|
||||
|
||||
if (!root) {
|
||||
// No content to restyle
|
||||
return;
|
||||
}
|
||||
|
||||
RestyleManager* restyleManager = mPresContext->RestyleManager();
|
||||
|
||||
if (scopeRoots.IsEmpty()) {
|
||||
// If scopeRoots is empty, we know that mStylesHaveChanged was true at
|
||||
// the beginning of this function, and that we need to restyle the whole
|
||||
// document.
|
||||
restyleManager->PostRestyleEventForCSSRuleChanges(root,
|
||||
eRestyle_Subtree,
|
||||
nsChangeHint(0));
|
||||
} else {
|
||||
for (Element* scopeRoot : scopeRoots) {
|
||||
restyleManager->PostRestyleEventForCSSRuleChanges(scopeRoot,
|
||||
eRestyle_Subtree,
|
||||
nsChangeHint(0));
|
||||
}
|
||||
}
|
||||
mStyleSet->InvalidateStyleForCSSRuleChanges();
|
||||
}
|
||||
|
||||
void
|
||||
@ -4602,27 +4568,9 @@ PresShell::RecordStyleSheetChange(StyleSheet* aStyleSheet)
|
||||
{
|
||||
// too bad we can't check that the update is UPDATE_STYLE
|
||||
NS_ASSERTION(mUpdateCount != 0, "must be in an update");
|
||||
MOZ_ASSERT(aStyleSheet->IsServo() == mStyleSet->IsServo());
|
||||
|
||||
if (mStylesHaveChanged)
|
||||
return;
|
||||
|
||||
// Tell Servo that the contents of style sheets have changed.
|
||||
if (ServoStyleSet* set = mStyleSet->GetAsServo()) {
|
||||
set->NoteStyleSheetsChanged();
|
||||
}
|
||||
|
||||
if (aStyleSheet->IsGecko()) {
|
||||
// XXXheycam ServoStyleSheets don't support <style scoped> yet.
|
||||
Element* scopeElement = aStyleSheet->AsGecko()->GetScopeElement();
|
||||
if (scopeElement) {
|
||||
mChangedScopeStyleRoots.AppendElement(scopeElement);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
NS_WARNING("stylo: ServoStyleSheets don't support <style scoped>");
|
||||
}
|
||||
|
||||
mStylesHaveChanged = true;
|
||||
mStyleSet->RecordStyleSheetChange(aStyleSheet);
|
||||
}
|
||||
|
||||
void
|
||||
@ -6352,7 +6300,7 @@ private:
|
||||
void
|
||||
PresShell::RecordShadowStyleChange(ShadowRoot* aShadowRoot)
|
||||
{
|
||||
mChangedScopeStyleRoots.AppendElement(aShadowRoot->GetHost()->AsElement());
|
||||
mStyleSet->RecordShadowStyleChange(aShadowRoot);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1862,11 +1862,6 @@ protected:
|
||||
// changes in a way that prevents us from being able to (usefully)
|
||||
// re-use old pixels.
|
||||
RenderFlags mRenderFlags;
|
||||
|
||||
// Indicates that the whole document must be restyled. Changes to scoped
|
||||
// style sheets are recorded in mChangedScopeStyleRoots rather than here
|
||||
// in mStylesHaveChanged.
|
||||
bool mStylesHaveChanged : 1;
|
||||
bool mDidInitialize : 1;
|
||||
bool mIsDestroying : 1;
|
||||
bool mIsReflowing : 1;
|
||||
@ -1906,15 +1901,6 @@ protected:
|
||||
|
||||
uint32_t mPresShellId;
|
||||
|
||||
// List of subtrees rooted at style scope roots that need to be restyled.
|
||||
// When a change to a scoped style sheet is made, we add the style scope
|
||||
// root to this array rather than setting mStylesHaveChanged = true, since
|
||||
// we know we don't need to restyle the whole document. However, if in the
|
||||
// same update block we have already had other changes that require
|
||||
// the whole document to be restyled (i.e., mStylesHaveChanged is already
|
||||
// true), then we don't bother adding the scope root here.
|
||||
AutoTArray<RefPtr<mozilla::dom::Element>,1> mChangedScopeStyleRoots;
|
||||
|
||||
static nsIContent* gKeyDownTarget;
|
||||
|
||||
// Cached font inflation values. This is done to prevent changing of font
|
||||
|
@ -125,6 +125,15 @@ ServoStyleSet::Shutdown()
|
||||
mRawSet = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
ServoStyleSet::InvalidateStyleForCSSRuleChanges()
|
||||
{
|
||||
if (Element* root = mPresContext->Document()->GetRootElement()) {
|
||||
mPresContext->RestyleManager()->PostRestyleEventForCSSRuleChanges(
|
||||
root, eRestyle_Subtree, nsChangeHint(0));
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
ServoStyleSet::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
|
@ -105,6 +105,24 @@ public:
|
||||
void BeginShutdown();
|
||||
void Shutdown();
|
||||
|
||||
void RecordStyleSheetChange(mozilla::ServoStyleSheet*)
|
||||
{
|
||||
NoteStyleSheetsChanged();
|
||||
}
|
||||
|
||||
void RecordShadowStyleChange(mozilla::dom::ShadowRoot* aShadowRoot) {
|
||||
// FIXME(emilio): When we properly support shadow dom we'll need to do
|
||||
// better.
|
||||
NoteStyleSheetsChanged();
|
||||
}
|
||||
|
||||
bool StyleSheetsHaveChanged() const
|
||||
{
|
||||
return StylistNeedsUpdate();
|
||||
}
|
||||
|
||||
void InvalidateStyleForCSSRuleChanges();
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
const RawServoStyleSet& RawSet() const { return *mRawSet; }
|
||||
|
||||
|
@ -22,6 +22,7 @@ class CSSStyleSheet;
|
||||
class ServoStyleSet;
|
||||
namespace dom {
|
||||
class Element;
|
||||
class ShadowRoot;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
class nsCSSCounterStyleRule;
|
||||
@ -153,6 +154,10 @@ public:
|
||||
inline StyleSheet* StyleSheetAt(SheetType aType, int32_t aIndex) const;
|
||||
inline nsresult RemoveDocStyleSheet(StyleSheet* aSheet);
|
||||
inline nsresult AddDocStyleSheet(StyleSheet* aSheet, nsIDocument* aDocument);
|
||||
inline void RecordStyleSheetChange(StyleSheet* aSheet);
|
||||
inline void RecordShadowStyleChange(mozilla::dom::ShadowRoot* aShadowRoot);
|
||||
inline bool StyleSheetsHaveChanged() const;
|
||||
inline void InvalidateStyleForCSSRuleChanges();
|
||||
inline already_AddRefed<nsStyleContext>
|
||||
ProbePseudoElementStyle(dom::Element* aParentElement,
|
||||
mozilla::CSSPseudoElementType aType,
|
||||
|
@ -220,6 +220,31 @@ StyleSetHandle::Ptr::AddDocStyleSheet(StyleSheet* aSheet,
|
||||
(aSheet->AsServo(), aDocument));
|
||||
}
|
||||
|
||||
void
|
||||
StyleSetHandle::Ptr::RecordStyleSheetChange(StyleSheet* aSheet)
|
||||
{
|
||||
FORWARD_CONCRETE(RecordStyleSheetChange, (aSheet->AsGecko()),
|
||||
(aSheet->AsServo()));
|
||||
}
|
||||
|
||||
void
|
||||
StyleSetHandle::Ptr::RecordShadowStyleChange(mozilla::dom::ShadowRoot* aShadowRoot)
|
||||
{
|
||||
FORWARD(RecordShadowStyleChange, (aShadowRoot));
|
||||
}
|
||||
|
||||
bool
|
||||
StyleSetHandle::Ptr::StyleSheetsHaveChanged() const
|
||||
{
|
||||
FORWARD(StyleSheetsHaveChanged, ());
|
||||
}
|
||||
|
||||
void
|
||||
StyleSetHandle::Ptr::InvalidateStyleForCSSRuleChanges()
|
||||
{
|
||||
FORWARD(InvalidateStyleForCSSRuleChanges, ());
|
||||
}
|
||||
|
||||
// check whether there is ::before/::after style for an element
|
||||
already_AddRefed<nsStyleContext>
|
||||
StyleSetHandle::Ptr::ProbePseudoElementStyle(dom::Element* aParentElement,
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "nsAnimationManager.h"
|
||||
#include "nsStyleSheetService.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/ShadowRoot.h"
|
||||
#include "GeckoProfiler.h"
|
||||
#include "nsHTMLCSSStyleSheet.h"
|
||||
#include "nsHTMLStyleSheet.h"
|
||||
@ -210,6 +211,7 @@ nsStyleSet::IsCSSSheetType(SheetType aSheetType)
|
||||
nsStyleSet::nsStyleSet()
|
||||
: mRuleTree(nullptr),
|
||||
mBatching(0),
|
||||
mStylesHaveChanged(0),
|
||||
mInShutdown(false),
|
||||
mInGC(false),
|
||||
mAuthorStyleDisabled(false),
|
||||
@ -2366,6 +2368,68 @@ nsStyleSet::Shutdown()
|
||||
MOZ_ASSERT(mUnusedRuleNodeCount == 0);
|
||||
}
|
||||
|
||||
void
|
||||
nsStyleSet::RecordStyleSheetChange(CSSStyleSheet* aStyleSheet)
|
||||
{
|
||||
MOZ_ASSERT(mBatching != 0, "Should be in an update");
|
||||
|
||||
if (mStylesHaveChanged) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Element* scopeElement = aStyleSheet->GetScopeElement()) {
|
||||
mChangedScopeStyleRoots.AppendElement(scopeElement);
|
||||
return;
|
||||
}
|
||||
|
||||
mStylesHaveChanged = true;
|
||||
// If we need to restyle everything, no need to restyle individual
|
||||
// scoped style roots.
|
||||
mChangedScopeStyleRoots.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
nsStyleSet::RecordShadowStyleChange(ShadowRoot* aShadowRoot)
|
||||
{
|
||||
if (mStylesHaveChanged) {
|
||||
return;
|
||||
}
|
||||
|
||||
mChangedScopeStyleRoots.AppendElement(aShadowRoot->GetHost()->AsElement());
|
||||
}
|
||||
|
||||
void
|
||||
nsStyleSet::InvalidateStyleForCSSRuleChanges()
|
||||
{
|
||||
MOZ_ASSERT_IF(mStylesHaveChanged, mChangedScopeStyleRoots.IsEmpty());
|
||||
|
||||
AutoTArray<RefPtr<mozilla::dom::Element>, 1> scopeRoots;
|
||||
mChangedScopeStyleRoots.SwapElements(scopeRoots);
|
||||
mStylesHaveChanged = false;
|
||||
|
||||
nsPresContext* presContext = PresContext();
|
||||
RestyleManager* restyleManager = presContext->RestyleManager();
|
||||
Element* root = presContext->Document()->GetRootElement();
|
||||
if (!root) {
|
||||
// No content to restyle
|
||||
return;
|
||||
}
|
||||
|
||||
if (scopeRoots.IsEmpty()) {
|
||||
// If scopeRoots is empty, we know that mStylesHaveChanged was true at
|
||||
// the beginning of this function, and that we need to restyle the whole
|
||||
// document.
|
||||
restyleManager->PostRestyleEventForCSSRuleChanges(root,
|
||||
eRestyle_Subtree,
|
||||
nsChangeHint(0));
|
||||
} else {
|
||||
for (Element* scopeRoot : scopeRoots) {
|
||||
restyleManager->PostRestyleEventForCSSRuleChanges(scopeRoot,
|
||||
eRestyle_Subtree,
|
||||
nsChangeHint(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsStyleSet::GCRuleTrees()
|
||||
|
@ -41,8 +41,11 @@ struct TreeMatchContext;
|
||||
|
||||
namespace mozilla {
|
||||
class CSSStyleSheet;
|
||||
class EventStates;
|
||||
enum class CSSPseudoElementType : uint8_t;
|
||||
class EventStates;
|
||||
namespace dom {
|
||||
class ShadowRoot;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
class nsEmptyStyleRule final : public nsIStyleRule
|
||||
@ -329,6 +332,19 @@ class nsStyleSet final
|
||||
// Free all of the data associated with this style set.
|
||||
void Shutdown();
|
||||
|
||||
// Notes that a style sheet has changed.
|
||||
void RecordStyleSheetChange(mozilla::CSSStyleSheet* aStyleSheet);
|
||||
|
||||
// Notes that style sheets have changed in a shadow root.
|
||||
void RecordShadowStyleChange(mozilla::dom::ShadowRoot* aShadowRoot);
|
||||
|
||||
bool StyleSheetsHaveChanged() const
|
||||
{
|
||||
return mStylesHaveChanged || !mChangedScopeStyleRoots.IsEmpty();
|
||||
}
|
||||
|
||||
void InvalidateStyleForCSSRuleChanges();
|
||||
|
||||
// Get a new style context that lives in a different parent
|
||||
// The new context will be the same as the old if the new parent is the
|
||||
// same as the old parent.
|
||||
@ -603,8 +619,21 @@ private:
|
||||
// lexicographic tree of matched rules that style
|
||||
// contexts use to look up properties.
|
||||
|
||||
// List of subtrees rooted at style scope roots that need to be restyled.
|
||||
// When a change to a scoped style sheet is made, we add the style scope
|
||||
// root to this array rather than setting mStylesHaveChanged = true, since
|
||||
// we know we don't need to restyle the whole document. However, if in the
|
||||
// same update block we have already had other changes that require
|
||||
// the whole document to be restyled (i.e., mStylesHaveChanged is already
|
||||
// true), then we don't bother adding the scope root here.
|
||||
AutoTArray<RefPtr<mozilla::dom::Element>,1> mChangedScopeStyleRoots;
|
||||
|
||||
uint16_t mBatching;
|
||||
|
||||
// Indicates that the whole document must be restyled. Changes to scoped
|
||||
// style sheets are recorded in mChangedScopeStyleRoots rather than here
|
||||
// in mStylesHaveChanged.
|
||||
unsigned mStylesHaveChanged : 1;
|
||||
unsigned mInShutdown : 1;
|
||||
unsigned mInGC : 1;
|
||||
unsigned mAuthorStyleDisabled: 1;
|
||||
|
Loading…
Reference in New Issue
Block a user