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