LCOV - code coverage report
Current view: top level - layout/style - StyleRule.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 240 734 32.7 %
Date: 2017-07-14 16:53:18 Functions: 40 92 43.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : /*
       7             :  * representation of CSS style rules (selectors+declaration), CSS
       8             :  * selectors, and DOM objects for style rules, selectors, and
       9             :  * declarations
      10             :  */
      11             : 
      12             : #include "mozilla/css/StyleRule.h"
      13             : 
      14             : #include "mozilla/DeclarationBlockInlines.h"
      15             : #include "mozilla/StyleSheetInlines.h"
      16             : #include "mozilla/MemoryReporting.h"
      17             : #include "mozilla/css/GroupRule.h"
      18             : #include "mozilla/css/Declaration.h"
      19             : #include "mozilla/dom/CSSStyleRuleBinding.h"
      20             : #include "nsIDocument.h"
      21             : #include "nsIAtom.h"
      22             : #include "nsString.h"
      23             : #include "nsStyleUtil.h"
      24             : #include "nsDOMCSSDeclaration.h"
      25             : #include "nsNameSpaceManager.h"
      26             : #include "nsXMLNameSpaceMap.h"
      27             : #include "nsCSSPseudoClasses.h"
      28             : #include "nsCSSAnonBoxes.h"
      29             : #include "nsTArray.h"
      30             : #include "nsContentUtils.h"
      31             : #include "nsError.h"
      32             : #include "mozAutoDocUpdate.h"
      33             : #include "nsRuleProcessorData.h"
      34             : 
      35             : class nsIDOMCSSStyleDeclaration;
      36             : class nsIDOMCSSStyleSheet;
      37             : 
      38             : using namespace mozilla;
      39             : 
      40             : #define NS_IF_CLONE(member_)                                                  \
      41             :   PR_BEGIN_MACRO                                                              \
      42             :     if (member_) {                                                            \
      43             :       result->member_ = member_->Clone();                                     \
      44             :       if (!result->member_) {                                                 \
      45             :         delete result;                                                        \
      46             :         return nullptr;                                                        \
      47             :       }                                                                       \
      48             :     }                                                                         \
      49             :   PR_END_MACRO
      50             : 
      51             : #define NS_IF_DELETE(ptr)                                                     \
      52             :   PR_BEGIN_MACRO                                                              \
      53             :     delete ptr;                                                               \
      54             :     ptr = nullptr;                                                             \
      55             :   PR_END_MACRO
      56             : 
      57             : /* ************************************************************************** */
      58             : 
      59           0 : nsAtomList::nsAtomList(nsIAtom* aAtom)
      60             :   : mAtom(aAtom),
      61           0 :     mNext(nullptr)
      62             : {
      63           0 :   MOZ_COUNT_CTOR(nsAtomList);
      64           0 : }
      65             : 
      66        4554 : nsAtomList::nsAtomList(const nsString& aAtomValue)
      67             :   : mAtom(nullptr),
      68        4554 :     mNext(nullptr)
      69             : {
      70        4554 :   MOZ_COUNT_CTOR(nsAtomList);
      71        4554 :   mAtom = NS_Atomize(aAtomValue);
      72        4554 : }
      73             : 
      74             : nsAtomList*
      75           0 : nsAtomList::Clone(bool aDeep) const
      76             : {
      77           0 :   nsAtomList *result = new nsAtomList(mAtom);
      78           0 :   if (!result)
      79           0 :     return nullptr;
      80             : 
      81           0 :   if (aDeep)
      82           0 :     NS_CSS_CLONE_LIST_MEMBER(nsAtomList, this, mNext, result, (false));
      83           0 :   return result;
      84             : }
      85             : 
      86             : size_t
      87          12 : nsAtomList::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
      88             : {
      89          12 :   size_t n = 0;
      90          12 :   const nsAtomList* a = this;
      91          36 :   while (a) {
      92          12 :     n += aMallocSizeOf(a);
      93             : 
      94             :     // The following members aren't measured:
      95             :     // - a->mAtom, because it may be shared
      96             : 
      97          12 :     a = a->mNext;
      98             :   }
      99          12 :   return n;
     100             : }
     101             : 
     102           0 : nsAtomList::~nsAtomList(void)
     103             : {
     104           0 :   MOZ_COUNT_DTOR(nsAtomList);
     105           0 :   NS_CSS_DELETE_LIST_MEMBER(nsAtomList, this, mNext);
     106           0 : }
     107             : 
     108        1588 : nsPseudoClassList::nsPseudoClassList(CSSPseudoClassType aType)
     109             :   : mType(aType),
     110        1588 :     mNext(nullptr)
     111             : {
     112        1588 :   NS_ASSERTION(!nsCSSPseudoClasses::HasStringArg(aType) &&
     113             :                !nsCSSPseudoClasses::HasNthPairArg(aType),
     114             :                "unexpected pseudo-class");
     115        1588 :   MOZ_COUNT_CTOR(nsPseudoClassList);
     116        1588 :   u.mMemory = nullptr;
     117        1588 : }
     118             : 
     119         176 : nsPseudoClassList::nsPseudoClassList(CSSPseudoClassType aType,
     120         176 :                                      const char16_t* aString)
     121             :   : mType(aType),
     122         176 :     mNext(nullptr)
     123             : {
     124         176 :   NS_ASSERTION(nsCSSPseudoClasses::HasStringArg(aType),
     125             :                "unexpected pseudo-class");
     126         176 :   NS_ASSERTION(aString, "string expected");
     127         176 :   MOZ_COUNT_CTOR(nsPseudoClassList);
     128         176 :   u.mString = NS_strdup(aString);
     129         176 : }
     130             : 
     131           1 : nsPseudoClassList::nsPseudoClassList(CSSPseudoClassType aType,
     132           1 :                                      const int32_t* aIntPair)
     133             :   : mType(aType),
     134           1 :     mNext(nullptr)
     135             : {
     136           1 :   NS_ASSERTION(nsCSSPseudoClasses::HasNthPairArg(aType),
     137             :                "unexpected pseudo-class");
     138           1 :   NS_ASSERTION(aIntPair, "integer pair expected");
     139           1 :   MOZ_COUNT_CTOR(nsPseudoClassList);
     140           1 :   u.mNumbers =
     141           1 :     static_cast<int32_t*>(nsMemory::Clone(aIntPair, sizeof(int32_t) * 2));
     142           1 : }
     143             : 
     144             : // adopts aSelectorList
     145         162 : nsPseudoClassList::nsPseudoClassList(CSSPseudoClassType aType,
     146         162 :                                      nsCSSSelectorList* aSelectorList)
     147             :   : mType(aType),
     148         162 :     mNext(nullptr)
     149             : {
     150         162 :   NS_ASSERTION(nsCSSPseudoClasses::HasSelectorListArg(aType),
     151             :                "unexpected pseudo-class");
     152         162 :   NS_ASSERTION(aSelectorList, "selector list expected");
     153         162 :   MOZ_COUNT_CTOR(nsPseudoClassList);
     154         162 :   u.mSelectors = aSelectorList;
     155         162 : }
     156             : 
     157             : nsPseudoClassList*
     158           0 : nsPseudoClassList::Clone(bool aDeep) const
     159             : {
     160             :   nsPseudoClassList *result;
     161           0 :   if (!u.mMemory) {
     162           0 :     result = new nsPseudoClassList(mType);
     163           0 :   } else if (nsCSSPseudoClasses::HasStringArg(mType)) {
     164           0 :     result = new nsPseudoClassList(mType, u.mString);
     165           0 :   } else if (nsCSSPseudoClasses::HasNthPairArg(mType)) {
     166           0 :     result = new nsPseudoClassList(mType, u.mNumbers);
     167             :   } else {
     168           0 :     NS_ASSERTION(nsCSSPseudoClasses::HasSelectorListArg(mType),
     169             :                  "unexpected pseudo-class");
     170             :     // This constructor adopts its selector list argument.
     171           0 :     result = new nsPseudoClassList(mType, u.mSelectors->Clone());
     172             :   }
     173             : 
     174           0 :   if (aDeep)
     175           0 :     NS_CSS_CLONE_LIST_MEMBER(nsPseudoClassList, this, mNext, result,
     176             :                              (false));
     177             : 
     178           0 :   return result;
     179             : }
     180             : 
     181             : size_t
     182           5 : nsPseudoClassList::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
     183             : {
     184           5 :   size_t n = 0;
     185           5 :   const nsPseudoClassList* p = this;
     186          15 :   while (p) {
     187           5 :     n += aMallocSizeOf(p);
     188           5 :     if (!p->u.mMemory) {
     189             :       // do nothing
     190             : 
     191           0 :     } else if (nsCSSPseudoClasses::HasStringArg(p->mType)) {
     192           0 :       n += aMallocSizeOf(p->u.mString);
     193             : 
     194           0 :     } else if (nsCSSPseudoClasses::HasNthPairArg(p->mType)) {
     195           0 :       n += aMallocSizeOf(p->u.mNumbers);
     196             : 
     197             :     } else {
     198           0 :       NS_ASSERTION(nsCSSPseudoClasses::HasSelectorListArg(p->mType),
     199             :                    "unexpected pseudo-class");
     200           0 :       n += p->u.mSelectors->SizeOfIncludingThis(aMallocSizeOf);
     201             :     }
     202           5 :     p = p->mNext;
     203             :   }
     204           5 :   return n;
     205             : }
     206             : 
     207           0 : nsPseudoClassList::~nsPseudoClassList(void)
     208             : {
     209           0 :   MOZ_COUNT_DTOR(nsPseudoClassList);
     210           0 :   if (nsCSSPseudoClasses::HasSelectorListArg(mType)) {
     211           0 :     delete u.mSelectors;
     212           0 :   } else if (u.mMemory) {
     213           0 :     free(u.mMemory);
     214             :   }
     215           0 :   NS_CSS_DELETE_LIST_MEMBER(nsPseudoClassList, this, mNext);
     216           0 : }
     217             : 
     218         737 : nsAttrSelector::nsAttrSelector(int32_t aNameSpace, const nsString& aAttr)
     219             :   : mValue(),
     220             :     mNext(nullptr),
     221             :     mLowercaseAttr(nullptr),
     222             :     mCasedAttr(nullptr),
     223             :     mNameSpace(aNameSpace),
     224             :     mFunction(NS_ATTR_FUNC_SET),
     225             :     // mValueCaseSensitivity doesn't matter; we have no value.
     226         737 :     mValueCaseSensitivity(ValueCaseSensitivity::CaseSensitive)
     227             : {
     228         737 :   MOZ_COUNT_CTOR(nsAttrSelector);
     229             : 
     230        1474 :   nsAutoString lowercase;
     231         737 :   nsContentUtils::ASCIIToLower(aAttr, lowercase);
     232             : 
     233         737 :   mCasedAttr = NS_Atomize(aAttr);
     234         737 :   mLowercaseAttr = NS_Atomize(lowercase);
     235         737 : }
     236             : 
     237        1645 : nsAttrSelector::nsAttrSelector(int32_t aNameSpace, const nsString& aAttr, uint8_t aFunction,
     238             :                                const nsString& aValue,
     239        1645 :                                ValueCaseSensitivity aValueCaseSensitivity)
     240             :   : mValue(aValue),
     241             :     mNext(nullptr),
     242             :     mLowercaseAttr(nullptr),
     243             :     mCasedAttr(nullptr),
     244             :     mNameSpace(aNameSpace),
     245             :     mFunction(aFunction),
     246        1645 :     mValueCaseSensitivity(aValueCaseSensitivity)
     247             : {
     248        1645 :   MOZ_COUNT_CTOR(nsAttrSelector);
     249             : 
     250        3290 :   nsAutoString lowercase;
     251        1645 :   nsContentUtils::ASCIIToLower(aAttr, lowercase);
     252             : 
     253        1645 :   mCasedAttr = NS_Atomize(aAttr);
     254        1645 :   mLowercaseAttr = NS_Atomize(lowercase);
     255        1645 : }
     256             : 
     257           0 : nsAttrSelector::nsAttrSelector(int32_t aNameSpace,  nsIAtom* aLowercaseAttr,
     258             :                                nsIAtom* aCasedAttr, uint8_t aFunction,
     259             :                                const nsString& aValue,
     260           0 :                                ValueCaseSensitivity aValueCaseSensitivity)
     261             :   : mValue(aValue),
     262             :     mNext(nullptr),
     263             :     mLowercaseAttr(aLowercaseAttr),
     264             :     mCasedAttr(aCasedAttr),
     265             :     mNameSpace(aNameSpace),
     266             :     mFunction(aFunction),
     267           0 :     mValueCaseSensitivity(aValueCaseSensitivity)
     268             : {
     269           0 :   MOZ_COUNT_CTOR(nsAttrSelector);
     270           0 : }
     271             : 
     272             : nsAttrSelector*
     273           0 : nsAttrSelector::Clone(bool aDeep) const
     274             : {
     275             :   nsAttrSelector *result =
     276           0 :     new nsAttrSelector(mNameSpace, mLowercaseAttr, mCasedAttr,
     277           0 :                        mFunction, mValue, mValueCaseSensitivity);
     278             : 
     279           0 :   if (aDeep)
     280           0 :     NS_CSS_CLONE_LIST_MEMBER(nsAttrSelector, this, mNext, result, (false));
     281             : 
     282           0 :   return result;
     283             : }
     284             : 
     285           0 : nsAttrSelector::~nsAttrSelector(void)
     286             : {
     287           0 :   MOZ_COUNT_DTOR(nsAttrSelector);
     288             : 
     289           0 :   NS_CSS_DELETE_LIST_MEMBER(nsAttrSelector, this, mNext);
     290           0 : }
     291             : 
     292             : size_t
     293           0 : nsAttrSelector::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
     294             : {
     295           0 :   size_t n = 0;
     296           0 :   const nsAttrSelector* p = this;
     297           0 :   while (p) {
     298           0 :     n += aMallocSizeOf(p);
     299           0 :     n += p->mValue.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
     300           0 :     p = p->mNext;
     301             :   }
     302           0 :   return n;
     303             : }
     304             : 
     305             : // -- nsCSSSelector -------------------------------
     306             : 
     307        9242 : nsCSSSelector::nsCSSSelector(void)
     308             :   : mLowercaseTag(nullptr),
     309             :     mCasedTag(nullptr),
     310             :     mIDList(nullptr),
     311             :     mClassList(nullptr),
     312             :     mPseudoClassList(nullptr),
     313             :     mAttrList(nullptr),
     314             :     mNegations(nullptr),
     315             :     mNext(nullptr),
     316             :     mNameSpace(kNameSpaceID_Unknown),
     317             :     mOperator(0),
     318        9242 :     mPseudoType(CSSPseudoElementType::NotPseudo)
     319             : {
     320        9242 :   MOZ_COUNT_CTOR(nsCSSSelector);
     321        9242 : }
     322             : 
     323             : nsCSSSelector*
     324           0 : nsCSSSelector::Clone(bool aDeepNext, bool aDeepNegations) const
     325             : {
     326           0 :   nsCSSSelector *result = new nsCSSSelector();
     327           0 :   if (!result)
     328           0 :     return nullptr;
     329             : 
     330           0 :   result->mNameSpace = mNameSpace;
     331           0 :   result->mLowercaseTag = mLowercaseTag;
     332           0 :   result->mCasedTag = mCasedTag;
     333           0 :   result->mOperator = mOperator;
     334           0 :   result->mPseudoType = mPseudoType;
     335             : 
     336           0 :   NS_IF_CLONE(mIDList);
     337           0 :   NS_IF_CLONE(mClassList);
     338           0 :   NS_IF_CLONE(mPseudoClassList);
     339           0 :   NS_IF_CLONE(mAttrList);
     340             : 
     341             :   // No need to worry about multiple levels of recursion since an
     342             :   // mNegations can't have an mNext.
     343           0 :   NS_ASSERTION(!mNegations || !mNegations->mNext,
     344             :                "mNegations can't have non-null mNext");
     345           0 :   if (aDeepNegations) {
     346           0 :     NS_CSS_CLONE_LIST_MEMBER(nsCSSSelector, this, mNegations, result,
     347             :                              (true, false));
     348             :   }
     349             : 
     350           0 :   if (aDeepNext) {
     351           0 :     NS_CSS_CLONE_LIST_MEMBER(nsCSSSelector, this, mNext, result,
     352             :                              (false, true));
     353             :   }
     354             : 
     355           0 :   return result;
     356             : }
     357             : 
     358          90 : nsCSSSelector::~nsCSSSelector(void)
     359             : {
     360          45 :   MOZ_COUNT_DTOR(nsCSSSelector);
     361          45 :   Reset();
     362             :   // No need to worry about multiple levels of recursion since an
     363             :   // mNegations can't have an mNext.
     364          45 :   NS_CSS_DELETE_LIST_MEMBER(nsCSSSelector, this, mNext);
     365          45 : }
     366             : 
     367          45 : void nsCSSSelector::Reset(void)
     368             : {
     369          45 :   mNameSpace = kNameSpaceID_Unknown;
     370          45 :   mLowercaseTag = nullptr;
     371          45 :   mCasedTag = nullptr;
     372          90 :   NS_IF_DELETE(mIDList);
     373          90 :   NS_IF_DELETE(mClassList);
     374          90 :   NS_IF_DELETE(mPseudoClassList);
     375          90 :   NS_IF_DELETE(mAttrList);
     376             :   // No need to worry about multiple levels of recursion since an
     377             :   // mNegations can't have an mNext.
     378          45 :   NS_ASSERTION(!mNegations || !mNegations->mNext,
     379             :                "mNegations can't have non-null mNext");
     380          45 :   NS_CSS_DELETE_LIST_MEMBER(nsCSSSelector, this, mNegations);
     381          45 :   mOperator = char16_t(0);
     382          45 : }
     383             : 
     384        8389 : void nsCSSSelector::SetNameSpace(int32_t aNameSpace)
     385             : {
     386        8389 :   mNameSpace = aNameSpace;
     387        8389 : }
     388             : 
     389        3619 : void nsCSSSelector::SetTag(const nsString& aTag)
     390             : {
     391        3619 :   if (aTag.IsEmpty()) {
     392           0 :     mLowercaseTag = mCasedTag =  nullptr;
     393           0 :     return;
     394             :   }
     395             : 
     396        3619 :   mCasedTag = NS_Atomize(aTag);
     397             : 
     398        7238 :   nsAutoString lowercase;
     399        3619 :   nsContentUtils::ASCIIToLower(aTag, lowercase);
     400        3619 :   mLowercaseTag = NS_Atomize(lowercase);
     401             : }
     402             : 
     403        1963 : void nsCSSSelector::AddID(const nsString& aID)
     404             : {
     405        1963 :   if (!aID.IsEmpty()) {
     406        1963 :     nsAtomList** list = &mIDList;
     407        1963 :     while (nullptr != *list) {
     408           0 :       list = &((*list)->mNext);
     409             :     }
     410        1963 :     *list = new nsAtomList(aID);
     411             :   }
     412        1963 : }
     413             : 
     414        2591 : void nsCSSSelector::AddClass(const nsString& aClass)
     415             : {
     416        2591 :   if (!aClass.IsEmpty()) {
     417        2591 :     nsAtomList** list = &mClassList;
     418        2891 :     while (nullptr != *list) {
     419         150 :       list = &((*list)->mNext);
     420             :     }
     421        2591 :     *list = new nsAtomList(aClass);
     422             :   }
     423        2591 : }
     424             : 
     425        1588 : void nsCSSSelector::AddPseudoClass(CSSPseudoClassType aType)
     426             : {
     427        1588 :   AddPseudoClassInternal(new nsPseudoClassList(aType));
     428        1588 : }
     429             : 
     430         176 : void nsCSSSelector::AddPseudoClass(CSSPseudoClassType aType,
     431             :                                    const char16_t* aString)
     432             : {
     433         176 :   AddPseudoClassInternal(new nsPseudoClassList(aType, aString));
     434         176 : }
     435             : 
     436           1 : void nsCSSSelector::AddPseudoClass(CSSPseudoClassType aType,
     437             :                                    const int32_t* aIntPair)
     438             : {
     439           1 :   AddPseudoClassInternal(new nsPseudoClassList(aType, aIntPair));
     440           1 : }
     441             : 
     442         162 : void nsCSSSelector::AddPseudoClass(CSSPseudoClassType aType,
     443             :                                    nsCSSSelectorList* aSelectorList)
     444             : {
     445             :   // Take ownership of nsCSSSelectorList instead of copying.
     446         162 :   AddPseudoClassInternal(new nsPseudoClassList(aType, aSelectorList));
     447         162 : }
     448             : 
     449        1927 : void nsCSSSelector::AddPseudoClassInternal(nsPseudoClassList *aPseudoClass)
     450             : {
     451        1927 :   nsPseudoClassList** list = &mPseudoClassList;
     452        2647 :   while (nullptr != *list) {
     453         360 :     list = &((*list)->mNext);
     454             :   }
     455        1927 :   *list = aPseudoClass;
     456        1927 : }
     457             : 
     458         737 : void nsCSSSelector::AddAttribute(int32_t aNameSpace, const nsString& aAttr)
     459             : {
     460         737 :   if (!aAttr.IsEmpty()) {
     461         737 :     nsAttrSelector** list = &mAttrList;
     462         841 :     while (nullptr != *list) {
     463          52 :       list = &((*list)->mNext);
     464             :     }
     465         737 :     *list = new nsAttrSelector(aNameSpace, aAttr);
     466             :   }
     467         737 : }
     468             : 
     469        1645 : void nsCSSSelector::AddAttribute(int32_t aNameSpace, const nsString& aAttr, uint8_t aFunc,
     470             :                                  const nsString& aValue,
     471             :                                  nsAttrSelector::ValueCaseSensitivity aCaseSensitivity)
     472             : {
     473        1645 :   if (!aAttr.IsEmpty()) {
     474        1645 :     nsAttrSelector** list = &mAttrList;
     475        1927 :     while (nullptr != *list) {
     476         141 :       list = &((*list)->mNext);
     477             :     }
     478        1645 :     *list = new nsAttrSelector(aNameSpace, aAttr, aFunc, aValue, aCaseSensitivity);
     479             :   }
     480        1645 : }
     481             : 
     482        3067 : void nsCSSSelector::SetOperator(char16_t aOperator)
     483             : {
     484        3067 :   mOperator = aOperator;
     485        3067 : }
     486             : 
     487        9105 : int32_t nsCSSSelector::CalcWeightWithoutNegations() const
     488             : {
     489        9105 :   int32_t weight = 0;
     490             : 
     491             : #ifdef MOZ_XUL
     492        9105 :   MOZ_ASSERT(!(IsPseudoElement() &&
     493             :                PseudoType() != CSSPseudoElementType::XULTree &&
     494             :                mClassList),
     495             :              "If non-XUL-tree pseudo-elements can have class selectors "
     496             :              "after them, specificity calculation must be updated");
     497             : #else
     498             :   MOZ_ASSERT(!(IsPseudoElement() && mClassList),
     499             :              "If pseudo-elements can have class selectors "
     500             :              "after them, specificity calculation must be updated");
     501             : #endif
     502        9105 :   MOZ_ASSERT(!(IsPseudoElement() && (mIDList || mAttrList)),
     503             :              "If pseudo-elements can have id or attribute selectors "
     504             :              "after them, specificity calculation must be updated");
     505             : 
     506        9105 :   if (nullptr != mCasedTag) {
     507        3619 :     weight += 0x000001;
     508             :   }
     509        9105 :   nsAtomList* list = mIDList;
     510       13031 :   while (nullptr != list) {
     511        1963 :     weight += 0x010000;
     512        1963 :     list = list->mNext;
     513             :   }
     514        9105 :   list = mClassList;
     515             : #ifdef MOZ_XUL
     516             :   // XUL tree pseudo-elements abuse mClassList to store some private
     517             :   // data; ignore that.
     518        9105 :   if (PseudoType() == CSSPseudoElementType::XULTree) {
     519          70 :     list = nullptr;
     520             :   }
     521             : #endif
     522       14099 :   while (nullptr != list) {
     523        2497 :     weight += 0x000100;
     524        2497 :     list = list->mNext;
     525             :   }
     526             :   // FIXME (bug 561154):  This is incorrect for :-moz-any(), which isn't
     527             :   // really a pseudo-class.  In order to handle :-moz-any() correctly,
     528             :   // we need to compute specificity after we match, based on which
     529             :   // option we matched with (and thus also need to try the
     530             :   // highest-specificity options first).
     531        9105 :   nsPseudoClassList *plist = mPseudoClassList;
     532       12959 :   while (nullptr != plist) {
     533        1927 :     weight += 0x000100;
     534        1927 :     plist = plist->mNext;
     535             :   }
     536        9105 :   nsAttrSelector* attr = mAttrList;
     537       13869 :   while (nullptr != attr) {
     538        2382 :     weight += 0x000100;
     539        2382 :     attr = attr->mNext;
     540             :   }
     541        9105 :   return weight;
     542             : }
     543             : 
     544        8531 : int32_t nsCSSSelector::CalcWeight() const
     545             : {
     546             :   // Loop over this selector and all its negations.
     547        8531 :   int32_t weight = 0;
     548       17636 :   for (const nsCSSSelector *n = this; n; n = n->mNegations) {
     549        9105 :     weight += n->CalcWeightWithoutNegations();
     550             :   }
     551        8531 :   return weight;
     552             : }
     553             : 
     554             : //
     555             : // Builds the textual representation of a selector. Called by DOM 2 CSS
     556             : // StyleRule:selectorText
     557             : //
     558             : void
     559           0 : nsCSSSelector::ToString(nsAString& aString, CSSStyleSheet* aSheet,
     560             :                         bool aAppend) const
     561             : {
     562           0 :   if (!aAppend)
     563           0 :    aString.Truncate();
     564             : 
     565             :   // selectors are linked from right-to-left, so the next selector in
     566             :   // the linked list actually precedes this one in the resulting string
     567           0 :   AutoTArray<const nsCSSSelector*, 8> stack;
     568           0 :   for (const nsCSSSelector *s = this; s; s = s->mNext) {
     569           0 :     stack.AppendElement(s);
     570             :   }
     571             : 
     572           0 :   while (!stack.IsEmpty()) {
     573           0 :     uint32_t index = stack.Length() - 1;
     574           0 :     const nsCSSSelector *s = stack.ElementAt(index);
     575           0 :     stack.RemoveElementAt(index);
     576             : 
     577           0 :     s->AppendToStringWithoutCombinators(aString, aSheet, false);
     578             : 
     579             :     // Append the combinator, if needed.
     580           0 :     if (!stack.IsEmpty()) {
     581           0 :       const nsCSSSelector *next = stack.ElementAt(index - 1);
     582           0 :       char16_t oper = s->mOperator;
     583           0 :       if (next->IsPseudoElement()) {
     584           0 :         NS_ASSERTION(oper == char16_t(':'),
     585             :                      "improperly chained pseudo element");
     586             :       } else {
     587           0 :         NS_ASSERTION(oper != char16_t(0),
     588             :                      "compound selector without combinator");
     589             : 
     590           0 :         aString.Append(char16_t(' '));
     591           0 :         if (oper != char16_t(' ')) {
     592           0 :           aString.Append(oper);
     593           0 :           aString.Append(char16_t(' '));
     594             :         }
     595             :       }
     596             :     }
     597             :   }
     598           0 : }
     599             : 
     600             : void
     601           0 : nsCSSSelector::AppendToStringWithoutCombinators(
     602             :     nsAString& aString,
     603             :     CSSStyleSheet* aSheet,
     604             :     bool aUseStandardNamespacePrefixes) const
     605             : {
     606           0 :   AppendToStringWithoutCombinatorsOrNegations(aString, aSheet, false,
     607           0 :                                               aUseStandardNamespacePrefixes);
     608             : 
     609           0 :   for (const nsCSSSelector* negation = mNegations; negation;
     610           0 :        negation = negation->mNegations) {
     611           0 :     aString.AppendLiteral(":not(");
     612           0 :     negation->AppendToStringWithoutCombinatorsOrNegations(
     613           0 :         aString, aSheet, true, aUseStandardNamespacePrefixes);
     614           0 :     aString.Append(char16_t(')'));
     615             :   }
     616           0 : }
     617             : 
     618             : #ifdef DEBUG
     619             : nsCString
     620           0 : nsCSSSelector::RestrictedSelectorToString() const
     621             : {
     622           0 :   MOZ_ASSERT(IsRestrictedSelector());
     623             : 
     624           0 :   nsString result;
     625           0 :   AppendToStringWithoutCombinators(result, nullptr, true);
     626           0 :   return NS_ConvertUTF16toUTF8(result);
     627             : }
     628             : 
     629             : static bool
     630           0 : AppendStandardNamespacePrefixToString(nsAString& aString, int32_t aNameSpace)
     631             : {
     632           0 :   if (aNameSpace == kNameSpaceID_Unknown) {
     633             :     // Wildcard namespace; no prefix to write.
     634           0 :     return false;
     635             :   }
     636           0 :   switch (aNameSpace) {
     637             :     case kNameSpaceID_None:
     638           0 :       break;
     639             :     case kNameSpaceID_XML:
     640           0 :       aString.AppendLiteral("xml");
     641           0 :       break;
     642             :     case kNameSpaceID_XHTML:
     643           0 :       aString.AppendLiteral("html");
     644           0 :       break;
     645             :     case kNameSpaceID_XLink:
     646           0 :       aString.AppendLiteral("xlink");
     647           0 :       break;
     648             :     case kNameSpaceID_XSLT:
     649           0 :       aString.AppendLiteral("xsl");
     650           0 :       break;
     651             :     case kNameSpaceID_XBL:
     652           0 :       aString.AppendLiteral("xbl");
     653           0 :       break;
     654             :     case kNameSpaceID_MathML:
     655           0 :       aString.AppendLiteral("math");
     656           0 :       break;
     657             :     case kNameSpaceID_RDF:
     658           0 :       aString.AppendLiteral("rdf");
     659           0 :       break;
     660             :     case kNameSpaceID_XUL:
     661           0 :       aString.AppendLiteral("xul");
     662           0 :       break;
     663             :     case kNameSpaceID_SVG:
     664           0 :       aString.AppendLiteral("svg");
     665           0 :       break;
     666             :     default:
     667           0 :       aString.AppendLiteral("ns");
     668           0 :       aString.AppendInt(aNameSpace);
     669           0 :       break;
     670             :   }
     671           0 :   return true;
     672             : }
     673             : #endif
     674             : 
     675             : void
     676           0 : nsCSSSelector::AppendToStringWithoutCombinatorsOrNegations
     677             :                    (nsAString& aString, CSSStyleSheet* aSheet,
     678             :                    bool aIsNegated,
     679             :                    bool aUseStandardNamespacePrefixes) const
     680             : {
     681           0 :   nsAutoString temp;
     682           0 :   bool isPseudoElement = IsPseudoElement();
     683             : 
     684             :   // For non-pseudo-element selectors or for lone pseudo-elements, deal with
     685             :   // namespace prefixes.
     686           0 :   bool wroteNamespace = false;
     687           0 :   if (!isPseudoElement || !mNext) {
     688             :     // append the namespace prefix if needed
     689           0 :     nsXMLNameSpaceMap *sheetNS = aSheet ? aSheet->GetNameSpaceMap() : nullptr;
     690             : 
     691             :     // sheetNS is non-null if and only if we had an @namespace rule.  If it's
     692             :     // null, that means that the only namespaces we could have are the
     693             :     // wildcard namespace (which can be implicit in this case) and the "none"
     694             :     // namespace, which then needs to be explicitly specified.
     695           0 :     if (aUseStandardNamespacePrefixes) {
     696             : #ifdef DEBUG
     697             :       // We have no sheet to look up prefix information from.  This is
     698             :       // only for debugging, so use some "standard" prefixes that
     699             :       // are recognizable.
     700             :       wroteNamespace =
     701           0 :         AppendStandardNamespacePrefixToString(aString, mNameSpace);
     702           0 :       if (wroteNamespace) {
     703           0 :         aString.Append(char16_t('|'));
     704             :       }
     705             : #endif
     706           0 :     } else if (!sheetNS) {
     707           0 :       NS_ASSERTION(mNameSpace == kNameSpaceID_Unknown ||
     708             :                    mNameSpace == kNameSpaceID_None,
     709             :                    "How did we get this namespace?");
     710           0 :       if (mNameSpace == kNameSpaceID_None) {
     711           0 :         aString.Append(char16_t('|'));
     712           0 :         wroteNamespace = true;
     713             :       }
     714           0 :     } else if (sheetNS->FindNameSpaceID(nullptr) == mNameSpace) {
     715             :       // We have the default namespace (possibly including the wildcard
     716             :       // namespace).  Do nothing.
     717           0 :       NS_ASSERTION(mNameSpace == kNameSpaceID_Unknown ||
     718             :                    CanBeNamespaced(aIsNegated),
     719             :                    "How did we end up with this namespace?");
     720           0 :     } else if (mNameSpace == kNameSpaceID_None) {
     721           0 :       NS_ASSERTION(CanBeNamespaced(aIsNegated),
     722             :                    "How did we end up with this namespace?");
     723           0 :       aString.Append(char16_t('|'));
     724           0 :       wroteNamespace = true;
     725           0 :     } else if (mNameSpace != kNameSpaceID_Unknown) {
     726           0 :       NS_ASSERTION(CanBeNamespaced(aIsNegated),
     727             :                    "How did we end up with this namespace?");
     728           0 :       nsIAtom *prefixAtom = sheetNS->FindPrefix(mNameSpace);
     729           0 :       NS_ASSERTION(prefixAtom, "how'd we get a non-default namespace "
     730             :                    "without a prefix?");
     731           0 :       nsStyleUtil::AppendEscapedCSSIdent(nsDependentAtomString(prefixAtom),
     732           0 :                                          aString);
     733           0 :       aString.Append(char16_t('|'));
     734           0 :       wroteNamespace = true;
     735             :     } else {
     736             :       // A selector for an element in any namespace, while the default
     737             :       // namespace is something else.  :not() is special in that the default
     738             :       // namespace is not implied for non-type selectors, so if this is a
     739             :       // negated non-type selector we don't need to output an explicit wildcard
     740             :       // namespace here, since those default to a wildcard namespace.
     741           0 :       if (CanBeNamespaced(aIsNegated)) {
     742           0 :         aString.AppendLiteral("*|");
     743           0 :         wroteNamespace = true;
     744             :       }
     745             :     }
     746             :   }
     747             : 
     748           0 :   if (!mLowercaseTag) {
     749             :     // Universal selector:  avoid writing the universal selector when we
     750             :     // can avoid it, especially since we're required to avoid it for the
     751             :     // inside of :not()
     752           0 :     if (wroteNamespace ||
     753           0 :         (!mIDList && !mClassList && !mPseudoClassList && !mAttrList &&
     754           0 :          (aIsNegated || !mNegations))) {
     755           0 :       aString.Append(char16_t('*'));
     756             :     }
     757             :   } else {
     758             :     // Append the tag name
     759           0 :     nsAutoString tag;
     760           0 :     (isPseudoElement ? mLowercaseTag : mCasedTag)->ToString(tag);
     761           0 :     if (isPseudoElement) {
     762           0 :       if (!mNext) {
     763             :         // Lone pseudo-element selector -- toss in a wildcard type selector
     764             :         // XXXldb Why?
     765           0 :         aString.Append(char16_t('*'));
     766             :       }
     767             :       // While our atoms use one colon, most pseudo-elements require two
     768             :       // colons (those not in CSS level 2) and all pseudo-elements allow
     769             :       // two colons. So serialize to the non-deprecated two colon syntax.
     770           0 :       aString.Append(char16_t(':'));
     771             :       // This should not be escaped since (a) the pseudo-element string
     772             :       // has a ":" that can't be escaped and (b) all pseudo-elements at
     773             :       // this point are known, and therefore we know they don't need
     774             :       // escaping.
     775           0 :       aString.Append(tag);
     776             :     } else {
     777           0 :       nsStyleUtil::AppendEscapedCSSIdent(tag, aString);
     778             :     }
     779             :   }
     780             : 
     781             :   // Append the id, if there is one
     782           0 :   if (mIDList) {
     783           0 :     nsAtomList* list = mIDList;
     784           0 :     while (list != nullptr) {
     785           0 :       list->mAtom->ToString(temp);
     786           0 :       aString.Append(char16_t('#'));
     787           0 :       nsStyleUtil::AppendEscapedCSSIdent(temp, aString);
     788           0 :       list = list->mNext;
     789             :     }
     790             :   }
     791             : 
     792             :   // Append each class in the linked list
     793           0 :   if (mClassList) {
     794           0 :     if (isPseudoElement) {
     795             : #ifdef MOZ_XUL
     796           0 :       MOZ_ASSERT(nsCSSAnonBoxes::IsTreePseudoElement(mLowercaseTag),
     797             :                  "must be tree pseudo-element");
     798             : 
     799           0 :       aString.Append(char16_t('('));
     800           0 :       for (nsAtomList* list = mClassList; list; list = list->mNext) {
     801           0 :         nsStyleUtil::AppendEscapedCSSIdent(nsDependentAtomString(list->mAtom), aString);
     802           0 :         aString.Append(char16_t(','));
     803             :       }
     804             :       // replace the final comma with a close-paren
     805           0 :       aString.Replace(aString.Length() - 1, 1, char16_t(')'));
     806             : #else
     807             :       NS_ERROR("Can't happen");
     808             : #endif
     809             :     } else {
     810           0 :       nsAtomList* list = mClassList;
     811           0 :       while (list != nullptr) {
     812           0 :         list->mAtom->ToString(temp);
     813           0 :         aString.Append(char16_t('.'));
     814           0 :         nsStyleUtil::AppendEscapedCSSIdent(temp, aString);
     815           0 :         list = list->mNext;
     816             :       }
     817             :     }
     818             :   }
     819             : 
     820             :   // Append each attribute selector in the linked list
     821           0 :   if (mAttrList) {
     822           0 :     nsAttrSelector* list = mAttrList;
     823           0 :     while (list != nullptr) {
     824           0 :       aString.Append(char16_t('['));
     825             :       // Append the namespace prefix
     826           0 :       if (list->mNameSpace == kNameSpaceID_Unknown) {
     827           0 :         aString.Append(char16_t('*'));
     828           0 :         aString.Append(char16_t('|'));
     829           0 :       } else if (list->mNameSpace != kNameSpaceID_None) {
     830           0 :         if (aUseStandardNamespacePrefixes) {
     831             : #ifdef DEBUG
     832           0 :           AppendStandardNamespacePrefixToString(aString, list->mNameSpace);
     833           0 :           aString.Append(char16_t('|'));
     834             : #endif
     835           0 :         } else if (aSheet) {
     836           0 :           nsXMLNameSpaceMap *sheetNS = aSheet->GetNameSpaceMap();
     837           0 :           nsIAtom *prefixAtom = sheetNS->FindPrefix(list->mNameSpace);
     838             :           // Default namespaces don't apply to attribute selectors, so
     839             :           // we must have a useful prefix.
     840           0 :           NS_ASSERTION(prefixAtom,
     841             :                        "How did we end up with a namespace if the prefix "
     842             :                        "is unknown?");
     843           0 :           nsAutoString prefix;
     844           0 :           prefixAtom->ToString(prefix);
     845           0 :           nsStyleUtil::AppendEscapedCSSIdent(prefix, aString);
     846           0 :           aString.Append(char16_t('|'));
     847             :         }
     848             :       }
     849             :       // Append the attribute name
     850           0 :       list->mCasedAttr->ToString(temp);
     851           0 :       nsStyleUtil::AppendEscapedCSSIdent(temp, aString);
     852             : 
     853           0 :       if (list->mFunction != NS_ATTR_FUNC_SET) {
     854             :         // Append the function
     855           0 :         if (list->mFunction == NS_ATTR_FUNC_INCLUDES)
     856           0 :           aString.Append(char16_t('~'));
     857           0 :         else if (list->mFunction == NS_ATTR_FUNC_DASHMATCH)
     858           0 :           aString.Append(char16_t('|'));
     859           0 :         else if (list->mFunction == NS_ATTR_FUNC_BEGINSMATCH)
     860           0 :           aString.Append(char16_t('^'));
     861           0 :         else if (list->mFunction == NS_ATTR_FUNC_ENDSMATCH)
     862           0 :           aString.Append(char16_t('$'));
     863           0 :         else if (list->mFunction == NS_ATTR_FUNC_CONTAINSMATCH)
     864           0 :           aString.Append(char16_t('*'));
     865             : 
     866           0 :         aString.Append(char16_t('='));
     867             : 
     868             :         // Append the value
     869           0 :         nsStyleUtil::AppendEscapedCSSString(list->mValue, aString);
     870             : 
     871           0 :         if (list->mValueCaseSensitivity ==
     872             :               nsAttrSelector::ValueCaseSensitivity::CaseInsensitive) {
     873           0 :           aString.Append(NS_LITERAL_STRING(" i"));
     874             :         }
     875             :       }
     876             : 
     877           0 :       aString.Append(char16_t(']'));
     878             : 
     879           0 :       list = list->mNext;
     880             :     }
     881             :   }
     882             : 
     883             :   // Append each pseudo-class in the linked list
     884           0 :   for (nsPseudoClassList* list = mPseudoClassList; list; list = list->mNext) {
     885           0 :     nsCSSPseudoClasses::PseudoTypeToString(list->mType, temp);
     886             :     // This should not be escaped since (a) the pseudo-class string
     887             :     // has a ":" that can't be escaped and (b) all pseudo-classes at
     888             :     // this point are known, and therefore we know they don't need
     889             :     // escaping.
     890           0 :     aString.Append(temp);
     891           0 :     if (list->u.mMemory) {
     892           0 :       aString.Append(char16_t('('));
     893           0 :       if (nsCSSPseudoClasses::HasStringArg(list->mType)) {
     894             :         nsStyleUtil::AppendEscapedCSSIdent(
     895           0 :           nsDependentString(list->u.mString), aString);
     896           0 :       } else if (nsCSSPseudoClasses::HasNthPairArg(list->mType)) {
     897           0 :         int32_t a = list->u.mNumbers[0],
     898           0 :                 b = list->u.mNumbers[1];
     899           0 :         temp.Truncate();
     900           0 :         if (a != 0) {
     901           0 :           if (a == -1) {
     902           0 :             temp.Append(char16_t('-'));
     903           0 :           } else if (a != 1) {
     904           0 :             temp.AppendInt(a);
     905             :           }
     906           0 :           temp.Append(char16_t('n'));
     907             :         }
     908           0 :         if (b != 0 || a == 0) {
     909           0 :           if (b >= 0 && a != 0) // check a != 0 for whether we printed above
     910           0 :             temp.Append(char16_t('+'));
     911           0 :           temp.AppendInt(b);
     912             :         }
     913           0 :         aString.Append(temp);
     914             :       } else {
     915           0 :         NS_ASSERTION(nsCSSPseudoClasses::HasSelectorListArg(list->mType),
     916             :                      "unexpected pseudo-class");
     917           0 :         nsString tmp;
     918           0 :         list->u.mSelectors->ToString(tmp, aSheet);
     919           0 :         aString.Append(tmp);
     920             :       }
     921           0 :       aString.Append(char16_t(')'));
     922             :     }
     923             :   }
     924           0 : }
     925             : 
     926             : bool
     927           0 : nsCSSSelector::CanBeNamespaced(bool aIsNegated) const
     928             : {
     929           0 :   return !aIsNegated ||
     930           0 :          (!mIDList && !mClassList && !mPseudoClassList && !mAttrList);
     931             : }
     932             : 
     933             : size_t
     934          18 : nsCSSSelector::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
     935             : {
     936          18 :   size_t n = 0;
     937          18 :   const nsCSSSelector* s = this;
     938          58 :   while (s) {
     939          20 :     n += aMallocSizeOf(s);
     940             : 
     941             :     #define MEASURE(x)   n += x ? x->SizeOfIncludingThis(aMallocSizeOf) : 0;
     942             : 
     943          20 :     MEASURE(s->mIDList);
     944          20 :     MEASURE(s->mClassList);
     945          20 :     MEASURE(s->mPseudoClassList);
     946          20 :     MEASURE(s->mNegations);
     947          20 :     MEASURE(s->mAttrList);
     948             : 
     949             :     // The following members aren't measured:
     950             :     // - s->mLowercaseTag, because it's an atom and therefore shared
     951             :     // - s->mCasedTag, because it's an atom and therefore shared
     952             : 
     953          20 :     s = s->mNext;
     954             :   }
     955          18 :   return n;
     956             : }
     957             : 
     958             : // -- nsCSSSelectorList -------------------------------
     959             : 
     960        5556 : nsCSSSelectorList::nsCSSSelectorList(void)
     961             :   : mSelectors(nullptr),
     962             :     mWeight(0),
     963        5556 :     mNext(nullptr)
     964             : {
     965        5556 :   MOZ_COUNT_CTOR(nsCSSSelectorList);
     966        5556 : }
     967             : 
     968           0 : nsCSSSelectorList::~nsCSSSelectorList()
     969             : {
     970           0 :   MOZ_COUNT_DTOR(nsCSSSelectorList);
     971           0 :   delete mSelectors;
     972           0 :   NS_CSS_DELETE_LIST_MEMBER(nsCSSSelectorList, this, mNext);
     973           0 : }
     974             : 
     975             : nsCSSSelector*
     976        8623 : nsCSSSelectorList::AddSelector(char16_t aOperator)
     977             : {
     978        8623 :   nsCSSSelector* newSel = new nsCSSSelector();
     979             : 
     980        8623 :   if (mSelectors) {
     981        3067 :     NS_ASSERTION(aOperator != char16_t(0), "chaining without combinator");
     982        3067 :     mSelectors->SetOperator(aOperator);
     983             :   } else {
     984        5556 :     NS_ASSERTION(aOperator == char16_t(0), "combinator without chaining");
     985             :   }
     986             : 
     987        8623 :   newSel->mNext = mSelectors;
     988        8623 :   mSelectors = newSel;
     989        8623 :   return newSel;
     990             : }
     991             : 
     992             : void
     993           0 : nsCSSSelectorList::RemoveRightmostSelector()
     994             : {
     995           0 :   nsCSSSelector* current = mSelectors;
     996           0 :   mSelectors = mSelectors->mNext;
     997           0 :   MOZ_ASSERT(mSelectors,
     998             :              "Rightmost selector has been removed, but now "
     999             :              "mSelectors is null");
    1000           0 :   mSelectors->SetOperator(char16_t(0));
    1001             : 
    1002             :   // Make sure that deleting current won't delete the whole list.
    1003           0 :   current->mNext = nullptr;
    1004           0 :   delete current;
    1005           0 : }
    1006             : 
    1007             : void
    1008           0 : nsCSSSelectorList::ToString(nsAString& aResult, CSSStyleSheet* aSheet)
    1009             : {
    1010           0 :   aResult.Truncate();
    1011           0 :   nsCSSSelectorList *p = this;
    1012             :   for (;;) {
    1013           0 :     p->mSelectors->ToString(aResult, aSheet, true);
    1014           0 :     p = p->mNext;
    1015           0 :     if (!p)
    1016           0 :       break;
    1017           0 :     aResult.AppendLiteral(", ");
    1018             :   }
    1019           0 : }
    1020             : 
    1021             : nsCSSSelectorList*
    1022           0 : nsCSSSelectorList::Clone(bool aDeep) const
    1023             : {
    1024           0 :   nsCSSSelectorList *result = new nsCSSSelectorList();
    1025           0 :   result->mWeight = mWeight;
    1026           0 :   NS_IF_CLONE(mSelectors);
    1027             : 
    1028           0 :   if (aDeep) {
    1029           0 :     NS_CSS_CLONE_LIST_MEMBER(nsCSSSelectorList, this, mNext, result,
    1030             :                              (false));
    1031             :   }
    1032           0 :   return result;
    1033             : }
    1034             : 
    1035             : size_t
    1036          14 : nsCSSSelectorList::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
    1037             : {
    1038          14 :   size_t n = 0;
    1039          14 :   const nsCSSSelectorList* s = this;
    1040          44 :   while (s) {
    1041          15 :     n += aMallocSizeOf(s);
    1042          15 :     n += s->mSelectors ? s->mSelectors->SizeOfIncludingThis(aMallocSizeOf) : 0;
    1043          15 :     s = s->mNext;
    1044             :   }
    1045          14 :   return n;
    1046             : }
    1047             : 
    1048             : // --------------------------------------------------------
    1049             : 
    1050             : class DOMCSSDeclarationImpl : public nsDOMCSSDeclaration
    1051             : {
    1052             : protected:
    1053             :   // Needs to be protected so we can use NS_IMPL_ADDREF_USING_AGGREGATOR.
    1054             :   virtual ~DOMCSSDeclarationImpl(void);
    1055             : 
    1056             :   // But we need to allow UniquePtr to delete us.
    1057             :   friend class mozilla::DefaultDelete<DOMCSSDeclarationImpl>;
    1058             : 
    1059             : public:
    1060             :   explicit DOMCSSDeclarationImpl(css::StyleRule *aRule);
    1061             : 
    1062             :   NS_IMETHOD GetParentRule(nsIDOMCSSRule **aParent) override;
    1063             :   virtual DeclarationBlock* GetCSSDeclaration(Operation aOperation) override;
    1064             :   virtual nsresult SetCSSDeclaration(DeclarationBlock* aDecl) override;
    1065             :   virtual void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv) override;
    1066             :   nsDOMCSSDeclaration::ServoCSSParsingEnvironment GetServoCSSParsingEnvironment() const final;
    1067             :   virtual nsIDocument* DocToUpdate() override;
    1068             : 
    1069             :   // Override |AddRef| and |Release| for being owned by StyleRule.  Also, we
    1070             :   // need to forward QI for cycle collection things to StyleRule.
    1071             :   NS_DECL_ISUPPORTS_INHERITED
    1072             : 
    1073           0 :   virtual nsINode *GetParentObject() override
    1074             :   {
    1075           0 :     return mRule ? mRule->GetDocument() : nullptr;
    1076             :   }
    1077             : 
    1078             : protected:
    1079             :   // This reference is not reference-counted. The rule object owns us and we go
    1080             :   // away when it does.
    1081             :   css::StyleRule *mRule;
    1082             : };
    1083             : 
    1084           0 : DOMCSSDeclarationImpl::DOMCSSDeclarationImpl(css::StyleRule *aRule)
    1085           0 :   : mRule(aRule)
    1086             : {
    1087           0 : }
    1088             : 
    1089           0 : DOMCSSDeclarationImpl::~DOMCSSDeclarationImpl(void)
    1090             : {
    1091           0 : }
    1092             : 
    1093           0 : NS_IMPL_ADDREF_USING_AGGREGATOR(DOMCSSDeclarationImpl, mRule)
    1094           0 : NS_IMPL_RELEASE_USING_AGGREGATOR(DOMCSSDeclarationImpl, mRule)
    1095             : 
    1096           0 : NS_INTERFACE_MAP_BEGIN(DOMCSSDeclarationImpl)
    1097           0 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
    1098             :   // We forward the cycle collection interfaces to mRule, which is
    1099             :   // never null.
    1100           0 :   if (aIID.Equals(NS_GET_IID(nsCycleCollectionISupports)) ||
    1101           0 :       aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant))) {
    1102           0 :     return mRule->QueryInterface(aIID, aInstancePtr);
    1103             :   }
    1104             :   else
    1105           0 : NS_IMPL_QUERY_TAIL_INHERITING(nsDOMCSSDeclaration)
    1106             : 
    1107             : DeclarationBlock*
    1108           0 : DOMCSSDeclarationImpl::GetCSSDeclaration(Operation aOperation)
    1109             : {
    1110           0 :   if (aOperation != eOperation_Read) {
    1111           0 :     RefPtr<CSSStyleSheet> sheet = mRule->GetStyleSheet();
    1112           0 :     if (sheet) {
    1113           0 :       sheet->WillDirty();
    1114             :     }
    1115             :   }
    1116           0 :   return mRule->GetDeclaration();
    1117             : }
    1118             : 
    1119             : void
    1120           0 : DOMCSSDeclarationImpl::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv)
    1121             : {
    1122           0 :   GetCSSParsingEnvironmentForRule(mRule, aCSSParseEnv);
    1123           0 : }
    1124             : 
    1125             : nsDOMCSSDeclaration::ServoCSSParsingEnvironment
    1126           0 : DOMCSSDeclarationImpl::GetServoCSSParsingEnvironment() const
    1127             : {
    1128           0 :   MOZ_CRASH("GetURLData shouldn't be calling on a Gecko rule");
    1129             : }
    1130             : 
    1131             : NS_IMETHODIMP
    1132           0 : DOMCSSDeclarationImpl::GetParentRule(nsIDOMCSSRule **aParent)
    1133             : {
    1134           0 :   NS_ENSURE_ARG_POINTER(aParent);
    1135             : 
    1136           0 :   NS_IF_ADDREF(*aParent = mRule);
    1137           0 :   return NS_OK;
    1138             : }
    1139             : 
    1140             : nsresult
    1141           0 : DOMCSSDeclarationImpl::SetCSSDeclaration(DeclarationBlock* aDecl)
    1142             : {
    1143           0 :   NS_PRECONDITION(mRule,
    1144             :          "can only be called when |GetCSSDeclaration| returned a declaration");
    1145             : 
    1146           0 :   nsCOMPtr<nsIDocument> doc;
    1147           0 :   RefPtr<CSSStyleSheet> sheet = mRule->GetStyleSheet();
    1148           0 :   if (sheet) {
    1149           0 :     doc = sheet->GetAssociatedDocument();
    1150             :   }
    1151             : 
    1152           0 :   mozAutoDocUpdate updateBatch(doc, UPDATE_STYLE, true);
    1153             : 
    1154           0 :   mRule->SetDeclaration(aDecl->AsGecko());
    1155             : 
    1156           0 :   if (sheet) {
    1157           0 :     sheet->DidDirty();
    1158             :   }
    1159             : 
    1160           0 :   if (doc) {
    1161           0 :     doc->StyleRuleChanged(sheet, mRule);
    1162             :   }
    1163           0 :   return NS_OK;
    1164             : }
    1165             : 
    1166             : nsIDocument*
    1167           0 : DOMCSSDeclarationImpl::DocToUpdate()
    1168             : {
    1169           0 :   return nullptr;
    1170             : }
    1171             : 
    1172             : // -- StyleRule ------------------------------------
    1173             : 
    1174             : namespace mozilla {
    1175             : namespace css {
    1176             : 
    1177             : uint16_t
    1178           0 : StyleRule::Type() const
    1179             : {
    1180           0 :   return nsIDOMCSSRule::STYLE_RULE;
    1181             : }
    1182             : 
    1183             : NS_IMETHODIMP
    1184           0 : StyleRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
    1185             : {
    1186           0 :   NS_ADDREF(*aStyle = Style());
    1187           0 :   return NS_OK;
    1188             : }
    1189             : 
    1190             : nsICSSDeclaration*
    1191           0 : StyleRule::Style()
    1192             : {
    1193           0 :   if (!mDOMDeclaration) {
    1194           0 :     mDOMDeclaration.reset(new DOMCSSDeclarationImpl(this));
    1195             :   }
    1196           0 :   return mDOMDeclaration.get();
    1197             : }
    1198             : 
    1199             : NS_IMETHODIMP
    1200           0 : StyleRule::GetCSSStyleRule(BindingStyleRule **aResult)
    1201             : {
    1202           0 :   *aResult = this;
    1203           0 :   NS_ADDREF(*aResult);
    1204           0 :   return NS_OK;
    1205             : }
    1206             : 
    1207        2933 : StyleRule::StyleRule(nsCSSSelectorList* aSelector,
    1208             :                      Declaration* aDeclaration,
    1209             :                      uint32_t aLineNumber,
    1210        2933 :                      uint32_t aColumnNumber)
    1211             :   : BindingStyleRule(aLineNumber, aColumnNumber),
    1212             :     mSelector(aSelector),
    1213        2933 :     mDeclaration(aDeclaration)
    1214             : {
    1215        2933 :   NS_PRECONDITION(aDeclaration, "must have a declaration");
    1216             : 
    1217        2933 :   mDeclaration->SetOwningRule(this);
    1218        2933 : }
    1219             : 
    1220             : // for |Clone|
    1221           0 : StyleRule::StyleRule(const StyleRule& aCopy)
    1222             :   : BindingStyleRule(aCopy),
    1223           0 :     mSelector(aCopy.mSelector ? aCopy.mSelector->Clone() : nullptr),
    1224           0 :     mDeclaration(new Declaration(*aCopy.mDeclaration))
    1225             : {
    1226           0 :   mDeclaration->SetOwningRule(this);
    1227             :   // rest is constructed lazily on existing data
    1228           0 : }
    1229             : 
    1230          48 : StyleRule::~StyleRule()
    1231             : {
    1232          16 :   delete mSelector;
    1233          16 :   DropReferences();
    1234          48 : }
    1235             : 
    1236             : void
    1237          16 : StyleRule::DropReferences()
    1238             : {
    1239          16 :   if (mDeclaration) {
    1240          16 :     mDeclaration->SetOwningRule(nullptr);
    1241             :   }
    1242          16 : }
    1243             : 
    1244             : // QueryInterface implementation for StyleRule
    1245        3061 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(StyleRule)
    1246          64 :   if (aIID.Equals(NS_GET_IID(mozilla::css::StyleRule))) {
    1247           0 :     *aInstancePtr = this;
    1248           0 :     NS_ADDREF_THIS();
    1249           0 :     return NS_OK;
    1250             :   }
    1251             :   else
    1252          64 :   NS_INTERFACE_MAP_ENTRY(nsICSSStyleRuleDOMWrapper)
    1253          64 :   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSStyleRule)
    1254          64 : NS_INTERFACE_MAP_END_INHERITING(Rule)
    1255             : 
    1256        5850 : NS_IMPL_ADDREF_INHERITED(StyleRule, Rule)
    1257        2933 : NS_IMPL_RELEASE_INHERITED(StyleRule, Rule)
    1258             : 
    1259             : NS_IMPL_CYCLE_COLLECTION_CLASS(StyleRule)
    1260          16 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(StyleRule, Rule)
    1261             :   // Keep this in sync with IsCCLeaf.
    1262             :   // Trace the wrapper for our declaration.  This just expands out
    1263             :   // NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER which we can't use
    1264             :   // directly because the wrapper is on the declaration, not on us.
    1265          16 :   if (tmp->mDOMDeclaration) {
    1266           0 :     tmp->mDOMDeclaration->TraceWrapper(aCallbacks, aClosure);
    1267             :   }
    1268          16 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
    1269           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(StyleRule, Rule)
    1270             :   // Unlink the wrapper for our declaraton.  This just expands out
    1271             :   // NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER which we can't use
    1272             :   // directly because the wrapper is on the declaration, not on us.
    1273           0 :   if (tmp->mDOMDeclaration) {
    1274           0 :     tmp->mDOMDeclaration->ReleaseWrapper(static_cast<nsISupports*>(p));
    1275             :   }
    1276           0 :   tmp->DropReferences();
    1277           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    1278           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(StyleRule, Rule)
    1279             :   // Keep this in sync with IsCCLeaf.
    1280           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    1281             : 
    1282             : bool
    1283           0 : StyleRule::IsCCLeaf() const
    1284             : {
    1285           0 :   if (!Rule::IsCCLeaf()) {
    1286           0 :     return false;
    1287             :   }
    1288             : 
    1289           0 :   return !mDOMDeclaration || !mDOMDeclaration->PreservingWrapper();
    1290             : }
    1291             : 
    1292             : /* virtual */ int32_t
    1293       11579 : StyleRule::GetType() const
    1294             : {
    1295       11579 :   return Rule::STYLE_RULE;
    1296             : }
    1297             : 
    1298             : /* virtual */ already_AddRefed<Rule>
    1299           0 : StyleRule::Clone() const
    1300             : {
    1301           0 :   RefPtr<Rule> clone = new StyleRule(*this);
    1302           0 :   return clone.forget();
    1303             : }
    1304             : 
    1305             : void
    1306           0 : StyleRule::SetDeclaration(Declaration* aDecl)
    1307             : {
    1308           0 :   if (aDecl == mDeclaration) {
    1309           0 :     return;
    1310             :   }
    1311           0 :   mDeclaration->SetOwningRule(nullptr);
    1312           0 :   mDeclaration = aDecl;
    1313           0 :   mDeclaration->SetOwningRule(this);
    1314             : }
    1315             : 
    1316             : #ifdef DEBUG
    1317             : /* virtual */ void
    1318           0 : StyleRule::List(FILE* out, int32_t aIndent) const
    1319             : {
    1320           0 :   nsAutoCString str;
    1321             :   // Indent
    1322           0 :   for (int32_t index = aIndent; --index >= 0; ) {
    1323           0 :     str.AppendLiteral("  ");
    1324             :   }
    1325             : 
    1326           0 :   if (mSelector) {
    1327           0 :     nsAutoString buffer;
    1328           0 :     mSelector->ToString(buffer, GetStyleSheet());
    1329           0 :     AppendUTF16toUTF8(buffer, str);
    1330           0 :     str.Append(' ');
    1331             :   }
    1332             : 
    1333           0 :   if (nullptr != mDeclaration) {
    1334           0 :     nsAutoString buffer;
    1335           0 :     str.AppendLiteral("{ ");
    1336           0 :     mDeclaration->ToString(buffer);
    1337           0 :     AppendUTF16toUTF8(buffer, str);
    1338           0 :     str.Append('}');
    1339           0 :     CSSStyleSheet* sheet = GetStyleSheet();
    1340           0 :     if (sheet) {
    1341           0 :       nsIURI* uri = sheet->GetSheetURI();
    1342           0 :       if (uri) {
    1343           0 :         str.Append(" /* ");
    1344           0 :         str.Append(uri->GetSpecOrDefault());
    1345           0 :         str.Append(':');
    1346           0 :         str.AppendInt(mLineNumber);
    1347           0 :         str.Append(" */");
    1348             :       }
    1349             :     }
    1350             :   }
    1351             :   else {
    1352           0 :     str.AppendLiteral("{ null declaration }");
    1353             :   }
    1354           0 :   str.Append('\n');
    1355           0 :   fprintf_stderr(out, "%s", str.get());
    1356           0 : }
    1357             : #endif
    1358             : 
    1359             : void
    1360           0 : StyleRule::GetCssTextImpl(nsAString& aCssText) const
    1361             : {
    1362           0 :   if (mSelector) {
    1363           0 :     mSelector->ToString(aCssText, GetStyleSheet());
    1364           0 :     aCssText.Append(char16_t(' '));
    1365             :   }
    1366           0 :   aCssText.Append(char16_t('{'));
    1367           0 :   aCssText.Append(char16_t(' '));
    1368           0 :   if (mDeclaration)
    1369             :   {
    1370           0 :     nsAutoString   tempString;
    1371           0 :     mDeclaration->ToString( tempString );
    1372           0 :     aCssText.Append( tempString );
    1373             :   }
    1374           0 :   aCssText.Append(char16_t(' '));
    1375           0 :   aCssText.Append(char16_t('}'));
    1376           0 : }
    1377             : 
    1378             : NS_IMETHODIMP
    1379           0 : StyleRule::GetSelectorText(nsAString& aSelectorText)
    1380             : {
    1381           0 :   if (mSelector)
    1382           0 :     mSelector->ToString(aSelectorText, GetStyleSheet());
    1383             :   else
    1384           0 :     aSelectorText.Truncate();
    1385           0 :   return NS_OK;
    1386             : }
    1387             : 
    1388             : NS_IMETHODIMP
    1389           0 : StyleRule::SetSelectorText(const nsAString& aSelectorText)
    1390             : {
    1391             :   // XXX TBI - get a parser and re-parse the selectors,
    1392             :   // XXX then need to re-compute the cascade
    1393             :   // XXX and dirty sheet
    1394           0 :   return NS_OK;
    1395             : }
    1396             : 
    1397             : /* virtual */ size_t
    1398          14 : StyleRule::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
    1399             : {
    1400          14 :   size_t n = aMallocSizeOf(this);
    1401          14 :   n += mSelector ? mSelector->SizeOfIncludingThis(aMallocSizeOf) : 0;
    1402          14 :   n += mDeclaration ? mDeclaration->SizeOfIncludingThis(aMallocSizeOf) : 0;
    1403             : 
    1404             :   // Measurement of the following members may be added later if DMD finds it is
    1405             :   // worthwhile:
    1406             :   // - mDOMRule;
    1407             : 
    1408          14 :   return n;
    1409             : }
    1410             : 
    1411             : nsCSSSelectorList*
    1412           0 : StyleRule::GetSelectorAtIndex(uint32_t aIndex, ErrorResult& rv)
    1413             : {
    1414             : 
    1415           0 :   for (nsCSSSelectorList* sel = mSelector; sel;
    1416           0 :        sel = sel->mNext, --aIndex) {
    1417           0 :     if (aIndex == 0) {
    1418           0 :       return sel;
    1419             :     }
    1420             :   }
    1421             : 
    1422             :   // Ran out of selectors
    1423           0 :   rv.Throw(NS_ERROR_INVALID_ARG);
    1424           0 :   return nullptr;
    1425             : }
    1426             : 
    1427             : uint32_t
    1428           0 : StyleRule::GetSelectorCount()
    1429             : {
    1430           0 :   uint32_t count = 0;
    1431           0 :   for (nsCSSSelectorList* sel = mSelector; sel; sel = sel->mNext) {
    1432           0 :     ++count;
    1433             :   }
    1434           0 :   return count;
    1435             : }
    1436             : 
    1437             : nsresult
    1438           0 : StyleRule::GetSelectorText(uint32_t aSelectorIndex, nsAString& aText)
    1439             : {
    1440           0 :   ErrorResult rv;
    1441           0 :   nsCSSSelectorList* sel = GetSelectorAtIndex(aSelectorIndex, rv);
    1442           0 :   if (rv.Failed()) {
    1443           0 :     return rv.StealNSResult();
    1444             :   }
    1445             : 
    1446           0 :   sel->mSelectors->ToString(aText, GetStyleSheet(), false);
    1447             : 
    1448           0 :   return NS_OK;
    1449             : }
    1450             : 
    1451             : nsresult
    1452           0 : StyleRule::GetSpecificity(uint32_t aSelectorIndex, uint64_t* aSpecificity)
    1453             : {
    1454           0 :   ErrorResult rv;
    1455           0 :   nsCSSSelectorList* sel = GetSelectorAtIndex(aSelectorIndex, rv);
    1456           0 :   if (rv.Failed()) {
    1457           0 :     return rv.StealNSResult();
    1458             :   }
    1459             : 
    1460           0 :   *aSpecificity = sel->mWeight;
    1461           0 :   return NS_OK;
    1462             : }
    1463             : 
    1464             : nsresult
    1465           0 : StyleRule::SelectorMatchesElement(Element* aElement,
    1466             :                                   uint32_t aSelectorIndex,
    1467             :                                   const nsAString& aPseudo,
    1468             :                                   bool* aMatches)
    1469             : {
    1470           0 :   ErrorResult rv;
    1471           0 :   nsCSSSelectorList* tail = GetSelectorAtIndex(aSelectorIndex, rv);
    1472           0 :   if (rv.Failed()) {
    1473           0 :     return rv.StealNSResult();
    1474             :   }
    1475             : 
    1476             :   // We want just the one list item, not the whole list tail
    1477           0 :   nsAutoPtr<nsCSSSelectorList> sel(tail->Clone(false));
    1478             : 
    1479             :   // Do not attempt to match if a pseudo element is requested and this is not
    1480             :   // a pseudo element selector, or vice versa.
    1481           0 :   if (aPseudo.IsEmpty() == sel->mSelectors->IsPseudoElement()) {
    1482           0 :     *aMatches = false;
    1483           0 :     return NS_OK;
    1484             :   }
    1485             : 
    1486           0 :   if (!aPseudo.IsEmpty()) {
    1487             :     // We need to make sure that the requested pseudo element type
    1488             :     // matches the selector pseudo element type before proceeding.
    1489           0 :     nsCOMPtr<nsIAtom> pseudoElt = NS_Atomize(aPseudo);
    1490           0 :     if (sel->mSelectors->PseudoType() != nsCSSPseudoElements::
    1491           0 :           GetPseudoType(pseudoElt, CSSEnabledState::eIgnoreEnabledState)) {
    1492           0 :       *aMatches = false;
    1493           0 :       return NS_OK;
    1494             :     }
    1495             : 
    1496             :     // We have a matching pseudo element, now remove it so we can compare
    1497             :     // directly against |element| when proceeding into SelectorListMatches.
    1498             :     // It's OK to do this - we just cloned sel and nothing else is using it.
    1499           0 :     sel->RemoveRightmostSelector();
    1500             :   }
    1501             : 
    1502             :   // XXXbz what exactly should we do with visited state here?  If we ever start
    1503             :   // caring about it, remember to do FlushPendingLinkUpdates().
    1504             :   TreeMatchContext matchingContext(false,
    1505             :                                    nsRuleWalker::eRelevantLinkUnvisited,
    1506             :                                    aElement->OwnerDoc(),
    1507           0 :                                    TreeMatchContext::eNeverMatchVisited);
    1508           0 :   *aMatches = nsCSSRuleProcessor::SelectorListMatches(aElement, matchingContext,
    1509             :                                                       sel);
    1510           0 :   return NS_OK;
    1511             : }
    1512             : 
    1513             : } // namespace css
    1514             : } // namespace mozilla

Generated by: LCOV version 1.13