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/. */
7 * representation of CSS style rules (selectors+declaration) and CSS
11 #ifndef mozilla_css_StyleRule_h__
12 #define mozilla_css_StyleRule_h__
14 #include "mozilla/Attributes.h"
15 #include "mozilla/MemoryReporting.h"
16 #include "mozilla/css/Rule.h"
20 #include "nsCSSPseudoElements.h"
21 #include "nsCSSPseudoClasses.h"
24 struct nsCSSSelectorList
;
25 class nsCSSCompressedDataBlock
;
29 } // namespace mozilla
33 explicit nsAtomList(nsIAtom
* aAtom
);
34 explicit nsAtomList(const nsString
& aAtomValue
);
37 /** Do a deep clone. Should be used only on the first in the linked list. */
38 nsAtomList
* Clone() const { return Clone(true); }
40 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
) const;
42 nsCOMPtr
<nsIAtom
> mAtom
;
45 nsAtomList
* Clone(bool aDeep
) const;
47 nsAtomList(const nsAtomList
& aCopy
) = delete;
48 nsAtomList
& operator=(const nsAtomList
& aCopy
) = delete;
51 struct nsPseudoClassList
{
53 explicit nsPseudoClassList(nsCSSPseudoClasses::Type aType
);
54 nsPseudoClassList(nsCSSPseudoClasses::Type aType
, const char16_t
*aString
);
55 nsPseudoClassList(nsCSSPseudoClasses::Type aType
, const int32_t *aIntPair
);
56 nsPseudoClassList(nsCSSPseudoClasses::Type aType
,
57 nsCSSSelectorList
*aSelectorList
/* takes ownership */);
58 ~nsPseudoClassList(void);
60 /** Do a deep clone. Should be used only on the first in the linked list. */
61 nsPseudoClassList
* Clone() const { return Clone(true); }
63 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
) const;
66 // For a given value of mType, we have either:
67 // a. no value, which means mMemory is always null
68 // (if none of the conditions for (b), (c), or (d) is true)
69 // b. a string value, which means mString/mMemory is non-null
70 // (if nsCSSPseudoClasses::HasStringArg(mType))
71 // c. an integer pair value, which means mNumbers/mMemory is non-null
72 // (if nsCSSPseudoClasses::HasNthPairArg(mType))
73 // d. a selector list, which means mSelectors is non-null
74 // (if nsCSSPseudoClasses::HasSelectorListArg(mType))
75 void* mMemory
; // mString and mNumbers use NS_Alloc/NS_Free
78 nsCSSSelectorList
* mSelectors
;
80 nsCSSPseudoClasses::Type mType
;
81 nsPseudoClassList
* mNext
;
83 nsPseudoClassList
* Clone(bool aDeep
) const;
85 nsPseudoClassList(const nsPseudoClassList
& aCopy
) = delete;
86 nsPseudoClassList
& operator=(const nsPseudoClassList
& aCopy
) = delete;
89 #define NS_ATTR_FUNC_SET 0 // [attr]
90 #define NS_ATTR_FUNC_EQUALS 1 // [attr=value]
91 #define NS_ATTR_FUNC_INCLUDES 2 // [attr~=value] (space separated)
92 #define NS_ATTR_FUNC_DASHMATCH 3 // [attr|=value] ('-' truncated)
93 #define NS_ATTR_FUNC_BEGINSMATCH 4 // [attr^=value] (begins with)
94 #define NS_ATTR_FUNC_ENDSMATCH 5 // [attr$=value] (ends with)
95 #define NS_ATTR_FUNC_CONTAINSMATCH 6 // [attr*=value] (contains substring)
97 struct nsAttrSelector
{
99 nsAttrSelector(int32_t aNameSpace
, const nsString
& aAttr
);
100 nsAttrSelector(int32_t aNameSpace
, const nsString
& aAttr
, uint8_t aFunction
,
101 const nsString
& aValue
, bool aCaseSensitive
);
102 nsAttrSelector(int32_t aNameSpace
, nsIAtom
* aLowercaseAttr
,
103 nsIAtom
* aCasedAttr
, uint8_t aFunction
,
104 const nsString
& aValue
, bool aCaseSensitive
);
105 ~nsAttrSelector(void);
107 /** Do a deep clone. Should be used only on the first in the linked list. */
108 nsAttrSelector
* Clone() const { return Clone(true); }
111 nsAttrSelector
* mNext
;
112 nsCOMPtr
<nsIAtom
> mLowercaseAttr
;
113 nsCOMPtr
<nsIAtom
> mCasedAttr
;
116 bool mCaseSensitive
; // If we are in an HTML document,
117 // is the value case sensitive?
119 nsAttrSelector
* Clone(bool aDeep
) const;
121 nsAttrSelector(const nsAttrSelector
& aCopy
) = delete;
122 nsAttrSelector
& operator=(const nsAttrSelector
& aCopy
) = delete;
125 struct nsCSSSelector
{
128 ~nsCSSSelector(void);
130 /** Do a deep clone. Should be used only on the first in the linked list. */
131 nsCSSSelector
* Clone() const { return Clone(true, true); }
134 void SetNameSpace(int32_t aNameSpace
);
135 void SetTag(const nsString
& aTag
);
136 void AddID(const nsString
& aID
);
137 void AddClass(const nsString
& aClass
);
138 void AddPseudoClass(nsCSSPseudoClasses::Type aType
);
139 void AddPseudoClass(nsCSSPseudoClasses::Type aType
, const char16_t
* aString
);
140 void AddPseudoClass(nsCSSPseudoClasses::Type aType
, const int32_t* aIntPair
);
141 // takes ownership of aSelectorList
142 void AddPseudoClass(nsCSSPseudoClasses::Type aType
,
143 nsCSSSelectorList
* aSelectorList
);
144 void AddAttribute(int32_t aNameSpace
, const nsString
& aAttr
);
145 void AddAttribute(int32_t aNameSpace
, const nsString
& aAttr
, uint8_t aFunc
,
146 const nsString
& aValue
, bool aCaseSensitive
);
147 void SetOperator(char16_t aOperator
);
149 inline bool HasTagSelector() const {
153 inline bool IsPseudoElement() const {
154 return mLowercaseTag
&& !mCasedTag
;
157 // Calculate the specificity of this selector (not including its mNext!).
158 int32_t CalcWeight() const;
160 void ToString(nsAString
& aString
, mozilla::CSSStyleSheet
* aSheet
,
161 bool aAppend
= false) const;
164 void AddPseudoClassInternal(nsPseudoClassList
*aPseudoClass
);
165 nsCSSSelector
* Clone(bool aDeepNext
, bool aDeepNegations
) const;
167 void AppendToStringWithoutCombinators(nsAString
& aString
,
168 mozilla::CSSStyleSheet
* aSheet
) const;
169 void AppendToStringWithoutCombinatorsOrNegations(nsAString
& aString
,
170 mozilla::CSSStyleSheet
* aSheet
,
173 // Returns true if this selector can have a namespace specified (which
174 // happens if and only if the default namespace would apply to this
176 bool CanBeNamespaced(bool aIsNegated
) const;
177 // Calculate the specificity of this selector (not including its mNext
178 // or its mNegations).
179 int32_t CalcWeightWithoutNegations() const;
182 // Get and set the selector's pseudo type
183 nsCSSPseudoElements::Type
PseudoType() const {
184 return static_cast<nsCSSPseudoElements::Type
>(mPseudoType
);
186 void SetPseudoType(nsCSSPseudoElements::Type aType
) {
187 NS_ASSERTION(static_cast<int32_t>(aType
) >= INT16_MIN
&&
188 static_cast<int32_t>(aType
) <= INT16_MAX
,
189 "Out of bounds - this will overflow mPseudoType");
190 mPseudoType
= static_cast<int16_t>(aType
);
193 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
) const;
195 // For case-sensitive documents, mLowercaseTag is the same as mCasedTag,
196 // but in case-insensitive documents (HTML) mLowercaseTag is lowercase.
197 // Also, for pseudo-elements mCasedTag will be null but mLowercaseTag
198 // contains their name.
199 nsCOMPtr
<nsIAtom
> mLowercaseTag
;
200 nsCOMPtr
<nsIAtom
> mCasedTag
;
202 nsAtomList
* mClassList
;
203 nsPseudoClassList
* mPseudoClassList
; // atom for the pseudo, string for
204 // the argument to functional pseudos
205 nsAttrSelector
* mAttrList
;
206 nsCSSSelector
* mNegations
;
207 nsCSSSelector
* mNext
;
211 // int16_t to make sure it packs well with mOperator
214 nsCSSSelector(const nsCSSSelector
& aCopy
) = delete;
215 nsCSSSelector
& operator=(const nsCSSSelector
& aCopy
) = delete;
219 * A selector list is the unit of selectors that each style rule has.
220 * For example, "P B, H1 B { ... }" would be a selector list with two
221 * items (where each |nsCSSSelectorList| object's |mSelectors| has
222 * an |mNext| for the P or H1). We represent them as linked lists.
226 struct nsCSSSelectorList
{
227 nsCSSSelectorList(void);
228 ~nsCSSSelectorList(void);
231 * Create a new selector and push it onto the beginning of |mSelectors|,
232 * setting its |mNext| to the current value of |mSelectors|. If there is an
233 * earlier selector, set its |mOperator| to |aOperator|; else |aOperator|
234 * must be char16_t(0).
235 * Returns the new selector.
236 * The list owns the new selector.
237 * The caller is responsible for updating |mWeight|.
239 nsCSSSelector
* AddSelector(char16_t aOperator
);
242 * Point |mSelectors| to its |mNext|, and delete the first node in the old
244 * Should only be used on a list with more than one selector in it.
246 void RemoveRightmostSelector();
249 * Should be used only on the first in the list
251 void ToString(nsAString
& aResult
, mozilla::CSSStyleSheet
* aSheet
);
254 * Do a deep clone. Should be used only on the first in the list.
256 nsCSSSelectorList
* Clone() const { return Clone(true); }
258 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
) const;
260 nsCSSSelector
* mSelectors
;
262 nsCSSSelectorList
* mNext
;
264 friend class inDOMUtils
;
265 nsCSSSelectorList
* Clone(bool aDeep
) const;
268 nsCSSSelectorList(const nsCSSSelectorList
& aCopy
) = delete;
269 nsCSSSelectorList
& operator=(const nsCSSSelectorList
& aCopy
) = delete;
272 // 464bab7a-2fce-4f30-ab44-b7a5f3aae57d
273 #define NS_CSS_STYLE_RULE_IMPL_CID \
274 { 0x464bab7a, 0x2fce, 0x4f30, \
275 { 0xab, 0x44, 0xb7, 0xa5, 0xf3, 0xaa, 0xe5, 0x7d } }
281 class DOMCSSStyleRule
;
285 class ImportantRule MOZ_FINAL
: public nsIStyleRule
{
287 explicit ImportantRule(Declaration
*aDeclaration
);
291 // nsIStyleRule interface
292 virtual void MapRuleInfoInto(nsRuleData
* aRuleData
) MOZ_OVERRIDE
;
294 virtual void List(FILE* out
= stdout
, int32_t aIndent
= 0) const MOZ_OVERRIDE
;
298 virtual ~ImportantRule();
300 // Not an owning reference; the StyleRule that owns this
301 // ImportantRule also owns the mDeclaration, and any rule node
302 // pointing to this rule keeps that StyleRule alive as well.
303 Declaration
* mDeclaration
;
305 friend class StyleRule
;
308 class StyleRule MOZ_FINAL
: public Rule
311 StyleRule(nsCSSSelectorList
* aSelector
,
312 Declaration
*aDeclaration
,
313 uint32_t aLineNumber
, uint32_t aColumnNumber
);
316 StyleRule(const StyleRule
& aCopy
);
317 // for |DeclarationChanged|
318 StyleRule(StyleRule
& aCopy
,
319 Declaration
*aDeclaration
);
321 NS_DECLARE_STATIC_IID_ACCESSOR(NS_CSS_STYLE_RULE_IMPL_CID
)
325 // null for style attribute
326 nsCSSSelectorList
* Selector() { return mSelector
; }
328 Declaration
* GetDeclaration() const { return mDeclaration
; }
331 * Return a new |nsIStyleRule| instance that replaces the current
332 * one, with |aDecl| replacing the previous declaration. Due to the
333 * |nsIStyleRule| contract of immutability, this must be called if
334 * the declaration is modified.
336 * |DeclarationChanged| handles replacing the object in the container
337 * sheet or group rule if |aHandleContainer| is true.
339 already_AddRefed
<StyleRule
>
340 DeclarationChanged(Declaration
* aDecl
, bool aHandleContainer
);
342 nsIStyleRule
* GetImportantRule() const { return mImportantRule
; }
345 * The rule processor must call this method before calling
346 * nsRuleWalker::Forward on this rule during rule matching.
350 // hooks for DOM rule
351 void GetCssText(nsAString
& aCssText
);
352 void SetCssText(const nsAString
& aCssText
);
353 void GetSelectorText(nsAString
& aSelectorText
);
354 void SetSelectorText(const nsAString
& aSelectorText
);
356 virtual int32_t GetType() const MOZ_OVERRIDE
;
358 virtual already_AddRefed
<Rule
> Clone() const MOZ_OVERRIDE
;
360 virtual nsIDOMCSSRule
* GetDOMRule() MOZ_OVERRIDE
;
362 virtual nsIDOMCSSRule
* GetExistingDOMRule() MOZ_OVERRIDE
;
364 // The new mapping function.
365 virtual void MapRuleInfoInto(nsRuleData
* aRuleData
) MOZ_OVERRIDE
;
368 virtual void List(FILE* out
= stdout
, int32_t aIndent
= 0) const MOZ_OVERRIDE
;
371 virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
) const MOZ_OVERRIDE
;
377 nsCSSSelectorList
* mSelector
; // null for style attribute
378 Declaration
* mDeclaration
;
379 nsRefPtr
<ImportantRule
> mImportantRule
; // initialized by RuleMatched
380 nsRefPtr
<DOMCSSStyleRule
> mDOMRule
;
383 StyleRule
& operator=(const StyleRule
& aCopy
) = delete;
386 NS_DEFINE_STATIC_IID_ACCESSOR(StyleRule
, NS_CSS_STYLE_RULE_IMPL_CID
)
389 } // namespace mozilla
391 #endif /* mozilla_css_StyleRule_h__ */