Bug 1180118 - Part 9: Clear nsCSSSelector pointers in the pending restyle tracker if they might be stale. r=bzbarsky

This commit is contained in:
Cameron McCormack 2015-08-05 22:42:21 +10:00
parent e55a3ea42c
commit 77856721a3
6 changed files with 74 additions and 0 deletions

View File

@ -127,6 +127,10 @@ public:
*/
nsresult ReparentStyleContext(nsIFrame* aFrame);
void ClearSelectors() {
mPendingRestyles.ClearSelectors();
}
private:
// Used when restyling an element with a frame.
void ComputeAndProcessStyleChange(nsIFrame* aFrame,

View File

@ -447,6 +447,9 @@ RestyleTracker::DoProcessRestyles()
}
}
// mPendingRestyles is now empty.
mHaveSelectors = false;
mRestyleManager->EndProcessingRestyles();
}
@ -512,4 +515,23 @@ RestyleTracker::AddRestyleRootsIfAwaitingRestyle(
}
}
void
RestyleTracker::ClearSelectors()
{
if (!mHaveSelectors) {
return;
}
for (auto it = mPendingRestyles.Iter(); !it.Done(); it.Next()) {
RestyleData* data = it.Data();
if (data->mRestyleHint & eRestyle_SomeDescendants) {
data->mRestyleHint =
(data->mRestyleHint & ~eRestyle_SomeDescendants) | eRestyle_Subtree;
data->mRestyleHintData.mSelectorsForDescendants.Clear();
} else {
MOZ_ASSERT(data->mRestyleHintData.mSelectorsForDescendants.IsEmpty());
}
}
mHaveSelectors = false;
}
} // namespace mozilla

View File

@ -231,6 +231,7 @@ public:
explicit RestyleTracker(Element::FlagsType aRestyleBits)
: mRestyleBits(aRestyleBits)
, mHaveLaterSiblingRestyles(false)
, mHaveSelectors(false)
{
NS_PRECONDITION((mRestyleBits & ~ELEMENT_ALL_RESTYLE_FLAGS) == 0,
"Why do we have these bits set?");
@ -352,6 +353,14 @@ public:
void AddRestyleRootsIfAwaitingRestyle(
const nsTArray<nsRefPtr<Element>>& aElements);
/**
* Converts any eRestyle_SomeDescendants restyle hints in the pending restyle
* table into eRestyle_Subtree hints and clears out the associated arrays of
* nsCSSSelector pointers. This is called in response to a style sheet change
* that might have cause an nsCSSSelector to be destroyed.
*/
void ClearSelectors();
/**
* The document we're associated with.
*/
@ -402,6 +411,9 @@ private:
// flag. We need this to avoid enumerating the hashtable looking
// for such entries when we can't possibly have any.
bool mHaveLaterSiblingRestyles;
// True if we have some entries with selectors in the restyle hint data.
// We use this to skip iterating over mPendingRestyles in ClearSelectors.
bool mHaveSelectors;
};
inline bool
@ -412,6 +424,11 @@ RestyleTracker::AddPendingRestyleToTable(Element* aElement,
{
RestyleData* existingData;
if (aRestyleHintData &&
!aRestyleHintData->mSelectorsForDescendants.IsEmpty()) {
mHaveSelectors = true;
}
// Check the RestyleBit() flag before doing the hashtable Get, since
// it's possible that the data in the hashtable isn't actually
// relevant anymore (if the flag is not set).

View File

@ -1709,6 +1709,15 @@ CSSStyleSheet::List(FILE* out, int32_t aIndent) const
void
CSSStyleSheet::ClearRuleCascades()
{
// We might be in ClearRuleCascades because we had a modification
// to the sheet that resulted in an nsCSSSelector being destroyed.
// Tell the RestyleManager for each document we're used in
// so that they can drop any nsCSSSelector pointers (used for
// eRestyle_SomeDescendants) in their mPendingRestyles.
for (nsStyleSet* styleSet : mStyleSets) {
styleSet->ClearSelectors();
}
bool removedSheetFromRuleProcessorCache = false;
if (mRuleProcessors) {
nsCSSRuleProcessor **iter = mRuleProcessors->Elements(),

View File

@ -385,6 +385,14 @@ SortStyleSheetsByScope(nsTArray<CSSStyleSheet*>& aSheets)
nsresult
nsStyleSet::GatherRuleProcessors(sheetType aType)
{
// We might be in GatherRuleProcessors because we are dropping a sheet,
// resulting in an nsCSSSelector being destroyed. Tell the
// RestyleManager for each document we're used in so that they can
// drop any nsCSSSelector pointers (used for eRestyle_SomeDescendants)
// in their mPendingRestyles.
if (IsCSSSheetType(aType)) {
ClearSelectors();
}
nsCOMPtr<nsIStyleRuleProcessor> oldRuleProcessor(mRuleProcessors[aType]);
nsTArray<nsCOMPtr<nsIStyleRuleProcessor>> oldScopedDocRuleProcessors;
if (aType == eAgentSheet || aType == eUserSheet) {
@ -2498,3 +2506,13 @@ nsStyleSet::HasRuleProcessorUsedByMultipleStyleSets(sheetType aSheetType)
static_cast<nsCSSRuleProcessor*>(mRuleProcessors[aSheetType].get());
return rp->IsUsedByMultipleStyleSets();
}
void
nsStyleSet::ClearSelectors()
{
// We might be called before we've done our first rule tree construction.
if (!mRuleTree) {
return;
}
PresContext()->RestyleManager()->ClearSelectors();
}

View File

@ -399,6 +399,10 @@ class nsStyleSet final
bool HasRuleProcessorUsedByMultipleStyleSets(sheetType aSheetType);
// Tells the RestyleManager for the document using this style set
// to drop any nsCSSSelector pointers it has.
void ClearSelectors();
private:
nsStyleSet(const nsStyleSet& aCopy) = delete;
nsStyleSet& operator=(const nsStyleSet& aCopy) = delete;