layout/style/nsRuleProcessorData.h

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

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 * data structures passed to nsIStyleRuleProcessor methods (to pull loop
michael@0 8 * invariant computations out of the loop)
michael@0 9 */
michael@0 10
michael@0 11 #ifndef nsRuleProcessorData_h_
michael@0 12 #define nsRuleProcessorData_h_
michael@0 13
michael@0 14 #include "nsPresContext.h" // for nsCompatibility
michael@0 15 #include "nsString.h"
michael@0 16 #include "nsChangeHint.h"
michael@0 17 #include "nsCSSPseudoElements.h"
michael@0 18 #include "nsRuleWalker.h"
michael@0 19 #include "nsNthIndexCache.h"
michael@0 20 #include "nsILoadContext.h"
michael@0 21 #include "nsIDocument.h"
michael@0 22 #include "mozilla/AutoRestore.h"
michael@0 23 #include "mozilla/BloomFilter.h"
michael@0 24 #include "mozilla/EventStates.h"
michael@0 25 #include "mozilla/GuardObjects.h"
michael@0 26
michael@0 27 class nsAttrValue;
michael@0 28 class nsIAtom;
michael@0 29 class nsIContent;
michael@0 30 class nsICSSPseudoComparator;
michael@0 31 class nsIStyleSheet;
michael@0 32 struct TreeMatchContext;
michael@0 33
michael@0 34 /**
michael@0 35 * An AncestorFilter is used to keep track of ancestors so that we can
michael@0 36 * quickly tell that a particular selector is not relevant to a given
michael@0 37 * element.
michael@0 38 */
michael@0 39 class MOZ_STACK_CLASS AncestorFilter {
michael@0 40 friend struct TreeMatchContext;
michael@0 41 public:
michael@0 42 /* Maintenance of our ancestor state */
michael@0 43 void PushAncestor(mozilla::dom::Element *aElement);
michael@0 44 void PopAncestor();
michael@0 45
michael@0 46 /* Check whether we might have an ancestor matching one of the given
michael@0 47 atom hashes. |hashes| must have length hashListLength */
michael@0 48 template<size_t hashListLength>
michael@0 49 bool MightHaveMatchingAncestor(const uint32_t* aHashes) const
michael@0 50 {
michael@0 51 MOZ_ASSERT(mFilter);
michael@0 52 for (size_t i = 0; i < hashListLength && aHashes[i]; ++i) {
michael@0 53 if (!mFilter->mightContain(aHashes[i])) {
michael@0 54 return false;
michael@0 55 }
michael@0 56 }
michael@0 57
michael@0 58 return true;
michael@0 59 }
michael@0 60
michael@0 61 bool HasFilter() const { return mFilter; }
michael@0 62
michael@0 63 #ifdef DEBUG
michael@0 64 void AssertHasAllAncestors(mozilla::dom::Element *aElement) const;
michael@0 65 #endif
michael@0 66
michael@0 67 private:
michael@0 68 // Using 2^12 slots makes the Bloom filter a nice round page in
michael@0 69 // size, so let's do that. We get a false positive rate of 1% or
michael@0 70 // less even with several hundred things in the filter. Note that
michael@0 71 // we allocate the filter lazily, because not all tree match
michael@0 72 // contexts can use one effectively.
michael@0 73 typedef mozilla::BloomFilter<12, nsIAtom> Filter;
michael@0 74 nsAutoPtr<Filter> mFilter;
michael@0 75
michael@0 76 // Stack of indices to pop to. These are indices into mHashes.
michael@0 77 nsTArray<uint32_t> mPopTargets;
michael@0 78
michael@0 79 // List of hashes; this is what we pop using mPopTargets. We store
michael@0 80 // hashes of our ancestor element tag names, ids, and classes in
michael@0 81 // here.
michael@0 82 nsTArray<uint32_t> mHashes;
michael@0 83
michael@0 84 // A debug-only stack of Elements for use in assertions
michael@0 85 #ifdef DEBUG
michael@0 86 nsTArray<mozilla::dom::Element*> mElements;
michael@0 87 #endif
michael@0 88 };
michael@0 89
michael@0 90 /**
michael@0 91 * A |TreeMatchContext| has data about a matching operation. The
michael@0 92 * data are not node-specific but are invariants of the DOM tree the
michael@0 93 * nodes being matched against are in.
michael@0 94 *
michael@0 95 * Most of the members are in parameters to selector matching. The
michael@0 96 * one out parameter is mHaveRelevantLink. Consumers that use a
michael@0 97 * TreeMatchContext for more than one matching operation and care
michael@0 98 * about :visited and mHaveRelevantLink need to
michael@0 99 * ResetForVisitedMatching() and ResetForUnvisitedMatching() as
michael@0 100 * needed.
michael@0 101 */
michael@0 102 struct MOZ_STACK_CLASS TreeMatchContext {
michael@0 103 // Reset this context for matching for the style-if-:visited.
michael@0 104 void ResetForVisitedMatching() {
michael@0 105 NS_PRECONDITION(mForStyling, "Why is this being called?");
michael@0 106 mHaveRelevantLink = false;
michael@0 107 mVisitedHandling = nsRuleWalker::eRelevantLinkVisited;
michael@0 108 }
michael@0 109
michael@0 110 void ResetForUnvisitedMatching() {
michael@0 111 NS_PRECONDITION(mForStyling, "Why is this being called?");
michael@0 112 mHaveRelevantLink = false;
michael@0 113 mVisitedHandling = nsRuleWalker::eRelevantLinkUnvisited;
michael@0 114 }
michael@0 115
michael@0 116 void SetHaveRelevantLink() { mHaveRelevantLink = true; }
michael@0 117 bool HaveRelevantLink() const { return mHaveRelevantLink; }
michael@0 118
michael@0 119 nsRuleWalker::VisitedHandlingType VisitedHandling() const
michael@0 120 {
michael@0 121 return mVisitedHandling;
michael@0 122 }
michael@0 123
michael@0 124 void AddScopeElement(mozilla::dom::Element* aElement) {
michael@0 125 NS_PRECONDITION(mHaveSpecifiedScope,
michael@0 126 "Should be set before calling AddScopeElement()");
michael@0 127 mScopes.AppendElement(aElement);
michael@0 128 }
michael@0 129 bool IsScopeElement(mozilla::dom::Element* aElement) const {
michael@0 130 return mScopes.Contains(aElement);
michael@0 131 }
michael@0 132 void SetHasSpecifiedScope() {
michael@0 133 mHaveSpecifiedScope = true;
michael@0 134 }
michael@0 135 bool HasSpecifiedScope() const {
michael@0 136 return mHaveSpecifiedScope;
michael@0 137 }
michael@0 138
michael@0 139 /**
michael@0 140 * Initialize the ancestor filter and list of style scopes. If aElement is
michael@0 141 * not null, it and all its ancestors will be passed to
michael@0 142 * mAncestorFilter.PushAncestor and PushStyleScope, starting from the root and
michael@0 143 * going down the tree. Must only be called for elements in a document.
michael@0 144 */
michael@0 145 void InitAncestors(mozilla::dom::Element *aElement);
michael@0 146
michael@0 147 /**
michael@0 148 * Like InitAncestors, but only initializes the style scope list, not the
michael@0 149 * ancestor filter. May be called for elements outside a document.
michael@0 150 */
michael@0 151 void InitStyleScopes(mozilla::dom::Element* aElement);
michael@0 152
michael@0 153 void PushStyleScope(mozilla::dom::Element* aElement)
michael@0 154 {
michael@0 155 NS_PRECONDITION(aElement, "aElement must not be null");
michael@0 156 if (aElement->IsScopedStyleRoot()) {
michael@0 157 mStyleScopes.AppendElement(aElement);
michael@0 158 }
michael@0 159 }
michael@0 160
michael@0 161 void PopStyleScope(mozilla::dom::Element* aElement)
michael@0 162 {
michael@0 163 NS_PRECONDITION(aElement, "aElement must not be null");
michael@0 164 if (mStyleScopes.SafeLastElement(nullptr) == aElement) {
michael@0 165 mStyleScopes.TruncateLength(mStyleScopes.Length() - 1);
michael@0 166 }
michael@0 167 }
michael@0 168
michael@0 169 bool PopStyleScopeForSelectorMatching(mozilla::dom::Element* aElement)
michael@0 170 {
michael@0 171 NS_ASSERTION(mForScopedStyle, "only call PopStyleScopeForSelectorMatching "
michael@0 172 "when mForScopedStyle is true");
michael@0 173
michael@0 174 if (!mCurrentStyleScope) {
michael@0 175 return false;
michael@0 176 }
michael@0 177 if (mCurrentStyleScope == aElement) {
michael@0 178 mCurrentStyleScope = nullptr;
michael@0 179 }
michael@0 180 return true;
michael@0 181 }
michael@0 182
michael@0 183 #ifdef DEBUG
michael@0 184 void AssertHasAllStyleScopes(mozilla::dom::Element* aElement)
michael@0 185 {
michael@0 186 nsINode* cur = aElement->GetParentNode();
michael@0 187 while (cur) {
michael@0 188 if (cur->IsScopedStyleRoot()) {
michael@0 189 MOZ_ASSERT(mStyleScopes.Contains(cur));
michael@0 190 }
michael@0 191 cur = cur->GetParentNode();
michael@0 192 }
michael@0 193 }
michael@0 194 #endif
michael@0 195
michael@0 196 bool SetStyleScopeForSelectorMatching(mozilla::dom::Element* aSubject,
michael@0 197 mozilla::dom::Element* aScope)
michael@0 198 {
michael@0 199 #ifdef DEBUG
michael@0 200 AssertHasAllStyleScopes(aSubject);
michael@0 201 #endif
michael@0 202
michael@0 203 mForScopedStyle = !!aScope;
michael@0 204 if (!aScope) {
michael@0 205 // This is not for a scoped style sheet; return true, as we want
michael@0 206 // selector matching to proceed.
michael@0 207 mCurrentStyleScope = nullptr;
michael@0 208 return true;
michael@0 209 }
michael@0 210 if (aScope == aSubject) {
michael@0 211 // Although the subject is the same element as the scope, as soon
michael@0 212 // as we continue with selector matching up the tree we don't want
michael@0 213 // to match any more elements. So we return true to indicate that
michael@0 214 // we want to do the initial selector matching, but set
michael@0 215 // mCurrentStyleScope to null so that no ancestor elements will match.
michael@0 216 mCurrentStyleScope = nullptr;
michael@0 217 return true;
michael@0 218 }
michael@0 219 if (mStyleScopes.Contains(aScope)) {
michael@0 220 // mStyleScopes contains all of the scope elements that are ancestors of
michael@0 221 // aSubject, so if aScope is in mStyleScopes, then we do want selector
michael@0 222 // matching to proceed.
michael@0 223 mCurrentStyleScope = aScope;
michael@0 224 return true;
michael@0 225 }
michael@0 226 // Otherwise, we're not in the scope, and we don't want to proceed
michael@0 227 // with selector matching.
michael@0 228 mCurrentStyleScope = nullptr;
michael@0 229 return false;
michael@0 230 }
michael@0 231
michael@0 232 bool IsWithinStyleScopeForSelectorMatching() const
michael@0 233 {
michael@0 234 NS_ASSERTION(mForScopedStyle, "only call IsWithinScopeForSelectorMatching "
michael@0 235 "when mForScopedStyle is true");
michael@0 236 return mCurrentStyleScope;
michael@0 237 }
michael@0 238
michael@0 239 /* Helper class for maintaining the ancestor state */
michael@0 240 class MOZ_STACK_CLASS AutoAncestorPusher {
michael@0 241 public:
michael@0 242 AutoAncestorPusher(TreeMatchContext& aTreeMatchContext
michael@0 243 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
michael@0 244 : mPushedAncestor(false)
michael@0 245 , mPushedStyleScope(false)
michael@0 246 , mTreeMatchContext(aTreeMatchContext)
michael@0 247 , mElement(nullptr)
michael@0 248 {
michael@0 249 MOZ_GUARD_OBJECT_NOTIFIER_INIT;
michael@0 250 }
michael@0 251
michael@0 252 void PushAncestorAndStyleScope(mozilla::dom::Element* aElement) {
michael@0 253 MOZ_ASSERT(!mElement);
michael@0 254 if (aElement) {
michael@0 255 mElement = aElement;
michael@0 256 mPushedAncestor = true;
michael@0 257 mPushedStyleScope = true;
michael@0 258 mTreeMatchContext.mAncestorFilter.PushAncestor(aElement);
michael@0 259 mTreeMatchContext.PushStyleScope(aElement);
michael@0 260 }
michael@0 261 }
michael@0 262
michael@0 263 void PushAncestorAndStyleScope(nsIContent* aContent) {
michael@0 264 if (aContent && aContent->IsElement()) {
michael@0 265 PushAncestorAndStyleScope(aContent->AsElement());
michael@0 266 }
michael@0 267 }
michael@0 268
michael@0 269 void PushStyleScope(mozilla::dom::Element* aElement) {
michael@0 270 MOZ_ASSERT(!mElement);
michael@0 271 if (aElement) {
michael@0 272 mElement = aElement;
michael@0 273 mPushedStyleScope = true;
michael@0 274 mTreeMatchContext.PushStyleScope(aElement);
michael@0 275 }
michael@0 276 }
michael@0 277
michael@0 278 void PushStyleScope(nsIContent* aContent) {
michael@0 279 if (aContent && aContent->IsElement()) {
michael@0 280 PushStyleScope(aContent->AsElement());
michael@0 281 }
michael@0 282 }
michael@0 283
michael@0 284 ~AutoAncestorPusher() {
michael@0 285 if (mPushedAncestor) {
michael@0 286 mTreeMatchContext.mAncestorFilter.PopAncestor();
michael@0 287 }
michael@0 288 if (mPushedStyleScope) {
michael@0 289 mTreeMatchContext.PopStyleScope(mElement);
michael@0 290 }
michael@0 291 }
michael@0 292
michael@0 293 private:
michael@0 294 bool mPushedAncestor;
michael@0 295 bool mPushedStyleScope;
michael@0 296 TreeMatchContext& mTreeMatchContext;
michael@0 297 mozilla::dom::Element* mElement;
michael@0 298 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
michael@0 299 };
michael@0 300
michael@0 301 /* Helper class for tracking whether we're skipping the ApplyStyleFixups
michael@0 302 * code for flex items.
michael@0 303 *
michael@0 304 * The optional second parameter aSkipFlexItemStyleFixup allows this
michael@0 305 * class to be instantiated but only conditionally activated (e.g.
michael@0 306 * in cases where we may or may not want to be skipping flex-item
michael@0 307 * style fixup for a particular chunk of code).
michael@0 308 */
michael@0 309 class MOZ_STACK_CLASS AutoFlexItemStyleFixupSkipper {
michael@0 310 public:
michael@0 311 AutoFlexItemStyleFixupSkipper(TreeMatchContext& aTreeMatchContext,
michael@0 312 bool aSkipFlexItemStyleFixup = true
michael@0 313 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
michael@0 314 : mAutoRestorer(aTreeMatchContext.mSkippingFlexItemStyleFixup)
michael@0 315 {
michael@0 316 MOZ_GUARD_OBJECT_NOTIFIER_INIT;
michael@0 317 if (aSkipFlexItemStyleFixup) {
michael@0 318 aTreeMatchContext.mSkippingFlexItemStyleFixup = true;
michael@0 319 }
michael@0 320 }
michael@0 321
michael@0 322 private:
michael@0 323 mozilla::AutoRestore<bool> mAutoRestorer;
michael@0 324 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
michael@0 325 };
michael@0 326
michael@0 327 // Is this matching operation for the creation of a style context?
michael@0 328 // (If it is, we need to set slow selector bits on nodes indicating
michael@0 329 // that certain restyling needs to happen.)
michael@0 330 const bool mForStyling;
michael@0 331
michael@0 332 private:
michael@0 333 // When mVisitedHandling is eRelevantLinkUnvisited, this is set to true if a
michael@0 334 // relevant link (see explanation in definition of VisitedHandling enum) was
michael@0 335 // encountered during the matching process, which means that matching needs
michael@0 336 // to be rerun with eRelevantLinkVisited. Otherwise, its behavior is
michael@0 337 // undefined (it might get set appropriately, or might not).
michael@0 338 bool mHaveRelevantLink;
michael@0 339
michael@0 340 // If true, then our contextual reference element set is specified,
michael@0 341 // and is given by mScopes.
michael@0 342 bool mHaveSpecifiedScope;
michael@0 343
michael@0 344 // How matching should be performed. See the documentation for
michael@0 345 // nsRuleWalker::VisitedHandlingType.
michael@0 346 nsRuleWalker::VisitedHandlingType mVisitedHandling;
michael@0 347
michael@0 348 // For matching :scope
michael@0 349 nsAutoTArray<mozilla::dom::Element*, 1> mScopes;
michael@0 350 public:
michael@0 351 // The document we're working with.
michael@0 352 nsIDocument* const mDocument;
michael@0 353
michael@0 354 // Root of scoped stylesheet (set and unset by the supplier of the
michael@0 355 // scoped stylesheet).
michael@0 356 nsIContent* mScopedRoot;
michael@0 357
michael@0 358 // Whether our document is HTML (as opposed to XML of some sort,
michael@0 359 // including XHTML).
michael@0 360 // XXX XBL2 issue: Should we be caching this? What should it be for XBL2?
michael@0 361 const bool mIsHTMLDocument;
michael@0 362
michael@0 363 // Possibly remove use of mCompatMode in SelectorMatches?
michael@0 364 // XXX XBL2 issue: Should we be caching this? What should it be for XBL2?
michael@0 365 const nsCompatibility mCompatMode;
michael@0 366
michael@0 367 // The nth-index cache we should use
michael@0 368 nsNthIndexCache mNthIndexCache;
michael@0 369
michael@0 370 // An ancestor filter
michael@0 371 AncestorFilter mAncestorFilter;
michael@0 372
michael@0 373 // Whether this document is using PB mode
michael@0 374 bool mUsingPrivateBrowsing;
michael@0 375
michael@0 376 // Whether we're currently skipping the flex item chunk of ApplyStyleFixups
michael@0 377 // when resolving style (e.g. for children of elements that have a mandatory
michael@0 378 // frame-type and can't be flex containers despite having "display:flex").
michael@0 379 bool mSkippingFlexItemStyleFixup;
michael@0 380
michael@0 381 // Whether this TreeMatchContext is being used with an nsCSSRuleProcessor
michael@0 382 // for an HTML5 scoped style sheet.
michael@0 383 bool mForScopedStyle;
michael@0 384
michael@0 385 enum MatchVisited {
michael@0 386 eNeverMatchVisited,
michael@0 387 eMatchVisitedDefault
michael@0 388 };
michael@0 389
michael@0 390 // List of ancestor elements that define a style scope (due to having a
michael@0 391 // <style scoped> child).
michael@0 392 nsAutoTArray<mozilla::dom::Element*, 1> mStyleScopes;
michael@0 393
michael@0 394 // The current style scope element for selector matching.
michael@0 395 mozilla::dom::Element* mCurrentStyleScope;
michael@0 396
michael@0 397 // Constructor to use when creating a tree match context for styling
michael@0 398 TreeMatchContext(bool aForStyling,
michael@0 399 nsRuleWalker::VisitedHandlingType aVisitedHandling,
michael@0 400 nsIDocument* aDocument,
michael@0 401 MatchVisited aMatchVisited = eMatchVisitedDefault)
michael@0 402 : mForStyling(aForStyling)
michael@0 403 , mHaveRelevantLink(false)
michael@0 404 , mHaveSpecifiedScope(false)
michael@0 405 , mVisitedHandling(aVisitedHandling)
michael@0 406 , mDocument(aDocument)
michael@0 407 , mScopedRoot(nullptr)
michael@0 408 , mIsHTMLDocument(aDocument->IsHTML())
michael@0 409 , mCompatMode(aDocument->GetCompatibilityMode())
michael@0 410 , mUsingPrivateBrowsing(false)
michael@0 411 , mSkippingFlexItemStyleFixup(false)
michael@0 412 , mForScopedStyle(false)
michael@0 413 , mCurrentStyleScope(nullptr)
michael@0 414 {
michael@0 415 if (aMatchVisited != eNeverMatchVisited) {
michael@0 416 nsCOMPtr<nsISupports> container = mDocument->GetContainer();
michael@0 417 if (container) {
michael@0 418 nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(container);
michael@0 419 NS_ASSERTION(loadContext, "Couldn't get loadContext from container; assuming no private browsing.");
michael@0 420 if (loadContext) {
michael@0 421 mUsingPrivateBrowsing = loadContext->UsePrivateBrowsing();
michael@0 422 }
michael@0 423 }
michael@0 424 }
michael@0 425 }
michael@0 426 };
michael@0 427
michael@0 428 struct MOZ_STACK_CLASS RuleProcessorData {
michael@0 429 RuleProcessorData(nsPresContext* aPresContext,
michael@0 430 nsRuleWalker* aRuleWalker)
michael@0 431 : mPresContext(aPresContext),
michael@0 432 mRuleWalker(aRuleWalker),
michael@0 433 mScope(nullptr)
michael@0 434 {
michael@0 435 NS_PRECONDITION(mPresContext, "Must have prescontext");
michael@0 436 }
michael@0 437
michael@0 438 nsPresContext* const mPresContext;
michael@0 439 nsRuleWalker* const mRuleWalker; // Used to add rules to our results.
michael@0 440 mozilla::dom::Element* mScope;
michael@0 441 };
michael@0 442
michael@0 443 struct MOZ_STACK_CLASS ElementDependentRuleProcessorData :
michael@0 444 public RuleProcessorData {
michael@0 445 ElementDependentRuleProcessorData(nsPresContext* aPresContext,
michael@0 446 mozilla::dom::Element* aElement,
michael@0 447 nsRuleWalker* aRuleWalker,
michael@0 448 TreeMatchContext& aTreeMatchContext)
michael@0 449 : RuleProcessorData(aPresContext, aRuleWalker)
michael@0 450 , mElement(aElement)
michael@0 451 , mTreeMatchContext(aTreeMatchContext)
michael@0 452 {
michael@0 453 NS_ASSERTION(aElement, "null element leaked into SelectorMatches");
michael@0 454 NS_ASSERTION(aElement->OwnerDoc(), "Document-less node here?");
michael@0 455 NS_PRECONDITION(aTreeMatchContext.mForStyling == !!aRuleWalker,
michael@0 456 "Should be styling if and only if we have a rule walker");
michael@0 457 }
michael@0 458
michael@0 459 mozilla::dom::Element* const mElement; // weak ref, must not be null
michael@0 460 TreeMatchContext& mTreeMatchContext;
michael@0 461 };
michael@0 462
michael@0 463 struct MOZ_STACK_CLASS ElementRuleProcessorData :
michael@0 464 public ElementDependentRuleProcessorData {
michael@0 465 ElementRuleProcessorData(nsPresContext* aPresContext,
michael@0 466 mozilla::dom::Element* aElement,
michael@0 467 nsRuleWalker* aRuleWalker,
michael@0 468 TreeMatchContext& aTreeMatchContext)
michael@0 469 : ElementDependentRuleProcessorData(aPresContext, aElement, aRuleWalker,
michael@0 470 aTreeMatchContext)
michael@0 471 {
michael@0 472 NS_PRECONDITION(aTreeMatchContext.mForStyling, "Styling here!");
michael@0 473 NS_PRECONDITION(aRuleWalker, "Must have rule walker");
michael@0 474 }
michael@0 475 };
michael@0 476
michael@0 477 struct MOZ_STACK_CLASS PseudoElementRuleProcessorData :
michael@0 478 public ElementDependentRuleProcessorData {
michael@0 479 PseudoElementRuleProcessorData(nsPresContext* aPresContext,
michael@0 480 mozilla::dom::Element* aParentElement,
michael@0 481 nsRuleWalker* aRuleWalker,
michael@0 482 nsCSSPseudoElements::Type aPseudoType,
michael@0 483 TreeMatchContext& aTreeMatchContext,
michael@0 484 mozilla::dom::Element* aPseudoElement)
michael@0 485 : ElementDependentRuleProcessorData(aPresContext, aParentElement, aRuleWalker,
michael@0 486 aTreeMatchContext),
michael@0 487 mPseudoType(aPseudoType),
michael@0 488 mPseudoElement(aPseudoElement)
michael@0 489 {
michael@0 490 NS_PRECONDITION(aPseudoType <
michael@0 491 nsCSSPseudoElements::ePseudo_PseudoElementCount,
michael@0 492 "invalid aPseudoType value");
michael@0 493 NS_PRECONDITION(aTreeMatchContext.mForStyling, "Styling here!");
michael@0 494 NS_PRECONDITION(aRuleWalker, "Must have rule walker");
michael@0 495 }
michael@0 496
michael@0 497 nsCSSPseudoElements::Type mPseudoType;
michael@0 498 mozilla::dom::Element* const mPseudoElement; // weak ref
michael@0 499 };
michael@0 500
michael@0 501 struct MOZ_STACK_CLASS AnonBoxRuleProcessorData : public RuleProcessorData {
michael@0 502 AnonBoxRuleProcessorData(nsPresContext* aPresContext,
michael@0 503 nsIAtom* aPseudoTag,
michael@0 504 nsRuleWalker* aRuleWalker)
michael@0 505 : RuleProcessorData(aPresContext, aRuleWalker),
michael@0 506 mPseudoTag(aPseudoTag)
michael@0 507 {
michael@0 508 NS_PRECONDITION(aPseudoTag, "Must have pseudo tag");
michael@0 509 NS_PRECONDITION(aRuleWalker, "Must have rule walker");
michael@0 510 }
michael@0 511
michael@0 512 nsIAtom* mPseudoTag;
michael@0 513 };
michael@0 514
michael@0 515 #ifdef MOZ_XUL
michael@0 516 struct MOZ_STACK_CLASS XULTreeRuleProcessorData :
michael@0 517 public ElementDependentRuleProcessorData {
michael@0 518 XULTreeRuleProcessorData(nsPresContext* aPresContext,
michael@0 519 mozilla::dom::Element* aParentElement,
michael@0 520 nsRuleWalker* aRuleWalker,
michael@0 521 nsIAtom* aPseudoTag,
michael@0 522 nsICSSPseudoComparator* aComparator,
michael@0 523 TreeMatchContext& aTreeMatchContext)
michael@0 524 : ElementDependentRuleProcessorData(aPresContext, aParentElement,
michael@0 525 aRuleWalker, aTreeMatchContext),
michael@0 526 mPseudoTag(aPseudoTag),
michael@0 527 mComparator(aComparator)
michael@0 528 {
michael@0 529 NS_PRECONDITION(aPseudoTag, "null pointer");
michael@0 530 NS_PRECONDITION(aRuleWalker, "Must have rule walker");
michael@0 531 NS_PRECONDITION(aComparator, "must have a comparator");
michael@0 532 NS_PRECONDITION(aTreeMatchContext.mForStyling, "Styling here!");
michael@0 533 }
michael@0 534
michael@0 535 nsIAtom* mPseudoTag;
michael@0 536 nsICSSPseudoComparator* mComparator;
michael@0 537 };
michael@0 538 #endif
michael@0 539
michael@0 540 struct MOZ_STACK_CLASS StateRuleProcessorData :
michael@0 541 public ElementDependentRuleProcessorData {
michael@0 542 StateRuleProcessorData(nsPresContext* aPresContext,
michael@0 543 mozilla::dom::Element* aElement,
michael@0 544 mozilla::EventStates aStateMask,
michael@0 545 TreeMatchContext& aTreeMatchContext)
michael@0 546 : ElementDependentRuleProcessorData(aPresContext, aElement, nullptr,
michael@0 547 aTreeMatchContext),
michael@0 548 mStateMask(aStateMask)
michael@0 549 {
michael@0 550 NS_PRECONDITION(!aTreeMatchContext.mForStyling, "Not styling here!");
michael@0 551 }
michael@0 552 // |HasStateDependentStyle| for which state(s)?
michael@0 553 // Constants defined in mozilla/EventStates.h .
michael@0 554 const mozilla::EventStates mStateMask;
michael@0 555 };
michael@0 556
michael@0 557 struct MOZ_STACK_CLASS PseudoElementStateRuleProcessorData :
michael@0 558 public StateRuleProcessorData {
michael@0 559 PseudoElementStateRuleProcessorData(nsPresContext* aPresContext,
michael@0 560 mozilla::dom::Element* aElement,
michael@0 561 mozilla::EventStates aStateMask,
michael@0 562 nsCSSPseudoElements::Type aPseudoType,
michael@0 563 TreeMatchContext& aTreeMatchContext,
michael@0 564 mozilla::dom::Element* aPseudoElement)
michael@0 565 : StateRuleProcessorData(aPresContext, aElement, aStateMask,
michael@0 566 aTreeMatchContext),
michael@0 567 mPseudoType(aPseudoType),
michael@0 568 mPseudoElement(aPseudoElement)
michael@0 569 {
michael@0 570 NS_PRECONDITION(!aTreeMatchContext.mForStyling, "Not styling here!");
michael@0 571 }
michael@0 572
michael@0 573 // We kind of want to inherit from both StateRuleProcessorData and
michael@0 574 // PseudoElementRuleProcessorData. Instead we've just copied those
michael@0 575 // members from PseudoElementRuleProcessorData to this struct.
michael@0 576 nsCSSPseudoElements::Type mPseudoType;
michael@0 577 mozilla::dom::Element* const mPseudoElement; // weak ref
michael@0 578 };
michael@0 579
michael@0 580 struct MOZ_STACK_CLASS AttributeRuleProcessorData :
michael@0 581 public ElementDependentRuleProcessorData {
michael@0 582 AttributeRuleProcessorData(nsPresContext* aPresContext,
michael@0 583 mozilla::dom::Element* aElement,
michael@0 584 nsIAtom* aAttribute,
michael@0 585 int32_t aModType,
michael@0 586 bool aAttrHasChanged,
michael@0 587 TreeMatchContext& aTreeMatchContext)
michael@0 588 : ElementDependentRuleProcessorData(aPresContext, aElement, nullptr,
michael@0 589 aTreeMatchContext),
michael@0 590 mAttribute(aAttribute),
michael@0 591 mModType(aModType),
michael@0 592 mAttrHasChanged(aAttrHasChanged)
michael@0 593 {
michael@0 594 NS_PRECONDITION(!aTreeMatchContext.mForStyling, "Not styling here!");
michael@0 595 }
michael@0 596 nsIAtom* mAttribute; // |HasAttributeDependentStyle| for which attribute?
michael@0 597 int32_t mModType; // The type of modification (see nsIDOMMutationEvent).
michael@0 598 bool mAttrHasChanged; // Whether the attribute has already changed.
michael@0 599 };
michael@0 600
michael@0 601 #endif /* !defined(nsRuleProcessorData_h_) */

mercurial