layout/style/StyleRule.cpp

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

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

mercurial