Line data Source code
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/. */
6 :
7 : /* representation of CSSRuleList for stylo */
8 :
9 : #include "mozilla/ServoCSSRuleList.h"
10 :
11 : #include "mozilla/IntegerRange.h"
12 : #include "mozilla/ServoBindings.h"
13 : #include "mozilla/ServoDocumentRule.h"
14 : #include "mozilla/ServoImportRule.h"
15 : #include "mozilla/ServoKeyframesRule.h"
16 : #include "mozilla/ServoMediaRule.h"
17 : #include "mozilla/ServoNamespaceRule.h"
18 : #include "mozilla/ServoPageRule.h"
19 : #include "mozilla/ServoStyleRule.h"
20 : #include "mozilla/ServoStyleSheet.h"
21 : #include "mozilla/ServoSupportsRule.h"
22 : #include "nsCSSCounterStyleRule.h"
23 : #include "nsCSSFontFaceRule.h"
24 :
25 : namespace mozilla {
26 :
27 0 : ServoCSSRuleList::ServoCSSRuleList(already_AddRefed<ServoCssRules> aRawRules,
28 0 : ServoStyleSheet* aDirectOwnerStyleSheet)
29 : : mStyleSheet(aDirectOwnerStyleSheet)
30 0 : , mRawRules(aRawRules)
31 : {
32 0 : Servo_CssRules_ListTypes(mRawRules, &mRules);
33 0 : }
34 :
35 : // QueryInterface implementation for ServoCSSRuleList
36 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServoCSSRuleList)
37 0 : NS_INTERFACE_MAP_END_INHERITING(dom::CSSRuleList)
38 :
39 0 : NS_IMPL_ADDREF_INHERITED(ServoCSSRuleList, dom::CSSRuleList)
40 0 : NS_IMPL_RELEASE_INHERITED(ServoCSSRuleList, dom::CSSRuleList)
41 :
42 : NS_IMPL_CYCLE_COLLECTION_CLASS(ServoCSSRuleList)
43 :
44 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ServoCSSRuleList)
45 0 : tmp->DropAllRules();
46 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(dom::CSSRuleList)
47 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ServoCSSRuleList,
48 : dom::CSSRuleList)
49 0 : tmp->EnumerateInstantiatedRules([&](css::Rule* aRule) {
50 0 : if (!aRule->IsCCLeaf()) {
51 0 : NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mRules[i]");
52 0 : cb.NoteXPCOMChild(aRule);
53 : // Note about @font-face and @counter-style rule again, since
54 : // there is an indirect owning edge through Servo's struct that
55 : // FontFaceRule / CounterStyleRule in Servo owns a Gecko
56 : // nsCSSFontFaceRule / nsCSSCounterStyleRule object.
57 0 : auto type = aRule->Type();
58 0 : if (type == nsIDOMCSSRule::FONT_FACE_RULE ||
59 : type == nsIDOMCSSRule::COUNTER_STYLE_RULE) {
60 0 : NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mRawRules[i]");
61 0 : cb.NoteXPCOMChild(aRule);
62 : }
63 : }
64 0 : });
65 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
66 :
67 : void
68 0 : ServoCSSRuleList::SetParentRule(css::GroupRule* aParentRule)
69 : {
70 0 : mParentRule = aParentRule;
71 0 : EnumerateInstantiatedRules([aParentRule](css::Rule* rule) {
72 0 : rule->SetParentRule(aParentRule);
73 0 : });
74 0 : }
75 :
76 : void
77 0 : ServoCSSRuleList::SetStyleSheet(StyleSheet* aStyleSheet)
78 : {
79 0 : mStyleSheet = aStyleSheet ? aStyleSheet->AsServo() : nullptr;
80 0 : EnumerateInstantiatedRules([this](css::Rule* rule) {
81 0 : rule->SetStyleSheet(mStyleSheet);
82 0 : });
83 0 : }
84 :
85 : css::Rule*
86 0 : ServoCSSRuleList::GetRule(uint32_t aIndex)
87 : {
88 0 : uintptr_t rule = mRules[aIndex];
89 0 : if (rule <= kMaxRuleType) {
90 0 : RefPtr<css::Rule> ruleObj = nullptr;
91 0 : switch (rule) {
92 : #define CASE_RULE(const_, name_) \
93 : case nsIDOMCSSRule::const_##_RULE: { \
94 : uint32_t line = 0, column = 0; \
95 : RefPtr<RawServo##name_##Rule> rule = \
96 : Servo_CssRules_Get##name_##RuleAt( \
97 : mRawRules, aIndex, &line, &column \
98 : ).Consume(); \
99 : MOZ_ASSERT(rule); \
100 : ruleObj = new Servo##name_##Rule(rule.forget(), line, column); \
101 : break; \
102 : }
103 0 : CASE_RULE(STYLE, Style)
104 0 : CASE_RULE(KEYFRAMES, Keyframes)
105 0 : CASE_RULE(MEDIA, Media)
106 0 : CASE_RULE(NAMESPACE, Namespace)
107 0 : CASE_RULE(PAGE, Page)
108 0 : CASE_RULE(SUPPORTS, Supports)
109 0 : CASE_RULE(DOCUMENT, Document)
110 0 : CASE_RULE(IMPORT, Import)
111 : #undef CASE_RULE
112 : // For @font-face and @counter-style rules, the function returns
113 : // a borrowed Gecko rule object directly, so we don't need to
114 : // create anything here. But we still need to have the style sheet
115 : // and parent rule set properly.
116 : case nsIDOMCSSRule::FONT_FACE_RULE: {
117 0 : ruleObj = Servo_CssRules_GetFontFaceRuleAt(mRawRules, aIndex);
118 0 : break;
119 : }
120 : case nsIDOMCSSRule::COUNTER_STYLE_RULE: {
121 0 : ruleObj = Servo_CssRules_GetCounterStyleRuleAt(mRawRules, aIndex);
122 0 : break;
123 : }
124 : case nsIDOMCSSRule::KEYFRAME_RULE:
125 0 : MOZ_ASSERT_UNREACHABLE("keyframe rule cannot be here");
126 : return nullptr;
127 : default:
128 0 : NS_WARNING("stylo: not implemented yet");
129 0 : return nullptr;
130 : }
131 0 : ruleObj->SetStyleSheet(mStyleSheet);
132 0 : ruleObj->SetParentRule(mParentRule);
133 0 : rule = CastToUint(ruleObj.forget().take());
134 0 : mRules[aIndex] = rule;
135 : }
136 0 : return CastToPtr(rule);
137 : }
138 :
139 : css::Rule*
140 0 : ServoCSSRuleList::IndexedGetter(uint32_t aIndex, bool& aFound)
141 : {
142 0 : if (aIndex >= mRules.Length()) {
143 0 : aFound = false;
144 0 : return nullptr;
145 : }
146 0 : aFound = true;
147 0 : return GetRule(aIndex);
148 : }
149 :
150 : template<typename Func>
151 : void
152 0 : ServoCSSRuleList::EnumerateInstantiatedRules(Func aCallback)
153 : {
154 0 : for (uintptr_t rule : mRules) {
155 0 : if (rule > kMaxRuleType) {
156 0 : aCallback(CastToPtr(rule));
157 : }
158 : }
159 0 : }
160 :
161 : static void
162 0 : DropRule(already_AddRefed<css::Rule> aRule)
163 : {
164 0 : RefPtr<css::Rule> rule = aRule;
165 0 : rule->SetStyleSheet(nullptr);
166 0 : rule->SetParentRule(nullptr);
167 0 : }
168 :
169 : void
170 0 : ServoCSSRuleList::DropAllRules()
171 : {
172 0 : EnumerateInstantiatedRules([](css::Rule* rule) {
173 0 : DropRule(already_AddRefed<css::Rule>(rule));
174 0 : });
175 0 : mRules.Clear();
176 0 : mRawRules = nullptr;
177 0 : }
178 :
179 : void
180 0 : ServoCSSRuleList::DropReference()
181 : {
182 0 : mStyleSheet = nullptr;
183 0 : mParentRule = nullptr;
184 0 : DropAllRules();
185 0 : }
186 :
187 : nsresult
188 0 : ServoCSSRuleList::InsertRule(const nsAString& aRule, uint32_t aIndex)
189 : {
190 0 : MOZ_ASSERT(mStyleSheet, "Caller must ensure that "
191 : "the list is not unlinked from stylesheet");
192 0 : NS_ConvertUTF16toUTF8 rule(aRule);
193 0 : bool nested = !!mParentRule;
194 0 : css::Loader* loader = nullptr;
195 0 : if (nsIDocument* doc = mStyleSheet->GetAssociatedDocument()) {
196 0 : loader = doc->CSSLoader();
197 : }
198 : uint16_t type;
199 0 : nsresult rv = Servo_CssRules_InsertRule(mRawRules, mStyleSheet->RawContents(),
200 : &rule, aIndex, nested,
201 0 : loader, mStyleSheet, &type);
202 0 : if (NS_FAILED(rv)) {
203 0 : return rv;
204 : }
205 0 : mRules.InsertElementAt(aIndex, type);
206 0 : return rv;
207 : }
208 :
209 : nsresult
210 0 : ServoCSSRuleList::DeleteRule(uint32_t aIndex)
211 : {
212 0 : nsresult rv = Servo_CssRules_DeleteRule(mRawRules, aIndex);
213 0 : if (!NS_FAILED(rv)) {
214 0 : uintptr_t rule = mRules[aIndex];
215 0 : if (rule > kMaxRuleType) {
216 0 : DropRule(already_AddRefed<css::Rule>(CastToPtr(rule)));
217 : }
218 0 : mRules.RemoveElementAt(aIndex);
219 : }
220 0 : return rv;
221 : }
222 :
223 : uint16_t
224 0 : ServoCSSRuleList::GetRuleType(uint32_t aIndex) const
225 : {
226 0 : uintptr_t rule = mRules[aIndex];
227 0 : if (rule <= kMaxRuleType) {
228 0 : return rule;
229 : }
230 0 : return CastToPtr(rule)->Type();
231 : }
232 :
233 0 : ServoCSSRuleList::~ServoCSSRuleList()
234 : {
235 0 : DropAllRules();
236 0 : }
237 :
238 : } // namespace mozilla
|