1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/dom/CSSStyleRule.h"
9 #include "mozilla/CSSEnabledState.h"
10 #include "mozilla/DeclarationBlock.h"
11 #include "mozilla/PseudoStyleType.h"
12 #include "mozilla/ServoBindings.h"
13 #include "mozilla/dom/CSSStyleRuleBinding.h"
14 #include "nsCSSPseudoElements.h"
16 #include "mozAutoDocUpdate.h"
18 using namespace mozilla::dom
;
23 // -- CSSStyleRuleDeclaration ---------------------------------------
25 CSSStyleRuleDeclaration::CSSStyleRuleDeclaration(
26 already_AddRefed
<RawServoDeclarationBlock
> aDecls
)
27 : mDecls(new DeclarationBlock(std::move(aDecls
))) {}
29 CSSStyleRuleDeclaration::~CSSStyleRuleDeclaration() {
30 mDecls
->SetOwningRule(nullptr);
33 // QueryInterface implementation for CSSStyleRuleDeclaration
34 NS_INTERFACE_MAP_BEGIN(CSSStyleRuleDeclaration
)
35 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
36 // We forward the cycle collection interfaces to Rule(), which is
37 // never null (in fact, we're part of that object!)
38 if (aIID
.Equals(NS_GET_IID(nsCycleCollectionISupports
)) ||
39 aIID
.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant
))) {
40 return Rule()->QueryInterface(aIID
, aInstancePtr
);
42 NS_INTERFACE_MAP_END_INHERITING(nsDOMCSSDeclaration
)
44 NS_IMPL_ADDREF_USING_AGGREGATOR(CSSStyleRuleDeclaration
, Rule())
45 NS_IMPL_RELEASE_USING_AGGREGATOR(CSSStyleRuleDeclaration
, Rule())
47 /* nsDOMCSSDeclaration implementation */
49 css::Rule
* CSSStyleRuleDeclaration::GetParentRule() { return Rule(); }
51 nsINode
* CSSStyleRuleDeclaration::GetParentObject() {
52 return Rule()->GetParentObject();
55 DeclarationBlock
* CSSStyleRuleDeclaration::GetOrCreateCSSDeclaration(
56 Operation aOperation
, DeclarationBlock
** aCreated
) {
60 nsresult
CSSStyleRuleDeclaration::SetCSSDeclaration(
61 DeclarationBlock
* aDecl
, MutationClosureData
* aClosureData
) {
62 CSSStyleRule
* rule
= Rule();
64 if (rule
->IsReadOnly()) {
68 if (RefPtr
<StyleSheet
> sheet
= rule
->GetStyleSheet()) {
69 if (aDecl
!= mDecls
) {
70 mDecls
->SetOwningRule(nullptr);
71 RefPtr
<DeclarationBlock
> decls
= aDecl
;
72 Servo_StyleRule_SetStyle(rule
->Raw(), decls
->Raw());
73 mDecls
= decls
.forget();
74 mDecls
->SetOwningRule(rule
);
76 sheet
->RuleChanged(rule
);
81 Document
* CSSStyleRuleDeclaration::DocToUpdate() { return nullptr; }
83 nsDOMCSSDeclaration::ParsingEnvironment
84 CSSStyleRuleDeclaration::GetParsingEnvironment(
85 nsIPrincipal
* aSubjectPrincipal
) const {
86 return GetParsingEnvironmentForRule(Rule());
89 // -- CSSStyleRule --------------------------------------------------
91 CSSStyleRule::CSSStyleRule(already_AddRefed
<RawServoStyleRule
> aRawRule
,
92 StyleSheet
* aSheet
, css::Rule
* aParentRule
,
93 uint32_t aLine
, uint32_t aColumn
)
94 : BindingStyleRule(aSheet
, aParentRule
, aLine
, aColumn
),
96 mDecls(Servo_StyleRule_GetStyle(mRawRule
).Consume()) {}
98 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(CSSStyleRule
, css::Rule
)
100 NS_IMPL_CYCLE_COLLECTION_CLASS(CSSStyleRule
)
102 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(CSSStyleRule
, css::Rule
)
103 // Keep this in sync with IsCCLeaf.
105 // Trace the wrapper for our declaration. This just expands out
106 // NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER which we can't use
107 // directly because the wrapper is on the declaration, not on us.
108 tmp
->mDecls
.TraceWrapper(aCallbacks
, aClosure
);
109 NS_IMPL_CYCLE_COLLECTION_TRACE_END
111 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CSSStyleRule
)
112 // Keep this in sync with IsCCLeaf.
114 // Unlink the wrapper for our declaration.
116 // Note that this has to happen before unlinking css::Rule.
117 tmp
->UnlinkDeclarationWrapper(tmp
->mDecls
);
118 NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(css::Rule
)
120 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(CSSStyleRule
, css::Rule
)
121 // Keep this in sync with IsCCLeaf.
122 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
124 bool CSSStyleRule::IsCCLeaf() const {
125 if (!Rule::IsCCLeaf()) {
129 return !mDecls
.PreservingWrapper();
132 size_t CSSStyleRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf
) const {
133 size_t n
= aMallocSizeOf(this);
135 // Measurement of the following members may be added later if DMD finds it
144 void CSSStyleRule::List(FILE* out
, int32_t aIndent
) const {
146 for (int32_t i
= 0; i
< aIndent
; i
++) {
147 str
.AppendLiteral(" ");
149 Servo_StyleRule_Debug(mRawRule
, &str
);
150 fprintf_stderr(out
, "%s\n", str
.get());
154 /* CSSRule implementation */
156 void CSSStyleRule::GetCssText(nsAString
& aCssText
) const {
157 Servo_StyleRule_GetCssText(mRawRule
, &aCssText
);
160 nsICSSDeclaration
* CSSStyleRule::Style() { return &mDecls
; }
162 /* CSSStyleRule implementation */
164 void CSSStyleRule::GetSelectorText(nsAString
& aSelectorText
) {
165 Servo_StyleRule_GetSelectorText(mRawRule
, &aSelectorText
);
168 void CSSStyleRule::SetSelectorText(const nsAString
& aSelectorText
) {
173 if (RefPtr
<StyleSheet
> sheet
= GetStyleSheet()) {
174 // StyleRule lives inside of the Inner, it is unsafe to call WillDirty
175 // if sheet does not already have a unique Inner.
176 sheet
->AssertHasUniqueInner();
179 const RawServoStyleSheetContents
* contents
= sheet
->RawContents();
180 if (Servo_StyleRule_SetSelectorText(contents
, mRawRule
, &aSelectorText
)) {
181 sheet
->RuleChanged(this);
186 uint32_t CSSStyleRule::GetSelectorCount() {
188 Servo_StyleRule_GetSelectorCount(mRawRule
, &aCount
);
192 nsresult
CSSStyleRule::GetSelectorText(uint32_t aSelectorIndex
,
194 Servo_StyleRule_GetSelectorTextAtIndex(mRawRule
, aSelectorIndex
, &aText
);
198 nsresult
CSSStyleRule::GetSpecificity(uint32_t aSelectorIndex
,
199 uint64_t* aSpecificity
) {
200 Servo_StyleRule_GetSpecificityAtIndex(mRawRule
, aSelectorIndex
, aSpecificity
);
204 nsresult
CSSStyleRule::SelectorMatchesElement(Element
* aElement
,
205 uint32_t aSelectorIndex
,
206 const nsAString
& aPseudo
,
207 bool aRelevantLinkVisited
,
209 PseudoStyleType pseudoType
= PseudoStyleType::NotPseudo
;
210 if (!aPseudo
.IsEmpty()) {
211 RefPtr
<nsAtom
> pseudoElt
= NS_Atomize(aPseudo
);
212 pseudoType
= nsCSSPseudoElements::GetPseudoType(
213 pseudoElt
, CSSEnabledState::IgnoreEnabledState
);
215 if (pseudoType
== PseudoStyleType::NotPseudo
) {
221 *aMatches
= Servo_StyleRule_SelectorMatchesElement(
222 mRawRule
, aElement
, aSelectorIndex
, pseudoType
, aRelevantLinkVisited
);
227 NotNull
<DeclarationBlock
*> CSSStyleRule::GetDeclarationBlock() const {
228 return WrapNotNull(mDecls
.mDecls
);
232 } // namespace mozilla