1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/style/nsRuleProcessorData.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,601 @@ 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 + * data structures passed to nsIStyleRuleProcessor methods (to pull loop 1.11 + * invariant computations out of the loop) 1.12 + */ 1.13 + 1.14 +#ifndef nsRuleProcessorData_h_ 1.15 +#define nsRuleProcessorData_h_ 1.16 + 1.17 +#include "nsPresContext.h" // for nsCompatibility 1.18 +#include "nsString.h" 1.19 +#include "nsChangeHint.h" 1.20 +#include "nsCSSPseudoElements.h" 1.21 +#include "nsRuleWalker.h" 1.22 +#include "nsNthIndexCache.h" 1.23 +#include "nsILoadContext.h" 1.24 +#include "nsIDocument.h" 1.25 +#include "mozilla/AutoRestore.h" 1.26 +#include "mozilla/BloomFilter.h" 1.27 +#include "mozilla/EventStates.h" 1.28 +#include "mozilla/GuardObjects.h" 1.29 + 1.30 +class nsAttrValue; 1.31 +class nsIAtom; 1.32 +class nsIContent; 1.33 +class nsICSSPseudoComparator; 1.34 +class nsIStyleSheet; 1.35 +struct TreeMatchContext; 1.36 + 1.37 +/** 1.38 + * An AncestorFilter is used to keep track of ancestors so that we can 1.39 + * quickly tell that a particular selector is not relevant to a given 1.40 + * element. 1.41 + */ 1.42 +class MOZ_STACK_CLASS AncestorFilter { 1.43 + friend struct TreeMatchContext; 1.44 + public: 1.45 + /* Maintenance of our ancestor state */ 1.46 + void PushAncestor(mozilla::dom::Element *aElement); 1.47 + void PopAncestor(); 1.48 + 1.49 + /* Check whether we might have an ancestor matching one of the given 1.50 + atom hashes. |hashes| must have length hashListLength */ 1.51 + template<size_t hashListLength> 1.52 + bool MightHaveMatchingAncestor(const uint32_t* aHashes) const 1.53 + { 1.54 + MOZ_ASSERT(mFilter); 1.55 + for (size_t i = 0; i < hashListLength && aHashes[i]; ++i) { 1.56 + if (!mFilter->mightContain(aHashes[i])) { 1.57 + return false; 1.58 + } 1.59 + } 1.60 + 1.61 + return true; 1.62 + } 1.63 + 1.64 + bool HasFilter() const { return mFilter; } 1.65 + 1.66 +#ifdef DEBUG 1.67 + void AssertHasAllAncestors(mozilla::dom::Element *aElement) const; 1.68 +#endif 1.69 + 1.70 + private: 1.71 + // Using 2^12 slots makes the Bloom filter a nice round page in 1.72 + // size, so let's do that. We get a false positive rate of 1% or 1.73 + // less even with several hundred things in the filter. Note that 1.74 + // we allocate the filter lazily, because not all tree match 1.75 + // contexts can use one effectively. 1.76 + typedef mozilla::BloomFilter<12, nsIAtom> Filter; 1.77 + nsAutoPtr<Filter> mFilter; 1.78 + 1.79 + // Stack of indices to pop to. These are indices into mHashes. 1.80 + nsTArray<uint32_t> mPopTargets; 1.81 + 1.82 + // List of hashes; this is what we pop using mPopTargets. We store 1.83 + // hashes of our ancestor element tag names, ids, and classes in 1.84 + // here. 1.85 + nsTArray<uint32_t> mHashes; 1.86 + 1.87 + // A debug-only stack of Elements for use in assertions 1.88 +#ifdef DEBUG 1.89 + nsTArray<mozilla::dom::Element*> mElements; 1.90 +#endif 1.91 +}; 1.92 + 1.93 +/** 1.94 + * A |TreeMatchContext| has data about a matching operation. The 1.95 + * data are not node-specific but are invariants of the DOM tree the 1.96 + * nodes being matched against are in. 1.97 + * 1.98 + * Most of the members are in parameters to selector matching. The 1.99 + * one out parameter is mHaveRelevantLink. Consumers that use a 1.100 + * TreeMatchContext for more than one matching operation and care 1.101 + * about :visited and mHaveRelevantLink need to 1.102 + * ResetForVisitedMatching() and ResetForUnvisitedMatching() as 1.103 + * needed. 1.104 + */ 1.105 +struct MOZ_STACK_CLASS TreeMatchContext { 1.106 + // Reset this context for matching for the style-if-:visited. 1.107 + void ResetForVisitedMatching() { 1.108 + NS_PRECONDITION(mForStyling, "Why is this being called?"); 1.109 + mHaveRelevantLink = false; 1.110 + mVisitedHandling = nsRuleWalker::eRelevantLinkVisited; 1.111 + } 1.112 + 1.113 + void ResetForUnvisitedMatching() { 1.114 + NS_PRECONDITION(mForStyling, "Why is this being called?"); 1.115 + mHaveRelevantLink = false; 1.116 + mVisitedHandling = nsRuleWalker::eRelevantLinkUnvisited; 1.117 + } 1.118 + 1.119 + void SetHaveRelevantLink() { mHaveRelevantLink = true; } 1.120 + bool HaveRelevantLink() const { return mHaveRelevantLink; } 1.121 + 1.122 + nsRuleWalker::VisitedHandlingType VisitedHandling() const 1.123 + { 1.124 + return mVisitedHandling; 1.125 + } 1.126 + 1.127 + void AddScopeElement(mozilla::dom::Element* aElement) { 1.128 + NS_PRECONDITION(mHaveSpecifiedScope, 1.129 + "Should be set before calling AddScopeElement()"); 1.130 + mScopes.AppendElement(aElement); 1.131 + } 1.132 + bool IsScopeElement(mozilla::dom::Element* aElement) const { 1.133 + return mScopes.Contains(aElement); 1.134 + } 1.135 + void SetHasSpecifiedScope() { 1.136 + mHaveSpecifiedScope = true; 1.137 + } 1.138 + bool HasSpecifiedScope() const { 1.139 + return mHaveSpecifiedScope; 1.140 + } 1.141 + 1.142 + /** 1.143 + * Initialize the ancestor filter and list of style scopes. If aElement is 1.144 + * not null, it and all its ancestors will be passed to 1.145 + * mAncestorFilter.PushAncestor and PushStyleScope, starting from the root and 1.146 + * going down the tree. Must only be called for elements in a document. 1.147 + */ 1.148 + void InitAncestors(mozilla::dom::Element *aElement); 1.149 + 1.150 + /** 1.151 + * Like InitAncestors, but only initializes the style scope list, not the 1.152 + * ancestor filter. May be called for elements outside a document. 1.153 + */ 1.154 + void InitStyleScopes(mozilla::dom::Element* aElement); 1.155 + 1.156 + void PushStyleScope(mozilla::dom::Element* aElement) 1.157 + { 1.158 + NS_PRECONDITION(aElement, "aElement must not be null"); 1.159 + if (aElement->IsScopedStyleRoot()) { 1.160 + mStyleScopes.AppendElement(aElement); 1.161 + } 1.162 + } 1.163 + 1.164 + void PopStyleScope(mozilla::dom::Element* aElement) 1.165 + { 1.166 + NS_PRECONDITION(aElement, "aElement must not be null"); 1.167 + if (mStyleScopes.SafeLastElement(nullptr) == aElement) { 1.168 + mStyleScopes.TruncateLength(mStyleScopes.Length() - 1); 1.169 + } 1.170 + } 1.171 + 1.172 + bool PopStyleScopeForSelectorMatching(mozilla::dom::Element* aElement) 1.173 + { 1.174 + NS_ASSERTION(mForScopedStyle, "only call PopStyleScopeForSelectorMatching " 1.175 + "when mForScopedStyle is true"); 1.176 + 1.177 + if (!mCurrentStyleScope) { 1.178 + return false; 1.179 + } 1.180 + if (mCurrentStyleScope == aElement) { 1.181 + mCurrentStyleScope = nullptr; 1.182 + } 1.183 + return true; 1.184 + } 1.185 + 1.186 +#ifdef DEBUG 1.187 + void AssertHasAllStyleScopes(mozilla::dom::Element* aElement) 1.188 + { 1.189 + nsINode* cur = aElement->GetParentNode(); 1.190 + while (cur) { 1.191 + if (cur->IsScopedStyleRoot()) { 1.192 + MOZ_ASSERT(mStyleScopes.Contains(cur)); 1.193 + } 1.194 + cur = cur->GetParentNode(); 1.195 + } 1.196 + } 1.197 +#endif 1.198 + 1.199 + bool SetStyleScopeForSelectorMatching(mozilla::dom::Element* aSubject, 1.200 + mozilla::dom::Element* aScope) 1.201 + { 1.202 +#ifdef DEBUG 1.203 + AssertHasAllStyleScopes(aSubject); 1.204 +#endif 1.205 + 1.206 + mForScopedStyle = !!aScope; 1.207 + if (!aScope) { 1.208 + // This is not for a scoped style sheet; return true, as we want 1.209 + // selector matching to proceed. 1.210 + mCurrentStyleScope = nullptr; 1.211 + return true; 1.212 + } 1.213 + if (aScope == aSubject) { 1.214 + // Although the subject is the same element as the scope, as soon 1.215 + // as we continue with selector matching up the tree we don't want 1.216 + // to match any more elements. So we return true to indicate that 1.217 + // we want to do the initial selector matching, but set 1.218 + // mCurrentStyleScope to null so that no ancestor elements will match. 1.219 + mCurrentStyleScope = nullptr; 1.220 + return true; 1.221 + } 1.222 + if (mStyleScopes.Contains(aScope)) { 1.223 + // mStyleScopes contains all of the scope elements that are ancestors of 1.224 + // aSubject, so if aScope is in mStyleScopes, then we do want selector 1.225 + // matching to proceed. 1.226 + mCurrentStyleScope = aScope; 1.227 + return true; 1.228 + } 1.229 + // Otherwise, we're not in the scope, and we don't want to proceed 1.230 + // with selector matching. 1.231 + mCurrentStyleScope = nullptr; 1.232 + return false; 1.233 + } 1.234 + 1.235 + bool IsWithinStyleScopeForSelectorMatching() const 1.236 + { 1.237 + NS_ASSERTION(mForScopedStyle, "only call IsWithinScopeForSelectorMatching " 1.238 + "when mForScopedStyle is true"); 1.239 + return mCurrentStyleScope; 1.240 + } 1.241 + 1.242 + /* Helper class for maintaining the ancestor state */ 1.243 + class MOZ_STACK_CLASS AutoAncestorPusher { 1.244 + public: 1.245 + AutoAncestorPusher(TreeMatchContext& aTreeMatchContext 1.246 + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) 1.247 + : mPushedAncestor(false) 1.248 + , mPushedStyleScope(false) 1.249 + , mTreeMatchContext(aTreeMatchContext) 1.250 + , mElement(nullptr) 1.251 + { 1.252 + MOZ_GUARD_OBJECT_NOTIFIER_INIT; 1.253 + } 1.254 + 1.255 + void PushAncestorAndStyleScope(mozilla::dom::Element* aElement) { 1.256 + MOZ_ASSERT(!mElement); 1.257 + if (aElement) { 1.258 + mElement = aElement; 1.259 + mPushedAncestor = true; 1.260 + mPushedStyleScope = true; 1.261 + mTreeMatchContext.mAncestorFilter.PushAncestor(aElement); 1.262 + mTreeMatchContext.PushStyleScope(aElement); 1.263 + } 1.264 + } 1.265 + 1.266 + void PushAncestorAndStyleScope(nsIContent* aContent) { 1.267 + if (aContent && aContent->IsElement()) { 1.268 + PushAncestorAndStyleScope(aContent->AsElement()); 1.269 + } 1.270 + } 1.271 + 1.272 + void PushStyleScope(mozilla::dom::Element* aElement) { 1.273 + MOZ_ASSERT(!mElement); 1.274 + if (aElement) { 1.275 + mElement = aElement; 1.276 + mPushedStyleScope = true; 1.277 + mTreeMatchContext.PushStyleScope(aElement); 1.278 + } 1.279 + } 1.280 + 1.281 + void PushStyleScope(nsIContent* aContent) { 1.282 + if (aContent && aContent->IsElement()) { 1.283 + PushStyleScope(aContent->AsElement()); 1.284 + } 1.285 + } 1.286 + 1.287 + ~AutoAncestorPusher() { 1.288 + if (mPushedAncestor) { 1.289 + mTreeMatchContext.mAncestorFilter.PopAncestor(); 1.290 + } 1.291 + if (mPushedStyleScope) { 1.292 + mTreeMatchContext.PopStyleScope(mElement); 1.293 + } 1.294 + } 1.295 + 1.296 + private: 1.297 + bool mPushedAncestor; 1.298 + bool mPushedStyleScope; 1.299 + TreeMatchContext& mTreeMatchContext; 1.300 + mozilla::dom::Element* mElement; 1.301 + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER 1.302 + }; 1.303 + 1.304 + /* Helper class for tracking whether we're skipping the ApplyStyleFixups 1.305 + * code for flex items. 1.306 + * 1.307 + * The optional second parameter aSkipFlexItemStyleFixup allows this 1.308 + * class to be instantiated but only conditionally activated (e.g. 1.309 + * in cases where we may or may not want to be skipping flex-item 1.310 + * style fixup for a particular chunk of code). 1.311 + */ 1.312 + class MOZ_STACK_CLASS AutoFlexItemStyleFixupSkipper { 1.313 + public: 1.314 + AutoFlexItemStyleFixupSkipper(TreeMatchContext& aTreeMatchContext, 1.315 + bool aSkipFlexItemStyleFixup = true 1.316 + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) 1.317 + : mAutoRestorer(aTreeMatchContext.mSkippingFlexItemStyleFixup) 1.318 + { 1.319 + MOZ_GUARD_OBJECT_NOTIFIER_INIT; 1.320 + if (aSkipFlexItemStyleFixup) { 1.321 + aTreeMatchContext.mSkippingFlexItemStyleFixup = true; 1.322 + } 1.323 + } 1.324 + 1.325 + private: 1.326 + mozilla::AutoRestore<bool> mAutoRestorer; 1.327 + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER 1.328 + }; 1.329 + 1.330 + // Is this matching operation for the creation of a style context? 1.331 + // (If it is, we need to set slow selector bits on nodes indicating 1.332 + // that certain restyling needs to happen.) 1.333 + const bool mForStyling; 1.334 + 1.335 + private: 1.336 + // When mVisitedHandling is eRelevantLinkUnvisited, this is set to true if a 1.337 + // relevant link (see explanation in definition of VisitedHandling enum) was 1.338 + // encountered during the matching process, which means that matching needs 1.339 + // to be rerun with eRelevantLinkVisited. Otherwise, its behavior is 1.340 + // undefined (it might get set appropriately, or might not). 1.341 + bool mHaveRelevantLink; 1.342 + 1.343 + // If true, then our contextual reference element set is specified, 1.344 + // and is given by mScopes. 1.345 + bool mHaveSpecifiedScope; 1.346 + 1.347 + // How matching should be performed. See the documentation for 1.348 + // nsRuleWalker::VisitedHandlingType. 1.349 + nsRuleWalker::VisitedHandlingType mVisitedHandling; 1.350 + 1.351 + // For matching :scope 1.352 + nsAutoTArray<mozilla::dom::Element*, 1> mScopes; 1.353 + public: 1.354 + // The document we're working with. 1.355 + nsIDocument* const mDocument; 1.356 + 1.357 + // Root of scoped stylesheet (set and unset by the supplier of the 1.358 + // scoped stylesheet). 1.359 + nsIContent* mScopedRoot; 1.360 + 1.361 + // Whether our document is HTML (as opposed to XML of some sort, 1.362 + // including XHTML). 1.363 + // XXX XBL2 issue: Should we be caching this? What should it be for XBL2? 1.364 + const bool mIsHTMLDocument; 1.365 + 1.366 + // Possibly remove use of mCompatMode in SelectorMatches? 1.367 + // XXX XBL2 issue: Should we be caching this? What should it be for XBL2? 1.368 + const nsCompatibility mCompatMode; 1.369 + 1.370 + // The nth-index cache we should use 1.371 + nsNthIndexCache mNthIndexCache; 1.372 + 1.373 + // An ancestor filter 1.374 + AncestorFilter mAncestorFilter; 1.375 + 1.376 + // Whether this document is using PB mode 1.377 + bool mUsingPrivateBrowsing; 1.378 + 1.379 + // Whether we're currently skipping the flex item chunk of ApplyStyleFixups 1.380 + // when resolving style (e.g. for children of elements that have a mandatory 1.381 + // frame-type and can't be flex containers despite having "display:flex"). 1.382 + bool mSkippingFlexItemStyleFixup; 1.383 + 1.384 + // Whether this TreeMatchContext is being used with an nsCSSRuleProcessor 1.385 + // for an HTML5 scoped style sheet. 1.386 + bool mForScopedStyle; 1.387 + 1.388 + enum MatchVisited { 1.389 + eNeverMatchVisited, 1.390 + eMatchVisitedDefault 1.391 + }; 1.392 + 1.393 + // List of ancestor elements that define a style scope (due to having a 1.394 + // <style scoped> child). 1.395 + nsAutoTArray<mozilla::dom::Element*, 1> mStyleScopes; 1.396 + 1.397 + // The current style scope element for selector matching. 1.398 + mozilla::dom::Element* mCurrentStyleScope; 1.399 + 1.400 + // Constructor to use when creating a tree match context for styling 1.401 + TreeMatchContext(bool aForStyling, 1.402 + nsRuleWalker::VisitedHandlingType aVisitedHandling, 1.403 + nsIDocument* aDocument, 1.404 + MatchVisited aMatchVisited = eMatchVisitedDefault) 1.405 + : mForStyling(aForStyling) 1.406 + , mHaveRelevantLink(false) 1.407 + , mHaveSpecifiedScope(false) 1.408 + , mVisitedHandling(aVisitedHandling) 1.409 + , mDocument(aDocument) 1.410 + , mScopedRoot(nullptr) 1.411 + , mIsHTMLDocument(aDocument->IsHTML()) 1.412 + , mCompatMode(aDocument->GetCompatibilityMode()) 1.413 + , mUsingPrivateBrowsing(false) 1.414 + , mSkippingFlexItemStyleFixup(false) 1.415 + , mForScopedStyle(false) 1.416 + , mCurrentStyleScope(nullptr) 1.417 + { 1.418 + if (aMatchVisited != eNeverMatchVisited) { 1.419 + nsCOMPtr<nsISupports> container = mDocument->GetContainer(); 1.420 + if (container) { 1.421 + nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(container); 1.422 + NS_ASSERTION(loadContext, "Couldn't get loadContext from container; assuming no private browsing."); 1.423 + if (loadContext) { 1.424 + mUsingPrivateBrowsing = loadContext->UsePrivateBrowsing(); 1.425 + } 1.426 + } 1.427 + } 1.428 + } 1.429 +}; 1.430 + 1.431 +struct MOZ_STACK_CLASS RuleProcessorData { 1.432 + RuleProcessorData(nsPresContext* aPresContext, 1.433 + nsRuleWalker* aRuleWalker) 1.434 + : mPresContext(aPresContext), 1.435 + mRuleWalker(aRuleWalker), 1.436 + mScope(nullptr) 1.437 + { 1.438 + NS_PRECONDITION(mPresContext, "Must have prescontext"); 1.439 + } 1.440 + 1.441 + nsPresContext* const mPresContext; 1.442 + nsRuleWalker* const mRuleWalker; // Used to add rules to our results. 1.443 + mozilla::dom::Element* mScope; 1.444 +}; 1.445 + 1.446 +struct MOZ_STACK_CLASS ElementDependentRuleProcessorData : 1.447 + public RuleProcessorData { 1.448 + ElementDependentRuleProcessorData(nsPresContext* aPresContext, 1.449 + mozilla::dom::Element* aElement, 1.450 + nsRuleWalker* aRuleWalker, 1.451 + TreeMatchContext& aTreeMatchContext) 1.452 + : RuleProcessorData(aPresContext, aRuleWalker) 1.453 + , mElement(aElement) 1.454 + , mTreeMatchContext(aTreeMatchContext) 1.455 + { 1.456 + NS_ASSERTION(aElement, "null element leaked into SelectorMatches"); 1.457 + NS_ASSERTION(aElement->OwnerDoc(), "Document-less node here?"); 1.458 + NS_PRECONDITION(aTreeMatchContext.mForStyling == !!aRuleWalker, 1.459 + "Should be styling if and only if we have a rule walker"); 1.460 + } 1.461 + 1.462 + mozilla::dom::Element* const mElement; // weak ref, must not be null 1.463 + TreeMatchContext& mTreeMatchContext; 1.464 +}; 1.465 + 1.466 +struct MOZ_STACK_CLASS ElementRuleProcessorData : 1.467 + public ElementDependentRuleProcessorData { 1.468 + ElementRuleProcessorData(nsPresContext* aPresContext, 1.469 + mozilla::dom::Element* aElement, 1.470 + nsRuleWalker* aRuleWalker, 1.471 + TreeMatchContext& aTreeMatchContext) 1.472 + : ElementDependentRuleProcessorData(aPresContext, aElement, aRuleWalker, 1.473 + aTreeMatchContext) 1.474 + { 1.475 + NS_PRECONDITION(aTreeMatchContext.mForStyling, "Styling here!"); 1.476 + NS_PRECONDITION(aRuleWalker, "Must have rule walker"); 1.477 + } 1.478 +}; 1.479 + 1.480 +struct MOZ_STACK_CLASS PseudoElementRuleProcessorData : 1.481 + public ElementDependentRuleProcessorData { 1.482 + PseudoElementRuleProcessorData(nsPresContext* aPresContext, 1.483 + mozilla::dom::Element* aParentElement, 1.484 + nsRuleWalker* aRuleWalker, 1.485 + nsCSSPseudoElements::Type aPseudoType, 1.486 + TreeMatchContext& aTreeMatchContext, 1.487 + mozilla::dom::Element* aPseudoElement) 1.488 + : ElementDependentRuleProcessorData(aPresContext, aParentElement, aRuleWalker, 1.489 + aTreeMatchContext), 1.490 + mPseudoType(aPseudoType), 1.491 + mPseudoElement(aPseudoElement) 1.492 + { 1.493 + NS_PRECONDITION(aPseudoType < 1.494 + nsCSSPseudoElements::ePseudo_PseudoElementCount, 1.495 + "invalid aPseudoType value"); 1.496 + NS_PRECONDITION(aTreeMatchContext.mForStyling, "Styling here!"); 1.497 + NS_PRECONDITION(aRuleWalker, "Must have rule walker"); 1.498 + } 1.499 + 1.500 + nsCSSPseudoElements::Type mPseudoType; 1.501 + mozilla::dom::Element* const mPseudoElement; // weak ref 1.502 +}; 1.503 + 1.504 +struct MOZ_STACK_CLASS AnonBoxRuleProcessorData : public RuleProcessorData { 1.505 + AnonBoxRuleProcessorData(nsPresContext* aPresContext, 1.506 + nsIAtom* aPseudoTag, 1.507 + nsRuleWalker* aRuleWalker) 1.508 + : RuleProcessorData(aPresContext, aRuleWalker), 1.509 + mPseudoTag(aPseudoTag) 1.510 + { 1.511 + NS_PRECONDITION(aPseudoTag, "Must have pseudo tag"); 1.512 + NS_PRECONDITION(aRuleWalker, "Must have rule walker"); 1.513 + } 1.514 + 1.515 + nsIAtom* mPseudoTag; 1.516 +}; 1.517 + 1.518 +#ifdef MOZ_XUL 1.519 +struct MOZ_STACK_CLASS XULTreeRuleProcessorData : 1.520 + public ElementDependentRuleProcessorData { 1.521 + XULTreeRuleProcessorData(nsPresContext* aPresContext, 1.522 + mozilla::dom::Element* aParentElement, 1.523 + nsRuleWalker* aRuleWalker, 1.524 + nsIAtom* aPseudoTag, 1.525 + nsICSSPseudoComparator* aComparator, 1.526 + TreeMatchContext& aTreeMatchContext) 1.527 + : ElementDependentRuleProcessorData(aPresContext, aParentElement, 1.528 + aRuleWalker, aTreeMatchContext), 1.529 + mPseudoTag(aPseudoTag), 1.530 + mComparator(aComparator) 1.531 + { 1.532 + NS_PRECONDITION(aPseudoTag, "null pointer"); 1.533 + NS_PRECONDITION(aRuleWalker, "Must have rule walker"); 1.534 + NS_PRECONDITION(aComparator, "must have a comparator"); 1.535 + NS_PRECONDITION(aTreeMatchContext.mForStyling, "Styling here!"); 1.536 + } 1.537 + 1.538 + nsIAtom* mPseudoTag; 1.539 + nsICSSPseudoComparator* mComparator; 1.540 +}; 1.541 +#endif 1.542 + 1.543 +struct MOZ_STACK_CLASS StateRuleProcessorData : 1.544 + public ElementDependentRuleProcessorData { 1.545 + StateRuleProcessorData(nsPresContext* aPresContext, 1.546 + mozilla::dom::Element* aElement, 1.547 + mozilla::EventStates aStateMask, 1.548 + TreeMatchContext& aTreeMatchContext) 1.549 + : ElementDependentRuleProcessorData(aPresContext, aElement, nullptr, 1.550 + aTreeMatchContext), 1.551 + mStateMask(aStateMask) 1.552 + { 1.553 + NS_PRECONDITION(!aTreeMatchContext.mForStyling, "Not styling here!"); 1.554 + } 1.555 + // |HasStateDependentStyle| for which state(s)? 1.556 + // Constants defined in mozilla/EventStates.h . 1.557 + const mozilla::EventStates mStateMask; 1.558 +}; 1.559 + 1.560 +struct MOZ_STACK_CLASS PseudoElementStateRuleProcessorData : 1.561 + public StateRuleProcessorData { 1.562 + PseudoElementStateRuleProcessorData(nsPresContext* aPresContext, 1.563 + mozilla::dom::Element* aElement, 1.564 + mozilla::EventStates aStateMask, 1.565 + nsCSSPseudoElements::Type aPseudoType, 1.566 + TreeMatchContext& aTreeMatchContext, 1.567 + mozilla::dom::Element* aPseudoElement) 1.568 + : StateRuleProcessorData(aPresContext, aElement, aStateMask, 1.569 + aTreeMatchContext), 1.570 + mPseudoType(aPseudoType), 1.571 + mPseudoElement(aPseudoElement) 1.572 + { 1.573 + NS_PRECONDITION(!aTreeMatchContext.mForStyling, "Not styling here!"); 1.574 + } 1.575 + 1.576 + // We kind of want to inherit from both StateRuleProcessorData and 1.577 + // PseudoElementRuleProcessorData. Instead we've just copied those 1.578 + // members from PseudoElementRuleProcessorData to this struct. 1.579 + nsCSSPseudoElements::Type mPseudoType; 1.580 + mozilla::dom::Element* const mPseudoElement; // weak ref 1.581 +}; 1.582 + 1.583 +struct MOZ_STACK_CLASS AttributeRuleProcessorData : 1.584 + public ElementDependentRuleProcessorData { 1.585 + AttributeRuleProcessorData(nsPresContext* aPresContext, 1.586 + mozilla::dom::Element* aElement, 1.587 + nsIAtom* aAttribute, 1.588 + int32_t aModType, 1.589 + bool aAttrHasChanged, 1.590 + TreeMatchContext& aTreeMatchContext) 1.591 + : ElementDependentRuleProcessorData(aPresContext, aElement, nullptr, 1.592 + aTreeMatchContext), 1.593 + mAttribute(aAttribute), 1.594 + mModType(aModType), 1.595 + mAttrHasChanged(aAttrHasChanged) 1.596 + { 1.597 + NS_PRECONDITION(!aTreeMatchContext.mForStyling, "Not styling here!"); 1.598 + } 1.599 + nsIAtom* mAttribute; // |HasAttributeDependentStyle| for which attribute? 1.600 + int32_t mModType; // The type of modification (see nsIDOMMutationEvent). 1.601 + bool mAttrHasChanged; // Whether the attribute has already changed. 1.602 +}; 1.603 + 1.604 +#endif /* !defined(nsRuleProcessorData_h_) */