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 a declaration block (or style attribute) in a CSS
11 #ifndef mozilla_css_Declaration_h
12 #define mozilla_css_Declaration_h
14 // This header is in EXPORTS because it's used in several places in content/,
15 // but it's not really a public interface.
16 #ifndef MOZILLA_INTERNAL_API
17 #error "This file should only be included within libxul"
20 #include "mozilla/Attributes.h"
21 #include "mozilla/MemoryReporting.h"
22 #include "CSSVariableDeclarations.h"
23 #include "nsCSSDataBlock.h"
24 #include "nsCSSProperty.h"
25 #include "nsCSSProps.h"
26 #include "nsStringFwd.h"
33 // Declaration objects have unusual lifetime rules. Every declaration
34 // begins life in an invalid state which ends when InitializeEmpty or
35 // CompressFrom is called upon it. After that, it can be attached to
36 // exactly one style rule, and will be destroyed when that style rule
37 // is destroyed. A declaration becomes immutable when its style rule's
38 // |RuleMatched| method is called; after that, it must be copied before
39 // it can be modified, which is taken care of by |EnsureMutable|.
44 * Construct an |Declaration| that is in an invalid state (null
45 * |mData|) and cannot be used until its |CompressFrom| method or
46 * |InitializeEmpty| method is called.
50 Declaration(const Declaration
& aCopy
);
55 * |ValueAppended| must be called to maintain this declaration's
56 * |mOrder| whenever a property is parsed into an expanded data block
57 * for this declaration. aProperty must not be a shorthand.
59 void ValueAppended(nsCSSProperty aProperty
);
61 void RemoveProperty(nsCSSProperty aProperty
);
63 bool HasProperty(nsCSSProperty aProperty
) const;
65 void GetValue(nsCSSProperty aProperty
, nsAString
& aValue
) const;
66 void GetAuthoredValue(nsCSSProperty aProperty
, nsAString
& aValue
) const;
68 bool HasImportantData() const {
69 return mImportantData
|| mImportantVariables
;
71 bool GetValueIsImportant(nsCSSProperty aProperty
) const;
72 bool GetValueIsImportant(const nsAString
& aProperty
) const;
75 * Adds a custom property declaration to this object.
77 * @param aName The variable name (i.e., without the "--" prefix).
78 * @param aType The type of value the variable has.
79 * @param aValue The value of the variable, if aType is
80 * CSSVariableDeclarations::eTokenStream.
81 * @param aIsImportant Whether the declaration is !important.
82 * @param aOverrideImportant When aIsImportant is false, whether an
83 * existing !important declaration will be overridden.
85 void AddVariableDeclaration(const nsAString
& aName
,
86 CSSVariableDeclarations::Type aType
,
87 const nsString
& aValue
,
89 bool aOverrideImportant
);
92 * Removes a custom property declaration from this object.
94 * @param aName The variable name (i.e., without the "--" prefix).
96 void RemoveVariableDeclaration(const nsAString
& aName
);
99 * Returns whether a custom property declaration for a variable with
100 * a given name exists on this object.
102 * @param aName The variable name (i.e., without the "--" prefix).
104 bool HasVariableDeclaration(const nsAString
& aName
) const;
107 * Gets the string value for a custom property declaration of a variable
110 * @param aName The variable name (i.e., without the "--" prefix).
111 * @param aValue Out parameter into which the variable's value will be
112 * stored. If the value is 'initial' or 'inherit', that exact string
113 * will be stored in aValue.
115 void GetVariableDeclaration(const nsAString
& aName
, nsAString
& aValue
) const;
118 * Returns whether the custom property declaration for a variable with
119 * the given name was !important.
121 bool GetVariableValueIsImportant(const nsAString
& aName
) const;
123 uint32_t Count() const {
124 return mOrder
.Length();
127 // Returns whether we actually had a property at aIndex
128 bool GetNthProperty(uint32_t aIndex
, nsAString
& aReturn
) const;
130 void ToString(nsAString
& aString
) const;
132 nsCSSCompressedDataBlock
* GetNormalBlock() const { return mData
; }
133 nsCSSCompressedDataBlock
* GetImportantBlock() const { return mImportantData
; }
136 * Initialize this declaration as holding no data. Cannot fail.
138 void InitializeEmpty();
141 * Transfer all of the state from |aExpandedData| into this declaration.
142 * After calling, |aExpandedData| should be in its initial state.
143 * Callers must make sure mOrder is updated as necessary.
145 void CompressFrom(nsCSSExpandedDataBlock
*aExpandedData
) {
146 NS_ABORT_IF_FALSE(!mData
, "oops");
147 NS_ABORT_IF_FALSE(!mImportantData
, "oops");
148 aExpandedData
->Compress(getter_Transfers(mData
),
149 getter_Transfers(mImportantData
),
151 aExpandedData
->AssertInitialState();
155 * Transfer all of the state from this declaration into
156 * |aExpandedData| and put this declaration temporarily into an
157 * invalid state (ended by |CompressFrom| or |InitializeEmpty|) that
158 * should last only during parsing. During this time only
159 * |ValueAppended| should be called.
161 void ExpandTo(nsCSSExpandedDataBlock
*aExpandedData
) {
163 aExpandedData
->AssertInitialState();
165 NS_ABORT_IF_FALSE(mData
, "oops");
166 aExpandedData
->Expand(mData
.forget(), mImportantData
.forget());
170 * Do what |nsIStyleRule::MapRuleInfoInto| needs to do for a style
171 * rule using this declaration for storage.
173 void MapNormalRuleInfoInto(nsRuleData
*aRuleData
) const {
174 NS_ABORT_IF_FALSE(mData
, "called while expanded");
175 mData
->MapRuleInfoInto(aRuleData
);
177 mVariables
->MapRuleInfoInto(aRuleData
);
180 void MapImportantRuleInfoInto(nsRuleData
*aRuleData
) const {
181 NS_ABORT_IF_FALSE(mData
, "called while expanded");
182 NS_ABORT_IF_FALSE(mImportantData
|| mImportantVariables
,
183 "must have important data or variables");
184 if (mImportantData
) {
185 mImportantData
->MapRuleInfoInto(aRuleData
);
187 if (mImportantVariables
) {
188 mImportantVariables
->MapRuleInfoInto(aRuleData
);
193 * Attempt to replace the value for |aProperty| stored in this
194 * declaration with the matching value from |aFromBlock|.
195 * This method may only be called on a mutable declaration.
196 * It will fail (returning false) if |aProperty| is shorthand,
197 * is not already in this declaration, or does not have the indicated
198 * importance level. If it returns true, it erases the value in
199 * |aFromBlock|. |aChanged| is set to true if the declaration
200 * changed as a result of the call, and to false otherwise.
202 bool TryReplaceValue(nsCSSProperty aProperty
, bool aIsImportant
,
203 nsCSSExpandedDataBlock
& aFromBlock
,
207 NS_ABORT_IF_FALSE(mData
, "called while expanded");
209 if (nsCSSProps::IsShorthand(aProperty
)) {
213 nsCSSCompressedDataBlock
*block
= aIsImportant
? mImportantData
: mData
;
214 // mImportantData might be null
222 nsCSSCompressedDataBlock
*other
= aIsImportant
? mData
: mImportantData
;
223 NS_ABORT_IF_FALSE(!other
|| !other
->ValueFor(aProperty
) ||
224 !block
->ValueFor(aProperty
),
225 "Property both important and not?");
228 return block
->TryReplaceValue(aProperty
, aFromBlock
, aChanged
);
231 bool HasNonImportantValueFor(nsCSSProperty aProperty
) const {
232 NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(aProperty
), "must be longhand");
233 return !!mData
->ValueFor(aProperty
);
237 * Return whether |this| may be modified.
239 bool IsMutable() const {
244 * Copy |this|, if necessary to ensure that it can be modified.
246 Declaration
* EnsureMutable();
249 * Crash if |this| cannot be modified.
251 void AssertMutable() const {
252 NS_ABORT_IF_FALSE(IsMutable(), "someone forgot to call EnsureMutable");
256 * Mark this declaration as unmodifiable. It's 'const' so it can
257 * be called from ToString.
259 void SetImmutable() const { mImmutable
= true; }
262 * Clear the data, in preparation for its replacement with entirely
263 * new data by a call to |CompressFrom|.
268 mImportantData
= nullptr;
269 mVariables
= nullptr;
270 mImportantVariables
= nullptr;
272 mVariableOrder
.Clear();
276 void List(FILE* out
= stdout
, int32_t aIndent
= 0) const;
280 Declaration
& operator=(const Declaration
& aCopy
) = delete;
281 bool operator==(const Declaration
& aCopy
) const = delete;
283 void GetValue(nsCSSProperty aProperty
, nsAString
& aValue
,
284 nsCSSValue::Serialization aValueSerialization
) const;
286 static void AppendImportanceToString(bool aIsImportant
, nsAString
& aString
);
287 // return whether there was a value in |aValue| (i.e., it had a non-null unit)
288 bool AppendValueToString(nsCSSProperty aProperty
, nsAString
& aResult
) const;
289 bool AppendValueToString(nsCSSProperty aProperty
, nsAString
& aResult
,
290 nsCSSValue::Serialization aValueSerialization
) const;
291 // Helper for ToString with strange semantics regarding aValue.
292 void AppendPropertyAndValueToString(nsCSSProperty aProperty
,
293 nsAutoString
& aValue
,
294 nsAString
& aResult
) const;
295 // helper for ToString that serializes a custom property declaration for
296 // a variable with the specified name
297 void AppendVariableAndValueToString(const nsAString
& aName
,
298 nsAString
& aResult
) const;
302 * Returns the property at the given index in the ordered list of
303 * declarations. For custom properties, eCSSPropertyExtra_variable
306 nsCSSProperty
GetPropertyAt(uint32_t aIndex
) const {
307 uint32_t value
= mOrder
[aIndex
];
308 if (value
>= eCSSProperty_COUNT
) {
309 return eCSSPropertyExtra_variable
;
311 return nsCSSProperty(value
);
315 * Gets the name of the custom property at the given index in the ordered
316 * list of declarations.
318 void GetCustomPropertyNameAt(uint32_t aIndex
, nsAString
& aResult
) const {
319 MOZ_ASSERT(mOrder
[aIndex
] >= eCSSProperty_COUNT
);
320 uint32_t variableIndex
= mOrder
[aIndex
] - eCSSProperty_COUNT
;
322 aResult
.AppendLiteral("--");
323 aResult
.Append(mVariableOrder
[variableIndex
]);
326 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
) const;
329 // The order of properties in this declaration. Longhand properties are
330 // represented by their nsCSSProperty value, and each custom property (--*)
331 // is represented by a value that begins at eCSSProperty_COUNT.
333 // Subtracting eCSSProperty_COUNT from those values that represent custom
334 // properties results in an index into mVariableOrder, which identifies the
335 // specific variable the custom property declaration is for.
336 nsAutoTArray
<uint32_t, 8> mOrder
;
338 // variable names of custom properties found in mOrder
339 nsTArray
<nsString
> mVariableOrder
;
341 // never null, except while expanded, or before the first call to
342 // InitializeEmpty or CompressFrom.
343 nsAutoPtr
<nsCSSCompressedDataBlock
> mData
;
346 nsAutoPtr
<nsCSSCompressedDataBlock
> mImportantData
;
349 nsAutoPtr
<CSSVariableDeclarations
> mVariables
;
352 nsAutoPtr
<CSSVariableDeclarations
> mImportantVariables
;
354 // set by style rules when |RuleMatched| is called;
355 // also by ToString (hence the 'mutable').
356 mutable bool mImmutable
;
360 } // namespace mozilla
362 #endif /* mozilla_css_Declaration_h */