layout/style/StyleRule.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/layout/style/StyleRule.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1546 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +/*
    1.10 + * representation of CSS style rules (selectors+declaration), CSS
    1.11 + * selectors, and DOM objects for style rules, selectors, and
    1.12 + * declarations
    1.13 + */
    1.14 +
    1.15 +#include "mozilla/css/StyleRule.h"
    1.16 +
    1.17 +#include "mozilla/MemoryReporting.h"
    1.18 +#include "mozilla/css/GroupRule.h"
    1.19 +#include "mozilla/css/Declaration.h"
    1.20 +#include "nsCSSStyleSheet.h"
    1.21 +#include "nsIDocument.h"
    1.22 +#include "nsIAtom.h"
    1.23 +#include "nsString.h"
    1.24 +#include "nsStyleUtil.h"
    1.25 +#include "nsICSSStyleRuleDOMWrapper.h"
    1.26 +#include "nsDOMCSSDeclaration.h"
    1.27 +#include "nsNameSpaceManager.h"
    1.28 +#include "nsXMLNameSpaceMap.h"
    1.29 +#include "nsCSSPseudoElements.h"
    1.30 +#include "nsCSSPseudoClasses.h"
    1.31 +#include "nsCSSAnonBoxes.h"
    1.32 +#include "nsTArray.h"
    1.33 +#include "nsDOMClassInfoID.h"
    1.34 +#include "nsContentUtils.h"
    1.35 +#include "nsError.h"
    1.36 +#include "mozAutoDocUpdate.h"
    1.37 +
    1.38 +class nsIDOMCSSStyleDeclaration;
    1.39 +class nsIDOMCSSStyleSheet;
    1.40 +
    1.41 +using namespace mozilla;
    1.42 +
    1.43 +#define NS_IF_CLONE(member_)                                                  \
    1.44 +  PR_BEGIN_MACRO                                                              \
    1.45 +    if (member_) {                                                            \
    1.46 +      result->member_ = member_->Clone();                                     \
    1.47 +      if (!result->member_) {                                                 \
    1.48 +        delete result;                                                        \
    1.49 +        return nullptr;                                                        \
    1.50 +      }                                                                       \
    1.51 +    }                                                                         \
    1.52 +  PR_END_MACRO
    1.53 +
    1.54 +#define NS_IF_DELETE(ptr)                                                     \
    1.55 +  PR_BEGIN_MACRO                                                              \
    1.56 +    delete ptr;                                                               \
    1.57 +    ptr = nullptr;                                                             \
    1.58 +  PR_END_MACRO
    1.59 +
    1.60 +/* ************************************************************************** */
    1.61 +
    1.62 +nsAtomList::nsAtomList(nsIAtom* aAtom)
    1.63 +  : mAtom(aAtom),
    1.64 +    mNext(nullptr)
    1.65 +{
    1.66 +  MOZ_COUNT_CTOR(nsAtomList);
    1.67 +}
    1.68 +
    1.69 +nsAtomList::nsAtomList(const nsString& aAtomValue)
    1.70 +  : mAtom(nullptr),
    1.71 +    mNext(nullptr)
    1.72 +{
    1.73 +  MOZ_COUNT_CTOR(nsAtomList);
    1.74 +  mAtom = do_GetAtom(aAtomValue);
    1.75 +}
    1.76 +
    1.77 +nsAtomList*
    1.78 +nsAtomList::Clone(bool aDeep) const
    1.79 +{
    1.80 +  nsAtomList *result = new nsAtomList(mAtom);
    1.81 +  if (!result)
    1.82 +    return nullptr;
    1.83 +
    1.84 +  if (aDeep)
    1.85 +    NS_CSS_CLONE_LIST_MEMBER(nsAtomList, this, mNext, result, (false));
    1.86 +  return result;
    1.87 +}
    1.88 +
    1.89 +size_t
    1.90 +nsAtomList::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
    1.91 +{
    1.92 +  size_t n = 0;
    1.93 +  const nsAtomList* a = this;
    1.94 +  while (a) {
    1.95 +    n += aMallocSizeOf(a);
    1.96 +
    1.97 +    // The following members aren't measured:
    1.98 +    // - a->mAtom, because it may be shared
    1.99 +
   1.100 +    a = a->mNext;
   1.101 +  }
   1.102 +  return n;
   1.103 +}
   1.104 +
   1.105 +nsAtomList::~nsAtomList(void)
   1.106 +{
   1.107 +  MOZ_COUNT_DTOR(nsAtomList);
   1.108 +  NS_CSS_DELETE_LIST_MEMBER(nsAtomList, this, mNext);
   1.109 +}
   1.110 +
   1.111 +nsPseudoClassList::nsPseudoClassList(nsCSSPseudoClasses::Type aType)
   1.112 +  : mType(aType),
   1.113 +    mNext(nullptr)
   1.114 +{
   1.115 +  NS_ASSERTION(!nsCSSPseudoClasses::HasStringArg(aType) &&
   1.116 +               !nsCSSPseudoClasses::HasNthPairArg(aType),
   1.117 +               "unexpected pseudo-class");
   1.118 +  MOZ_COUNT_CTOR(nsPseudoClassList);
   1.119 +  u.mMemory = nullptr;
   1.120 +}
   1.121 +
   1.122 +nsPseudoClassList::nsPseudoClassList(nsCSSPseudoClasses::Type aType,
   1.123 +                                     const char16_t* aString)
   1.124 +  : mType(aType),
   1.125 +    mNext(nullptr)
   1.126 +{
   1.127 +  NS_ASSERTION(nsCSSPseudoClasses::HasStringArg(aType),
   1.128 +               "unexpected pseudo-class");
   1.129 +  NS_ASSERTION(aString, "string expected");
   1.130 +  MOZ_COUNT_CTOR(nsPseudoClassList);
   1.131 +  u.mString = NS_strdup(aString);
   1.132 +}
   1.133 +
   1.134 +nsPseudoClassList::nsPseudoClassList(nsCSSPseudoClasses::Type aType,
   1.135 +                                     const int32_t* aIntPair)
   1.136 +  : mType(aType),
   1.137 +    mNext(nullptr)
   1.138 +{
   1.139 +  NS_ASSERTION(nsCSSPseudoClasses::HasNthPairArg(aType),
   1.140 +               "unexpected pseudo-class");
   1.141 +  NS_ASSERTION(aIntPair, "integer pair expected");
   1.142 +  MOZ_COUNT_CTOR(nsPseudoClassList);
   1.143 +  u.mNumbers =
   1.144 +    static_cast<int32_t*>(nsMemory::Clone(aIntPair, sizeof(int32_t) * 2));
   1.145 +}
   1.146 +
   1.147 +// adopts aSelectorList
   1.148 +nsPseudoClassList::nsPseudoClassList(nsCSSPseudoClasses::Type aType,
   1.149 +                                     nsCSSSelectorList* aSelectorList)
   1.150 +  : mType(aType),
   1.151 +    mNext(nullptr)
   1.152 +{
   1.153 +  NS_ASSERTION(nsCSSPseudoClasses::HasSelectorListArg(aType),
   1.154 +               "unexpected pseudo-class");
   1.155 +  NS_ASSERTION(aSelectorList, "selector list expected");
   1.156 +  MOZ_COUNT_CTOR(nsPseudoClassList);
   1.157 +  u.mSelectors = aSelectorList;
   1.158 +}
   1.159 +
   1.160 +nsPseudoClassList*
   1.161 +nsPseudoClassList::Clone(bool aDeep) const
   1.162 +{
   1.163 +  nsPseudoClassList *result;
   1.164 +  if (!u.mMemory) {
   1.165 +    result = new nsPseudoClassList(mType);
   1.166 +  } else if (nsCSSPseudoClasses::HasStringArg(mType)) {
   1.167 +    result = new nsPseudoClassList(mType, u.mString);
   1.168 +  } else if (nsCSSPseudoClasses::HasNthPairArg(mType)) {
   1.169 +    result = new nsPseudoClassList(mType, u.mNumbers);
   1.170 +  } else {
   1.171 +    NS_ASSERTION(nsCSSPseudoClasses::HasSelectorListArg(mType),
   1.172 +                 "unexpected pseudo-class");
   1.173 +    // This constructor adopts its selector list argument.
   1.174 +    result = new nsPseudoClassList(mType, u.mSelectors->Clone());
   1.175 +  }
   1.176 +
   1.177 +  if (aDeep)
   1.178 +    NS_CSS_CLONE_LIST_MEMBER(nsPseudoClassList, this, mNext, result,
   1.179 +                             (false));
   1.180 +
   1.181 +  return result;
   1.182 +}
   1.183 +
   1.184 +size_t
   1.185 +nsPseudoClassList::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
   1.186 +{
   1.187 +  size_t n = 0;
   1.188 +  const nsPseudoClassList* p = this;
   1.189 +  while (p) {
   1.190 +    n += aMallocSizeOf(p);
   1.191 +    if (!p->u.mMemory) {
   1.192 +      // do nothing
   1.193 +
   1.194 +    } else if (nsCSSPseudoClasses::HasStringArg(p->mType)) {
   1.195 +      n += aMallocSizeOf(p->u.mString);
   1.196 +
   1.197 +    } else if (nsCSSPseudoClasses::HasNthPairArg(p->mType)) {
   1.198 +      n += aMallocSizeOf(p->u.mNumbers);
   1.199 +
   1.200 +    } else {
   1.201 +      NS_ASSERTION(nsCSSPseudoClasses::HasSelectorListArg(p->mType),
   1.202 +                   "unexpected pseudo-class");
   1.203 +      n += p->u.mSelectors->SizeOfIncludingThis(aMallocSizeOf);
   1.204 +    }
   1.205 +    p = p->mNext;
   1.206 +  }
   1.207 +  return n;
   1.208 +}
   1.209 +
   1.210 +nsPseudoClassList::~nsPseudoClassList(void)
   1.211 +{
   1.212 +  MOZ_COUNT_DTOR(nsPseudoClassList);
   1.213 +  if (nsCSSPseudoClasses::HasSelectorListArg(mType)) {
   1.214 +    delete u.mSelectors;
   1.215 +  } else if (u.mMemory) {
   1.216 +    NS_Free(u.mMemory);
   1.217 +  }
   1.218 +  NS_CSS_DELETE_LIST_MEMBER(nsPseudoClassList, this, mNext);
   1.219 +}
   1.220 +
   1.221 +nsAttrSelector::nsAttrSelector(int32_t aNameSpace, const nsString& aAttr)
   1.222 +  : mValue(),
   1.223 +    mNext(nullptr),
   1.224 +    mLowercaseAttr(nullptr),
   1.225 +    mCasedAttr(nullptr),
   1.226 +    mNameSpace(aNameSpace),
   1.227 +    mFunction(NS_ATTR_FUNC_SET),
   1.228 +    mCaseSensitive(1)
   1.229 +{
   1.230 +  MOZ_COUNT_CTOR(nsAttrSelector);
   1.231 +
   1.232 +  nsAutoString lowercase;
   1.233 +  nsContentUtils::ASCIIToLower(aAttr, lowercase);
   1.234 +  
   1.235 +  mCasedAttr = do_GetAtom(aAttr);
   1.236 +  mLowercaseAttr = do_GetAtom(lowercase);
   1.237 +}
   1.238 +
   1.239 +nsAttrSelector::nsAttrSelector(int32_t aNameSpace, const nsString& aAttr, uint8_t aFunction, 
   1.240 +                               const nsString& aValue, bool aCaseSensitive)
   1.241 +  : mValue(aValue),
   1.242 +    mNext(nullptr),
   1.243 +    mLowercaseAttr(nullptr),
   1.244 +    mCasedAttr(nullptr),
   1.245 +    mNameSpace(aNameSpace),
   1.246 +    mFunction(aFunction),
   1.247 +    mCaseSensitive(aCaseSensitive)
   1.248 +{
   1.249 +  MOZ_COUNT_CTOR(nsAttrSelector);
   1.250 +
   1.251 +  nsAutoString lowercase;
   1.252 +  nsContentUtils::ASCIIToLower(aAttr, lowercase);
   1.253 +  
   1.254 +  mCasedAttr = do_GetAtom(aAttr);
   1.255 +  mLowercaseAttr = do_GetAtom(lowercase);
   1.256 +}
   1.257 +
   1.258 +nsAttrSelector::nsAttrSelector(int32_t aNameSpace,  nsIAtom* aLowercaseAttr,
   1.259 +                               nsIAtom* aCasedAttr, uint8_t aFunction, 
   1.260 +                               const nsString& aValue, bool aCaseSensitive)
   1.261 +  : mValue(aValue),
   1.262 +    mNext(nullptr),
   1.263 +    mLowercaseAttr(aLowercaseAttr),
   1.264 +    mCasedAttr(aCasedAttr),
   1.265 +    mNameSpace(aNameSpace),
   1.266 +    mFunction(aFunction),
   1.267 +    mCaseSensitive(aCaseSensitive)
   1.268 +{
   1.269 +  MOZ_COUNT_CTOR(nsAttrSelector);
   1.270 +}
   1.271 +
   1.272 +nsAttrSelector*
   1.273 +nsAttrSelector::Clone(bool aDeep) const
   1.274 +{
   1.275 +  nsAttrSelector *result =
   1.276 +    new nsAttrSelector(mNameSpace, mLowercaseAttr, mCasedAttr, 
   1.277 +                       mFunction, mValue, mCaseSensitive);
   1.278 +
   1.279 +  if (aDeep)
   1.280 +    NS_CSS_CLONE_LIST_MEMBER(nsAttrSelector, this, mNext, result, (false));
   1.281 +
   1.282 +  return result;
   1.283 +}
   1.284 +
   1.285 +nsAttrSelector::~nsAttrSelector(void)
   1.286 +{
   1.287 +  MOZ_COUNT_DTOR(nsAttrSelector);
   1.288 +
   1.289 +  NS_CSS_DELETE_LIST_MEMBER(nsAttrSelector, this, mNext);
   1.290 +}
   1.291 +
   1.292 +// -- nsCSSSelector -------------------------------
   1.293 +
   1.294 +nsCSSSelector::nsCSSSelector(void)
   1.295 +  : mLowercaseTag(nullptr),
   1.296 +    mCasedTag(nullptr),
   1.297 +    mIDList(nullptr),
   1.298 +    mClassList(nullptr),
   1.299 +    mPseudoClassList(nullptr),
   1.300 +    mAttrList(nullptr),
   1.301 +    mNegations(nullptr),
   1.302 +    mNext(nullptr),
   1.303 +    mNameSpace(kNameSpaceID_Unknown),
   1.304 +    mOperator(0),
   1.305 +    mPseudoType(nsCSSPseudoElements::ePseudo_NotPseudoElement)
   1.306 +{
   1.307 +  MOZ_COUNT_CTOR(nsCSSSelector);
   1.308 +  static_assert(nsCSSPseudoElements::ePseudo_MAX < INT16_MAX,
   1.309 +                "nsCSSPseudoElements::Type values overflow mPseudoType");
   1.310 +}
   1.311 +
   1.312 +nsCSSSelector*
   1.313 +nsCSSSelector::Clone(bool aDeepNext, bool aDeepNegations) const
   1.314 +{
   1.315 +  nsCSSSelector *result = new nsCSSSelector();
   1.316 +  if (!result)
   1.317 +    return nullptr;
   1.318 +
   1.319 +  result->mNameSpace = mNameSpace;
   1.320 +  result->mLowercaseTag = mLowercaseTag;
   1.321 +  result->mCasedTag = mCasedTag;
   1.322 +  result->mOperator = mOperator;
   1.323 +  result->mPseudoType = mPseudoType;
   1.324 +  
   1.325 +  NS_IF_CLONE(mIDList);
   1.326 +  NS_IF_CLONE(mClassList);
   1.327 +  NS_IF_CLONE(mPseudoClassList);
   1.328 +  NS_IF_CLONE(mAttrList);
   1.329 +
   1.330 +  // No need to worry about multiple levels of recursion since an
   1.331 +  // mNegations can't have an mNext.
   1.332 +  NS_ASSERTION(!mNegations || !mNegations->mNext,
   1.333 +               "mNegations can't have non-null mNext");
   1.334 +  if (aDeepNegations) {
   1.335 +    NS_CSS_CLONE_LIST_MEMBER(nsCSSSelector, this, mNegations, result,
   1.336 +                             (true, false));
   1.337 +  }
   1.338 +
   1.339 +  if (aDeepNext) {
   1.340 +    NS_CSS_CLONE_LIST_MEMBER(nsCSSSelector, this, mNext, result,
   1.341 +                             (false, true));
   1.342 +  }
   1.343 +
   1.344 +  return result;
   1.345 +}
   1.346 +
   1.347 +nsCSSSelector::~nsCSSSelector(void)  
   1.348 +{
   1.349 +  MOZ_COUNT_DTOR(nsCSSSelector);
   1.350 +  Reset();
   1.351 +  // No need to worry about multiple levels of recursion since an
   1.352 +  // mNegations can't have an mNext.
   1.353 +  NS_CSS_DELETE_LIST_MEMBER(nsCSSSelector, this, mNext);
   1.354 +}
   1.355 +
   1.356 +void nsCSSSelector::Reset(void)
   1.357 +{
   1.358 +  mNameSpace = kNameSpaceID_Unknown;
   1.359 +  mLowercaseTag = nullptr;
   1.360 +  mCasedTag = nullptr;
   1.361 +  NS_IF_DELETE(mIDList);
   1.362 +  NS_IF_DELETE(mClassList);
   1.363 +  NS_IF_DELETE(mPseudoClassList);
   1.364 +  NS_IF_DELETE(mAttrList);
   1.365 +  // No need to worry about multiple levels of recursion since an
   1.366 +  // mNegations can't have an mNext.
   1.367 +  NS_ASSERTION(!mNegations || !mNegations->mNext,
   1.368 +               "mNegations can't have non-null mNext");
   1.369 +  NS_CSS_DELETE_LIST_MEMBER(nsCSSSelector, this, mNegations);
   1.370 +  mOperator = char16_t(0);
   1.371 +}
   1.372 +
   1.373 +void nsCSSSelector::SetNameSpace(int32_t aNameSpace)
   1.374 +{
   1.375 +  mNameSpace = aNameSpace;
   1.376 +}
   1.377 +
   1.378 +void nsCSSSelector::SetTag(const nsString& aTag)
   1.379 +{
   1.380 +  if (aTag.IsEmpty()) {
   1.381 +    mLowercaseTag = mCasedTag =  nullptr;
   1.382 +    return;
   1.383 +  }
   1.384 +
   1.385 +  mCasedTag = do_GetAtom(aTag);
   1.386 + 
   1.387 +  nsAutoString lowercase;
   1.388 +  nsContentUtils::ASCIIToLower(aTag, lowercase);
   1.389 +  mLowercaseTag = do_GetAtom(lowercase);
   1.390 +}
   1.391 +
   1.392 +void nsCSSSelector::AddID(const nsString& aID)
   1.393 +{
   1.394 +  if (!aID.IsEmpty()) {
   1.395 +    nsAtomList** list = &mIDList;
   1.396 +    while (nullptr != *list) {
   1.397 +      list = &((*list)->mNext);
   1.398 +    }
   1.399 +    *list = new nsAtomList(aID);
   1.400 +  }
   1.401 +}
   1.402 +
   1.403 +void nsCSSSelector::AddClass(const nsString& aClass)
   1.404 +{
   1.405 +  if (!aClass.IsEmpty()) {
   1.406 +    nsAtomList** list = &mClassList;
   1.407 +    while (nullptr != *list) {
   1.408 +      list = &((*list)->mNext);
   1.409 +    }
   1.410 +    *list = new nsAtomList(aClass);
   1.411 +  }
   1.412 +}
   1.413 +
   1.414 +void nsCSSSelector::AddPseudoClass(nsCSSPseudoClasses::Type aType)
   1.415 +{
   1.416 +  AddPseudoClassInternal(new nsPseudoClassList(aType));
   1.417 +}
   1.418 +
   1.419 +void nsCSSSelector::AddPseudoClass(nsCSSPseudoClasses::Type aType,
   1.420 +                                   const char16_t* aString)
   1.421 +{
   1.422 +  AddPseudoClassInternal(new nsPseudoClassList(aType, aString));
   1.423 +}
   1.424 +
   1.425 +void nsCSSSelector::AddPseudoClass(nsCSSPseudoClasses::Type aType,
   1.426 +                                   const int32_t* aIntPair)
   1.427 +{
   1.428 +  AddPseudoClassInternal(new nsPseudoClassList(aType, aIntPair));
   1.429 +}
   1.430 +
   1.431 +void nsCSSSelector::AddPseudoClass(nsCSSPseudoClasses::Type aType,
   1.432 +                                   nsCSSSelectorList* aSelectorList)
   1.433 +{
   1.434 +  // Take ownership of nsCSSSelectorList instead of copying.
   1.435 +  AddPseudoClassInternal(new nsPseudoClassList(aType, aSelectorList));
   1.436 +}
   1.437 +
   1.438 +void nsCSSSelector::AddPseudoClassInternal(nsPseudoClassList *aPseudoClass)
   1.439 +{
   1.440 +  nsPseudoClassList** list = &mPseudoClassList;
   1.441 +  while (nullptr != *list) {
   1.442 +    list = &((*list)->mNext);
   1.443 +  }
   1.444 +  *list = aPseudoClass;
   1.445 +}
   1.446 +
   1.447 +void nsCSSSelector::AddAttribute(int32_t aNameSpace, const nsString& aAttr)
   1.448 +{
   1.449 +  if (!aAttr.IsEmpty()) {
   1.450 +    nsAttrSelector** list = &mAttrList;
   1.451 +    while (nullptr != *list) {
   1.452 +      list = &((*list)->mNext);
   1.453 +    }
   1.454 +    *list = new nsAttrSelector(aNameSpace, aAttr);
   1.455 +  }
   1.456 +}
   1.457 +
   1.458 +void nsCSSSelector::AddAttribute(int32_t aNameSpace, const nsString& aAttr, uint8_t aFunc, 
   1.459 +                                 const nsString& aValue, bool aCaseSensitive)
   1.460 +{
   1.461 +  if (!aAttr.IsEmpty()) {
   1.462 +    nsAttrSelector** list = &mAttrList;
   1.463 +    while (nullptr != *list) {
   1.464 +      list = &((*list)->mNext);
   1.465 +    }
   1.466 +    *list = new nsAttrSelector(aNameSpace, aAttr, aFunc, aValue, aCaseSensitive);
   1.467 +  }
   1.468 +}
   1.469 +
   1.470 +void nsCSSSelector::SetOperator(char16_t aOperator)
   1.471 +{
   1.472 +  mOperator = aOperator;
   1.473 +}
   1.474 +
   1.475 +int32_t nsCSSSelector::CalcWeightWithoutNegations() const
   1.476 +{
   1.477 +  int32_t weight = 0;
   1.478 +
   1.479 +#ifdef MOZ_XUL
   1.480 +  MOZ_ASSERT(!(IsPseudoElement() &&
   1.481 +               PseudoType() != nsCSSPseudoElements::ePseudo_XULTree &&
   1.482 +               mClassList),
   1.483 +             "If non-XUL-tree pseudo-elements can have class selectors "
   1.484 +             "after them, specificity calculation must be updated");
   1.485 +#else
   1.486 +  MOZ_ASSERT(!(IsPseudoElement() && mClassList),
   1.487 +             "If pseudo-elements can have class selectors "
   1.488 +             "after them, specificity calculation must be updated");
   1.489 +#endif
   1.490 +  MOZ_ASSERT(!(IsPseudoElement() && (mIDList || mAttrList)),
   1.491 +             "If pseudo-elements can have id or attribute selectors "
   1.492 +             "after them, specificity calculation must be updated");
   1.493 +
   1.494 +  if (nullptr != mCasedTag) {
   1.495 +    weight += 0x000001;
   1.496 +  }
   1.497 +  nsAtomList* list = mIDList;
   1.498 +  while (nullptr != list) {
   1.499 +    weight += 0x010000;
   1.500 +    list = list->mNext;
   1.501 +  }
   1.502 +  list = mClassList;
   1.503 +#ifdef MOZ_XUL
   1.504 +  // XUL tree pseudo-elements abuse mClassList to store some private
   1.505 +  // data; ignore that.
   1.506 +  if (PseudoType() == nsCSSPseudoElements::ePseudo_XULTree) {
   1.507 +    list = nullptr;
   1.508 +  }
   1.509 +#endif
   1.510 +  while (nullptr != list) {
   1.511 +    weight += 0x000100;
   1.512 +    list = list->mNext;
   1.513 +  }
   1.514 +  // FIXME (bug 561154):  This is incorrect for :-moz-any(), which isn't
   1.515 +  // really a pseudo-class.  In order to handle :-moz-any() correctly,
   1.516 +  // we need to compute specificity after we match, based on which
   1.517 +  // option we matched with (and thus also need to try the
   1.518 +  // highest-specificity options first).
   1.519 +  nsPseudoClassList *plist = mPseudoClassList;
   1.520 +  while (nullptr != plist) {
   1.521 +    weight += 0x000100;
   1.522 +    plist = plist->mNext;
   1.523 +  }
   1.524 +  nsAttrSelector* attr = mAttrList;
   1.525 +  while (nullptr != attr) {
   1.526 +    weight += 0x000100;
   1.527 +    attr = attr->mNext;
   1.528 +  }
   1.529 +  return weight;
   1.530 +}
   1.531 +
   1.532 +int32_t nsCSSSelector::CalcWeight() const
   1.533 +{
   1.534 +  // Loop over this selector and all its negations.
   1.535 +  int32_t weight = 0;
   1.536 +  for (const nsCSSSelector *n = this; n; n = n->mNegations) {
   1.537 +    weight += n->CalcWeightWithoutNegations();
   1.538 +  }
   1.539 +  return weight;
   1.540 +}
   1.541 +
   1.542 +//
   1.543 +// Builds the textual representation of a selector. Called by DOM 2 CSS 
   1.544 +// StyleRule:selectorText
   1.545 +//
   1.546 +void
   1.547 +nsCSSSelector::ToString(nsAString& aString, nsCSSStyleSheet* aSheet,
   1.548 +                        bool aAppend) const
   1.549 +{
   1.550 +  if (!aAppend)
   1.551 +   aString.Truncate();
   1.552 +
   1.553 +  // selectors are linked from right-to-left, so the next selector in
   1.554 +  // the linked list actually precedes this one in the resulting string
   1.555 +  nsAutoTArray<const nsCSSSelector*, 8> stack;
   1.556 +  for (const nsCSSSelector *s = this; s; s = s->mNext) {
   1.557 +    stack.AppendElement(s);
   1.558 +  }
   1.559 +
   1.560 +  while (!stack.IsEmpty()) {
   1.561 +    uint32_t index = stack.Length() - 1;
   1.562 +    const nsCSSSelector *s = stack.ElementAt(index);
   1.563 +    stack.RemoveElementAt(index);
   1.564 +
   1.565 +    s->AppendToStringWithoutCombinators(aString, aSheet);
   1.566 +
   1.567 +    // Append the combinator, if needed.
   1.568 +    if (!stack.IsEmpty()) {
   1.569 +      const nsCSSSelector *next = stack.ElementAt(index - 1);
   1.570 +      char16_t oper = s->mOperator;
   1.571 +      if (next->IsPseudoElement()) {
   1.572 +        NS_ASSERTION(oper == char16_t(':'),
   1.573 +                     "improperly chained pseudo element");
   1.574 +      } else {
   1.575 +        NS_ASSERTION(oper != char16_t(0),
   1.576 +                     "compound selector without combinator");
   1.577 +
   1.578 +        aString.Append(char16_t(' '));
   1.579 +        if (oper != char16_t(' ')) {
   1.580 +          aString.Append(oper);
   1.581 +          aString.Append(char16_t(' '));
   1.582 +        }
   1.583 +      }
   1.584 +    }
   1.585 +  }
   1.586 +}
   1.587 +
   1.588 +void
   1.589 +nsCSSSelector::AppendToStringWithoutCombinators
   1.590 +                   (nsAString& aString, nsCSSStyleSheet* aSheet) const
   1.591 +{
   1.592 +  AppendToStringWithoutCombinatorsOrNegations(aString, aSheet, false);
   1.593 +
   1.594 +  for (const nsCSSSelector* negation = mNegations; negation;
   1.595 +       negation = negation->mNegations) {
   1.596 +    aString.AppendLiteral(":not(");
   1.597 +    negation->AppendToStringWithoutCombinatorsOrNegations(aString, aSheet,
   1.598 +                                                          true);
   1.599 +    aString.Append(char16_t(')'));
   1.600 +  }
   1.601 +}
   1.602 +
   1.603 +void
   1.604 +nsCSSSelector::AppendToStringWithoutCombinatorsOrNegations
   1.605 +                   (nsAString& aString, nsCSSStyleSheet* aSheet,
   1.606 +                   bool aIsNegated) const
   1.607 +{
   1.608 +  nsAutoString temp;
   1.609 +  bool isPseudoElement = IsPseudoElement();
   1.610 +
   1.611 +  // For non-pseudo-element selectors or for lone pseudo-elements, deal with
   1.612 +  // namespace prefixes.
   1.613 +  bool wroteNamespace = false;
   1.614 +  if (!isPseudoElement || !mNext) {
   1.615 +    // append the namespace prefix if needed
   1.616 +    nsXMLNameSpaceMap *sheetNS = aSheet ? aSheet->GetNameSpaceMap() : nullptr;
   1.617 +
   1.618 +    // sheetNS is non-null if and only if we had an @namespace rule.  If it's
   1.619 +    // null, that means that the only namespaces we could have are the
   1.620 +    // wildcard namespace (which can be implicit in this case) and the "none"
   1.621 +    // namespace, which then needs to be explicitly specified.
   1.622 +    if (!sheetNS) {
   1.623 +      NS_ASSERTION(mNameSpace == kNameSpaceID_Unknown ||
   1.624 +                   mNameSpace == kNameSpaceID_None,
   1.625 +                   "How did we get this namespace?");
   1.626 +      if (mNameSpace == kNameSpaceID_None) {
   1.627 +        aString.Append(char16_t('|'));
   1.628 +        wroteNamespace = true;
   1.629 +      }
   1.630 +    } else if (sheetNS->FindNameSpaceID(nullptr) == mNameSpace) {
   1.631 +      // We have the default namespace (possibly including the wildcard
   1.632 +      // namespace).  Do nothing.
   1.633 +      NS_ASSERTION(mNameSpace == kNameSpaceID_Unknown ||
   1.634 +                   CanBeNamespaced(aIsNegated),
   1.635 +                   "How did we end up with this namespace?");
   1.636 +    } else if (mNameSpace == kNameSpaceID_None) {
   1.637 +      NS_ASSERTION(CanBeNamespaced(aIsNegated),
   1.638 +                   "How did we end up with this namespace?");
   1.639 +      aString.Append(char16_t('|'));
   1.640 +      wroteNamespace = true;
   1.641 +    } else if (mNameSpace != kNameSpaceID_Unknown) {
   1.642 +      NS_ASSERTION(CanBeNamespaced(aIsNegated),
   1.643 +                   "How did we end up with this namespace?");
   1.644 +      nsIAtom *prefixAtom = sheetNS->FindPrefix(mNameSpace);
   1.645 +      NS_ASSERTION(prefixAtom, "how'd we get a non-default namespace "
   1.646 +                   "without a prefix?");
   1.647 +      nsStyleUtil::AppendEscapedCSSIdent(nsDependentAtomString(prefixAtom),
   1.648 +                                         aString);
   1.649 +      aString.Append(char16_t('|'));
   1.650 +      wroteNamespace = true;
   1.651 +    } else {
   1.652 +      // A selector for an element in any namespace, while the default
   1.653 +      // namespace is something else.  :not() is special in that the default
   1.654 +      // namespace is not implied for non-type selectors, so if this is a
   1.655 +      // negated non-type selector we don't need to output an explicit wildcard
   1.656 +      // namespace here, since those default to a wildcard namespace.
   1.657 +      if (CanBeNamespaced(aIsNegated)) {
   1.658 +        aString.AppendLiteral("*|");
   1.659 +        wroteNamespace = true;
   1.660 +      }
   1.661 +    }
   1.662 +  }
   1.663 +      
   1.664 +  if (!mLowercaseTag) {
   1.665 +    // Universal selector:  avoid writing the universal selector when we
   1.666 +    // can avoid it, especially since we're required to avoid it for the
   1.667 +    // inside of :not()
   1.668 +    if (wroteNamespace ||
   1.669 +        (!mIDList && !mClassList && !mPseudoClassList && !mAttrList &&
   1.670 +         (aIsNegated || !mNegations))) {
   1.671 +      aString.Append(char16_t('*'));
   1.672 +    }
   1.673 +  } else {
   1.674 +    // Append the tag name
   1.675 +    nsAutoString tag;
   1.676 +    (isPseudoElement ? mLowercaseTag : mCasedTag)->ToString(tag);
   1.677 +    if (isPseudoElement) {
   1.678 +      if (!mNext) {
   1.679 +        // Lone pseudo-element selector -- toss in a wildcard type selector
   1.680 +        // XXXldb Why?
   1.681 +        aString.Append(char16_t('*'));
   1.682 +      }
   1.683 +      if (!nsCSSPseudoElements::IsCSS2PseudoElement(mLowercaseTag)) {
   1.684 +        aString.Append(char16_t(':'));
   1.685 +      }
   1.686 +      // This should not be escaped since (a) the pseudo-element string
   1.687 +      // has a ":" that can't be escaped and (b) all pseudo-elements at
   1.688 +      // this point are known, and therefore we know they don't need
   1.689 +      // escaping.
   1.690 +      aString.Append(tag);
   1.691 +    } else {
   1.692 +      nsStyleUtil::AppendEscapedCSSIdent(tag, aString);
   1.693 +    }
   1.694 +  }
   1.695 +
   1.696 +  // Append the id, if there is one
   1.697 +  if (mIDList) {
   1.698 +    nsAtomList* list = mIDList;
   1.699 +    while (list != nullptr) {
   1.700 +      list->mAtom->ToString(temp);
   1.701 +      aString.Append(char16_t('#'));
   1.702 +      nsStyleUtil::AppendEscapedCSSIdent(temp, aString);
   1.703 +      list = list->mNext;
   1.704 +    }
   1.705 +  }
   1.706 +
   1.707 +  // Append each class in the linked list
   1.708 +  if (mClassList) {
   1.709 +    if (isPseudoElement) {
   1.710 +#ifdef MOZ_XUL
   1.711 +      NS_ABORT_IF_FALSE(nsCSSAnonBoxes::IsTreePseudoElement(mLowercaseTag),
   1.712 +                        "must be tree pseudo-element");
   1.713 +
   1.714 +      aString.Append(char16_t('('));
   1.715 +      for (nsAtomList* list = mClassList; list; list = list->mNext) {
   1.716 +        nsStyleUtil::AppendEscapedCSSIdent(nsDependentAtomString(list->mAtom), aString);
   1.717 +        aString.Append(char16_t(','));
   1.718 +      }
   1.719 +      // replace the final comma with a close-paren
   1.720 +      aString.Replace(aString.Length() - 1, 1, char16_t(')'));
   1.721 +#else
   1.722 +      NS_ERROR("Can't happen");
   1.723 +#endif
   1.724 +    } else {
   1.725 +      nsAtomList* list = mClassList;
   1.726 +      while (list != nullptr) {
   1.727 +        list->mAtom->ToString(temp);
   1.728 +        aString.Append(char16_t('.'));
   1.729 +        nsStyleUtil::AppendEscapedCSSIdent(temp, aString);
   1.730 +        list = list->mNext;
   1.731 +      }
   1.732 +    }
   1.733 +  }
   1.734 +
   1.735 +  // Append each attribute selector in the linked list
   1.736 +  if (mAttrList) {
   1.737 +    nsAttrSelector* list = mAttrList;
   1.738 +    while (list != nullptr) {
   1.739 +      aString.Append(char16_t('['));
   1.740 +      // Append the namespace prefix
   1.741 +      if (list->mNameSpace == kNameSpaceID_Unknown) {
   1.742 +        aString.Append(char16_t('*'));
   1.743 +        aString.Append(char16_t('|'));
   1.744 +      } else if (list->mNameSpace != kNameSpaceID_None) {
   1.745 +        if (aSheet) {
   1.746 +          nsXMLNameSpaceMap *sheetNS = aSheet->GetNameSpaceMap();
   1.747 +          nsIAtom *prefixAtom = sheetNS->FindPrefix(list->mNameSpace);
   1.748 +          // Default namespaces don't apply to attribute selectors, so
   1.749 +          // we must have a useful prefix.
   1.750 +          NS_ASSERTION(prefixAtom,
   1.751 +                       "How did we end up with a namespace if the prefix "
   1.752 +                       "is unknown?");
   1.753 +          nsAutoString prefix;
   1.754 +          prefixAtom->ToString(prefix);
   1.755 +          nsStyleUtil::AppendEscapedCSSIdent(prefix, aString);
   1.756 +          aString.Append(char16_t('|'));
   1.757 +        }
   1.758 +      }
   1.759 +      // Append the attribute name
   1.760 +      list->mCasedAttr->ToString(temp);
   1.761 +      nsStyleUtil::AppendEscapedCSSIdent(temp, aString);
   1.762 +
   1.763 +      if (list->mFunction != NS_ATTR_FUNC_SET) {
   1.764 +        // Append the function
   1.765 +        if (list->mFunction == NS_ATTR_FUNC_INCLUDES)
   1.766 +          aString.Append(char16_t('~'));
   1.767 +        else if (list->mFunction == NS_ATTR_FUNC_DASHMATCH)
   1.768 +          aString.Append(char16_t('|'));
   1.769 +        else if (list->mFunction == NS_ATTR_FUNC_BEGINSMATCH)
   1.770 +          aString.Append(char16_t('^'));
   1.771 +        else if (list->mFunction == NS_ATTR_FUNC_ENDSMATCH)
   1.772 +          aString.Append(char16_t('$'));
   1.773 +        else if (list->mFunction == NS_ATTR_FUNC_CONTAINSMATCH)
   1.774 +          aString.Append(char16_t('*'));
   1.775 +
   1.776 +        aString.Append(char16_t('='));
   1.777 +      
   1.778 +        // Append the value
   1.779 +        nsStyleUtil::AppendEscapedCSSString(list->mValue, aString);
   1.780 +      }
   1.781 +
   1.782 +      aString.Append(char16_t(']'));
   1.783 +      
   1.784 +      list = list->mNext;
   1.785 +    }
   1.786 +  }
   1.787 +
   1.788 +  // Append each pseudo-class in the linked list
   1.789 +  for (nsPseudoClassList* list = mPseudoClassList; list; list = list->mNext) {
   1.790 +    nsCSSPseudoClasses::PseudoTypeToString(list->mType, temp);
   1.791 +    // This should not be escaped since (a) the pseudo-class string
   1.792 +    // has a ":" that can't be escaped and (b) all pseudo-classes at
   1.793 +    // this point are known, and therefore we know they don't need
   1.794 +    // escaping.
   1.795 +    aString.Append(temp);
   1.796 +    if (list->u.mMemory) {
   1.797 +      aString.Append(char16_t('('));
   1.798 +      if (nsCSSPseudoClasses::HasStringArg(list->mType)) {
   1.799 +        nsStyleUtil::AppendEscapedCSSIdent(
   1.800 +          nsDependentString(list->u.mString), aString);
   1.801 +      } else if (nsCSSPseudoClasses::HasNthPairArg(list->mType)) {
   1.802 +        int32_t a = list->u.mNumbers[0],
   1.803 +                b = list->u.mNumbers[1];
   1.804 +        temp.Truncate();
   1.805 +        if (a != 0) {
   1.806 +          if (a == -1) {
   1.807 +            temp.Append(char16_t('-'));
   1.808 +          } else if (a != 1) {
   1.809 +            temp.AppendInt(a);
   1.810 +          }
   1.811 +          temp.Append(char16_t('n'));
   1.812 +        }
   1.813 +        if (b != 0 || a == 0) {
   1.814 +          if (b >= 0 && a != 0) // check a != 0 for whether we printed above
   1.815 +            temp.Append(char16_t('+'));
   1.816 +          temp.AppendInt(b);
   1.817 +        }
   1.818 +        aString.Append(temp);
   1.819 +      } else {
   1.820 +        NS_ASSERTION(nsCSSPseudoClasses::HasSelectorListArg(list->mType),
   1.821 +                     "unexpected pseudo-class");
   1.822 +        nsString tmp;
   1.823 +        list->u.mSelectors->ToString(tmp, aSheet);
   1.824 +        aString.Append(tmp);
   1.825 +      }
   1.826 +      aString.Append(char16_t(')'));
   1.827 +    }
   1.828 +  }
   1.829 +}
   1.830 +
   1.831 +bool
   1.832 +nsCSSSelector::CanBeNamespaced(bool aIsNegated) const
   1.833 +{
   1.834 +  return !aIsNegated ||
   1.835 +         (!mIDList && !mClassList && !mPseudoClassList && !mAttrList);
   1.836 +}
   1.837 +
   1.838 +size_t
   1.839 +nsCSSSelector::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
   1.840 +{
   1.841 +  size_t n = 0;
   1.842 +  const nsCSSSelector* s = this;
   1.843 +  while (s) {
   1.844 +    n += aMallocSizeOf(s);
   1.845 +
   1.846 +    #define MEASURE(x)   n += x ? x->SizeOfIncludingThis(aMallocSizeOf) : 0;
   1.847 +
   1.848 +    MEASURE(s->mIDList);
   1.849 +    MEASURE(s->mClassList);
   1.850 +    MEASURE(s->mPseudoClassList);
   1.851 +    MEASURE(s->mNegations);
   1.852 +
   1.853 +    // Measurement of the following members may be added later if DMD finds it is
   1.854 +    // worthwhile:
   1.855 +    // - s->mAttrList
   1.856 +    //
   1.857 +    // The following members aren't measured:
   1.858 +    // - s->mLowercaseTag, because it's an atom and therefore shared
   1.859 +    // - s->mCasedTag, because it's an atom and therefore shared
   1.860 +
   1.861 +    s = s->mNext;
   1.862 +  }
   1.863 +  return n;
   1.864 +}
   1.865 +
   1.866 +// -- nsCSSSelectorList -------------------------------
   1.867 +
   1.868 +nsCSSSelectorList::nsCSSSelectorList(void)
   1.869 +  : mSelectors(nullptr),
   1.870 +    mWeight(0),
   1.871 +    mNext(nullptr)
   1.872 +{
   1.873 +  MOZ_COUNT_CTOR(nsCSSSelectorList);
   1.874 +}
   1.875 +
   1.876 +nsCSSSelectorList::~nsCSSSelectorList()
   1.877 +{
   1.878 +  MOZ_COUNT_DTOR(nsCSSSelectorList);
   1.879 +  delete mSelectors;
   1.880 +  NS_CSS_DELETE_LIST_MEMBER(nsCSSSelectorList, this, mNext);
   1.881 +}
   1.882 +
   1.883 +nsCSSSelector*
   1.884 +nsCSSSelectorList::AddSelector(char16_t aOperator)
   1.885 +{
   1.886 +  nsCSSSelector* newSel = new nsCSSSelector();
   1.887 +
   1.888 +  if (mSelectors) {
   1.889 +    NS_ASSERTION(aOperator != char16_t(0), "chaining without combinator");
   1.890 +    mSelectors->SetOperator(aOperator);
   1.891 +  } else {
   1.892 +    NS_ASSERTION(aOperator == char16_t(0), "combinator without chaining");
   1.893 +  }
   1.894 +
   1.895 +  newSel->mNext = mSelectors;
   1.896 +  mSelectors = newSel;
   1.897 +  return newSel;
   1.898 +}
   1.899 +
   1.900 +void
   1.901 +nsCSSSelectorList::ToString(nsAString& aResult, nsCSSStyleSheet* aSheet)
   1.902 +{
   1.903 +  aResult.Truncate();
   1.904 +  nsCSSSelectorList *p = this;
   1.905 +  for (;;) {
   1.906 +    p->mSelectors->ToString(aResult, aSheet, true);
   1.907 +    p = p->mNext;
   1.908 +    if (!p)
   1.909 +      break;
   1.910 +    aResult.AppendLiteral(", ");
   1.911 +  }
   1.912 +}
   1.913 +
   1.914 +nsCSSSelectorList*
   1.915 +nsCSSSelectorList::Clone(bool aDeep) const
   1.916 +{
   1.917 +  nsCSSSelectorList *result = new nsCSSSelectorList();
   1.918 +  result->mWeight = mWeight;
   1.919 +  NS_IF_CLONE(mSelectors);
   1.920 +
   1.921 +  if (aDeep) {
   1.922 +    NS_CSS_CLONE_LIST_MEMBER(nsCSSSelectorList, this, mNext, result,
   1.923 +                             (false));
   1.924 +  }
   1.925 +  return result;
   1.926 +}
   1.927 +
   1.928 +size_t
   1.929 +nsCSSSelectorList::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
   1.930 +{
   1.931 +  size_t n = 0;
   1.932 +  const nsCSSSelectorList* s = this;
   1.933 +  while (s) {
   1.934 +    n += aMallocSizeOf(s);
   1.935 +    n += s->mSelectors ? s->mSelectors->SizeOfIncludingThis(aMallocSizeOf) : 0;
   1.936 +    s = s->mNext;
   1.937 +  }
   1.938 +  return n;
   1.939 +}
   1.940 +
   1.941 +// -- ImportantRule ----------------------------------
   1.942 +
   1.943 +namespace mozilla {
   1.944 +namespace css {
   1.945 +
   1.946 +ImportantRule::ImportantRule(Declaration* aDeclaration)
   1.947 +  : mDeclaration(aDeclaration)
   1.948 +{
   1.949 +}
   1.950 +
   1.951 +ImportantRule::~ImportantRule()
   1.952 +{
   1.953 +}
   1.954 +
   1.955 +NS_IMPL_ISUPPORTS(ImportantRule, nsIStyleRule)
   1.956 +
   1.957 +/* virtual */ void
   1.958 +ImportantRule::MapRuleInfoInto(nsRuleData* aRuleData)
   1.959 +{
   1.960 +  mDeclaration->MapImportantRuleInfoInto(aRuleData);
   1.961 +}
   1.962 +
   1.963 +#ifdef DEBUG
   1.964 +/* virtual */ void
   1.965 +ImportantRule::List(FILE* out, int32_t aIndent) const
   1.966 +{
   1.967 +  // Indent
   1.968 +  for (int32_t index = aIndent; --index >= 0; ) fputs("  ", out);
   1.969 +
   1.970 +  fprintf(out, "! Important declaration=%p\n",
   1.971 +          static_cast<void*>(mDeclaration));
   1.972 +}
   1.973 +#endif
   1.974 +
   1.975 +} // namespace css
   1.976 +} // namespace mozilla
   1.977 +
   1.978 +// --------------------------------------------------------
   1.979 +
   1.980 +namespace mozilla {
   1.981 +namespace css {
   1.982 +class DOMCSSStyleRule;
   1.983 +}
   1.984 +}
   1.985 +
   1.986 +class DOMCSSDeclarationImpl : public nsDOMCSSDeclaration
   1.987 +{
   1.988 +public:
   1.989 +  DOMCSSDeclarationImpl(css::StyleRule *aRule);
   1.990 +  virtual ~DOMCSSDeclarationImpl(void);
   1.991 +
   1.992 +  NS_IMETHOD GetParentRule(nsIDOMCSSRule **aParent) MOZ_OVERRIDE;
   1.993 +  void DropReference(void);
   1.994 +  virtual css::Declaration* GetCSSDeclaration(bool aAllocate) MOZ_OVERRIDE;
   1.995 +  virtual nsresult SetCSSDeclaration(css::Declaration* aDecl) MOZ_OVERRIDE;
   1.996 +  virtual void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv) MOZ_OVERRIDE;
   1.997 +  virtual nsIDocument* DocToUpdate() MOZ_OVERRIDE;
   1.998 +
   1.999 +  // Override |AddRef| and |Release| for being a member of
  1.1000 +  // |DOMCSSStyleRule|.  Also, we need to forward QI for cycle
  1.1001 +  // collection things to DOMCSSStyleRule.
  1.1002 +  NS_DECL_ISUPPORTS_INHERITED
  1.1003 +
  1.1004 +  virtual nsINode *GetParentObject() MOZ_OVERRIDE
  1.1005 +  {
  1.1006 +    return mRule ? mRule->GetDocument() : nullptr;
  1.1007 +  }
  1.1008 +
  1.1009 +  friend class css::DOMCSSStyleRule;
  1.1010 +
  1.1011 +protected:
  1.1012 +  // This reference is not reference-counted. The rule object tells us
  1.1013 +  // when it's about to go away.
  1.1014 +  css::StyleRule *mRule;
  1.1015 +
  1.1016 +  inline css::DOMCSSStyleRule* DomRule();
  1.1017 +
  1.1018 +private:
  1.1019 +  // NOT TO BE IMPLEMENTED
  1.1020 +  // This object cannot be allocated on its own.  It must be a member of
  1.1021 +  // DOMCSSStyleRule.
  1.1022 +  void* operator new(size_t size) CPP_THROW_NEW;
  1.1023 +};
  1.1024 +
  1.1025 +namespace mozilla {
  1.1026 +namespace css {
  1.1027 +
  1.1028 +class DOMCSSStyleRule : public nsICSSStyleRuleDOMWrapper
  1.1029 +{
  1.1030 +public:
  1.1031 +  DOMCSSStyleRule(StyleRule *aRule);
  1.1032 +  virtual ~DOMCSSStyleRule();
  1.1033 +
  1.1034 +  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
  1.1035 +  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMCSSStyleRule)
  1.1036 +  NS_DECL_NSIDOMCSSRULE
  1.1037 +  NS_DECL_NSIDOMCSSSTYLERULE
  1.1038 +
  1.1039 +  // nsICSSStyleRuleDOMWrapper
  1.1040 +  NS_IMETHOD GetCSSStyleRule(StyleRule **aResult);
  1.1041 +
  1.1042 +  DOMCSSDeclarationImpl* DOMDeclaration() { return &mDOMDeclaration; }
  1.1043 +
  1.1044 +  friend class ::DOMCSSDeclarationImpl;
  1.1045 +
  1.1046 +protected:
  1.1047 +  DOMCSSDeclarationImpl mDOMDeclaration;
  1.1048 +
  1.1049 +  StyleRule* Rule() {
  1.1050 +    return mDOMDeclaration.mRule;
  1.1051 +  }
  1.1052 +};
  1.1053 +
  1.1054 +} // namespace css
  1.1055 +} // namespace mozilla
  1.1056 +
  1.1057 +DOMCSSDeclarationImpl::DOMCSSDeclarationImpl(css::StyleRule *aRule)
  1.1058 +  : mRule(aRule)
  1.1059 +{
  1.1060 +  MOZ_COUNT_CTOR(DOMCSSDeclarationImpl);
  1.1061 +}
  1.1062 +
  1.1063 +DOMCSSDeclarationImpl::~DOMCSSDeclarationImpl(void)
  1.1064 +{
  1.1065 +  NS_ASSERTION(!mRule, "DropReference not called.");
  1.1066 +
  1.1067 +  MOZ_COUNT_DTOR(DOMCSSDeclarationImpl);
  1.1068 +}
  1.1069 +
  1.1070 +inline css::DOMCSSStyleRule* DOMCSSDeclarationImpl::DomRule()
  1.1071 +{
  1.1072 +  return reinterpret_cast<css::DOMCSSStyleRule*>
  1.1073 +                         (reinterpret_cast<char*>(this) -
  1.1074 +           offsetof(css::DOMCSSStyleRule, mDOMDeclaration));
  1.1075 +}
  1.1076 +
  1.1077 +NS_IMPL_ADDREF_USING_AGGREGATOR(DOMCSSDeclarationImpl, DomRule())
  1.1078 +NS_IMPL_RELEASE_USING_AGGREGATOR(DOMCSSDeclarationImpl, DomRule())
  1.1079 +
  1.1080 +NS_INTERFACE_MAP_BEGIN(DOMCSSDeclarationImpl)
  1.1081 +  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
  1.1082 +  // We forward the cycle collection interfaces to DomRule(), which is
  1.1083 +  // never null (in fact, we're part of that object!)
  1.1084 +  if (aIID.Equals(NS_GET_IID(nsCycleCollectionISupports)) ||
  1.1085 +      aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant))) {
  1.1086 +    return DomRule()->QueryInterface(aIID, aInstancePtr);
  1.1087 +  }
  1.1088 +  else
  1.1089 +NS_IMPL_QUERY_TAIL_INHERITING(nsDOMCSSDeclaration)
  1.1090 +
  1.1091 +void
  1.1092 +DOMCSSDeclarationImpl::DropReference(void)
  1.1093 +{
  1.1094 +  mRule = nullptr;
  1.1095 +}
  1.1096 +
  1.1097 +css::Declaration*
  1.1098 +DOMCSSDeclarationImpl::GetCSSDeclaration(bool aAllocate)
  1.1099 +{
  1.1100 +  if (mRule) {
  1.1101 +    return mRule->GetDeclaration();
  1.1102 +  } else {
  1.1103 +    return nullptr;
  1.1104 +  }
  1.1105 +}
  1.1106 +
  1.1107 +void
  1.1108 +DOMCSSDeclarationImpl::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv)
  1.1109 +{
  1.1110 +  GetCSSParsingEnvironmentForRule(mRule, aCSSParseEnv);
  1.1111 +}
  1.1112 +
  1.1113 +NS_IMETHODIMP
  1.1114 +DOMCSSDeclarationImpl::GetParentRule(nsIDOMCSSRule **aParent)
  1.1115 +{
  1.1116 +  NS_ENSURE_ARG_POINTER(aParent);
  1.1117 +
  1.1118 +  if (!mRule) {
  1.1119 +    *aParent = nullptr;
  1.1120 +    return NS_OK;
  1.1121 +  }
  1.1122 +
  1.1123 +  NS_IF_ADDREF(*aParent = mRule->GetDOMRule());
  1.1124 +  return NS_OK;
  1.1125 +}
  1.1126 +
  1.1127 +nsresult
  1.1128 +DOMCSSDeclarationImpl::SetCSSDeclaration(css::Declaration* aDecl)
  1.1129 +{
  1.1130 +  NS_PRECONDITION(mRule,
  1.1131 +         "can only be called when |GetCSSDeclaration| returned a declaration");
  1.1132 +
  1.1133 +  nsCOMPtr<nsIDocument> owningDoc;
  1.1134 +  nsCOMPtr<nsIStyleSheet> sheet = mRule->GetStyleSheet();
  1.1135 +  if (sheet) {
  1.1136 +    owningDoc = sheet->GetOwningDocument();
  1.1137 +  }
  1.1138 +
  1.1139 +  mozAutoDocUpdate updateBatch(owningDoc, UPDATE_STYLE, true);
  1.1140 +
  1.1141 +  nsRefPtr<css::StyleRule> oldRule = mRule;
  1.1142 +  mRule = oldRule->DeclarationChanged(aDecl, true).take();
  1.1143 +  if (!mRule)
  1.1144 +    return NS_ERROR_OUT_OF_MEMORY;
  1.1145 +  nsrefcnt cnt = mRule->Release();
  1.1146 +  if (cnt == 0) {
  1.1147 +    NS_NOTREACHED("container didn't take ownership");
  1.1148 +    mRule = nullptr;
  1.1149 +    return NS_ERROR_UNEXPECTED;
  1.1150 +  }
  1.1151 +
  1.1152 +  if (owningDoc) {
  1.1153 +    owningDoc->StyleRuleChanged(sheet, oldRule, mRule);
  1.1154 +  }
  1.1155 +  return NS_OK;
  1.1156 +}
  1.1157 +
  1.1158 +nsIDocument*
  1.1159 +DOMCSSDeclarationImpl::DocToUpdate()
  1.1160 +{
  1.1161 +  return nullptr;
  1.1162 +}
  1.1163 +
  1.1164 +// needs to be outside the namespace
  1.1165 +DOMCI_DATA(CSSStyleRule, css::DOMCSSStyleRule)
  1.1166 +
  1.1167 +namespace mozilla {
  1.1168 +namespace css {
  1.1169 +
  1.1170 +DOMCSSStyleRule::DOMCSSStyleRule(StyleRule* aRule)
  1.1171 +  : mDOMDeclaration(aRule)
  1.1172 +{
  1.1173 +}
  1.1174 +
  1.1175 +DOMCSSStyleRule::~DOMCSSStyleRule()
  1.1176 +{
  1.1177 +}
  1.1178 +
  1.1179 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMCSSStyleRule)
  1.1180 +  NS_INTERFACE_MAP_ENTRY(nsICSSStyleRuleDOMWrapper)
  1.1181 +  NS_INTERFACE_MAP_ENTRY(nsIDOMCSSStyleRule)
  1.1182 +  NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
  1.1183 +  NS_INTERFACE_MAP_ENTRY(nsISupports)
  1.1184 +  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSStyleRule)
  1.1185 +NS_INTERFACE_MAP_END
  1.1186 +
  1.1187 +NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMCSSStyleRule)
  1.1188 +NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMCSSStyleRule)
  1.1189 +
  1.1190 +NS_IMPL_CYCLE_COLLECTION_CLASS(DOMCSSStyleRule)
  1.1191 +
  1.1192 +NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMCSSStyleRule)
  1.1193 +  // Trace the wrapper for our declaration.  This just expands out
  1.1194 +  // NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER which we can't use
  1.1195 +  // directly because the wrapper is on the declaration, not on us.
  1.1196 +  tmp->DOMDeclaration()->TraceWrapper(aCallbacks, aClosure);
  1.1197 +NS_IMPL_CYCLE_COLLECTION_TRACE_END
  1.1198 +
  1.1199 +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMCSSStyleRule)
  1.1200 +  // Unlink the wrapper for our declaraton.  This just expands out
  1.1201 +  // NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER which we can't use
  1.1202 +  // directly because the wrapper is on the declaration, not on us.
  1.1203 +  tmp->DOMDeclaration()->ReleaseWrapper(static_cast<nsISupports*>(p));
  1.1204 +NS_IMPL_CYCLE_COLLECTION_UNLINK_END
  1.1205 +
  1.1206 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMCSSStyleRule)
  1.1207 +  // Just NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS here: that will call
  1.1208 +  // into our Trace hook, where we do the right thing with declarations
  1.1209 +  // already.
  1.1210 +  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
  1.1211 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
  1.1212 +
  1.1213 +NS_IMETHODIMP
  1.1214 +DOMCSSStyleRule::GetType(uint16_t* aType)
  1.1215 +{
  1.1216 +  *aType = nsIDOMCSSRule::STYLE_RULE;
  1.1217 +  
  1.1218 +  return NS_OK;
  1.1219 +}
  1.1220 +
  1.1221 +NS_IMETHODIMP
  1.1222 +DOMCSSStyleRule::GetCssText(nsAString& aCssText)
  1.1223 +{
  1.1224 +  if (!Rule()) {
  1.1225 +    aCssText.Truncate();
  1.1226 +  } else {
  1.1227 +    Rule()->GetCssText(aCssText);
  1.1228 +  }
  1.1229 +  return NS_OK;
  1.1230 +}
  1.1231 +
  1.1232 +NS_IMETHODIMP
  1.1233 +DOMCSSStyleRule::SetCssText(const nsAString& aCssText)
  1.1234 +{
  1.1235 +  if (Rule()) {
  1.1236 +    Rule()->SetCssText(aCssText);
  1.1237 +  }
  1.1238 +  return NS_OK;
  1.1239 +}
  1.1240 +
  1.1241 +NS_IMETHODIMP
  1.1242 +DOMCSSStyleRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
  1.1243 +{
  1.1244 +  if (!Rule()) {
  1.1245 +    *aSheet = nullptr;
  1.1246 +    return NS_OK;
  1.1247 +  }
  1.1248 +  return Rule()->GetParentStyleSheet(aSheet);
  1.1249 +}
  1.1250 +
  1.1251 +NS_IMETHODIMP
  1.1252 +DOMCSSStyleRule::GetParentRule(nsIDOMCSSRule** aParentRule)
  1.1253 +{
  1.1254 +  if (!Rule()) {
  1.1255 +    *aParentRule = nullptr;
  1.1256 +    return NS_OK;
  1.1257 +  }
  1.1258 +  return Rule()->GetParentRule(aParentRule);
  1.1259 +}
  1.1260 +
  1.1261 +NS_IMETHODIMP
  1.1262 +DOMCSSStyleRule::GetSelectorText(nsAString& aSelectorText)
  1.1263 +{
  1.1264 +  if (!Rule()) {
  1.1265 +    aSelectorText.Truncate();
  1.1266 +  } else {
  1.1267 +    Rule()->GetSelectorText(aSelectorText);
  1.1268 +  }
  1.1269 +  return NS_OK;
  1.1270 +}
  1.1271 +
  1.1272 +NS_IMETHODIMP
  1.1273 +DOMCSSStyleRule::SetSelectorText(const nsAString& aSelectorText)
  1.1274 +{
  1.1275 +  if (Rule()) {
  1.1276 +    Rule()->SetSelectorText(aSelectorText);
  1.1277 +  }
  1.1278 +  return NS_OK;
  1.1279 +}
  1.1280 +
  1.1281 +NS_IMETHODIMP
  1.1282 +DOMCSSStyleRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
  1.1283 +{
  1.1284 +  *aStyle = &mDOMDeclaration;
  1.1285 +  NS_ADDREF(*aStyle);
  1.1286 +  return NS_OK;
  1.1287 +}
  1.1288 +
  1.1289 +NS_IMETHODIMP
  1.1290 +DOMCSSStyleRule::GetCSSStyleRule(StyleRule **aResult)
  1.1291 +{
  1.1292 +  *aResult = Rule();
  1.1293 +  NS_IF_ADDREF(*aResult);
  1.1294 +  return NS_OK;
  1.1295 +}
  1.1296 +
  1.1297 +} // namespace css
  1.1298 +} // namespace mozilla
  1.1299 +
  1.1300 +// -- StyleRule ------------------------------------
  1.1301 +
  1.1302 +namespace mozilla {
  1.1303 +namespace css {
  1.1304 +
  1.1305 +StyleRule::StyleRule(nsCSSSelectorList* aSelector,
  1.1306 +                     Declaration* aDeclaration)
  1.1307 +  : Rule(),
  1.1308 +    mSelector(aSelector),
  1.1309 +    mDeclaration(aDeclaration),
  1.1310 +    mImportantRule(nullptr),
  1.1311 +    mDOMRule(nullptr),
  1.1312 +    mLineNumber(0),
  1.1313 +    mColumnNumber(0),
  1.1314 +    mWasMatched(false)
  1.1315 +{
  1.1316 +  NS_PRECONDITION(aDeclaration, "must have a declaration");
  1.1317 +}
  1.1318 +
  1.1319 +// for |Clone|
  1.1320 +StyleRule::StyleRule(const StyleRule& aCopy)
  1.1321 +  : Rule(aCopy),
  1.1322 +    mSelector(aCopy.mSelector ? aCopy.mSelector->Clone() : nullptr),
  1.1323 +    mDeclaration(new Declaration(*aCopy.mDeclaration)),
  1.1324 +    mImportantRule(nullptr),
  1.1325 +    mDOMRule(nullptr),
  1.1326 +    mLineNumber(aCopy.mLineNumber),
  1.1327 +    mColumnNumber(aCopy.mColumnNumber),
  1.1328 +    mWasMatched(false)
  1.1329 +{
  1.1330 +  // rest is constructed lazily on existing data
  1.1331 +}
  1.1332 +
  1.1333 +// for |SetCSSDeclaration|
  1.1334 +StyleRule::StyleRule(StyleRule& aCopy,
  1.1335 +                     Declaration* aDeclaration)
  1.1336 +  : Rule(aCopy),
  1.1337 +    mSelector(aCopy.mSelector),
  1.1338 +    mDeclaration(aDeclaration),
  1.1339 +    mImportantRule(nullptr),
  1.1340 +    mDOMRule(aCopy.mDOMRule),
  1.1341 +    mLineNumber(aCopy.mLineNumber),
  1.1342 +    mColumnNumber(aCopy.mColumnNumber),
  1.1343 +    mWasMatched(false)
  1.1344 +{
  1.1345 +  // The DOM rule is replacing |aCopy| with |this|, so transfer
  1.1346 +  // the reverse pointer as well (and transfer ownership).
  1.1347 +  aCopy.mDOMRule = nullptr;
  1.1348 +
  1.1349 +  // Similarly for the selector.
  1.1350 +  aCopy.mSelector = nullptr;
  1.1351 +
  1.1352 +  // We are probably replacing the old declaration with |aDeclaration|
  1.1353 +  // instead of taking ownership of the old declaration; only null out
  1.1354 +  // aCopy.mDeclaration if we are taking ownership.
  1.1355 +  if (mDeclaration == aCopy.mDeclaration) {
  1.1356 +    // This should only ever happen if the declaration was modifiable.
  1.1357 +    mDeclaration->AssertMutable();
  1.1358 +    aCopy.mDeclaration = nullptr;
  1.1359 +  }
  1.1360 +}
  1.1361 +
  1.1362 +StyleRule::~StyleRule()
  1.1363 +{
  1.1364 +  delete mSelector;
  1.1365 +  delete mDeclaration;
  1.1366 +  NS_IF_RELEASE(mImportantRule);
  1.1367 +  if (mDOMRule) {
  1.1368 +    mDOMRule->DOMDeclaration()->DropReference();
  1.1369 +    NS_RELEASE(mDOMRule);
  1.1370 +  }
  1.1371 +}
  1.1372 +
  1.1373 +// QueryInterface implementation for StyleRule
  1.1374 +NS_INTERFACE_MAP_BEGIN(StyleRule)
  1.1375 +  if (aIID.Equals(NS_GET_IID(mozilla::css::StyleRule))) {
  1.1376 +    *aInstancePtr = this;
  1.1377 +    NS_ADDREF_THIS();
  1.1378 +    return NS_OK;
  1.1379 +  }
  1.1380 +  else
  1.1381 +  NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
  1.1382 +  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
  1.1383 +NS_INTERFACE_MAP_END
  1.1384 +
  1.1385 +NS_IMPL_ADDREF(StyleRule)
  1.1386 +NS_IMPL_RELEASE(StyleRule)
  1.1387 +
  1.1388 +void
  1.1389 +StyleRule::RuleMatched()
  1.1390 +{
  1.1391 +  if (!mWasMatched) {
  1.1392 +    NS_ABORT_IF_FALSE(!mImportantRule, "should not have important rule yet");
  1.1393 +
  1.1394 +    mWasMatched = true;
  1.1395 +    mDeclaration->SetImmutable();
  1.1396 +    if (mDeclaration->HasImportantData()) {
  1.1397 +      NS_ADDREF(mImportantRule = new ImportantRule(mDeclaration));
  1.1398 +    }
  1.1399 +  }
  1.1400 +}
  1.1401 +
  1.1402 +/* virtual */ int32_t
  1.1403 +StyleRule::GetType() const
  1.1404 +{
  1.1405 +  return Rule::STYLE_RULE;
  1.1406 +}
  1.1407 +
  1.1408 +/* virtual */ already_AddRefed<Rule>
  1.1409 +StyleRule::Clone() const
  1.1410 +{
  1.1411 +  nsRefPtr<Rule> clone = new StyleRule(*this);
  1.1412 +  return clone.forget();
  1.1413 +}
  1.1414 +
  1.1415 +/* virtual */ nsIDOMCSSRule*
  1.1416 +StyleRule::GetDOMRule()
  1.1417 +{
  1.1418 +  if (!mDOMRule) {
  1.1419 +    if (!GetStyleSheet()) {
  1.1420 +      // Inline style rules aren't supposed to have a DOM rule object, only
  1.1421 +      // a declaration.  But if we do have one already, from a style sheet
  1.1422 +      // rule that used to be in a document, we still want to return it.
  1.1423 +      return nullptr;
  1.1424 +    }
  1.1425 +    mDOMRule = new DOMCSSStyleRule(this);
  1.1426 +    NS_ADDREF(mDOMRule);
  1.1427 +  }
  1.1428 +  return mDOMRule;
  1.1429 +}
  1.1430 +
  1.1431 +/* virtual */ nsIDOMCSSRule*
  1.1432 +StyleRule::GetExistingDOMRule()
  1.1433 +{
  1.1434 +  return mDOMRule;
  1.1435 +}
  1.1436 +
  1.1437 +/* virtual */ already_AddRefed<StyleRule>
  1.1438 +StyleRule::DeclarationChanged(Declaration* aDecl,
  1.1439 +                              bool aHandleContainer)
  1.1440 +{
  1.1441 +  nsRefPtr<StyleRule> clone = new StyleRule(*this, aDecl);
  1.1442 +
  1.1443 +  if (aHandleContainer) {
  1.1444 +    nsCSSStyleSheet* sheet = GetStyleSheet();
  1.1445 +    if (mParentRule) {
  1.1446 +      if (sheet) {
  1.1447 +        sheet->ReplaceRuleInGroup(mParentRule, this, clone);
  1.1448 +      } else {
  1.1449 +        mParentRule->ReplaceStyleRule(this, clone);
  1.1450 +      }
  1.1451 +    } else if (sheet) {
  1.1452 +      sheet->ReplaceStyleRule(this, clone);
  1.1453 +    }
  1.1454 +  }
  1.1455 +
  1.1456 +  return clone.forget();
  1.1457 +}
  1.1458 +
  1.1459 +/* virtual */ void
  1.1460 +StyleRule::MapRuleInfoInto(nsRuleData* aRuleData)
  1.1461 +{
  1.1462 +  NS_ABORT_IF_FALSE(mWasMatched,
  1.1463 +                    "somebody forgot to call css::StyleRule::RuleMatched");
  1.1464 +  mDeclaration->MapNormalRuleInfoInto(aRuleData);
  1.1465 +}
  1.1466 +
  1.1467 +#ifdef DEBUG
  1.1468 +/* virtual */ void
  1.1469 +StyleRule::List(FILE* out, int32_t aIndent) const
  1.1470 +{
  1.1471 +  // Indent
  1.1472 +  for (int32_t index = aIndent; --index >= 0; ) fputs("  ", out);
  1.1473 +
  1.1474 +  nsAutoString buffer;
  1.1475 +  if (mSelector)
  1.1476 +    mSelector->ToString(buffer, GetStyleSheet());
  1.1477 +
  1.1478 +  buffer.AppendLiteral(" ");
  1.1479 +  fputs(NS_LossyConvertUTF16toASCII(buffer).get(), out);
  1.1480 +  if (nullptr != mDeclaration) {
  1.1481 +    mDeclaration->List(out);
  1.1482 +  }
  1.1483 +  else {
  1.1484 +    fputs("{ null declaration }", out);
  1.1485 +  }
  1.1486 +  fputs("\n", out);
  1.1487 +}
  1.1488 +#endif
  1.1489 +
  1.1490 +void
  1.1491 +StyleRule::GetCssText(nsAString& aCssText)
  1.1492 +{
  1.1493 +  if (mSelector) {
  1.1494 +    mSelector->ToString(aCssText, GetStyleSheet());
  1.1495 +    aCssText.Append(char16_t(' '));
  1.1496 +  }
  1.1497 +  aCssText.Append(char16_t('{'));
  1.1498 +  aCssText.Append(char16_t(' '));
  1.1499 +  if (mDeclaration)
  1.1500 +  {
  1.1501 +    nsAutoString   tempString;
  1.1502 +    mDeclaration->ToString( tempString );
  1.1503 +    aCssText.Append( tempString );
  1.1504 +  }
  1.1505 +  aCssText.Append(char16_t(' '));
  1.1506 +  aCssText.Append(char16_t('}'));
  1.1507 +}
  1.1508 +
  1.1509 +void
  1.1510 +StyleRule::SetCssText(const nsAString& aCssText)
  1.1511 +{
  1.1512 +  // XXX TBI - need to re-parse rule & declaration
  1.1513 +}
  1.1514 +
  1.1515 +void
  1.1516 +StyleRule::GetSelectorText(nsAString& aSelectorText)
  1.1517 +{
  1.1518 +  if (mSelector)
  1.1519 +    mSelector->ToString(aSelectorText, GetStyleSheet());
  1.1520 +  else
  1.1521 +    aSelectorText.Truncate();
  1.1522 +}
  1.1523 +
  1.1524 +void
  1.1525 +StyleRule::SetSelectorText(const nsAString& aSelectorText)
  1.1526 +{
  1.1527 +  // XXX TBI - get a parser and re-parse the selectors,
  1.1528 +  // XXX then need to re-compute the cascade
  1.1529 +  // XXX and dirty sheet
  1.1530 +}
  1.1531 +
  1.1532 +/* virtual */ size_t
  1.1533 +StyleRule::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
  1.1534 +{
  1.1535 +  size_t n = aMallocSizeOf(this);
  1.1536 +  n += mSelector ? mSelector->SizeOfIncludingThis(aMallocSizeOf) : 0;
  1.1537 +  n += mDeclaration ? mDeclaration->SizeOfIncludingThis(aMallocSizeOf) : 0;
  1.1538 +
  1.1539 +  // Measurement of the following members may be added later if DMD finds it is
  1.1540 +  // worthwhile:
  1.1541 +  // - mImportantRule;
  1.1542 +  // - mDOMRule;
  1.1543 +
  1.1544 +  return n;
  1.1545 +}
  1.1546 +
  1.1547 +
  1.1548 +} // namespace css
  1.1549 +} // namespace mozilla

mercurial