mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-01 21:07:30 +09:00
Issue #2828 - Part 3: Refactor selector matching and rule cascade data into separate files/classes
This commit is contained in:
parent
7b51aa7ca1
commit
03f29e75ec
20 changed files with 4432 additions and 4171 deletions
|
|
@ -107,7 +107,7 @@
|
||||||
#include "nsIScrollableFrame.h"
|
#include "nsIScrollableFrame.h"
|
||||||
#include "mozilla/css/StyleRule.h" /* For nsCSSSelectorList */
|
#include "mozilla/css/StyleRule.h" /* For nsCSSSelectorList */
|
||||||
#include "mozilla/css/Declaration.h"
|
#include "mozilla/css/Declaration.h"
|
||||||
#include "nsCSSRuleProcessor.h"
|
#include "nsCSSRuleUtils.h"
|
||||||
#include "nsRuleProcessorData.h"
|
#include "nsRuleProcessorData.h"
|
||||||
#include "nsTextNode.h"
|
#include "nsTextNode.h"
|
||||||
|
|
||||||
|
|
@ -3434,9 +3434,9 @@ Element::Closest(const nsAString& aSelector, ErrorResult& aResult)
|
||||||
matchingContext.AddScopeElement(this);
|
matchingContext.AddScopeElement(this);
|
||||||
for (nsINode* node = this; node; node = node->GetParentNode()) {
|
for (nsINode* node = this; node; node = node->GetParentNode()) {
|
||||||
if (node->IsElement() &&
|
if (node->IsElement() &&
|
||||||
nsCSSRuleProcessor::RestrictedSelectorListMatches(node->AsElement(),
|
nsCSSRuleUtils::RestrictedSelectorListMatches(node->AsElement(),
|
||||||
matchingContext,
|
matchingContext,
|
||||||
selectorList)) {
|
selectorList)) {
|
||||||
return node->AsElement();
|
return node->AsElement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3460,9 +3460,9 @@ Element::Matches(const nsAString& aSelector, ErrorResult& aError)
|
||||||
TreeMatchContext::eNeverMatchVisited);
|
TreeMatchContext::eNeverMatchVisited);
|
||||||
matchingContext.SetHasSpecifiedScope();
|
matchingContext.SetHasSpecifiedScope();
|
||||||
matchingContext.AddScopeElement(this);
|
matchingContext.AddScopeElement(this);
|
||||||
return nsCSSRuleProcessor::RestrictedSelectorListMatches(this,
|
return nsCSSRuleUtils::RestrictedSelectorListMatches(this,
|
||||||
matchingContext,
|
matchingContext,
|
||||||
selectorList);
|
selectorList);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const nsAttrValue::EnumTable kCORSAttributeTable[] = {
|
static const nsAttrValue::EnumTable kCORSAttributeTable[] = {
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "prprf.h"
|
#include "prprf.h"
|
||||||
#include "xpcpublic.h"
|
#include "xpcpublic.h"
|
||||||
#include "nsCSSRuleProcessor.h"
|
#include "nsCSSRuleUtils.h"
|
||||||
#include "nsCSSParser.h"
|
#include "nsCSSParser.h"
|
||||||
#include "HTMLLegendElement.h"
|
#include "HTMLLegendElement.h"
|
||||||
#include "nsWrapperCacheInlines.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
|
// We have an element with the right id and it's a strict descendant
|
||||||
// of aRoot. Make sure it really matches the selector.
|
// of aRoot. Make sure it really matches the selector.
|
||||||
if (!aMatchInfo ||
|
if (!aMatchInfo ||
|
||||||
nsCSSRuleProcessor::RestrictedSelectorListMatches(element,
|
nsCSSRuleUtils::RestrictedSelectorListMatches(element,
|
||||||
aMatchInfo->mMatchContext,
|
aMatchInfo->mMatchContext,
|
||||||
aMatchInfo->mSelectorList)) {
|
aMatchInfo->mSelectorList)) {
|
||||||
aList.AppendElement(element);
|
aList.AppendElement(element);
|
||||||
if (onlyFirstMatch) {
|
if (onlyFirstMatch) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -2965,9 +2965,9 @@ FindMatchingElements(nsINode* aRoot, nsCSSSelectorList* aSelectorList, T &aList,
|
||||||
cur;
|
cur;
|
||||||
cur = cur->GetNextNode(aRoot)) {
|
cur = cur->GetNextNode(aRoot)) {
|
||||||
if (cur->IsElement() &&
|
if (cur->IsElement() &&
|
||||||
nsCSSRuleProcessor::RestrictedSelectorListMatches(cur->AsElement(),
|
nsCSSRuleUtils::RestrictedSelectorListMatches(cur->AsElement(),
|
||||||
matchingContext,
|
matchingContext,
|
||||||
aSelectorList)) {
|
aSelectorList)) {
|
||||||
if (onlyFirstMatch) {
|
if (onlyFirstMatch) {
|
||||||
aList.AppendElement(cur->AsElement());
|
aList.AppendElement(cur->AsElement());
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@
|
||||||
#include "nsDisplayList.h"
|
#include "nsDisplayList.h"
|
||||||
#include "RestyleTrackerInlines.h"
|
#include "RestyleTrackerInlines.h"
|
||||||
#include "nsSMILAnimationController.h"
|
#include "nsSMILAnimationController.h"
|
||||||
#include "nsCSSRuleProcessor.h"
|
#include "nsCSSRuleUtils.h"
|
||||||
#include "ChildIterator.h"
|
#include "ChildIterator.h"
|
||||||
#include "Layers.h"
|
#include "Layers.h"
|
||||||
|
|
||||||
|
|
@ -2550,8 +2550,8 @@ ElementRestyler::SelectorMatchesForRestyle(Element* aElement)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (nsCSSSelector* selector : mSelectorsForDescendants) {
|
for (nsCSSSelector* selector : mSelectorsForDescendants) {
|
||||||
if (nsCSSRuleProcessor::RestrictedSelectorMatches(aElement, selector,
|
if (nsCSSRuleUtils::RestrictedSelectorMatches(aElement, selector,
|
||||||
mTreeMatchContext)) {
|
mTreeMatchContext)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
#include "nsViewManager.h"
|
#include "nsViewManager.h"
|
||||||
#include "mozilla/RestyleManager.h"
|
#include "mozilla/RestyleManager.h"
|
||||||
#include "SurfaceCacheUtils.h"
|
#include "SurfaceCacheUtils.h"
|
||||||
#include "nsCSSRuleProcessor.h"
|
#include "nsCSSRuleUtils.h"
|
||||||
#include "nsRuleNode.h"
|
#include "nsRuleNode.h"
|
||||||
#include "gfxPlatform.h"
|
#include "gfxPlatform.h"
|
||||||
#include "nsCSSRules.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
|
// 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
|
// Changes to system metrics can change media queries on them, or
|
||||||
// :-moz-system-metric selectors (which requires eRestyle_Subtree).
|
// :-moz-system-metric selectors (which requires eRestyle_Subtree).
|
||||||
|
|
@ -1691,7 +1691,7 @@ nsPresContext::SysColorChangedInternal()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invalidate cached '-moz-windows-accent-color-applies' media query:
|
// Invalidate cached '-moz-windows-accent-color-applies' media query:
|
||||||
nsCSSRuleProcessor::FreeSystemMetrics();
|
nsCSSRuleUtils::FreeSystemMetrics();
|
||||||
|
|
||||||
// Reset default background and foreground colors for the document since
|
// Reset default background and foreground colors for the document since
|
||||||
// they may be using system colors
|
// they may be using system colors
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@
|
||||||
#include "nsTextFrame.h"
|
#include "nsTextFrame.h"
|
||||||
#include "nsCCUncollectableMarker.h"
|
#include "nsCCUncollectableMarker.h"
|
||||||
#include "nsTextFragment.h"
|
#include "nsTextFragment.h"
|
||||||
#include "nsCSSRuleProcessor.h"
|
#include "nsCSSRuleUtils.h"
|
||||||
#include "nsCORSListenerProxy.h"
|
#include "nsCORSListenerProxy.h"
|
||||||
#include "nsHTMLDNSPrefetch.h"
|
#include "nsHTMLDNSPrefetch.h"
|
||||||
#include "nsHtml5Atoms.h"
|
#include "nsHtml5Atoms.h"
|
||||||
|
|
@ -242,7 +242,7 @@ nsLayoutStatics::Initialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCSSParser::Startup();
|
nsCSSParser::Startup();
|
||||||
nsCSSRuleProcessor::Startup();
|
nsCSSRuleUtils::Startup();
|
||||||
|
|
||||||
#ifdef MOZ_XUL
|
#ifdef MOZ_XUL
|
||||||
rv = nsXULPopupManager::Init();
|
rv = nsXULPopupManager::Init();
|
||||||
|
|
@ -330,7 +330,7 @@ nsLayoutStatics::Shutdown()
|
||||||
EventListenerManager::Shutdown();
|
EventListenerManager::Shutdown();
|
||||||
IMEStateManager::Shutdown();
|
IMEStateManager::Shutdown();
|
||||||
nsCSSParser::Shutdown();
|
nsCSSParser::Shutdown();
|
||||||
nsCSSRuleProcessor::Shutdown();
|
nsCSSRuleUtils::Shutdown();
|
||||||
nsHTMLDNSPrefetch::Shutdown();
|
nsHTMLDNSPrefetch::Shutdown();
|
||||||
nsCSSRendering::Shutdown();
|
nsCSSRendering::Shutdown();
|
||||||
StaticPresData::Shutdown();
|
StaticPresData::Shutdown();
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@
|
||||||
#include "nsRuleWalker.h"
|
#include "nsRuleWalker.h"
|
||||||
#include "nsRuleProcessorData.h"
|
#include "nsRuleProcessorData.h"
|
||||||
#include "nsCSSPseudoClasses.h"
|
#include "nsCSSPseudoClasses.h"
|
||||||
#include "nsCSSRuleProcessor.h"
|
#include "nsCSSRuleUtils.h"
|
||||||
#include "mozilla/dom/CSSLexer.h"
|
#include "mozilla/dom/CSSLexer.h"
|
||||||
#include "mozilla/dom/InspectorUtilsBinding.h"
|
#include "mozilla/dom/InspectorUtilsBinding.h"
|
||||||
#include "mozilla/dom/ToJSValue.h"
|
#include "mozilla/dom/ToJSValue.h"
|
||||||
|
|
@ -467,9 +467,9 @@ inDOMUtils::SelectorMatchesElement(nsIDOMElement* aElement,
|
||||||
nsRuleWalker::eRelevantLinkUnvisited,
|
nsRuleWalker::eRelevantLinkUnvisited,
|
||||||
element->OwnerDoc(),
|
element->OwnerDoc(),
|
||||||
TreeMatchContext::eNeverMatchVisited);
|
TreeMatchContext::eNeverMatchVisited);
|
||||||
*aMatches = nsCSSRuleProcessor::RestrictedSelectorListMatches(element,
|
*aMatches = nsCSSRuleUtils::RestrictedSelectorListMatches(element,
|
||||||
matchingContext,
|
matchingContext,
|
||||||
sel);
|
sel);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1183,26 +1183,6 @@ inDOMUtils::GetUsedFontFaces(nsIDOMRange* aRange,
|
||||||
static EventStates
|
static EventStates
|
||||||
GetStatesForPseudoClass(const nsAString& aStatePseudo)
|
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);
|
nsCOMPtr<nsIAtom> atom = NS_Atomize(aStatePseudo);
|
||||||
CSSPseudoClassType type = nsCSSPseudoClasses::
|
CSSPseudoClassType type = nsCSSPseudoClasses::
|
||||||
GetPseudoType(atom, CSSEnabledState::eIgnoreEnabledState);
|
GetPseudoType(atom, CSSEnabledState::eIgnoreEnabledState);
|
||||||
|
|
@ -1215,7 +1195,7 @@ GetStatesForPseudoClass(const nsAString& aStatePseudo)
|
||||||
}
|
}
|
||||||
// Our array above is long enough that indexing into it with
|
// Our array above is long enough that indexing into it with
|
||||||
// NotPseudo is ok.
|
// NotPseudo is ok.
|
||||||
return sPseudoClassStates[static_cast<CSSPseudoClassTypeBase>(type)];
|
return nsCSSPseudoClasses::sPseudoClassStates[static_cast<CSSPseudoClassTypeBase>(type)];
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
|
|
||||||
1783
layout/style/RuleCascadeData.cpp
Normal file
1783
layout/style/RuleCascadeData.cpp
Normal file
File diff suppressed because it is too large
Load diff
411
layout/style/RuleCascadeData.h
Normal file
411
layout/style/RuleCascadeData.h
Normal file
|
|
@ -0,0 +1,411 @@
|
||||||
|
/* -*- 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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(nsIAtom* aMedium, 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);
|
||||||
|
|
||||||
|
nsMediaQueryResultCacheKey mCacheKey;
|
||||||
|
|
||||||
|
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 ResolvedRuleCascades
|
||||||
|
{
|
||||||
|
ResolvedRuleCascades()
|
||||||
|
: mUnlayered(nullptr)
|
||||||
|
, mNext(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~ResolvedRuleCascades()
|
||||||
|
{
|
||||||
|
for (RuleCascadeData* data : mOrderedData) {
|
||||||
|
delete data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nsTArray<RuleCascadeData*> mOrderedData;
|
||||||
|
RuleCascadeData* mUnlayered;
|
||||||
|
ResolvedRuleCascades* mNext; // for a different medium
|
||||||
|
|
||||||
|
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CascadeEnumData
|
||||||
|
{
|
||||||
|
CascadeEnumData(nsPresContext* aPresContext,
|
||||||
|
nsString aName,
|
||||||
|
#ifdef DEBUG
|
||||||
|
CascadeEnumData* aParent,
|
||||||
|
#endif
|
||||||
|
nsAutoPtr<ResolvedRuleCascades>& aContainer,
|
||||||
|
bool aIsWeak,
|
||||||
|
nsTArray<css::DocumentRule*>& aDocumentRules,
|
||||||
|
nsDocumentRuleResultCacheKey& aDocumentKey,
|
||||||
|
SheetType aSheetType,
|
||||||
|
bool aMustGatherDocumentRules);
|
||||||
|
|
||||||
|
CascadeEnumData(nsPresContext* aPresContext,
|
||||||
|
nsAutoPtr<ResolvedRuleCascades>& aContainer,
|
||||||
|
nsTArray<css::DocumentRule*>& aDocumentRules,
|
||||||
|
nsDocumentRuleResultCacheKey& aDocumentKey,
|
||||||
|
SheetType aSheetType,
|
||||||
|
bool aMustGatherDocumentRules);
|
||||||
|
|
||||||
|
~CascadeEnumData();
|
||||||
|
|
||||||
|
nsPresContext* mPresContext;
|
||||||
|
nsString mName;
|
||||||
|
bool mIsAnonymous;
|
||||||
|
bool mIsWeak;
|
||||||
|
bool mWasFlattened;
|
||||||
|
|
||||||
|
RuleCascadeData* mData;
|
||||||
|
|
||||||
|
nsTArray<css::StyleRule*> mStyleRules;
|
||||||
|
nsTArray<css::DocumentRule*>& mDocumentRules;
|
||||||
|
nsDocumentRuleResultCacheKey& mDocumentCacheKey;
|
||||||
|
SheetType mSheetType;
|
||||||
|
bool mMustGatherDocumentRules;
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
CascadeEnumData* mParent;
|
||||||
|
bool mIsRoot;
|
||||||
|
#endif
|
||||||
|
nsAutoPtr<ResolvedRuleCascades>& mContainer;
|
||||||
|
nsTArray<CascadeEnumData*> mPreLayers;
|
||||||
|
nsTArray<CascadeEnumData*> mPostLayers;
|
||||||
|
nsDataHashtable<nsStringHashKey, CascadeEnumData*> mLayers;
|
||||||
|
|
||||||
|
CascadeEnumData* CreateNamedChildLayer(const nsTArray<nsString>& aPath);
|
||||||
|
CascadeEnumData* CreateAnonymousChildLayer();
|
||||||
|
void Flatten();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Initialize();
|
||||||
|
void AddRules();
|
||||||
|
|
||||||
|
static const PLDHashTableOps sRulesByWeightOps;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* RuleCascadeData_h___ */
|
||||||
|
|
@ -22,6 +22,16 @@
|
||||||
#include "nsIStyleRule.h"
|
#include "nsIStyleRule.h"
|
||||||
#include "nsICSSStyleRuleDOMWrapper.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;
|
class nsIAtom;
|
||||||
struct nsCSSSelectorList;
|
struct nsCSSSelectorList;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ EXPORTS += [
|
||||||
'nsCSSPseudoElementList.h',
|
'nsCSSPseudoElementList.h',
|
||||||
'nsCSSPseudoElements.h',
|
'nsCSSPseudoElements.h',
|
||||||
'nsCSSRuleProcessor.h',
|
'nsCSSRuleProcessor.h',
|
||||||
|
'nsCSSRuleUtils.h',
|
||||||
'nsCSSScanner.h',
|
'nsCSSScanner.h',
|
||||||
'nsCSSValue.h',
|
'nsCSSValue.h',
|
||||||
'nsDOMCSSAttrDeclaration.h',
|
'nsDOMCSSAttrDeclaration.h',
|
||||||
|
|
@ -70,6 +71,7 @@ EXPORTS += [
|
||||||
'nsStyleStructInlines.h',
|
'nsStyleStructInlines.h',
|
||||||
'nsStyleTransformMatrix.h',
|
'nsStyleTransformMatrix.h',
|
||||||
'nsStyleUtil.h',
|
'nsStyleUtil.h',
|
||||||
|
'RuleCascadeData.h',
|
||||||
]
|
]
|
||||||
|
|
||||||
EXPORTS.mozilla += [
|
EXPORTS.mozilla += [
|
||||||
|
|
@ -146,7 +148,9 @@ UNIFIED_SOURCES += [
|
||||||
'nsCSSProps.cpp',
|
'nsCSSProps.cpp',
|
||||||
'nsCSSPseudoClasses.cpp',
|
'nsCSSPseudoClasses.cpp',
|
||||||
'nsCSSPseudoElements.cpp',
|
'nsCSSPseudoElements.cpp',
|
||||||
|
'nsCSSRuleProcessor.cpp',
|
||||||
'nsCSSRules.cpp',
|
'nsCSSRules.cpp',
|
||||||
|
'nsCSSRuleUtils.cpp',
|
||||||
'nsCSSScanner.cpp',
|
'nsCSSScanner.cpp',
|
||||||
'nsCSSValue.cpp',
|
'nsCSSValue.cpp',
|
||||||
'nsDOMCSSAttrDeclaration.cpp',
|
'nsDOMCSSAttrDeclaration.cpp',
|
||||||
|
|
@ -184,14 +188,14 @@ UNIFIED_SOURCES += [
|
||||||
# includes, via nsStyleCoord.h, <type_traits>, which ends up including
|
# includes, via nsStyleCoord.h, <type_traits>, which ends up including
|
||||||
# <xutility>, which fails in much the way described in
|
# <xutility>, which fails in much the way described in
|
||||||
# <https://bugzilla.mozilla.org/show_bug.cgi?id=1331102>.
|
# <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.
|
# plarena.h.
|
||||||
# - nsLayoutStylesheetCache.cpp needs to be built separately because it uses
|
# - nsLayoutStylesheetCache.cpp needs to be built separately because it uses
|
||||||
# nsExceptionHandler.h, which includes windows.h.
|
# nsExceptionHandler.h, which includes windows.h.
|
||||||
SOURCES += [
|
SOURCES += [
|
||||||
'BindingStyleRule.cpp',
|
'BindingStyleRule.cpp',
|
||||||
'nsCSSRuleProcessor.cpp',
|
|
||||||
'nsLayoutStylesheetCache.cpp',
|
'nsLayoutStylesheetCache.cpp',
|
||||||
|
'RuleCascadeData.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
include('/ipc/chromium/chromium-config.mozbuild')
|
include('/ipc/chromium/chromium-config.mozbuild')
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,40 @@ nsCSSPseudoClasses::sPseudoClassEnabled[] = {
|
||||||
#undef IS_ENABLED_BY_DEFAULT
|
#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()
|
void nsCSSPseudoClasses::AddRefAtoms()
|
||||||
{
|
{
|
||||||
NS_RegisterStaticAtoms(CSSPseudoClasses_info);
|
NS_RegisterStaticAtoms(CSSPseudoClasses_info);
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,9 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const mozilla::EventStates sPseudoClassStateDependences[];
|
||||||
|
static const mozilla::EventStates sPseudoClassStates[];
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const uint32_t kPseudoClassFlags[size_t(Type::Count)];
|
static const uint32_t kPseudoClassFlags[size_t(Type::Count)];
|
||||||
static bool sPseudoClassEnabled[size_t(Type::Count)];
|
static bool sPseudoClassEnabled[size_t(Type::Count)];
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -25,11 +25,8 @@
|
||||||
|
|
||||||
struct CascadeEnumData;
|
struct CascadeEnumData;
|
||||||
struct ElementDependentRuleProcessorData;
|
struct ElementDependentRuleProcessorData;
|
||||||
struct nsCSSSelector;
|
|
||||||
struct nsCSSSelectorList;
|
|
||||||
struct nsFontFaceRuleContainer;
|
struct nsFontFaceRuleContainer;
|
||||||
struct ResolvedRuleCascades;
|
struct ResolvedRuleCascades;
|
||||||
struct TreeMatchContext;
|
|
||||||
class nsCSSKeyframesRule;
|
class nsCSSKeyframesRule;
|
||||||
class nsCSSPageRule;
|
class nsCSSPageRule;
|
||||||
class nsCSSFontFeatureValuesRule;
|
class nsCSSFontFeatureValuesRule;
|
||||||
|
|
@ -79,59 +76,6 @@ public:
|
||||||
public:
|
public:
|
||||||
nsresult ClearRuleCascades();
|
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);
|
|
||||||
|
|
||||||
// nsIStyleRuleProcessor
|
// nsIStyleRuleProcessor
|
||||||
virtual void RulesMatching(ElementRuleProcessorData* aData) override;
|
virtual void RulesMatching(ElementRuleProcessorData* aData) override;
|
||||||
|
|
||||||
|
|
@ -207,24 +151,6 @@ public:
|
||||||
bool IsInRuleProcessorCache() const { return mInRuleProcessorCache; }
|
bool IsInRuleProcessorCache() const { return mInRuleProcessorCache; }
|
||||||
bool IsUsedByMultipleStyleSets() const { return mStyleSetRefCnt > 1; }
|
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:
|
protected:
|
||||||
virtual ~nsCSSRuleProcessor();
|
virtual ~nsCSSRuleProcessor();
|
||||||
|
|
||||||
|
|
@ -282,10 +208,6 @@ private:
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
bool mDocumentRulesAndCacheKeyValid;
|
bool mDocumentRulesAndCacheKeyValid;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef XP_WIN
|
|
||||||
static uint8_t sWinThemeId;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* nsCSSRuleProcessor_h_ */
|
#endif /* nsCSSRuleProcessor_h_ */
|
||||||
|
|
|
||||||
1746
layout/style/nsCSSRuleUtils.cpp
Normal file
1746
layout/style/nsCSSRuleUtils.cpp
Normal file
File diff suppressed because it is too large
Load diff
137
layout/style/nsCSSRuleUtils.h
Normal file
137
layout/style/nsCSSRuleUtils.h
Normal 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___ */
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
#include "nsRuleData.h"
|
#include "nsRuleData.h"
|
||||||
#include "nsError.h"
|
#include "nsError.h"
|
||||||
#include "nsRuleProcessorData.h"
|
#include "nsRuleProcessorData.h"
|
||||||
#include "nsCSSRuleProcessor.h"
|
#include "nsCSSRuleUtils.h"
|
||||||
#include "mozilla/MemoryReporting.h"
|
#include "mozilla/MemoryReporting.h"
|
||||||
#include "mozilla/dom/Element.h"
|
#include "mozilla/dom/Element.h"
|
||||||
#include "nsHashKeys.h"
|
#include "nsHashKeys.h"
|
||||||
|
|
@ -310,13 +310,13 @@ nsHTMLStyleSheet::RulesMatching(ElementRuleProcessorData* aData)
|
||||||
if (aData->mElement->IsHTMLElement(nsGkAtoms::a)) {
|
if (aData->mElement->IsHTMLElement(nsGkAtoms::a)) {
|
||||||
if (mLinkRule || mVisitedRule || mActiveRule) {
|
if (mLinkRule || mVisitedRule || mActiveRule) {
|
||||||
EventStates state =
|
EventStates state =
|
||||||
nsCSSRuleProcessor::GetContentStateForVisitedHandling(
|
nsCSSRuleUtils::GetContentStateForVisitedHandling(
|
||||||
aData->mElement,
|
aData->mElement,
|
||||||
aData->mTreeMatchContext,
|
aData->mTreeMatchContext,
|
||||||
aData->mTreeMatchContext.VisitedHandling(),
|
aData->mTreeMatchContext.VisitedHandling(),
|
||||||
// If the node being matched is a link,
|
// If the node being matched is a link,
|
||||||
// it's the relevant link.
|
// it's the relevant link.
|
||||||
nsCSSRuleProcessor::IsLink(aData->mElement));
|
nsCSSRuleUtils::IsLink(aData->mElement));
|
||||||
if (mLinkRule && state.HasState(NS_EVENT_STATE_UNVISITED)) {
|
if (mLinkRule && state.HasState(NS_EVENT_STATE_UNVISITED)) {
|
||||||
ruleWalker->Forward(mLinkRule);
|
ruleWalker->Forward(mLinkRule);
|
||||||
aData->mTreeMatchContext.SetHaveRelevantLink();
|
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
|
// 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)) {
|
state.HasState(NS_EVENT_STATE_ACTIVE)) {
|
||||||
ruleWalker->Forward(mActiveRule);
|
ruleWalker->Forward(mActiveRule);
|
||||||
}
|
}
|
||||||
|
|
@ -372,7 +372,7 @@ nsHTMLStyleSheet::RulesMatching(ElementRuleProcessorData* aData)
|
||||||
nsHTMLStyleSheet::HasStateDependentStyle(StateRuleProcessorData* aData)
|
nsHTMLStyleSheet::HasStateDependentStyle(StateRuleProcessorData* aData)
|
||||||
{
|
{
|
||||||
if (aData->mElement->IsHTMLElement(nsGkAtoms::a) &&
|
if (aData->mElement->IsHTMLElement(nsGkAtoms::a) &&
|
||||||
nsCSSRuleProcessor::IsLink(aData->mElement) &&
|
nsCSSRuleUtils::IsLink(aData->mElement) &&
|
||||||
((mActiveRule && aData->mStateMask.HasState(NS_EVENT_STATE_ACTIVE)) ||
|
((mActiveRule && aData->mStateMask.HasState(NS_EVENT_STATE_ACTIVE)) ||
|
||||||
(mLinkRule && aData->mStateMask.HasState(NS_EVENT_STATE_VISITED)) ||
|
(mLinkRule && aData->mStateMask.HasState(NS_EVENT_STATE_VISITED)) ||
|
||||||
(mVisitedRule && aData->mStateMask.HasState(NS_EVENT_STATE_VISITED)))) {
|
(mVisitedRule && aData->mStateMask.HasState(NS_EVENT_STATE_VISITED)))) {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
#include "mozilla/LookAndFeel.h"
|
#include "mozilla/LookAndFeel.h"
|
||||||
#endif
|
#endif
|
||||||
#include "nsCSSRuleProcessor.h"
|
#include "nsCSSRuleUtils.h"
|
||||||
#include "nsDeviceContext.h"
|
#include "nsDeviceContext.h"
|
||||||
#include "nsIBaseWindow.h"
|
#include "nsIBaseWindow.h"
|
||||||
#include "nsIDocument.h"
|
#include "nsIDocument.h"
|
||||||
|
|
@ -404,7 +404,7 @@ GetSystemMetric(nsPresContext* aPresContext, const nsMediaFeature* aFeature,
|
||||||
MOZ_ASSERT(aFeature->mValueType == nsMediaFeature::eBoolInteger,
|
MOZ_ASSERT(aFeature->mValueType == nsMediaFeature::eBoolInteger,
|
||||||
"unexpected type");
|
"unexpected type");
|
||||||
nsIAtom *metricAtom = *aFeature->mData.mMetric;
|
nsIAtom *metricAtom = *aFeature->mData.mMetric;
|
||||||
bool hasMetric = nsCSSRuleProcessor::HasSystemMetric(metricAtom);
|
bool hasMetric = nsCSSRuleUtils::HasSystemMetric(metricAtom);
|
||||||
aResult.SetIntValue(hasMetric ? 1 : 0, eCSSUnit_Integer);
|
aResult.SetIntValue(hasMetric ? 1 : 0, eCSSUnit_Integer);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
@ -420,7 +420,7 @@ GetWindowsTheme(nsPresContext* aPresContext, const nsMediaFeature* aFeature,
|
||||||
|
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
uint8_t windowsThemeId =
|
uint8_t windowsThemeId =
|
||||||
nsCSSRuleProcessor::GetWindowsThemeIdentifier();
|
nsCSSRuleUtils::GetWindowsThemeIdentifier();
|
||||||
|
|
||||||
// Classic mode should fail to match.
|
// Classic mode should fail to match.
|
||||||
if (windowsThemeId == LookAndFeel::eWindowsTheme_Classic)
|
if (windowsThemeId == LookAndFeel::eWindowsTheme_Classic)
|
||||||
|
|
|
||||||
|
|
@ -483,6 +483,58 @@ struct MOZ_STACK_CLASS RuleProcessorData {
|
||||||
mozilla::dom::Element* mScope;
|
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 :
|
struct MOZ_STACK_CLASS ElementDependentRuleProcessorData :
|
||||||
public RuleProcessorData {
|
public RuleProcessorData {
|
||||||
ElementDependentRuleProcessorData(nsPresContext* aPresContext,
|
ElementDependentRuleProcessorData(nsPresContext* aPresContext,
|
||||||
|
|
@ -649,4 +701,48 @@ struct MOZ_STACK_CLASS AttributeRuleProcessorData :
|
||||||
bool mAttrHasChanged; // Whether the attribute has already changed.
|
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_) */
|
#endif /* !defined(nsRuleProcessorData_h_) */
|
||||||
|
|
|
||||||
|
|
@ -1373,10 +1373,10 @@ nsStyleSet::ResolveStyleFor(Element* aElement,
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t flags = eDoAnimation;
|
uint32_t flags = eDoAnimation;
|
||||||
if (nsCSSRuleProcessor::IsLink(aElement)) {
|
if (nsCSSRuleUtils::IsLink(aElement)) {
|
||||||
flags |= eIsLink;
|
flags |= eIsLink;
|
||||||
}
|
}
|
||||||
if (nsCSSRuleProcessor::GetContentState(aElement, aTreeMatchContext).
|
if (nsCSSRuleUtils::GetContentState(aElement, aTreeMatchContext).
|
||||||
HasState(NS_EVENT_STATE_VISITED)) {
|
HasState(NS_EVENT_STATE_VISITED)) {
|
||||||
flags |= eIsVisitedLink;
|
flags |= eIsVisitedLink;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue