Merge remote-tracking branch 'origin/tracking' into custom

This commit is contained in:
roytam1 2025-07-25 20:53:55 +08:00
commit 7e0ddfef73
37 changed files with 5391 additions and 4167 deletions

View file

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

View file

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

View file

@ -107,7 +107,7 @@
#include "nsIScrollableFrame.h"
#include "mozilla/css/StyleRule.h" /* For nsCSSSelectorList */
#include "mozilla/css/Declaration.h"
#include "nsCSSRuleProcessor.h"
#include "nsCSSRuleUtils.h"
#include "nsRuleProcessorData.h"
#include "nsTextNode.h"
@ -3434,9 +3434,9 @@ Element::Closest(const nsAString& aSelector, ErrorResult& aResult)
matchingContext.AddScopeElement(this);
for (nsINode* node = this; node; node = node->GetParentNode()) {
if (node->IsElement() &&
nsCSSRuleProcessor::RestrictedSelectorListMatches(node->AsElement(),
matchingContext,
selectorList)) {
nsCSSRuleUtils::RestrictedSelectorListMatches(node->AsElement(),
matchingContext,
selectorList)) {
return node->AsElement();
}
}
@ -3460,9 +3460,9 @@ Element::Matches(const nsAString& aSelector, ErrorResult& aError)
TreeMatchContext::eNeverMatchVisited);
matchingContext.SetHasSpecifiedScope();
matchingContext.AddScopeElement(this);
return nsCSSRuleProcessor::RestrictedSelectorListMatches(this,
matchingContext,
selectorList);
return nsCSSRuleUtils::RestrictedSelectorListMatches(this,
matchingContext,
selectorList);
}
static const nsAttrValue::EnumTable kCORSAttributeTable[] = {

View file

@ -91,7 +91,7 @@
#include "mozilla/Preferences.h"
#include "prprf.h"
#include "xpcpublic.h"
#include "nsCSSRuleProcessor.h"
#include "nsCSSRuleUtils.h"
#include "nsCSSParser.h"
#include "HTMLLegendElement.h"
#include "nsWrapperCacheInlines.h"
@ -2912,9 +2912,9 @@ FindMatchingElementsWithId(const nsAString& aId, nsINode* aRoot,
// We have an element with the right id and it's a strict descendant
// of aRoot. Make sure it really matches the selector.
if (!aMatchInfo ||
nsCSSRuleProcessor::RestrictedSelectorListMatches(element,
aMatchInfo->mMatchContext,
aMatchInfo->mSelectorList)) {
nsCSSRuleUtils::RestrictedSelectorListMatches(element,
aMatchInfo->mMatchContext,
aMatchInfo->mSelectorList)) {
aList.AppendElement(element);
if (onlyFirstMatch) {
return;
@ -2965,9 +2965,9 @@ FindMatchingElements(nsINode* aRoot, nsCSSSelectorList* aSelectorList, T &aList,
cur;
cur = cur->GetNextNode(aRoot)) {
if (cur->IsElement() &&
nsCSSRuleProcessor::RestrictedSelectorListMatches(cur->AsElement(),
matchingContext,
aSelectorList)) {
nsCSSRuleUtils::RestrictedSelectorListMatches(cur->AsElement(),
matchingContext,
aSelectorList)) {
if (onlyFirstMatch) {
aList.AppendElement(cur->AsElement());
return;

View file

@ -47,7 +47,7 @@
#include "nsDisplayList.h"
#include "RestyleTrackerInlines.h"
#include "nsSMILAnimationController.h"
#include "nsCSSRuleProcessor.h"
#include "nsCSSRuleUtils.h"
#include "ChildIterator.h"
#include "Layers.h"
@ -2550,8 +2550,8 @@ ElementRestyler::SelectorMatchesForRestyle(Element* aElement)
return false;
}
for (nsCSSSelector* selector : mSelectorsForDescendants) {
if (nsCSSRuleProcessor::RestrictedSelectorMatches(aElement, selector,
mTreeMatchContext)) {
if (nsCSSRuleUtils::RestrictedSelectorMatches(aElement, selector,
mTreeMatchContext)) {
return true;
}
}

View file

@ -35,7 +35,7 @@
#include "nsViewManager.h"
#include "mozilla/RestyleManager.h"
#include "SurfaceCacheUtils.h"
#include "nsCSSRuleProcessor.h"
#include "nsCSSRuleUtils.h"
#include "nsRuleNode.h"
#include "gfxPlatform.h"
#include "nsCSSRules.h"
@ -1650,7 +1650,7 @@ nsPresContext::ThemeChangedInternal()
}
// This will force the system metrics to be generated the next time they're used
nsCSSRuleProcessor::FreeSystemMetrics();
nsCSSRuleUtils::FreeSystemMetrics();
// Changes to system metrics can change media queries on them, or
// :-moz-system-metric selectors (which requires eRestyle_Subtree).
@ -1691,7 +1691,7 @@ nsPresContext::SysColorChangedInternal()
}
// Invalidate cached '-moz-windows-accent-color-applies' media query:
nsCSSRuleProcessor::FreeSystemMetrics();
nsCSSRuleUtils::FreeSystemMetrics();
// Reset default background and foreground colors for the document since
// they may be using system colors

View file

@ -46,7 +46,7 @@
#include "nsTextFrame.h"
#include "nsCCUncollectableMarker.h"
#include "nsTextFragment.h"
#include "nsCSSRuleProcessor.h"
#include "nsCSSRuleUtils.h"
#include "nsCORSListenerProxy.h"
#include "nsHTMLDNSPrefetch.h"
#include "nsHtml5Atoms.h"
@ -242,7 +242,7 @@ nsLayoutStatics::Initialize()
}
nsCSSParser::Startup();
nsCSSRuleProcessor::Startup();
nsCSSRuleUtils::Startup();
#ifdef MOZ_XUL
rv = nsXULPopupManager::Init();
@ -330,7 +330,7 @@ nsLayoutStatics::Shutdown()
EventListenerManager::Shutdown();
IMEStateManager::Shutdown();
nsCSSParser::Shutdown();
nsCSSRuleProcessor::Shutdown();
nsCSSRuleUtils::Shutdown();
nsHTMLDNSPrefetch::Shutdown();
nsCSSRendering::Shutdown();
StaticPresData::Shutdown();

View file

@ -40,7 +40,7 @@
#include "nsRuleWalker.h"
#include "nsRuleProcessorData.h"
#include "nsCSSPseudoClasses.h"
#include "nsCSSRuleProcessor.h"
#include "nsCSSRuleUtils.h"
#include "mozilla/dom/CSSLexer.h"
#include "mozilla/dom/InspectorUtilsBinding.h"
#include "mozilla/dom/ToJSValue.h"
@ -467,9 +467,9 @@ inDOMUtils::SelectorMatchesElement(nsIDOMElement* aElement,
nsRuleWalker::eRelevantLinkUnvisited,
element->OwnerDoc(),
TreeMatchContext::eNeverMatchVisited);
*aMatches = nsCSSRuleProcessor::RestrictedSelectorListMatches(element,
matchingContext,
sel);
*aMatches = nsCSSRuleUtils::RestrictedSelectorListMatches(element,
matchingContext,
sel);
return NS_OK;
}
@ -1183,26 +1183,6 @@ inDOMUtils::GetUsedFontFaces(nsIDOMRange* aRange,
static EventStates
GetStatesForPseudoClass(const nsAString& aStatePseudo)
{
// An array of the states that are relevant for various pseudoclasses.
// XXXbz this duplicates code in nsCSSRuleProcessor
static const EventStates sPseudoClassStates[] = {
#define CSS_PSEUDO_CLASS(_name, _value, _flags, _pref) \
EventStates(),
#define CSS_STATE_PSEUDO_CLASS(_name, _value, _flags, _pref, _states) \
_states,
#include "nsCSSPseudoClassList.h"
#undef CSS_STATE_PSEUDO_CLASS
#undef CSS_PSEUDO_CLASS
// Add more entries for our fake values to make sure we can't
// index out of bounds into this array no matter what.
EventStates(),
EventStates()
};
static_assert(MOZ_ARRAY_LENGTH(sPseudoClassStates) ==
static_cast<size_t>(CSSPseudoClassType::MAX),
"Length of PseudoClassStates array is incorrect");
nsCOMPtr<nsIAtom> atom = NS_Atomize(aStatePseudo);
CSSPseudoClassType type = nsCSSPseudoClasses::
GetPseudoType(atom, CSSEnabledState::eIgnoreEnabledState);
@ -1215,7 +1195,7 @@ GetStatesForPseudoClass(const nsAString& aStatePseudo)
}
// Our array above is long enough that indexing into it with
// NotPseudo is ok.
return sPseudoClassStates[static_cast<CSSPseudoClassTypeBase>(type)];
return nsCSSPseudoClasses::sPseudoClassStates[static_cast<CSSPseudoClassTypeBase>(type)];
}
NS_IMETHODIMP

View file

@ -1594,7 +1594,7 @@ CSSStyleSheet::ClearRuleCascades()
RuleProcessorCache::RemoveSheet(this);
removedSheetFromRuleProcessorCache = true;
}
(*iter)->ClearRuleCascades();
(*iter)->ClearGroup();
}
}
if (mParent) {

View file

@ -0,0 +1,330 @@
/* -*- 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(
CascadeLayer* 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;
// The cascade layer owns the rule cascade, so we don't count it here.
// We do count the layer itself, though.
n += mLayer->SizeOfIncludingThis(aMallocSizeOf);
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 CascadeLayer;
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 styles, which are treated as belonging to an
* implicit layer.
*/
class CascadeLayerRuleProcessor : public nsIStyleRuleProcessor
{
public:
CascadeLayerRuleProcessor(CascadeLayer* 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();
CascadeLayer* mLayer;
RuleCascadeData* mCascade;
private:
nsRestyleHint HasStateDependentStyle(
ElementDependentRuleProcessorData* aData,
mozilla::dom::Element* aStatefulElement,
mozilla::CSSPseudoElementType aPseudoType,
mozilla::EventStates aStateMask);
};
#endif /* CascadeLayerRuleProcessor_h_ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,393 @@
/* -*- 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/. */
#ifndef RuleCascadeData_h___
#define RuleCascadeData_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 "mozilla/css/StyleRule.h"
#include "nsContentUtils.h"
#include "nsCSSRules.h"
#include "nsExpirationTracker.h"
#include "nsIMediaList.h"
#include "nsIStyleRuleProcessor.h"
#include "nsRuleWalker.h"
#include "nsTArray.h"
#include "nsRuleProcessorData.h"
using namespace mozilla;
using namespace mozilla::dom;
struct nsFontFaceRuleContainer;
struct PerWeightData;
/**
* A struct representing a given CSS rule and a particular selector
* from that rule's selector list.
*/
struct RuleSelectorPair
{
RuleSelectorPair(css::StyleRule* aRule, nsCSSSelector* aSelector)
: mRule(aRule)
, mSelector(aSelector)
{
}
// If this class ever grows a destructor, deal with
// PerWeightDataListItem appropriately.
css::StyleRule* mRule;
nsCSSSelector* mSelector; // which of |mRule|'s selectors
};
/**
* A struct representing a particular rule in an ordered list of rules
* (the ordering depending on the weight of mSelector and the order of
* our rules to start with).
*/
struct RuleValue : RuleSelectorPair
{
enum
{
eMaxAncestorHashes = 4
};
RuleValue(const RuleSelectorPair& aRuleSelectorPair,
int32_t aIndex,
bool aQuirksMode)
: RuleSelectorPair(aRuleSelectorPair)
, mIndex(aIndex)
{
CollectAncestorHashes(aQuirksMode);
}
int32_t mIndex; // High index means high weight/order.
uint32_t mAncestorSelectorHashes[eMaxAncestorHashes];
private:
void CollectAncestorHashes(bool aQuirksMode)
{
// Collect up our mAncestorSelectorHashes. It's not clear whether it's
// better to stop once we've found eMaxAncestorHashes of them or to keep
// going and preferentially collect information from selectors higher up the
// chain... Let's do the former for now.
size_t hashIndex = 0;
for (nsCSSSelector* sel = mSelector->mNext; sel; sel = sel->mNext) {
if (!NS_IS_ANCESTOR_OPERATOR(sel->mOperator)) {
// |sel| is going to select something that's not actually one of our
// ancestors, so don't add it to mAncestorSelectorHashes. But keep
// going, because it'll select a sibling of one of our ancestors, so its
// ancestors would be our ancestors too.
continue;
}
// Now sel is supposed to select one of our ancestors. Grab
// whatever info we can from it into mAncestorSelectorHashes.
// But in qurks mode, don't grab IDs and classes because those
// need to be matched case-insensitively.
if (!aQuirksMode) {
nsAtomList* ids = sel->mIDList;
while (ids) {
mAncestorSelectorHashes[hashIndex++] = ids->mAtom->hash();
if (hashIndex == eMaxAncestorHashes) {
return;
}
ids = ids->mNext;
}
nsAtomList* classes = sel->mClassList;
while (classes) {
mAncestorSelectorHashes[hashIndex++] = classes->mAtom->hash();
if (hashIndex == eMaxAncestorHashes) {
return;
}
classes = classes->mNext;
}
}
// Only put in the tag name if it's all-lowercase. Otherwise we run into
// trouble because we may test the wrong one of mLowercaseTag and
// mCasedTag against the filter.
if (sel->mLowercaseTag && sel->mCasedTag == sel->mLowercaseTag) {
mAncestorSelectorHashes[hashIndex++] = sel->mLowercaseTag->hash();
if (hashIndex == eMaxAncestorHashes) {
return;
}
}
}
while (hashIndex != eMaxAncestorHashes) {
mAncestorSelectorHashes[hashIndex++] = 0;
}
}
};
/**
* A struct that stores an nsCSSSelector pointer along side a pointer to
* the rightmost nsCSSSelector in the selector. For example, for
*
* .main p > span
*
* if mSelector points to the |p| nsCSSSelector, mRightmostSelector would
* point to the |span| nsCSSSelector.
*
* Both mSelector and mRightmostSelector are always top-level selectors,
* i.e. they aren't selectors within a :not() or :-moz-any().
*/
struct SelectorPair
{
SelectorPair(nsCSSSelector* aSelector, nsCSSSelector* aRightmostSelector)
: mSelector(aSelector)
, mRightmostSelector(aRightmostSelector)
{
MOZ_ASSERT(aSelector);
MOZ_ASSERT(mRightmostSelector);
}
SelectorPair(const SelectorPair& aOther) = default;
nsCSSSelector* const mSelector;
nsCSSSelector* const mRightmostSelector;
};
struct StateSelector
{
StateSelector(mozilla::EventStates aStates, nsCSSSelector* aSelector)
: mStates(aStates)
, mSelector(aSelector)
{
}
mozilla::EventStates mStates;
nsCSSSelector* mSelector;
};
class RuleHash
{
public:
explicit RuleHash(bool aQuirksMode);
~RuleHash();
void AppendRule(const RuleSelectorPair& aRuleInfo);
void EnumerateAllRules(Element* aElement,
ElementDependentRuleProcessorData* aData,
NodeMatchContext& aNodeMatchContext);
size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const;
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
static void AppendRuleToTagTable(PLDHashTable* aTable,
nsIAtom* aKey,
const RuleValue& aRuleInfo);
static const PLDHashTableOps TagTable_Ops;
static const PLDHashTableOps ClassTable_CSOps;
static const PLDHashTableOps ClassTable_CIOps;
static const PLDHashTableOps IdTable_CSOps;
static const PLDHashTableOps IdTable_CIOps;
static const PLDHashTableOps NameSpaceTable_Ops;
protected:
typedef nsTArray<RuleValue> RuleValueList;
void AppendRuleToTable(PLDHashTable* aTable,
const void* aKey,
const RuleSelectorPair& aRuleInfo);
void AppendUniversalRule(const RuleSelectorPair& aRuleInfo);
int32_t mRuleCount;
PLDHashTable mIdTable;
PLDHashTable mClassTable;
PLDHashTable mTagTable;
PLDHashTable mNameSpaceTable;
RuleValueList mUniversalRules;
struct EnumData
{
const RuleValue* mCurValue;
const RuleValue* mEnd;
};
EnumData* mEnumList;
int32_t mEnumListSize;
bool mQuirksMode;
inline EnumData ToEnumData(const RuleValueList& arr)
{
EnumData data = { arr.Elements(), arr.Elements() + arr.Length() };
return data;
}
#ifdef RULE_HASH_STATS
uint32_t mUniversalSelectors;
uint32_t mNameSpaceSelectors;
uint32_t mTagSelectors;
uint32_t mClassSelectors;
uint32_t mIdSelectors;
uint32_t mElementsMatched;
uint32_t mElementUniversalCalls;
uint32_t mElementNameSpaceCalls;
uint32_t mElementTagCalls;
uint32_t mElementClassCalls;
uint32_t mElementIdCalls;
#endif // RULE_HASH_STATS
};
struct AttributeEnumData
{
AttributeEnumData(AttributeRuleProcessorData* aData,
RestyleHintData& aRestyleHintData)
: data(aData)
, change(nsRestyleHint(0))
, hintData(aRestyleHintData)
{
}
AttributeRuleProcessorData* data;
nsRestyleHint change;
RestyleHintData& hintData;
};
struct RuleCascadeData
{
RuleCascadeData(bool aQuirksMode);
~RuleCascadeData();
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
RuleHash mRuleHash;
RuleHash* mPseudoElementRuleHashes[static_cast<CSSPseudoElementTypeBase>(
CSSPseudoElementType::Count)];
nsTArray<StateSelector> mStateSelectors;
EventStates mSelectorDocumentStates;
PLDHashTable mClassSelectors;
PLDHashTable mIdSelectors;
nsTArray<nsCSSSelector*> mPossiblyNegatedClassSelectors;
nsTArray<nsCSSSelector*> mPossiblyNegatedIDSelectors;
PLDHashTable mAttributeSelectors;
PLDHashTable mAnonBoxRules;
PLDHashTable mXULTreeRules;
nsTArray<nsFontFaceRuleContainer> mFontFaceRules;
nsTArray<nsCSSKeyframesRule*> mKeyframesRules;
nsTArray<nsCSSFontFeatureValuesRule*> mFontFeatureValuesRules;
nsTArray<nsCSSPageRule*> mPageRules;
nsTArray<nsCSSCounterStyleRule*> mCounterStyleRules;
nsDataHashtable<nsStringHashKey, nsCSSKeyframesRule*> mKeyframesRuleTable;
nsDataHashtable<nsStringHashKey, nsCSSCounterStyleRule*>
mCounterStyleRuleTable;
// Looks up or creates the appropriate list in |mAttributeSelectors|.
// Returns null only on allocation failure.
nsTArray<SelectorPair>* AttributeListFor(nsIAtom* aAttribute);
const bool mQuirksMode;
void RulesMatching(ElementRuleProcessorData* aData);
void RulesMatching(PseudoElementRuleProcessorData* aData);
void RulesMatching(AnonBoxRuleProcessorData* aData);
void RulesMatching(XULTreeRuleProcessorData* aData);
void HasStateDependentStyle(ElementDependentRuleProcessorData* aData,
Element* aStatefulElement,
CSSPseudoElementType aPseudoType,
EventStates aStateMask,
nsRestyleHint& aHint);
void HasAttributeDependentStyle(
AttributeRuleProcessorData* aData,
AttributeEnumData* aEnumData,
mozilla::RestyleHintData& aRestyleHintDataResult);
bool AddSelector(
// The part between combinators at the top level of the selector
nsCSSSelector* aSelectorInTopLevel,
// The part we should look through (might be in :not or :-moz-any())
nsCSSSelector* aSelectorPart,
// The right-most selector at the top level
nsCSSSelector* aRightmostSelector);
bool AddRule(RuleSelectorPair* aRuleInfo);
private:
static const PLDHashTableOps AtomSelector_CSOps;
static const PLDHashTableOps AtomSelector_CIOps;
};
struct CascadeLayer
{
CascadeLayer(nsPresContext* aPresContext,
#ifdef DEBUG
CascadeLayer* aParent,
#endif
nsTArray<css::DocumentRule*>& aDocumentRules,
nsDocumentRuleResultCacheKey& aDocumentKey,
SheetType aSheetType,
bool aMustGatherDocumentRules,
nsMediaQueryResultCacheKey& aCacheKey);
~CascadeLayer();
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
nsPresContext* mPresContext;
nsString mName;
bool mIsAnonymous;
#ifdef DEBUG
bool mIsStrong;
#endif
bool mRulesAdded;
RuleCascadeData* mData;
nsTArray<css::StyleRule*> mStyleRules;
nsTArray<css::DocumentRule*>& mDocumentRules;
nsDocumentRuleResultCacheKey& mDocumentCacheKey;
nsMediaQueryResultCacheKey& mCacheKey;
SheetType mSheetType;
bool mMustGatherDocumentRules;
#ifdef DEBUG
CascadeLayer* mParent;
#endif
nsTArray<CascadeLayer*> mPreLayers;
#ifdef DEBUG
nsTArray<CascadeLayer*> mPostLayers;
#endif
nsDataHashtable<nsStringHashKey, CascadeLayer*> mLayers;
CascadeLayer* CreateNamedChildLayer(const nsTArray<nsString>& aPath);
CascadeLayer* CreateAnonymousChildLayer();
typedef void (*nsLayerEnumFunc)(CascadeLayer* aLayer, void* aData);
void EnumerateAllLayers(nsLayerEnumFunc aFunc, void* aData);
void AddRules();
private:
struct WeightedRuleData
{
WeightedRuleData();
~WeightedRuleData();
UniquePtr<PerWeightData[]> Consume(nsTArray<css::StyleRule*>& aStyleRules);
PLArenaPool mArena;
// Hooray, a manual PLDHashTable since nsClassHashtable doesn't
// provide a getter that gives me a *reference* to the value.
PLDHashTable mRulesByWeight; // of PerWeightDataListItem linked lists
private:
static const PLDHashTableOps sRulesByWeightOps;
};
};
#endif /* RuleCascadeData_h___ */

View file

@ -0,0 +1,17 @@
/* -*- 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/. */
#include "RuleProcessorGroup.h"
size_t
RuleProcessorGroup::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
{
size_t n = aMallocSizeOf(this);
for (uint32_t i = 0; i < mItems.Length(); i++) {
n += mItems[i]->SizeOfIncludingThis(aMallocSizeOf);
}
n += mItems.ShallowSizeOfExcludingThis(aMallocSizeOf);
return n;
}

View file

@ -0,0 +1,26 @@
/* -*- 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/. */
#ifndef RuleProcessorGroup_h___
#define RuleProcessorGroup_h___
struct RuleProcessorGroup
{
RuleProcessorGroup(nsIAtom* aMedium)
: mCacheKey(aMedium)
, mNext(nullptr)
{
}
~RuleProcessorGroup() { mItems.Clear(); }
nsTArray<nsCOMPtr<nsIStyleRuleProcessor>> mItems;
nsMediaQueryResultCacheKey mCacheKey;
RuleProcessorGroup* mNext; // for a different medium
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
};
#endif /* RuleProcessorGroup_h___ */

View file

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

View file

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

View file

@ -22,6 +22,16 @@
#include "nsIStyleRule.h"
#include "nsICSSStyleRuleDOMWrapper.h"
// Right now, there are four operators:
// ' ', the descendant combinator, is greedy
// '~', the indirect adjacent sibling combinator, is greedy
// '+' and '>', the direct adjacent sibling and child combinators, are not
#define NS_IS_GREEDY_OPERATOR(ch) \
((ch) == char16_t(' ') || (ch) == char16_t('~'))
#define NS_IS_ANCESTOR_OPERATOR(ch) \
((ch) == char16_t(' ') || (ch) == char16_t('>'))
class nsIAtom;
struct nsCSSSelectorList;

View file

@ -24,6 +24,7 @@ TEST_DIRS += ['test']
EXPORTS += [
'!nsStyleStructList.h',
'AnimationCommon.h',
'CascadeLayerRuleProcessor.h',
'CounterStyleManager.h',
'nsAnimationManager.h',
'nsComputedDOMStylePropertyList.h',
@ -45,6 +46,7 @@ EXPORTS += [
'nsCSSPseudoElementList.h',
'nsCSSPseudoElements.h',
'nsCSSRuleProcessor.h',
'nsCSSRuleUtils.h',
'nsCSSScanner.h',
'nsCSSValue.h',
'nsDOMCSSAttrDeclaration.h',
@ -70,6 +72,8 @@ EXPORTS += [
'nsStyleStructInlines.h',
'nsStyleTransformMatrix.h',
'nsStyleUtil.h',
'RuleCascadeData.h',
'RuleProcessorGroup.h',
]
EXPORTS.mozilla += [
@ -119,6 +123,7 @@ EXPORTS.mozilla.css += [
UNIFIED_SOURCES += [
'AnimationCollection.cpp',
'AnimationCommon.cpp',
'CascadeLayerRuleProcessor.cpp',
'CounterStyleManager.cpp',
'CSS.cpp',
'CSSLexer.cpp',
@ -146,7 +151,9 @@ UNIFIED_SOURCES += [
'nsCSSProps.cpp',
'nsCSSPseudoClasses.cpp',
'nsCSSPseudoElements.cpp',
'nsCSSRuleProcessor.cpp',
'nsCSSRules.cpp',
'nsCSSRuleUtils.cpp',
'nsCSSScanner.cpp',
'nsCSSValue.cpp',
'nsDOMCSSAttrDeclaration.cpp',
@ -172,6 +179,7 @@ UNIFIED_SOURCES += [
'nsTransitionManager.cpp',
'RuleNodeCacheConditions.cpp',
'RuleProcessorCache.cpp',
'RuleProcessorGroup.cpp',
'StyleAnimationValue.cpp',
'StyleRule.cpp',
'StyleSheet.cpp',
@ -184,14 +192,14 @@ UNIFIED_SOURCES += [
# includes, via nsStyleCoord.h, <type_traits>, which ends up including
# <xutility>, which fails in much the way described in
# <https://bugzilla.mozilla.org/show_bug.cgi?id=1331102>.
# - nsCSSRuleProcessor.cpp needs to be built separately because it uses
# - RuleCascadeData.cpp needs to be built separately because it uses
# plarena.h.
# - nsLayoutStylesheetCache.cpp needs to be built separately because it uses
# nsExceptionHandler.h, which includes windows.h.
SOURCES += [
'BindingStyleRule.cpp',
'nsCSSRuleProcessor.cpp',
'nsLayoutStylesheetCache.cpp',
'RuleCascadeData.cpp',
]
include('/ipc/chromium/chromium-config.mozbuild')

View file

@ -5241,8 +5241,11 @@ CSSParserImpl::ParseSupportsConditionTermsAfterOperator(
bool
CSSParserImpl::ParseLayerRule(RuleAppendFunc aAppendFunc, void* aProcessData)
{
nsString layerName;
nsTArray<nsString>* nameList = new nsTArray<nsString>();
nsString name;
nsTArray<nsString> path;
nsTArray<nsString> nameList;
nsTArray<nsTArray<nsString>> pathList;
uint32_t linenum, colnum;
if (!GetNextTokenLocation(true, &linenum, &colnum)) {
@ -5258,8 +5261,8 @@ CSSParserImpl::ParseLayerRule(RuleAppendFunc aAppendFunc, void* aProcessData)
// followed by a "{", which indicates an anonymous layer.
bool isStatement = false;
if (tk->mType == eCSSToken_Ident) {
nsString* currentName = new nsString();
currentName->Assign(tk->mIdent);
name.Assign(tk->mIdent);
path.AppendElement(tk->mIdent);
bool parsing = true;
bool expectIdent = false;
@ -5272,49 +5275,40 @@ CSSParserImpl::ParseLayerRule(RuleAppendFunc aAppendFunc, void* aProcessData)
case eCSSToken_Symbol: {
if ('.' == tk->mSymbol) {
expectIdent = true;
if (!currentName->IsEmpty()) {
currentName->Append(tk->mSymbol);
if (!name.IsEmpty()) {
name.Append(tk->mSymbol);
continue;
}
parsing = false;
break;
} else if (',' == tk->mSymbol) {
} else if (',' == tk->mSymbol || ';' == tk->mSymbol || '{' == tk->mSymbol) {
if (expectIdent) {
parsing = false;
break;
}
nameList->AppendElement(*currentName);
currentName = new nsString();
nameList.AppendElement(name);
pathList.AppendElement(path);
if ('{' == tk->mSymbol) {
if (nameList.Length() > 1) {
return false;
}
parsing = false;
break;
} else if (';' == tk->mSymbol) {
isStatement = true;
parsing = false;
break;
}
name.Truncate();
path.Clear();
expectIdent = true;
continue;
} else if (';' == tk->mSymbol) {
if (expectIdent) {
parsing = false;
break;
}
nameList->AppendElement(*currentName);
currentName = new nsString();
isStatement = true;
parsing = false;
break;
} else if ('{' == tk->mSymbol) {
if (expectIdent) {
parsing = false;
break;
}
nameList->AppendElement(*currentName);
uint32_t nameListLength = nameList->Length();
if (nameListLength == 0 || nameListLength > 1) {
return false;
}
layerName.Assign(nameList->ElementAt(0));
parsing = false;
break;
}
}
case eCSSToken_Ident: {
expectIdent = false;
currentName->Append(tk->mIdent);
name.Append(tk->mIdent);
path.AppendElement(tk->mIdent);
break;
}
default: {
@ -5326,22 +5320,26 @@ CSSParserImpl::ParseLayerRule(RuleAppendFunc aAppendFunc, void* aProcessData)
if (expectIdent) {
UngetToken();
return false;
}
} else if (tk->mType == eCSSToken_Symbol && '{' != tk->mSymbol) {
UngetToken();
}
} else if (tk->mType == eCSSToken_Symbol) {
if ('{' != tk->mSymbol) {
UngetToken();
return false;
}
} else {
return false;
}
if (isStatement) {
RefPtr<CSSLayerStatementRule> rule =
new CSSLayerStatementRule(*nameList, linenum, colnum);
new CSSLayerStatementRule(nameList, pathList, linenum, colnum);
(*aAppendFunc)(rule, aProcessData);
return true;
}
UngetToken();
RefPtr<css::GroupRule> rule =
new CSSLayerBlockRule(layerName, linenum, colnum);
new CSSLayerBlockRule(name, path, linenum, colnum);
return ParseGroupRule(rule, aAppendFunc, aProcessData);
}

View file

@ -70,6 +70,40 @@ nsCSSPseudoClasses::sPseudoClassEnabled[] = {
#undef IS_ENABLED_BY_DEFAULT
};
// Arrays of the states that are relevant for various pseudoclasses.
/* static */ const mozilla::EventStates
nsCSSPseudoClasses::sPseudoClassStateDependences[] = {
#define CSS_PSEUDO_CLASS(_name, _value, _flags, _pref) EventStates(),
#define CSS_STATE_DEPENDENT_PSEUDO_CLASS( \
_name, _value, _flags, _pref, _states) \
_states,
#include "nsCSSPseudoClassList.h"
#undef CSS_STATE_DEPENDENT_PSEUDO_CLASS
#undef CSS_PSEUDO_CLASS
// Add more entries for our fake values to make sure we can't
// index out of bounds into this array no matter what.
EventStates(),
EventStates()
};
/* static */ const mozilla::EventStates
nsCSSPseudoClasses::sPseudoClassStates[] = {
#define CSS_PSEUDO_CLASS(_name, _value, _flags, _pref) EventStates(),
#define CSS_STATE_PSEUDO_CLASS(_name, _value, _flags, _pref, _states) _states,
#include "nsCSSPseudoClassList.h"
#undef CSS_STATE_PSEUDO_CLASS
#undef CSS_PSEUDO_CLASS
// Add more entries for our fake values to make sure we can't
// index out of bounds into this array no matter what.
EventStates(),
EventStates()
};
static_assert(MOZ_ARRAY_LENGTH(nsCSSPseudoClasses::sPseudoClassStates) ==
static_cast<size_t>(CSSPseudoClassType::MAX),
"CSSPseudoClassType::MAX is no longer equal to the length of "
"nsCSSPseudoClasses::sPseudoClassStates");
void nsCSSPseudoClasses::AddRefAtoms()
{
NS_RegisterStaticAtoms(CSSPseudoClasses_info);

View file

@ -87,6 +87,9 @@ public:
return false;
}
static const mozilla::EventStates sPseudoClassStateDependences[];
static const mozilla::EventStates sPseudoClassStates[];
private:
static const uint32_t kPseudoClassFlags[size_t(Type::Count)];
static bool sPseudoClassEnabled[size_t(Type::Count)];

File diff suppressed because it is too large Load diff

View file

@ -23,13 +23,10 @@
#include "nsRuleWalker.h"
#include "nsTArray.h"
struct CascadeEnumData;
struct CascadeLayer;
struct ElementDependentRuleProcessorData;
struct nsCSSSelector;
struct nsCSSSelectorList;
struct nsFontFaceRuleContainer;
struct RuleCascadeData;
struct TreeMatchContext;
struct RuleProcessorGroup;
class nsCSSKeyframesRule;
class nsCSSPageRule;
class nsCSSFontFeatureValuesRule;
@ -54,7 +51,7 @@ class DocumentRule;
* is told when the rule processor is going away (via DropRuleProcessor).
*/
class nsCSSRuleProcessor: public nsIStyleRuleProcessor {
class nsCSSRuleProcessor : public nsIStyleRuleProcessor {
public:
typedef nsTArray<RefPtr<mozilla::CSSStyleSheet>> sheet_array_type;
@ -77,60 +74,7 @@ public:
NS_DECL_CYCLE_COLLECTION_CLASS(nsCSSRuleProcessor)
public:
nsresult ClearRuleCascades();
static void Startup();
static void Shutdown();
static void FreeSystemMetrics();
static bool HasSystemMetric(nsIAtom* aMetric);
/*
* Returns true if the given aElement matches one of the
* selectors in aSelectorList. Note that this method will assume
* the given aElement is not a relevant link. aSelectorList must not
* include any pseudo-element selectors. aSelectorList is allowed
* to be null; in this case false will be returned.
*/
static bool RestrictedSelectorListMatches(mozilla::dom::Element* aElement,
TreeMatchContext& aTreeMatchContext,
nsCSSSelectorList* aSelectorList);
/*
* Helper to get the content state for a content node. This may be
* slightly adjusted from IntrinsicState().
*/
static mozilla::EventStates GetContentState(
mozilla::dom::Element* aElement,
const TreeMatchContext& aTreeMatchContext);
/*
* Helper to get the content state for :visited handling for an element
*/
static mozilla::EventStates GetContentStateForVisitedHandling(
mozilla::dom::Element* aElement,
const TreeMatchContext& aTreeMatchContext,
nsRuleWalker::VisitedHandlingType aVisitedHandling,
bool aIsRelevantLink);
/*
* Helper to test whether a node is a link
*/
static bool IsLink(const mozilla::dom::Element* aElement);
/**
* Returns true if the given aElement matches aSelector.
* Like nsCSSRuleProcessor.cpp's SelectorMatches (and unlike
* SelectorMatchesTree), this does not check an entire selector list
* separated by combinators.
*
* :visited and :link will match both visited and non-visited links,
* as if aTreeMatchContext->mVisitedHandling were eLinksVisitedOrUnvisited.
*
* aSelector is restricted to not containing pseudo-elements.
*/
static bool RestrictedSelectorMatches(mozilla::dom::Element* aElement,
nsCSSSelector* aSelector,
TreeMatchContext& aTreeMatchContext);
nsresult ClearGroup();
// nsIStyleRuleProcessor
virtual void RulesMatching(ElementRuleProcessorData* aData) override;
@ -155,6 +99,9 @@ public:
virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) override;
virtual nsTArray<nsCOMPtr<nsIStyleRuleProcessor>>* GetChildRuleProcessors()
override;
/**
* If this rule processor currently has a substantive media query
* result cache key, return a copy of it.
@ -207,33 +154,15 @@ public:
bool IsInRuleProcessorCache() const { return mInRuleProcessorCache; }
bool IsUsedByMultipleStyleSets() const { return mStyleSetRefCnt > 1; }
#ifdef XP_WIN
// Cached theme identifier for the moz-windows-theme media query.
static uint8_t GetWindowsThemeIdentifier();
static void SetWindowsThemeIdentifier(uint8_t aId) {
sWinThemeId = aId;
}
#endif
struct StateSelector {
StateSelector(mozilla::EventStates aStates, nsCSSSelector* aSelector)
: mStates(aStates),
mSelector(aSelector)
{}
mozilla::EventStates mStates;
nsCSSSelector* mSelector;
};
protected:
virtual ~nsCSSRuleProcessor();
private:
static bool CascadeSheet(mozilla::CSSStyleSheet* aSheet,
CascadeEnumData* aData);
CascadeLayer* aLayer);
RuleCascadeData* GetRuleCascade(nsPresContext* aPresContext);
void RefreshRuleCascade(nsPresContext* aPresContext);
RuleProcessorGroup* GetGroup(nsPresContext* aPresContext);
void RefreshGroup(nsPresContext* aPresContext);
nsRestyleHint HasStateDependentStyle(ElementDependentRuleProcessorData* aData,
mozilla::dom::Element* aStatefulElement,
@ -246,14 +175,14 @@ private:
sheet_array_type mSheets;
// active first, then cached (most recent first)
RuleCascadeData* mRuleCascades;
RuleProcessorGroup* mGroup;
// If we cleared our mRuleCascades or replaced a previous rule
// If we cleared our mGroup or replaced a previous rule
// processor, this is the media query result cache key that was used
// before we lost the old rule cascades.
// before we lost the old group.
mozilla::UniquePtr<nsMediaQueryResultCacheKey> mPreviousCacheKey;
// The last pres context for which GetRuleCascades was called.
// The last pres context for which GetGroup was called.
nsPresContext *mLastPresContext;
// The scope element for this rule processor's scoped style sheets.
@ -272,9 +201,9 @@ private:
const bool mIsShared;
// Whether we need to build up mDocumentCacheKey and mDocumentRules as
// we build a RuleCascadeData. Is true only for shared rule processors
// and only before we build the first RuleCascadeData. See comment in
// RefreshRuleCascade for why.
// we build RuleProcessorGroup. Is true only for shared rule processors
// and only before we build the first RuleProcessorGroup. See comment in
// RefreshGroup for why.
bool mMustGatherDocumentRules;
bool mInRuleProcessorCache;
@ -282,10 +211,6 @@ private:
#ifdef DEBUG
bool mDocumentRulesAndCacheKeyValid;
#endif
#ifdef XP_WIN
static uint8_t sWinThemeId;
#endif
};
#endif /* nsCSSRuleProcessor_h_ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,137 @@
/* -*- 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/. */
#ifndef nsCSSRuleUtils_h___
#define nsCSSRuleUtils_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 "nsRuleProcessorData.h"
#include "nsTArray.h"
#include "StyleRule.h"
struct nsCSSRuleUtils
{
static void Startup();
static void Shutdown();
static void FreeSystemMetrics();
static bool HasSystemMetric(nsIAtom* aMetric);
#ifdef XP_WIN
// Cached theme identifier for the moz-windows-theme media query.
static uint8_t GetWindowsThemeIdentifier();
static void SetWindowsThemeIdentifier(uint8_t aId) { sWinThemeId = aId; }
#endif
static bool StateSelectorMatches(Element* aElement,
nsCSSSelector* aSelector,
NodeMatchContext& aNodeMatchContext,
TreeMatchContext& aTreeMatchContext,
SelectorMatchesFlags aSelectorFlags,
bool* const aDependence,
mozilla::EventStates aStatesToCheck);
static bool StateSelectorMatches(Element* aElement,
nsCSSSelector* aSelector,
NodeMatchContext& aNodeMatchContext,
TreeMatchContext& aTreeMatchContext,
SelectorMatchesFlags aSelectorFlags);
static bool SelectorMatches(Element* aElement,
nsCSSSelector* aSelector,
NodeMatchContext& aNodeMatchContext,
TreeMatchContext& aTreeMatchContext,
SelectorMatchesFlags aSelectorFlags,
bool* const aDependence = nullptr);
static bool SelectorMatchesTree(Element* aPrevElement,
nsCSSSelector* aSelector,
TreeMatchContext& aTreeMatchContext,
SelectorMatchesTreeFlags aFlags);
static bool SelectorListMatches(Element* aElement,
nsCSSSelectorList* aList,
NodeMatchContext& aNodeMatchContext,
TreeMatchContext& aTreeMatchContext,
SelectorMatchesFlags aSelectorFlags,
bool aIsForgiving = false,
bool aPreventComplexSelectors = false);
static bool SelectorListMatches(Element* aElement,
nsPseudoClassList* aList,
NodeMatchContext& aNodeMatchContext,
TreeMatchContext& aTreeMatchContext,
bool aIsForgiving = false,
bool aPreventComplexSelectors = false);
#ifdef DEBUG
static bool HasPseudoClassSelectorArgsWithCombinators(
nsCSSSelector* aSelector);
#endif
/**
* Returns true if the given aElement matches aSelector.
* Like nsCSSRuleUtil.cpp's SelectorMatches (and unlike
* SelectorMatchesTree), this does not check an entire selector list
* separated by combinators.
*
* :visited and :link will match both visited and non-visited links,
* as if aTreeMatchContext->mVisitedHandling were eLinksVisitedOrUnvisited.
*
* aSelector is restricted to not containing pseudo-elements.
*/
static bool RestrictedSelectorMatches(mozilla::dom::Element* aElement,
nsCSSSelector* aSelector,
TreeMatchContext& aTreeMatchContext);
/**
* Returns true if the given aElement matches one of the
* selectors in aSelectorList. Note that this method will assume
* the given aElement is not a relevant link. aSelectorList must not
* include any pseudo-element selectors. aSelectorList is allowed
* to be null; in this case false will be returned.
*/
static bool RestrictedSelectorListMatches(mozilla::dom::Element* aElement,
TreeMatchContext& aTreeMatchContext,
nsCSSSelectorList* aSelectorList);
static bool CanMatchFeaturelessElement(nsCSSSelector* aSelector);
/**
* Helper to get the content state for a content node. This may be
* slightly adjusted from IntrinsicState().
*/
static mozilla::EventStates GetContentState(
mozilla::dom::Element* aElement,
const TreeMatchContext& aTreeMatchContext);
/**
* Helper to get the content state for :visited handling for an element
*/
static mozilla::EventStates GetContentStateForVisitedHandling(
mozilla::dom::Element* aElement,
const TreeMatchContext& aTreeMatchContext,
nsRuleWalker::VisitedHandlingType aVisitedHandling,
bool aIsRelevantLink);
/*
* Helper to test whether a node is a link
*/
static bool IsLink(const mozilla::dom::Element* aElement);
#ifdef XP_WIN
static uint8_t sWinThemeId;
#endif
};
#endif /* nsCSSRuleUtils_h___ */

View file

@ -3372,15 +3372,18 @@ namespace mozilla {
CSSLayerStatementRule::CSSLayerStatementRule(
const nsTArray<nsString>& aNameList,
const nsTArray<nsTArray<nsString>>& aPathList,
uint32_t aLineNumber, uint32_t aColumnNumber)
: Rule(aLineNumber, aColumnNumber)
, mNameList(aNameList)
, mPathList(aPathList)
{
}
CSSLayerStatementRule::CSSLayerStatementRule(const CSSLayerStatementRule& aCopy)
: Rule(aCopy)
, mNameList(aCopy.mNameList)
, mPathList(aCopy.mPathList)
{
}
@ -3407,6 +3410,7 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(CSSLayerStatementRule)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CSSLayerStatementRule)
tmp->mNameList.Clear();
tmp->mPathList.Clear();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(CSSLayerStatementRule, mozilla::css::Rule)
@ -3458,10 +3462,28 @@ CSSLayerStatementRule::GetNameList(nsTArray<nsString>& aResult)
aResult = mNameList;
}
void
CSSLayerStatementRule::GetPathList(nsTArray<nsTArray<nsString>>& aResult)
{
aResult = mPathList;
}
/* virtual */ size_t
CSSLayerStatementRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
{
return aMallocSizeOf(this);
size_t n = aMallocSizeOf(this);
n += mNameList.ShallowSizeOfExcludingThis(aMallocSizeOf);
for (const nsString& s : mNameList) {
n += s.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
}
n += mPathList.ShallowSizeOfExcludingThis(aMallocSizeOf);
for (const nsTArray<nsString>& inner : mPathList) {
n += inner.ShallowSizeOfExcludingThis(aMallocSizeOf);
for (const nsString& str : inner) {
n += str.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
}
}
return n;
}
/* virtual */ JSObject*
@ -3477,9 +3499,11 @@ CSSLayerStatementRule::WrapObject(JSContext* aCx,
//
CSSLayerBlockRule::CSSLayerBlockRule(const nsString& aName,
const nsTArray<nsString>& aPath,
uint32_t aLineNumber, uint32_t aColumnNumber)
: css::GroupRule(aLineNumber, aColumnNumber)
, mName(aName)
, mPath(aPath)
{
}
@ -3490,6 +3514,7 @@ CSSLayerBlockRule::~CSSLayerBlockRule()
CSSLayerBlockRule::CSSLayerBlockRule(const CSSLayerBlockRule& aCopy)
: css::GroupRule(aCopy)
, mName(aCopy.mName)
, mPath(aCopy.mPath)
{
}
@ -3522,15 +3547,32 @@ CSSLayerBlockRule::UseForPresentation(nsPresContext* aPresContext,
return true;
}
NS_IMPL_ADDREF_INHERITED(CSSLayerBlockRule, css::GroupRule)
NS_IMPL_RELEASE_INHERITED(CSSLayerBlockRule, css::GroupRule)
void
CSSLayerBlockRule::GetPath(nsTArray<nsString>& aResult)
{
aResult = mPath;
}
NS_IMPL_ADDREF_INHERITED(CSSLayerBlockRule, GroupRule)
NS_IMPL_RELEASE_INHERITED(CSSLayerBlockRule, GroupRule)
// QueryInterface implementation for CSSLayerBlockRule
NS_INTERFACE_MAP_BEGIN(CSSLayerBlockRule)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CSSLayerBlockRule)
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSGroupingRule)
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSLayerBlockRule)
NS_INTERFACE_MAP_END_INHERITING(GroupRule)
NS_IMPL_CYCLE_COLLECTION_CLASS(CSSLayerBlockRule)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(CSSLayerBlockRule,
GroupRule)
tmp->mPath.Clear();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(CSSLayerBlockRule,
GroupRule)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
uint16_t
CSSLayerBlockRule::Type() const
{
@ -3566,9 +3608,9 @@ CSSLayerBlockRule::DeleteRule(uint32_t aIndex)
// nsIDOMCSSLayerBlockRule methods
NS_IMETHODIMP
CSSLayerBlockRule::GetName(nsAString& aConditionText)
CSSLayerBlockRule::GetName(nsAString& aLayerName)
{
aConditionText.Assign(mName);
aLayerName.Assign(mName);
return NS_OK;
}
@ -3578,6 +3620,10 @@ CSSLayerBlockRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
size_t n = aMallocSizeOf(this);
n += css::GroupRule::SizeOfExcludingThis(aMallocSizeOf);
n += mName.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
n += mPath.ShallowSizeOfExcludingThis(aMallocSizeOf);
for (const nsString& s : mPath) {
n += s.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
}
return n;
}

View file

@ -746,6 +746,7 @@ class CSSLayerStatementRule final : public css::Rule,
{
public:
CSSLayerStatementRule(const nsTArray<nsString>& aNameList,
const nsTArray<nsTArray<nsString>>& aPathList,
uint32_t aLineNumber, uint32_t aColumnNumber);
CSSLayerStatementRule(const CSSLayerStatementRule& aCopy);
@ -768,6 +769,7 @@ public:
uint16_t Type() const override;
void GetCssTextImpl(nsAString& aCssText) const override;
void GetNameList(nsTArray<nsString>& aResult);
void GetPathList(nsTArray<nsTArray<nsString>>& aResult);
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
@ -777,6 +779,7 @@ protected:
virtual ~CSSLayerStatementRule();
nsTArray<nsString> mNameList;
nsTArray<nsTArray<nsString>> mPathList;
};
class CSSLayerBlockRule final : public css::GroupRule,
@ -784,6 +787,7 @@ class CSSLayerBlockRule final : public css::GroupRule,
{
public:
CSSLayerBlockRule(const nsString& aName,
const nsTArray<nsString>& aPath,
uint32_t aLineNumber, uint32_t aColumnNumber);
CSSLayerBlockRule(const CSSLayerBlockRule& aCopy);
@ -796,7 +800,9 @@ public:
virtual already_AddRefed<mozilla::css::Rule> Clone() const override;
virtual bool UseForPresentation(nsPresContext* aPresContext,
nsMediaQueryResultCacheKey& aKey) override;
void GetPath(nsTArray<nsString>& aResult);
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(CSSLayerBlockRule, GroupRule)
NS_DECL_ISUPPORTS_INHERITED
// nsIDOMCSSGroupingRule interface
@ -818,6 +824,7 @@ protected:
virtual ~CSSLayerBlockRule();
nsString mName;
nsTArray<nsString> mPath;
};
} // namespace mozilla

View file

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

View file

@ -47,6 +47,8 @@ public:
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 aMallocSizeOf)
const MOZ_MUST_OVERRIDE override;
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)

View file

@ -29,7 +29,7 @@
#include "nsRuleData.h"
#include "nsError.h"
#include "nsRuleProcessorData.h"
#include "nsCSSRuleProcessor.h"
#include "nsCSSRuleUtils.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/dom/Element.h"
#include "nsHashKeys.h"
@ -310,13 +310,13 @@ nsHTMLStyleSheet::RulesMatching(ElementRuleProcessorData* aData)
if (aData->mElement->IsHTMLElement(nsGkAtoms::a)) {
if (mLinkRule || mVisitedRule || mActiveRule) {
EventStates state =
nsCSSRuleProcessor::GetContentStateForVisitedHandling(
nsCSSRuleUtils::GetContentStateForVisitedHandling(
aData->mElement,
aData->mTreeMatchContext,
aData->mTreeMatchContext.VisitedHandling(),
// If the node being matched is a link,
// it's the relevant link.
nsCSSRuleProcessor::IsLink(aData->mElement));
nsCSSRuleUtils::IsLink(aData->mElement));
if (mLinkRule && state.HasState(NS_EVENT_STATE_UNVISITED)) {
ruleWalker->Forward(mLinkRule);
aData->mTreeMatchContext.SetHaveRelevantLink();
@ -327,7 +327,7 @@ nsHTMLStyleSheet::RulesMatching(ElementRuleProcessorData* aData)
}
// No need to add to the active rule if it's not a link
if (mActiveRule && nsCSSRuleProcessor::IsLink(aData->mElement) &&
if (mActiveRule && nsCSSRuleUtils::IsLink(aData->mElement) &&
state.HasState(NS_EVENT_STATE_ACTIVE)) {
ruleWalker->Forward(mActiveRule);
}
@ -372,7 +372,7 @@ nsHTMLStyleSheet::RulesMatching(ElementRuleProcessorData* aData)
nsHTMLStyleSheet::HasStateDependentStyle(StateRuleProcessorData* aData)
{
if (aData->mElement->IsHTMLElement(nsGkAtoms::a) &&
nsCSSRuleProcessor::IsLink(aData->mElement) &&
nsCSSRuleUtils::IsLink(aData->mElement) &&
((mActiveRule && aData->mStateMask.HasState(NS_EVENT_STATE_ACTIVE)) ||
(mLinkRule && aData->mStateMask.HasState(NS_EVENT_STATE_VISITED)) ||
(mVisitedRule && aData->mStateMask.HasState(NS_EVENT_STATE_VISITED)))) {
@ -439,6 +439,12 @@ nsHTMLStyleSheet::MediumFeaturesChanged(nsPresContext* aPresContext)
return false;
}
/* virtual */ nsTArray<nsCOMPtr<nsIStyleRuleProcessor>>*
nsHTMLStyleSheet::GetChildRuleProcessors()
{
return nullptr;
}
/* virtual */ size_t
nsHTMLStyleSheet::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
{

View file

@ -47,6 +47,8 @@ public:
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 aMallocSizeOf)
const MOZ_MUST_OVERRIDE override;
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)

View file

@ -62,7 +62,7 @@ struct nsMediaExpression {
*
* This object may not be used after any media rules in any of the
* sheets it was given to have been modified. However, this is
* generally not a problem since ClearRuleCascades is called on the
* generally not a problem since ClearGroup is called on the
* sheet whenever this happens, and these objects are stored inside the
* rule cascades. (FIXME: We're not actually doing this all the time.)
*

View file

@ -126,6 +126,13 @@ public:
*/
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
* processor may return 0.

View file

@ -14,7 +14,7 @@
#ifdef XP_WIN
#include "mozilla/LookAndFeel.h"
#endif
#include "nsCSSRuleProcessor.h"
#include "nsCSSRuleUtils.h"
#include "nsDeviceContext.h"
#include "nsIBaseWindow.h"
#include "nsIDocument.h"
@ -404,7 +404,7 @@ GetSystemMetric(nsPresContext* aPresContext, const nsMediaFeature* aFeature,
MOZ_ASSERT(aFeature->mValueType == nsMediaFeature::eBoolInteger,
"unexpected type");
nsIAtom *metricAtom = *aFeature->mData.mMetric;
bool hasMetric = nsCSSRuleProcessor::HasSystemMetric(metricAtom);
bool hasMetric = nsCSSRuleUtils::HasSystemMetric(metricAtom);
aResult.SetIntValue(hasMetric ? 1 : 0, eCSSUnit_Integer);
return NS_OK;
}
@ -420,7 +420,7 @@ GetWindowsTheme(nsPresContext* aPresContext, const nsMediaFeature* aFeature,
#ifdef XP_WIN
uint8_t windowsThemeId =
nsCSSRuleProcessor::GetWindowsThemeIdentifier();
nsCSSRuleUtils::GetWindowsThemeIdentifier();
// Classic mode should fail to match.
if (windowsThemeId == LookAndFeel::eWindowsTheme_Classic)

View file

@ -483,6 +483,58 @@ struct MOZ_STACK_CLASS RuleProcessorData {
mozilla::dom::Element* mScope;
};
/**
* A |NodeMatchContext| has data about matching a selector (without
* combinators) against a single node. It contains only input to the
* matching.
*
* Unlike |RuleProcessorData|, which is similar, a |NodeMatchContext|
* can vary depending on the selector matching process. In other words,
* there might be multiple NodeMatchContexts corresponding to a single
* node, but only one possible RuleProcessorData.
*/
struct NodeMatchContext
{
// In order to implement nsCSSRuleProcessor::HasStateDependentStyle,
// we need to be able to see if a node might match an
// event-state-dependent selector for any value of that event state.
// So mStateMask contains the states that should NOT be tested.
//
// NOTE: For |mStateMask| to work correctly, it's important that any
// change that changes multiple state bits include all those state
// bits in the notification. Otherwise, if multiple states change but
// we do separate notifications then we might determine the style is
// not state-dependent when it really is (e.g., determining that a
// :hover:active rule no longer matches when both states are unset).
const mozilla::EventStates mStateMask;
// Is this link the unique link whose visitedness can affect the style
// of the node being matched? (That link is the nearest link to the
// node being matched that is itself or an ancestor.)
//
// Always false when TreeMatchContext::mForStyling is false. (We
// could figure it out for RestrictedSelectorListMatches, but we're
// starting from the middle of the selector list when doing
// Has{Attribute,State}DependentStyle, so we can't tell. So when
// mForStyling is false, we have to assume we don't know.)
const bool mIsRelevantLink;
// If the node should be considered featureless (as specified in
// selectors 4), then mIsFeature should be set to true to prevent
// matching unless the selector is a special pseudo class or pseudo
// element that matches featureless elements.
const bool mIsFeatureless;
NodeMatchContext(mozilla::EventStates aStateMask,
bool aIsRelevantLink,
bool aIsFeatureless = false)
: mStateMask(aStateMask)
, mIsRelevantLink(aIsRelevantLink)
, mIsFeatureless(aIsFeatureless)
{
}
};
struct MOZ_STACK_CLASS ElementDependentRuleProcessorData :
public RuleProcessorData {
ElementDependentRuleProcessorData(nsPresContext* aPresContext,
@ -649,4 +701,48 @@ struct MOZ_STACK_CLASS AttributeRuleProcessorData :
bool mAttrHasChanged; // Whether the attribute has already changed.
};
/**
* Additional information about a selector (without combinators) that is
* being matched.
*/
enum class SelectorMatchesFlags : uint8_t
{
NONE = 0,
// The selector's flags are unknown. This happens when you don't know
// if you're starting from the top of a selector. Only used in cases
// where it's acceptable for matching to return a false positive.
// (It's not OK to return a false negative.)
UNKNOWN = 1 << 0,
// The selector is part of a compound selector which has been split in
// half, where the other half is a pseudo-element. The current
// selector is not a pseudo-element itself.
HAS_PSEUDO_ELEMENT = 1 << 1,
// The selector is part of an argument to a functional pseudo-class or
// pseudo-element.
IS_PSEUDO_CLASS_ARGUMENT = 1 << 2,
// The selector should be blocked from matching because it is called
// from outside the shadow tree.
IS_OUTSIDE_SHADOW_TREE = 1 << 3
};
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(SelectorMatchesFlags)
/**
* Flags for SelectorMatchesTree.
*/
enum SelectorMatchesTreeFlags
{
// Whether we still have not found the closest ancestor link element and
// thus have to check the current element for it.
eLookForRelevantLink = 0x1,
// Whether SelectorMatchesTree should check for, and return true upon
// finding, an ancestor element that has an eRestyle_SomeDescendants
// restyle hint pending.
eMatchOnConditionalRestyleAncestor = 0x2,
};
#endif /* !defined(nsRuleProcessorData_h_) */

View file

@ -1086,6 +1086,43 @@ nsStyleSet::AssertNoCSSRules(nsRuleNode* aCurrLevelNode,
}
#endif
static MOZ_ALWAYS_INLINE void
FileRulesFromAllChildProcessors(
nsCOMPtr<nsIStyleRuleProcessor> aParentProcessor,
nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
RuleProcessorData* aData,
nsRuleWalker* aRuleWalker,
mozilla::SheetType aLevel,
nsRuleNode*& aLastRN,
nsTArray<nsRuleNode*>& aLastRNs,
nsTArray<bool>& aHaveImportantOriginRules,
bool& aHaveAnyImportantOriginRules)
{
if (!aParentProcessor) {
return;
}
nsTArray<nsCOMPtr<nsIStyleRuleProcessor>>* processors =
aParentProcessor->GetChildRuleProcessors();
if (!processors) {
(*aCollectorFunc)(aParentProcessor, aData);
return;
}
for (nsCOMPtr<nsIStyleRuleProcessor> processor : *processors) {
aRuleWalker->SetLevel(aLevel, false, true);
(*aCollectorFunc)(processor, aData);
aLastRN = aRuleWalker->CurrentNode();
aLastRNs.AppendElement(aLastRN);
bool haveImportantRules = !aRuleWalker->GetCheckForImportantRules();
aHaveImportantOriginRules.AppendElement(haveImportantRules);
aHaveAnyImportantOriginRules =
aHaveAnyImportantOriginRules || haveImportantRules;
}
}
// Enumerate the rules in a way that cares about the order of the rules.
void
nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
@ -1097,6 +1134,9 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
NS_ASSERTION(mBatching == 0, "rule processors out of date");
bool skipUserStyles =
aElement && aElement->IsInNativeAnonymousSubtree();
// Cascading order:
// [least important]
// - UA normal rules = Agent normal
@ -1117,19 +1157,41 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
// this will be either the root or one of the restriction rules.
nsRuleNode* lastRestrictionRN = aRuleWalker->CurrentNode();
aRuleWalker->SetLevel(SheetType::Agent, false, true);
if (mRuleProcessors[SheetType::Agent])
(*aCollectorFunc)(mRuleProcessors[SheetType::Agent], aData);
nsRuleNode* lastAgentRN = aRuleWalker->CurrentNode();
bool haveImportantUARules = !aRuleWalker->GetCheckForImportantRules();
nsRuleNode* lastAgentRN = nullptr;
nsTArray<nsRuleNode*> lastAgentRNs;
nsTArray<bool> haveImportantAgentRules;
bool haveAnyImportantAgentRules = false;
FileRulesFromAllChildProcessors(mRuleProcessors[SheetType::Agent],
aCollectorFunc,
aData,
aRuleWalker,
SheetType::Agent,
lastAgentRN,
lastAgentRNs,
haveImportantAgentRules,
haveAnyImportantAgentRules);
if (!lastAgentRN) {
lastAgentRN = aRuleWalker->CurrentNode();
}
aRuleWalker->SetLevel(SheetType::User, false, true);
bool skipUserStyles =
aElement && aElement->IsInNativeAnonymousSubtree();
if (!skipUserStyles && mRuleProcessors[SheetType::User]) // NOTE: different
(*aCollectorFunc)(mRuleProcessors[SheetType::User], aData);
nsRuleNode* lastUserRN = aRuleWalker->CurrentNode();
bool haveImportantUserRules = !aRuleWalker->GetCheckForImportantRules();
nsRuleNode* lastUserRN = nullptr;
nsTArray<nsRuleNode*> lastUserRNs;
nsTArray<bool> haveImportantUserRules;
bool haveAnyImportantUserRules = false;
if (!skipUserStyles) { // NOTE: different
FileRulesFromAllChildProcessors(mRuleProcessors[SheetType::User],
aCollectorFunc,
aData,
aRuleWalker,
SheetType::User,
lastUserRN,
lastUserRNs,
haveImportantUserRules,
haveAnyImportantUserRules);
}
if (!lastUserRN) {
lastUserRN = aRuleWalker->CurrentNode();
}
aRuleWalker->SetLevel(SheetType::PresHint, false, false);
if (mRuleProcessors[SheetType::PresHint])
@ -1148,16 +1210,35 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
static_cast<ElementDependentRuleProcessorData*>(aData),
&cutOffInheritance);
}
if (!skipUserStyles && !cutOffInheritance && // NOTE: different
mRuleProcessors[SheetType::Doc])
(*aCollectorFunc)(mRuleProcessors[SheetType::Doc], aData);
nsRuleNode* lastDocRN = aRuleWalker->CurrentNode();
bool haveImportantDocRules = !aRuleWalker->GetCheckForImportantRules();
bool haveImportantNACRules = !aRuleWalker->GetCheckForImportantRules();
nsRuleNode* lastDocRN = nullptr;
nsTArray<nsRuleNode*> lastDocRNs;
nsTArray<bool> haveImportantDocRules;
bool haveAnyImportantDocRules = haveImportantNACRules;
if (!skipUserStyles && !cutOffInheritance) { // NOTE: different
FileRulesFromAllChildProcessors(mRuleProcessors[SheetType::Doc],
aCollectorFunc,
aData,
aRuleWalker,
SheetType::Doc,
lastDocRN,
lastDocRNs,
haveImportantDocRules,
haveAnyImportantDocRules);
}
if (!lastDocRN) {
lastDocRN = aRuleWalker->CurrentNode();
}
nsTArray<nsRuleNode*> lastScopedRNs;
nsTArray<bool> haveImportantScopedRules;
bool haveAnyImportantScopedRules = false;
if (!skipUserStyles && !cutOffInheritance &&
aElement && aElement->IsElementInStyleScope()) {
// XXX: Scoped style sheets will add important rules from cascade
// layers in reverse order. Behavior for layers inside this isn't
// specced and isn't worth the additional complexity.
lastScopedRNs.SetLength(mScopedDocSheetRuleProcessors.Length());
haveImportantScopedRules.SetLength(mScopedDocSheetRuleProcessors.Length());
for (uint32_t i = 0; i < mScopedDocSheetRuleProcessors.Length(); i++) {
@ -1173,6 +1254,7 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
aData->mScope = nullptr;
}
nsRuleNode* lastScopedRN = aRuleWalker->CurrentNode();
aRuleWalker->SetLevel(SheetType::StyleAttr, false, true);
if (mRuleProcessors[SheetType::StyleAttr])
(*aCollectorFunc)(mRuleProcessors[SheetType::StyleAttr], aData);
@ -1210,9 +1292,21 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
}
#endif
if (haveImportantDocRules) {
aRuleWalker->SetLevel(SheetType::Doc, true, false);
AddImportantRules(lastDocRN, lastSVGAttrAnimationRN, aRuleWalker); // doc
if (haveAnyImportantDocRules) {
for (uint32_t i = lastDocRNs.Length(); i-- != 0; ) {
aRuleWalker->SetLevel(SheetType::Doc, true, false);
nsRuleNode* startRN = lastDocRNs[i];
nsRuleNode* endRN = i == 0 ? lastSVGAttrAnimationRN : lastDocRNs[i - 1];
bool isNearestToNACWithImportantRules = i == 0 && haveImportantNACRules;
if (haveImportantDocRules[i] || isNearestToNACWithImportantRules) {
AddImportantRules(startRN, endRN, aRuleWalker); // doc
}
#ifdef DEBUG
else {
AssertNoImportantRules(startRN, endRN);
}
#endif
}
}
#ifdef DEBUG
else {
@ -1244,9 +1338,20 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
AssertNoCSSRules(lastSVGAttrAnimationRN, lastUserRN);
#endif
if (haveImportantUserRules) {
aRuleWalker->SetLevel(SheetType::User, true, false);
AddImportantRules(lastUserRN, lastAgentRN, aRuleWalker); //user
if (haveAnyImportantUserRules) {
for (uint32_t i = lastUserRNs.Length(); i-- != 0;) {
aRuleWalker->SetLevel(SheetType::User, true, false);
nsRuleNode* startRN = lastUserRNs[i];
nsRuleNode* endRN = i == 0 ? lastAgentRN : lastUserRNs[i - 1];
if (haveImportantUserRules[i]) {
AddImportantRules(startRN, endRN, aRuleWalker); // user
}
#ifdef DEBUG
else {
AssertNoImportantRules(startRN, endRN);
}
#endif
}
}
#ifdef DEBUG
else {
@ -1254,9 +1359,20 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
}
#endif
if (haveImportantUARules) {
aRuleWalker->SetLevel(SheetType::Agent, true, false);
AddImportantRules(lastAgentRN, lastRestrictionRN, aRuleWalker); //agent
if (haveAnyImportantAgentRules) {
for (uint32_t i = lastAgentRNs.Length(); i-- != 0;) {
aRuleWalker->SetLevel(SheetType::Agent, true, false);
nsRuleNode* startRN = lastAgentRNs[i];
nsRuleNode* endRN = i == 0 ? lastRestrictionRN : lastAgentRNs[i - 1];
if (haveImportantAgentRules[i]) {
AddImportantRules(startRN, endRN, aRuleWalker); // agent
}
#ifdef DEBUG
else {
AssertNoImportantRules(startRN, endRN);
}
#endif
}
}
#ifdef DEBUG
else {
@ -1373,10 +1489,10 @@ nsStyleSet::ResolveStyleFor(Element* aElement,
}
uint32_t flags = eDoAnimation;
if (nsCSSRuleProcessor::IsLink(aElement)) {
if (nsCSSRuleUtils::IsLink(aElement)) {
flags |= eIsLink;
}
if (nsCSSRuleProcessor::GetContentState(aElement, aTreeMatchContext).
if (nsCSSRuleUtils::GetContentState(aElement, aTreeMatchContext).
HasState(NS_EVENT_STATE_VISITED)) {
flags |= eIsVisitedLink;
}