Issue #2828 - Part 5: Implement child rule processors

This commit is contained in:
Francis Dominic Fajardo 2025-07-19 01:45:14 +08:00 • committed by roytam1
commit e05d4d8306
16 changed files with 632 additions and 155 deletions

View file

@ -838,6 +838,12 @@ EffectCompositor::AnimationStyleRuleProcessor::MediumFeaturesChanged(
return false; return false;
} }
nsTArray<nsCOMPtr<nsIStyleRuleProcessor>>*
EffectCompositor::AnimationStyleRuleProcessor::GetChildRuleProcessors()
{
return nullptr;
}
void void
EffectCompositor::AnimationStyleRuleProcessor::RulesMatching( EffectCompositor::AnimationStyleRuleProcessor::RulesMatching(
ElementRuleProcessorData* aData) ElementRuleProcessorData* aData)

View file

@ -278,6 +278,8 @@ private:
AttributeRuleProcessorData* aData, AttributeRuleProcessorData* aData,
RestyleHintData& aRestyleHintDataResult) override; RestyleHintData& aRestyleHintDataResult) override;
bool MediumFeaturesChanged(nsPresContext* aPresContext) override; bool MediumFeaturesChanged(nsPresContext* aPresContext) override;
nsTArray<nsCOMPtr<nsIStyleRuleProcessor>>* GetChildRuleProcessors()
override;
void RulesMatching(ElementRuleProcessorData* aData) override; void RulesMatching(ElementRuleProcessorData* aData) override;
void RulesMatching(PseudoElementRuleProcessorData* aData) override; void RulesMatching(PseudoElementRuleProcessorData* aData) override;
void RulesMatching(AnonBoxRuleProcessorData* aData) override; void RulesMatching(AnonBoxRuleProcessorData* aData) override;

View file

@ -0,0 +1,329 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* style rule processor for cascade layers
*/
#include "nsAutoPtr.h"
#include "nsCSSRuleProcessor.h"
#include "nsRuleProcessorData.h"
#include <algorithm>
#include "nsIAtom.h"
#include "PLDHashTable.h"
#include "nsICSSPseudoComparator.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/css/StyleRule.h"
#include "mozilla/css/GroupRule.h"
#include "nsIDocument.h"
#include "nsPresContext.h"
#include "nsGkAtoms.h"
#include "nsUnicharUtils.h"
#include "nsError.h"
#include "nsRuleWalker.h"
#include "nsCSSPseudoClasses.h"
#include "nsCSSPseudoElements.h"
#include "nsIContent.h"
#include "nsCOMPtr.h"
#include "nsHashKeys.h"
#include "nsStyleUtil.h"
#include "nsQuickSort.h"
#include "nsAttrValue.h"
#include "nsAttrValueInlines.h"
#include "nsAttrName.h"
#include "nsTArray.h"
#include "nsContentUtils.h"
#include "nsIMediaList.h"
#include "nsCSSRules.h"
#include "nsStyleSet.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/HTMLSlotElement.h"
#include "mozilla/dom/ShadowRoot.h"
#include "nsNthIndexCache.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/EventStates.h"
#include "mozilla/Preferences.h"
#include "mozilla/LookAndFeel.h"
#include "mozilla/Likely.h"
#include "mozilla/OperatorNewExtensions.h"
#include "mozilla/TypedEnumBits.h"
#include "RuleProcessorCache.h"
#include "nsIDOMMutationEvent.h"
#include "nsIMozBrowserFrame.h"
#include "RuleCascadeData.h"
#include "nsCSSRuleUtils.h"
#include "CascadeLayerRuleProcessor.h"
using namespace mozilla;
using namespace mozilla::dom;
// -------------------------------
// Cascade layer style rule processor implementation
//
CascadeLayerRuleProcessor::CascadeLayerRuleProcessor(
CascadeEnumData* aLayer)
: mLayer(aLayer)
, mCascade(aLayer->mData)
{
MOZ_ASSERT(mLayer,
"Layer rule processor must have an attached cascade layer");
MOZ_ASSERT(mCascade, "Cascade layer is missing its data");
}
/* virtual */ void
CascadeLayerRuleProcessor::RulesMatching(ElementRuleProcessorData* aData)
{
if (mCascade) {
mCascade->RulesMatching(aData);
}
}
/* virtual */ void
CascadeLayerRuleProcessor::RulesMatching(
PseudoElementRuleProcessorData* aData)
{
if (mCascade) {
mCascade->RulesMatching(aData);
}
}
/* virtual */ void
CascadeLayerRuleProcessor::RulesMatching(AnonBoxRuleProcessorData* aData)
{
if (mCascade) {
mCascade->RulesMatching(aData);
}
}
/* virtual */ void
CascadeLayerRuleProcessor::RulesMatching(XULTreeRuleProcessorData* aData)
{
if (mCascade) {
mCascade->RulesMatching(aData);
}
}
nsRestyleHint
CascadeLayerRuleProcessor::HasStateDependentStyle(
ElementDependentRuleProcessorData* aData,
Element* aStatefulElement,
CSSPseudoElementType aPseudoType,
EventStates aStateMask,
nsRestyleHint& aHint)
{
if (mCascade) {
mCascade->HasStateDependentStyle(
aData, aStatefulElement, aPseudoType, aStateMask, aHint);
}
return aHint;
}
nsRestyleHint
CascadeLayerRuleProcessor::HasStateDependentStyle(
ElementDependentRuleProcessorData* aData,
Element* aStatefulElement,
CSSPseudoElementType aPseudoType,
EventStates aStateMask)
{
nsRestyleHint hint = nsRestyleHint(0);
return HasStateDependentStyle(
aData, aStatefulElement, aPseudoType, aStateMask, hint);
}
/* virtual */ nsRestyleHint
CascadeLayerRuleProcessor::HasStateDependentStyle(
StateRuleProcessorData* aData)
{
return HasStateDependentStyle(
aData, aData->mElement, CSSPseudoElementType::NotPseudo, aData->mStateMask);
}
/* virtual */ nsRestyleHint
CascadeLayerRuleProcessor::HasStateDependentStyle(
PseudoElementStateRuleProcessorData* aData)
{
return HasStateDependentStyle(
aData, aData->mPseudoElement, aData->mPseudoType, aData->mStateMask);
}
/* virtual */ bool
CascadeLayerRuleProcessor::HasDocumentStateDependentStyle(
StateRuleProcessorData* aData)
{
if (mCascade && mCascade->mSelectorDocumentStates.HasAtLeastOneOfStates(
aData->mStateMask)) {
return true;
}
return false;
}
nsRestyleHint
CascadeLayerRuleProcessor::HasAttributeDependentStyle(
AttributeRuleProcessorData* aData,
AttributeEnumData* aEnumData,
mozilla::RestyleHintData& aRestyleHintDataResult)
{
// We could try making use of aData->mModType, but :not rules make it a bit
// of a pain to do so... So just ignore it for now.
// Don't do our special handling of certain attributes if the attr
// hasn't changed yet.
if (aData->mAttrHasChanged) {
// check for the lwtheme and lwthemetextcolor attribute on root XUL elements
if ((aData->mAttribute == nsGkAtoms::lwtheme ||
aData->mAttribute == nsGkAtoms::lwthemetextcolor) &&
aData->mElement->GetNameSpaceID() == kNameSpaceID_XUL &&
aData->mElement == aData->mElement->OwnerDoc()->GetRootElement()) {
aEnumData->change = nsRestyleHint(aEnumData->change | eRestyle_Subtree);
}
// We don't know the namespace of the attribute, and xml:lang applies to
// all elements. If the lang attribute changes, we need to restyle our
// whole subtree, since the :lang selector on our descendants can examine
// our lang attribute.
if (aData->mAttribute == nsGkAtoms::lang) {
aEnumData->change = nsRestyleHint(aEnumData->change | eRestyle_Subtree);
}
}
if (mCascade) {
mCascade->HasAttributeDependentStyle(aData, aEnumData, aRestyleHintDataResult);
}
return aEnumData->change;
}
/* virtual */ nsRestyleHint
CascadeLayerRuleProcessor::HasAttributeDependentStyle(
AttributeRuleProcessorData* aData,
mozilla::RestyleHintData& aRestyleHintDataResult)
{
AttributeEnumData data(aData, aRestyleHintDataResult);
return HasAttributeDependentStyle(aData, &data, aRestyleHintDataResult);
}
/* virtual */ bool
CascadeLayerRuleProcessor::MediumFeaturesChanged(nsPresContext* aPresContext)
{
// This is handled by our parent rule processor, so we don't need to do
// anything here.
return false;
}
/* virtual */ nsTArray<nsCOMPtr<nsIStyleRuleProcessor>>*
CascadeLayerRuleProcessor::GetChildRuleProcessors()
{
return nullptr;
}
/* virtual */ size_t
CascadeLayerRuleProcessor::SizeOfExcludingThis(
mozilla::MallocSizeOf aMallocSizeOf) const
{
size_t n = 0;
n += mCascade->SizeOfIncludingThis(aMallocSizeOf);
// FIXME: size of attached cascade layer is not included.
return n;
}
/* virtual */ size_t
CascadeLayerRuleProcessor::SizeOfIncludingThis(
mozilla::MallocSizeOf aMallocSizeOf) const
{
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
}
nsCSSKeyframesRule*
CascadeLayerRuleProcessor::KeyframesRuleForName(nsPresContext* aPresContext,
const nsString& aName)
{
if (mCascade) {
return mCascade->mKeyframesRuleTable.Get(aName);
}
return nullptr;
}
nsCSSCounterStyleRule*
CascadeLayerRuleProcessor::CounterStyleRuleForName(
nsPresContext* aPresContext,
const nsAString& aName)
{
if (mCascade) {
return mCascade->mCounterStyleRuleTable.Get(aName);
}
return nullptr;
}
// Append all the currently-active font face rules to aArray. Return
// true for success and false for failure.
bool
CascadeLayerRuleProcessor::AppendFontFaceRules(
nsPresContext* aPresContext,
nsTArray<nsFontFaceRuleContainer>& aArray)
{
if (mCascade) {
if (!aArray.AppendElements(mCascade->mFontFaceRules)) {
return false;
}
}
return true;
}
// Append all the currently-active page rules to aArray. Return
// true for success and false for failure.
bool
CascadeLayerRuleProcessor::AppendPageRules(nsPresContext* aPresContext,
nsTArray<nsCSSPageRule*>& aArray)
{
if (mCascade) {
if (!aArray.AppendElements(mCascade->mPageRules)) {
return false;
}
}
return true;
}
bool
CascadeLayerRuleProcessor::AppendFontFeatureValuesRules(
nsPresContext* aPresContext,
nsTArray<nsCSSFontFeatureValuesRule*>& aArray)
{
if (mCascade) {
if (!aArray.AppendElements(mCascade->mFontFeatureValuesRules)) {
return false;
}
}
return true;
}
CascadeLayerRuleProcessor::~CascadeLayerRuleProcessor()
{
mCascade = nullptr;
if (mLayer) {
delete mLayer;
}
mLayer = nullptr;
}
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CascadeLayerRuleProcessor)
NS_INTERFACE_MAP_ENTRY(nsIStyleRuleProcessor)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(CascadeLayerRuleProcessor)
NS_IMPL_CYCLE_COLLECTING_RELEASE(CascadeLayerRuleProcessor)
NS_IMPL_CYCLE_COLLECTION_CLASS(CascadeLayerRuleProcessor)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CascadeLayerRuleProcessor)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CascadeLayerRuleProcessor)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END

View file

@ -0,0 +1,138 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* style rule processor for cascade layers
*/
#ifndef CascadeLayerRuleProcessor_h_
#define CascadeLayerRuleProcessor_h_
#include "mozilla/Attributes.h"
#include "mozilla/EventStates.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/RefCountType.h"
#include "mozilla/SheetType.h"
#include "mozilla/UniquePtr.h"
#include "nsExpirationTracker.h"
#include "nsIMediaList.h"
#include "nsIStyleRuleProcessor.h"
#include "nsRuleWalker.h"
#include "nsTArray.h"
struct AttributeEnumData;
struct CascadeEnumData;
struct RuleCascadeData;
struct ElementDependentRuleProcessorData;
struct nsFontFaceRuleContainer;
struct ResolvedRuleCascades;
class nsCSSKeyframesRule;
class nsCSSPageRule;
class nsCSSFontFeatureValuesRule;
class nsCSSCounterStyleRule;
namespace mozilla {
class CSSStyleSheet;
enum class CSSPseudoElementType : uint8_t;
namespace css {
class DocumentRule;
} // namespace css
} // namespace mozilla
/**
* The cascade layer rule processor handles rules collected by the CSS style
* rule processor within the context of a specific cascade layer. It ensures
* rules are applied in the correct order, as defined by the CSS specification.
*
* It also handles unlayered rules, which are treated as belonging to an
* implicit base layer.
*/
class CascadeLayerRuleProcessor : public nsIStyleRuleProcessor
{
public:
CascadeLayerRuleProcessor(CascadeEnumData* aLayer);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(CascadeLayerRuleProcessor)
public:
// nsIStyleRuleProcessor
virtual void RulesMatching(ElementRuleProcessorData* aData) override;
virtual void RulesMatching(PseudoElementRuleProcessorData* aData) override;
virtual void RulesMatching(AnonBoxRuleProcessorData* aData) override;
virtual void RulesMatching(XULTreeRuleProcessorData* aData) override;
virtual nsRestyleHint HasStateDependentStyle(
StateRuleProcessorData* aData) override;
virtual nsRestyleHint HasStateDependentStyle(
PseudoElementStateRuleProcessorData* aData) override;
virtual bool HasDocumentStateDependentStyle(
StateRuleProcessorData* aData) override;
virtual nsRestyleHint HasAttributeDependentStyle(
AttributeRuleProcessorData* aData,
mozilla::RestyleHintData& aRestyleHintDataResult) override;
virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) override;
virtual nsTArray<nsCOMPtr<nsIStyleRuleProcessor>>* GetChildRuleProcessors()
override;
virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
MOZ_MUST_OVERRIDE override;
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
MOZ_MUST_OVERRIDE override;
// The following API methods are consumed by nsStyleSet.
nsCSSKeyframesRule* KeyframesRuleForName(nsPresContext* aPresContext,
const nsString& aName);
nsCSSCounterStyleRule* CounterStyleRuleForName(nsPresContext* aPresContext,
const nsAString& aName);
bool AppendFontFaceRules(nsPresContext* aPresContext,
nsTArray<nsFontFaceRuleContainer>& aArray);
bool AppendPageRules(nsPresContext* aPresContext,
nsTArray<nsCSSPageRule*>& aArray);
bool AppendFontFeatureValuesRules(
nsPresContext* aPresContext,
nsTArray<nsCSSFontFeatureValuesRule*>& aArray);
// The following API methods are consumed by nsCSSRuleProcessor only.
nsRestyleHint HasAttributeDependentStyle(
AttributeRuleProcessorData* aData,
AttributeEnumData* aEnumData,
mozilla::RestyleHintData& aRestyleHintDataResult);
nsRestyleHint HasStateDependentStyle(
ElementDependentRuleProcessorData* aData,
mozilla::dom::Element* aStatefulElement,
mozilla::CSSPseudoElementType aPseudoType,
mozilla::EventStates aStateMask,
nsRestyleHint& aHint);
protected:
virtual ~CascadeLayerRuleProcessor();
CascadeEnumData* mLayer;
RuleCascadeData* mCascade;
private:
nsRestyleHint HasStateDependentStyle(
ElementDependentRuleProcessorData* aData,
mozilla::dom::Element* aStatefulElement,
mozilla::CSSPseudoElementType aPseudoType,
mozilla::EventStates aStateMask);
};
#endif /* CascadeLayerRuleProcessor_h_ */

View file

@ -1188,6 +1188,13 @@ RuleCascadeData::HasAttributeDependentStyle(
AttributeEnumData* aEnumData, AttributeEnumData* aEnumData,
mozilla::RestyleHintData& aRestyleHintDataResult) mozilla::RestyleHintData& aRestyleHintDataResult)
{ {
// Since we get both before and after notifications for attributes, we
// don't have to ignore aData->mAttribute while matching. Just check
// whether we have selectors relevant to aData->mAttribute that we
// match. If this is the before change notification, that will catch
// rules we might stop matching; if the after change notification, the
// ones we might have started matching.
if (aData->mAttribute == nsGkAtoms::id) { if (aData->mAttribute == nsGkAtoms::id) {
nsIAtom* id = aData->mElement->GetID(); nsIAtom* id = aData->mElement->GetID();
if (id) { if (id) {
@ -1475,10 +1482,10 @@ size_t
ResolvedRuleCascades::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const ResolvedRuleCascades::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
{ {
size_t n = aMallocSizeOf(this); size_t n = aMallocSizeOf(this);
n += mOrderedData.ShallowSizeOfExcludingThis(aMallocSizeOf); for (uint32_t i = 0; i < mProcessors.Length(); i++) {
for (RuleCascadeData* data : mOrderedData) { n += mProcessors[i]->SizeOfIncludingThis(aMallocSizeOf);
n += data->SizeOfIncludingThis(aMallocSizeOf);
} }
n += mProcessors.ShallowSizeOfExcludingThis(aMallocSizeOf);
return n; return n;
} }
@ -1553,7 +1560,6 @@ CascadeEnumData::CascadeEnumData(nsPresContext* aPresContext,
#ifdef DEBUG #ifdef DEBUG
CascadeEnumData* aParent, CascadeEnumData* aParent,
#endif #endif
nsAutoPtr<ResolvedRuleCascades>& aContainer,
bool aIsWeak, bool aIsWeak,
nsTArray<css::DocumentRule*>& aDocumentRules, nsTArray<css::DocumentRule*>& aDocumentRules,
nsDocumentRuleResultCacheKey& aDocumentKey, nsDocumentRuleResultCacheKey& aDocumentKey,
@ -1569,7 +1575,6 @@ CascadeEnumData::CascadeEnumData(nsPresContext* aPresContext,
, mParent(aParent) , mParent(aParent)
, mIsRoot(false) , mIsRoot(false)
#endif #endif
, mContainer(aContainer)
, mDocumentRules(aDocumentRules) , mDocumentRules(aDocumentRules)
, mDocumentCacheKey(aDocumentKey) , mDocumentCacheKey(aDocumentKey)
, mSheetType(aSheetType) , mSheetType(aSheetType)
@ -1581,14 +1586,12 @@ CascadeEnumData::CascadeEnumData(nsPresContext* aPresContext,
} }
CascadeEnumData::CascadeEnumData(nsPresContext* aPresContext, CascadeEnumData::CascadeEnumData(nsPresContext* aPresContext,
nsAutoPtr<ResolvedRuleCascades>& aContainer,
nsTArray<css::DocumentRule*>& aDocumentRules, nsTArray<css::DocumentRule*>& aDocumentRules,
nsDocumentRuleResultCacheKey& aDocumentKey, nsDocumentRuleResultCacheKey& aDocumentKey,
SheetType aSheetType, SheetType aSheetType,
bool aMustGatherDocumentRules, bool aMustGatherDocumentRules,
nsMediaQueryResultCacheKey& aCacheKey) nsMediaQueryResultCacheKey& aCacheKey)
: mPresContext(aPresContext) : mPresContext(aPresContext)
, mContainer(aContainer)
, mIsAnonymous(false) , mIsAnonymous(false)
, mIsWeak(false) , mIsWeak(false)
, mWasFlattened(false) , mWasFlattened(false)
@ -1608,6 +1611,7 @@ CascadeEnumData::CascadeEnumData(nsPresContext* aPresContext,
CascadeEnumData::~CascadeEnumData() CascadeEnumData::~CascadeEnumData()
{ {
delete mData;
PL_FinishArenaPool(&mArena); PL_FinishArenaPool(&mArena);
} }
@ -1628,7 +1632,6 @@ CascadeEnumData::CreateNamedChildLayer(const nsTArray<nsString>& aPath)
#ifdef DEBUG #ifdef DEBUG
this, this,
#endif #endif
mContainer,
false, false,
mDocumentRules, mDocumentRules,
mDocumentCacheKey, mDocumentCacheKey,
@ -1659,7 +1662,6 @@ CascadeEnumData::CreateAnonymousChildLayer()
#ifdef DEBUG #ifdef DEBUG
this, this,
#endif #endif
mContainer,
false, false,
mDocumentRules, mDocumentRules,
mDocumentCacheKey, mDocumentCacheKey,
@ -1751,7 +1753,7 @@ CascadeEnumData::AddRules()
} }
void void
CascadeEnumData::Flatten() CascadeEnumData::EnumerateAllLayers(nsLayerEnumFunc aFunc, void* aData)
{ {
if (mWasFlattened) { if (mWasFlattened) {
return; return;
@ -1759,16 +1761,15 @@ CascadeEnumData::Flatten()
if (mPreLayers.Length() > 0) { if (mPreLayers.Length() > 0) {
for (CascadeEnumData* pre : mPreLayers) { for (CascadeEnumData* pre : mPreLayers) {
pre->Flatten(); pre->EnumerateAllLayers(aFunc, aData);
} }
} }
mContainer->mOrderedData.AppendElement(mData); (*aFunc)(this, aData);
AddRules();
if (mPostLayers.Length() > 0) { if (mPostLayers.Length() > 0) {
for (CascadeEnumData* post : mPostLayers) { for (CascadeEnumData* post : mPostLayers) {
post->Flatten(); post->EnumerateAllLayers(aFunc, aData);
} }
} }

View file

@ -325,21 +325,17 @@ private:
struct ResolvedRuleCascades struct ResolvedRuleCascades
{ {
ResolvedRuleCascades(nsIAtom* aMedium) ResolvedRuleCascades(nsIAtom* aMedium)
: mUnlayered(nullptr) : mCacheKey(aMedium)
, mCacheKey(aMedium)
, mNext(nullptr) , mNext(nullptr)
{ {
} }
~ResolvedRuleCascades() ~ResolvedRuleCascades()
{ {
for (RuleCascadeData* data : mOrderedData) { mProcessors.Clear();
delete data;
}
} }
nsTArray<RuleCascadeData*> mOrderedData; nsTArray<nsCOMPtr<nsIStyleRuleProcessor>> mProcessors;
RuleCascadeData* mUnlayered;
nsMediaQueryResultCacheKey mCacheKey; nsMediaQueryResultCacheKey mCacheKey;
ResolvedRuleCascades* mNext; // for a different medium ResolvedRuleCascades* mNext; // for a different medium
@ -353,7 +349,6 @@ struct CascadeEnumData
#ifdef DEBUG #ifdef DEBUG
CascadeEnumData* aParent, CascadeEnumData* aParent,
#endif #endif
nsAutoPtr<ResolvedRuleCascades>& aContainer,
bool aIsWeak, bool aIsWeak,
nsTArray<css::DocumentRule*>& aDocumentRules, nsTArray<css::DocumentRule*>& aDocumentRules,
nsDocumentRuleResultCacheKey& aDocumentKey, nsDocumentRuleResultCacheKey& aDocumentKey,
@ -362,7 +357,6 @@ struct CascadeEnumData
nsMediaQueryResultCacheKey& aCacheKey); nsMediaQueryResultCacheKey& aCacheKey);
CascadeEnumData(nsPresContext* aPresContext, CascadeEnumData(nsPresContext* aPresContext,
nsAutoPtr<ResolvedRuleCascades>& aContainer,
nsTArray<css::DocumentRule*>& aDocumentRules, nsTArray<css::DocumentRule*>& aDocumentRules,
nsDocumentRuleResultCacheKey& aDocumentKey, nsDocumentRuleResultCacheKey& aDocumentKey,
SheetType aSheetType, SheetType aSheetType,
@ -395,18 +389,19 @@ struct CascadeEnumData
CascadeEnumData* mParent; CascadeEnumData* mParent;
bool mIsRoot; bool mIsRoot;
#endif #endif
nsAutoPtr<ResolvedRuleCascades>& mContainer;
nsTArray<CascadeEnumData*> mPreLayers; nsTArray<CascadeEnumData*> mPreLayers;
nsTArray<CascadeEnumData*> mPostLayers; nsTArray<CascadeEnumData*> mPostLayers;
nsDataHashtable<nsStringHashKey, CascadeEnumData*> mLayers; nsDataHashtable<nsStringHashKey, CascadeEnumData*> mLayers;
CascadeEnumData* CreateNamedChildLayer(const nsTArray<nsString>& aPath); CascadeEnumData* CreateNamedChildLayer(const nsTArray<nsString>& aPath);
CascadeEnumData* CreateAnonymousChildLayer(); CascadeEnumData* CreateAnonymousChildLayer();
void Flatten();
typedef void (*nsLayerEnumFunc)(CascadeEnumData* aLayer, void* aData);
void EnumerateAllLayers(nsLayerEnumFunc aFunc, void* aData);
void AddRules();
private: private:
void Initialize(); void Initialize();
void AddRules();
static const PLDHashTableOps sRulesByWeightOps; static const PLDHashTableOps sRulesByWeightOps;
}; };

View file

@ -75,6 +75,12 @@ SVGAttrAnimationRuleProcessor::MediumFeaturesChanged(nsPresContext* aPresContext
return false; return false;
} }
/* virtual */ nsTArray<nsCOMPtr<nsIStyleRuleProcessor>>*
SVGAttrAnimationRuleProcessor::GetChildRuleProcessors()
{
return nullptr;
}
/* virtual */ void /* virtual */ void
SVGAttrAnimationRuleProcessor::RulesMatching(PseudoElementRuleProcessorData* aData) SVGAttrAnimationRuleProcessor::RulesMatching(PseudoElementRuleProcessorData* aData)
{ {

View file

@ -47,6 +47,8 @@ public:
HasAttributeDependentStyle(AttributeRuleProcessorData* aData, HasAttributeDependentStyle(AttributeRuleProcessorData* aData,
RestyleHintData& aRestyleHintDataResult) override; RestyleHintData& aRestyleHintDataResult) override;
virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) override; virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) override;
virtual nsTArray<nsCOMPtr<nsIStyleRuleProcessor>>* GetChildRuleProcessors()
override;
virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)
const MOZ_MUST_OVERRIDE override; const MOZ_MUST_OVERRIDE override;
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)

View file

@ -24,6 +24,7 @@ TEST_DIRS += ['test']
EXPORTS += [ EXPORTS += [
'!nsStyleStructList.h', '!nsStyleStructList.h',
'AnimationCommon.h', 'AnimationCommon.h',
'CascadeLayerRuleProcessor.h',
'CounterStyleManager.h', 'CounterStyleManager.h',
'nsAnimationManager.h', 'nsAnimationManager.h',
'nsComputedDOMStylePropertyList.h', 'nsComputedDOMStylePropertyList.h',
@ -121,6 +122,7 @@ EXPORTS.mozilla.css += [
UNIFIED_SOURCES += [ UNIFIED_SOURCES += [
'AnimationCollection.cpp', 'AnimationCollection.cpp',
'AnimationCommon.cpp', 'AnimationCommon.cpp',
'CascadeLayerRuleProcessor.cpp',
'CounterStyleManager.cpp', 'CounterStyleManager.cpp',
'CSS.cpp', 'CSS.cpp',
'CSSLexer.cpp', 'CSSLexer.cpp',

View file

@ -55,6 +55,7 @@
#include "nsIMozBrowserFrame.h" #include "nsIMozBrowserFrame.h"
#include "RuleCascadeData.h" #include "RuleCascadeData.h"
#include "nsCSSRuleUtils.h" #include "nsCSSRuleUtils.h"
#include "CascadeLayerRuleProcessor.h"
using namespace mozilla; using namespace mozilla;
using namespace mozilla::dom; using namespace mozilla::dom;
@ -146,39 +147,30 @@ nsCSSRuleProcessor::ClearSheets()
/* virtual */ void /* virtual */ void
nsCSSRuleProcessor::RulesMatching(ElementRuleProcessorData *aData) nsCSSRuleProcessor::RulesMatching(ElementRuleProcessorData *aData)
{ {
ResolvedRuleCascades* resolvedCascade = GetRuleCascade(aData->mPresContext); if (ResolvedRuleCascades* cascades = GetRuleCascade(aData->mPresContext)) {
for (nsCOMPtr<nsIStyleRuleProcessor> processor : cascades->mProcessors) {
if (!resolvedCascade) { processor->RulesMatching(aData);
return; }
}
for (RuleCascadeData* cascade : resolvedCascade->mOrderedData) {
cascade->RulesMatching(aData);
} }
} }
/* virtual */ void /* virtual */ void
nsCSSRuleProcessor::RulesMatching(PseudoElementRuleProcessorData* aData) nsCSSRuleProcessor::RulesMatching(PseudoElementRuleProcessorData* aData)
{ {
ResolvedRuleCascades* resolvedCascade = GetRuleCascade(aData->mPresContext); if (ResolvedRuleCascades* cascades = GetRuleCascade(aData->mPresContext)) {
for (nsCOMPtr<nsIStyleRuleProcessor> processor : cascades->mProcessors) {
if (!resolvedCascade) { processor->RulesMatching(aData);
return; }
}
for (RuleCascadeData* cascade : resolvedCascade->mOrderedData) {
cascade->RulesMatching(aData);
} }
} }
/* virtual */ void /* virtual */ void
nsCSSRuleProcessor::RulesMatching(AnonBoxRuleProcessorData* aData) nsCSSRuleProcessor::RulesMatching(AnonBoxRuleProcessorData* aData)
{ {
ResolvedRuleCascades* resolvedCascade = GetRuleCascade(aData->mPresContext); if (ResolvedRuleCascades* cascades = GetRuleCascade(aData->mPresContext)) {
for (nsCOMPtr<nsIStyleRuleProcessor> processor : cascades->mProcessors) {
if (!resolvedCascade) { processor->RulesMatching(aData);
return; }
}
for (RuleCascadeData* cascade : resolvedCascade->mOrderedData) {
cascade->RulesMatching(aData);
} }
} }
@ -186,13 +178,10 @@ nsCSSRuleProcessor::RulesMatching(AnonBoxRuleProcessorData* aData)
/* virtual */ void /* virtual */ void
nsCSSRuleProcessor::RulesMatching(XULTreeRuleProcessorData* aData) nsCSSRuleProcessor::RulesMatching(XULTreeRuleProcessorData* aData)
{ {
ResolvedRuleCascades* resolvedCascade = GetRuleCascade(aData->mPresContext); if (ResolvedRuleCascades* cascades = GetRuleCascade(aData->mPresContext)) {
for (nsCOMPtr<nsIStyleRuleProcessor> processor : cascades->mProcessors) {
if (!resolvedCascade) { processor->RulesMatching(aData);
return; }
}
for (RuleCascadeData* cascade : resolvedCascade->mOrderedData) {
cascade->RulesMatching(aData);
} }
} }
#endif #endif
@ -207,19 +196,19 @@ nsCSSRuleProcessor::HasStateDependentStyle(ElementDependentRuleProcessorData* aD
"mCurrentStyleScope will need to be saved and restored after the " "mCurrentStyleScope will need to be saved and restored after the "
"SelectorMatchesTree call"); "SelectorMatchesTree call");
ResolvedRuleCascades* resolvedCascade = GetRuleCascade(aData->mPresContext);
nsRestyleHint hint = nsRestyleHint(0); nsRestyleHint hint = nsRestyleHint(0);
if (resolvedCascade) { if (ResolvedRuleCascades* cascades = GetRuleCascade(aData->mPresContext)) {
for (RuleCascadeData* cascade : resolvedCascade->mOrderedData) { for (nsCOMPtr<nsIStyleRuleProcessor> processor : cascades->mProcessors) {
cascade->HasStateDependentStyle( CascadeLayerRuleProcessor* layerProcessor =
static_cast<CascadeLayerRuleProcessor*>(processor.get());
layerProcessor->HasStateDependentStyle(
aData, aStatefulElement, aPseudoType, aStateMask, hint); aData, aStatefulElement, aPseudoType, aStateMask, hint);
} }
} }
return hint; return hint;
} }
nsRestyleHint /* virtual */ nsRestyleHint
nsCSSRuleProcessor::HasStateDependentStyle(StateRuleProcessorData* aData) nsCSSRuleProcessor::HasStateDependentStyle(StateRuleProcessorData* aData)
{ {
return HasStateDependentStyle(aData, return HasStateDependentStyle(aData,
@ -228,7 +217,7 @@ nsCSSRuleProcessor::HasStateDependentStyle(StateRuleProcessorData* aData)
aData->mStateMask); aData->mStateMask);
} }
nsRestyleHint /* virtual */ nsRestyleHint
nsCSSRuleProcessor::HasStateDependentStyle(PseudoElementStateRuleProcessorData* aData) nsCSSRuleProcessor::HasStateDependentStyle(PseudoElementStateRuleProcessorData* aData)
{ {
return HasStateDependentStyle(aData, return HasStateDependentStyle(aData,
@ -237,15 +226,12 @@ nsCSSRuleProcessor::HasStateDependentStyle(PseudoElementStateRuleProcessorData*
aData->mStateMask); aData->mStateMask);
} }
bool /* virtual */ bool
nsCSSRuleProcessor::HasDocumentStateDependentStyle(StateRuleProcessorData* aData) nsCSSRuleProcessor::HasDocumentStateDependentStyle(StateRuleProcessorData* aData)
{ {
ResolvedRuleCascades* resolvedCascade = GetRuleCascade(aData->mPresContext); if (ResolvedRuleCascades* cascades = GetRuleCascade(aData->mPresContext)) {
for (nsCOMPtr<nsIStyleRuleProcessor> processor : cascades->mProcessors) {
if (resolvedCascade) { if (processor->HasDocumentStateDependentStyle(aData)) {
for (RuleCascadeData* cascade : resolvedCascade->mOrderedData) {
if (cascade->mSelectorDocumentStates.HasAtLeastOneOfStates(
aData->mStateMask)) {
return true; return true;
} }
} }
@ -259,47 +245,15 @@ nsCSSRuleProcessor::HasAttributeDependentStyle(
AttributeRuleProcessorData* aData, AttributeRuleProcessorData* aData,
RestyleHintData& aRestyleHintDataResult) RestyleHintData& aRestyleHintDataResult)
{ {
// We could try making use of aData->mModType, but :not rules make it a bit
// of a pain to do so... So just ignore it for now.
AttributeEnumData data(aData, aRestyleHintDataResult); AttributeEnumData data(aData, aRestyleHintDataResult);
if (ResolvedRuleCascades* cascades = GetRuleCascade(aData->mPresContext)) {
// Don't do our special handling of certain attributes if the attr for (nsCOMPtr<nsIStyleRuleProcessor> processor : cascades->mProcessors) {
// hasn't changed yet. CascadeLayerRuleProcessor* layerProcessor =
if (aData->mAttrHasChanged) { static_cast<CascadeLayerRuleProcessor*>(processor.get());
// check for the lwtheme and lwthemetextcolor attribute on root XUL elements layerProcessor->HasAttributeDependentStyle(
if ((aData->mAttribute == nsGkAtoms::lwtheme ||
aData->mAttribute == nsGkAtoms::lwthemetextcolor) &&
aData->mElement->GetNameSpaceID() == kNameSpaceID_XUL &&
aData->mElement == aData->mElement->OwnerDoc()->GetRootElement())
{
data.change = nsRestyleHint(data.change | eRestyle_Subtree);
}
// We don't know the namespace of the attribute, and xml:lang applies to
// all elements. If the lang attribute changes, we need to restyle our
// whole subtree, since the :lang selector on our descendants can examine
// our lang attribute.
if (aData->mAttribute == nsGkAtoms::lang) {
data.change = nsRestyleHint(data.change | eRestyle_Subtree);
}
}
ResolvedRuleCascades* resolvedCascade = GetRuleCascade(aData->mPresContext);
// Since we get both before and after notifications for attributes, we
// don't have to ignore aData->mAttribute while matching. Just check
// whether we have selectors relevant to aData->mAttribute that we
// match. If this is the before change notification, that will catch
// rules we might stop matching; if the after change notification, the
// ones we might have started matching.
if (resolvedCascade) {
for (RuleCascadeData* cascade : resolvedCascade->mOrderedData) {
cascade->HasAttributeDependentStyle(
aData, &data, aRestyleHintDataResult); aData, &data, aRestyleHintDataResult);
} }
} }
return data.change; return data.change;
} }
@ -341,13 +295,21 @@ nsCSSRuleProcessor::MediumFeaturesChanged(nsPresContext* aPresContext)
return false; return false;
} }
/* virtual */ nsTArray<nsCOMPtr<nsIStyleRuleProcessor>>*
nsCSSRuleProcessor::GetChildRuleProcessors()
{
return mRuleCascades
? &mRuleCascades->mProcessors
: nullptr;
}
UniquePtr<nsMediaQueryResultCacheKey> UniquePtr<nsMediaQueryResultCacheKey>
nsCSSRuleProcessor::CloneMQCacheKey() nsCSSRuleProcessor::CloneMQCacheKey()
{ {
MOZ_ASSERT(!(mRuleCascades && mPreviousCacheKey)); MOZ_ASSERT(!(mRuleCascades && mPreviousCacheKey));
ResolvedRuleCascades* c = mRuleCascades; ResolvedRuleCascades* c = mRuleCascades;
if (!c || !c->mUnlayered) { if (!c) {
// We might have an mPreviousCacheKey. It already comes from a call // We might have an mPreviousCacheKey. It already comes from a call
// to CloneMQCacheKey, so don't bother checking // to CloneMQCacheKey, so don't bother checking
// HasFeatureConditions(). // HasFeatureConditions().
@ -373,9 +335,9 @@ nsCSSRuleProcessor::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
{ {
size_t n = 0; size_t n = 0;
n += mSheets.ShallowSizeOfExcludingThis(aMallocSizeOf); n += mSheets.ShallowSizeOfExcludingThis(aMallocSizeOf);
for (ResolvedRuleCascades* cascade = mRuleCascades; cascade; for (ResolvedRuleCascades* cascades = mRuleCascades; cascades;
cascade = cascade->mNext) { cascades = cascades->mNext) {
n += cascade->SizeOfIncludingThis(aMallocSizeOf); n += cascades->SizeOfIncludingThis(aMallocSizeOf);
} }
return n; return n;
@ -387,18 +349,16 @@ nsCSSRuleProcessor::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
} }
// Append all the currently-active font face rules to aArray. Return
// true for success and false for failure.
bool bool
nsCSSRuleProcessor::AppendFontFaceRules( nsCSSRuleProcessor::AppendFontFaceRules(
nsPresContext *aPresContext, nsPresContext *aPresContext,
nsTArray<nsFontFaceRuleContainer>& aArray) nsTArray<nsFontFaceRuleContainer>& aArray)
{ {
ResolvedRuleCascades* resolvedCascade = GetRuleCascade(aPresContext); if (ResolvedRuleCascades* cascades = GetRuleCascade(aPresContext)) {
for (nsCOMPtr<nsIStyleRuleProcessor> processor : cascades->mProcessors) {
if (resolvedCascade) { CascadeLayerRuleProcessor* layerProcessor =
for (RuleCascadeData* cascade : resolvedCascade->mOrderedData) { static_cast<CascadeLayerRuleProcessor*>(processor.get());
if (!aArray.AppendElements(cascade->mFontFaceRules)) { if (!layerProcessor->AppendFontFaceRules(aPresContext, aArray)) {
return false; return false;
} }
} }
@ -411,13 +371,14 @@ nsCSSKeyframesRule*
nsCSSRuleProcessor::KeyframesRuleForName(nsPresContext* aPresContext, nsCSSRuleProcessor::KeyframesRuleForName(nsPresContext* aPresContext,
const nsString& aName) const nsString& aName)
{ {
ResolvedRuleCascades* resolvedCascade = GetRuleCascade(aPresContext);
nsCSSKeyframesRule* rule = nullptr; nsCSSKeyframesRule* rule = nullptr;
if (resolvedCascade) {
for (RuleCascadeData* cascade : resolvedCascade->mOrderedData) { if (ResolvedRuleCascades* cascades = GetRuleCascade(aPresContext)) {
for (nsCOMPtr<nsIStyleRuleProcessor> processor : cascades->mProcessors) {
CascadeLayerRuleProcessor* layerProcessor =
static_cast<CascadeLayerRuleProcessor*>(processor.get());
if (nsCSSKeyframesRule* newRule = if (nsCSSKeyframesRule* newRule =
cascade->mKeyframesRuleTable.Get(aName)) { layerProcessor->KeyframesRuleForName(aPresContext, aName)) {
rule = newRule; rule = newRule;
} }
} }
@ -430,13 +391,13 @@ nsCSSCounterStyleRule*
nsCSSRuleProcessor::CounterStyleRuleForName(nsPresContext* aPresContext, nsCSSRuleProcessor::CounterStyleRuleForName(nsPresContext* aPresContext,
const nsAString& aName) const nsAString& aName)
{ {
ResolvedRuleCascades* resolvedCascade = GetRuleCascade(aPresContext);
nsCSSCounterStyleRule* rule = nullptr; nsCSSCounterStyleRule* rule = nullptr;
if (resolvedCascade) { if (ResolvedRuleCascades* cascades = GetRuleCascade(aPresContext)) {
for (RuleCascadeData* cascade : resolvedCascade->mOrderedData) { for (nsCOMPtr<nsIStyleRuleProcessor> processor : cascades->mProcessors) {
CascadeLayerRuleProcessor* layerProcessor =
static_cast<CascadeLayerRuleProcessor*>(processor.get());
if (nsCSSCounterStyleRule* newRule = if (nsCSSCounterStyleRule* newRule =
cascade->mCounterStyleRuleTable.Get(aName)) { layerProcessor->CounterStyleRuleForName(aPresContext, aName)) {
rule = newRule; rule = newRule;
} }
} }
@ -445,18 +406,16 @@ nsCSSRuleProcessor::CounterStyleRuleForName(nsPresContext* aPresContext,
return rule; return rule;
} }
// Append all the currently-active page rules to aArray. Return
// true for success and false for failure.
bool bool
nsCSSRuleProcessor::AppendPageRules( nsCSSRuleProcessor::AppendPageRules(
nsPresContext* aPresContext, nsPresContext* aPresContext,
nsTArray<nsCSSPageRule*>& aArray) nsTArray<nsCSSPageRule*>& aArray)
{ {
ResolvedRuleCascades* resolvedCascade = GetRuleCascade(aPresContext); if (ResolvedRuleCascades* cascades = GetRuleCascade(aPresContext)) {
for (nsCOMPtr<nsIStyleRuleProcessor> processor : cascades->mProcessors) {
if (resolvedCascade) { CascadeLayerRuleProcessor* layerProcessor =
for (RuleCascadeData* cascade : resolvedCascade->mOrderedData) { static_cast<CascadeLayerRuleProcessor*>(processor.get());
if (!aArray.AppendElements(cascade->mPageRules)) { if (!layerProcessor->AppendPageRules(aPresContext, aArray)) {
return false; return false;
} }
} }
@ -470,11 +429,11 @@ nsCSSRuleProcessor::AppendFontFeatureValuesRules(
nsPresContext *aPresContext, nsPresContext *aPresContext,
nsTArray<nsCSSFontFeatureValuesRule*>& aArray) nsTArray<nsCSSFontFeatureValuesRule*>& aArray)
{ {
ResolvedRuleCascades* resolvedCascade = GetRuleCascade(aPresContext); if (ResolvedRuleCascades* cascades = GetRuleCascade(aPresContext)) {
for (nsCOMPtr<nsIStyleRuleProcessor> processor : cascades->mProcessors) {
if (resolvedCascade) { CascadeLayerRuleProcessor* layerProcessor =
for (RuleCascadeData* cascade : resolvedCascade->mOrderedData) { static_cast<CascadeLayerRuleProcessor*>(processor.get());
if (!aArray.AppendElements(cascade->mFontFeatureValuesRules)) { if (!layerProcessor->AppendFontFeatureValuesRules(aPresContext, aArray)) {
return false; return false;
} }
} }
@ -733,6 +692,19 @@ nsCSSRuleProcessor::GetRuleCascade(nsPresContext* aPresContext)
return mRuleCascades; return mRuleCascades;
} }
/**
* This enumerates layers in a sheet and creates child rule processors
* for each layer. The child rule processors are created in the order
* that the layers are encountered.
*/
static void
CreateChildProcessorsEnumFunc(CascadeEnumData* aLayer, void* aData)
{
aLayer->AddRules();
ResolvedRuleCascades* data = static_cast<ResolvedRuleCascades*>(aData);
data->mProcessors.AppendElement(new CascadeLayerRuleProcessor(aLayer));
}
void void
nsCSSRuleProcessor::RefreshRuleCascade(nsPresContext* aPresContext) nsCSSRuleProcessor::RefreshRuleCascade(nsPresContext* aPresContext)
{ {
@ -760,24 +732,26 @@ nsCSSRuleProcessor::RefreshRuleCascade(nsPresContext* aPresContext)
mPreviousCacheKey = nullptr; mPreviousCacheKey = nullptr;
if (mSheets.Length() != 0) { if (mSheets.Length() != 0) {
nsAutoPtr<ResolvedRuleCascades> resolvedCascade( nsAutoPtr<ResolvedRuleCascades> cascades(
new ResolvedRuleCascades(aPresContext->Medium())); new ResolvedRuleCascades(aPresContext->Medium()));
CascadeEnumData unlayered(aPresContext, CascadeEnumData* unlayered(new CascadeEnumData(aPresContext,
resolvedCascade, mDocumentRules,
mDocumentRules, mDocumentCacheKey,
mDocumentCacheKey, mSheetType,
mSheetType, mMustGatherDocumentRules,
mMustGatherDocumentRules, cascades->mCacheKey));
resolvedCascade->mCacheKey); if (unlayered->mData) {
if (unlayered.mData) {
for (uint32_t i = 0; i < mSheets.Length(); ++i) { for (uint32_t i = 0; i < mSheets.Length(); ++i) {
if (!CascadeSheet(mSheets.ElementAt(i), &unlayered)) { if (!CascadeSheet(mSheets.ElementAt(i), unlayered)) {
return; /* out of memory */ return; /* out of memory */
} }
} }
unlayered.Flatten(); // Ensure that the current one is always mRuleCascades.
resolvedCascade->mUnlayered = unlayered.mData; cascades->mNext = mRuleCascades;
mRuleCascades = cascades.forget();
unlayered->EnumerateAllLayers(CreateChildProcessorsEnumFunc, mRuleCascades);
// mMustGatherDocumentRules controls whether we build mDocumentRules // mMustGatherDocumentRules controls whether we build mDocumentRules
// and mDocumentCacheKey so that they can be used as keys by the // and mDocumentCacheKey so that they can be used as keys by the
@ -812,10 +786,6 @@ nsCSSRuleProcessor::RefreshRuleCascade(nsPresContext* aPresContext)
mDocumentRulesAndCacheKeyValid = true; mDocumentRulesAndCacheKeyValid = true;
#endif #endif
} }
// Ensure that the current one is always mRuleCascades.
resolvedCascade->mNext = mRuleCascades;
mRuleCascades = resolvedCascade.forget();
} }
} }
return; return;

View file

@ -51,7 +51,7 @@ class DocumentRule;
* is told when the rule processor is going away (via DropRuleProcessor). * is told when the rule processor is going away (via DropRuleProcessor).
*/ */
class nsCSSRuleProcessor: public nsIStyleRuleProcessor { class nsCSSRuleProcessor : public nsIStyleRuleProcessor {
public: public:
typedef nsTArray<RefPtr<mozilla::CSSStyleSheet>> sheet_array_type; typedef nsTArray<RefPtr<mozilla::CSSStyleSheet>> sheet_array_type;
@ -99,6 +99,9 @@ public:
virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) override; virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) override;
virtual nsTArray<nsCOMPtr<nsIStyleRuleProcessor>>* GetChildRuleProcessors()
override;
/** /**
* If this rule processor currently has a substantive media query * If this rule processor currently has a substantive media query
* result cache key, return a copy of it. * result cache key, return a copy of it.

View file

@ -162,6 +162,12 @@ nsHTMLCSSStyleSheet::MediumFeaturesChanged(nsPresContext* aPresContext)
return false; return false;
} }
/* virtual */ nsTArray<nsCOMPtr<nsIStyleRuleProcessor>>*
nsHTMLCSSStyleSheet::GetChildRuleProcessors()
{
return nullptr;
}
/* virtual */ size_t /* virtual */ size_t
nsHTMLCSSStyleSheet::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const nsHTMLCSSStyleSheet::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
{ {

View file

@ -47,6 +47,8 @@ public:
HasAttributeDependentStyle(AttributeRuleProcessorData* aData, HasAttributeDependentStyle(AttributeRuleProcessorData* aData,
mozilla::RestyleHintData& aRestyleHintDataResult) override; mozilla::RestyleHintData& aRestyleHintDataResult) override;
virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) override; virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) override;
virtual nsTArray<nsCOMPtr<nsIStyleRuleProcessor>>* GetChildRuleProcessors()
override;
virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)
const MOZ_MUST_OVERRIDE override; const MOZ_MUST_OVERRIDE override;
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)

View file

@ -439,6 +439,12 @@ nsHTMLStyleSheet::MediumFeaturesChanged(nsPresContext* aPresContext)
return false; return false;
} }
/* virtual */ nsTArray<nsCOMPtr<nsIStyleRuleProcessor>>*
nsHTMLStyleSheet::GetChildRuleProcessors()
{
return nullptr;
}
/* virtual */ size_t /* virtual */ size_t
nsHTMLStyleSheet::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const nsHTMLStyleSheet::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
{ {

View file

@ -47,6 +47,8 @@ public:
HasAttributeDependentStyle(AttributeRuleProcessorData* aData, HasAttributeDependentStyle(AttributeRuleProcessorData* aData,
mozilla::RestyleHintData& aRestyleHintDataResult) override; mozilla::RestyleHintData& aRestyleHintDataResult) override;
virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) override; virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) override;
virtual nsTArray<nsCOMPtr<nsIStyleRuleProcessor>>* GetChildRuleProcessors()
override;
virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)
const MOZ_MUST_OVERRIDE override; const MOZ_MUST_OVERRIDE override;
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)

View file

@ -126,6 +126,13 @@ public:
*/ */
virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) = 0; virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) = 0;
/**
* Returns an array of style rule processors if this origin supports
* cascade layers. The array will contain the rule processors for each
* layer in the order in which they should be applied.
*/
virtual nsTArray<nsCOMPtr<nsIStyleRuleProcessor>>* GetChildRuleProcessors() = 0;
/** /**
* Report the size of this style rule processor to about:memory. A * Report the size of this style rule processor to about:memory. A
* processor may return 0. * processor may return 0.