Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/style/ServoCSSRuleList.cpp
Line
Count
Source (jump to first uncovered line)
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/dom/CSSCounterStyleRule.h"
12
#include "mozilla/dom/CSSFontFaceRule.h"
13
#include "mozilla/dom/CSSFontFeatureValuesRule.h"
14
#include "mozilla/dom/CSSImportRule.h"
15
#include "mozilla/dom/CSSKeyframesRule.h"
16
#include "mozilla/dom/CSSMediaRule.h"
17
#include "mozilla/dom/CSSMozDocumentRule.h"
18
#include "mozilla/dom/CSSNamespaceRule.h"
19
#include "mozilla/dom/CSSPageRule.h"
20
#include "mozilla/dom/CSSStyleRule.h"
21
#include "mozilla/dom/CSSSupportsRule.h"
22
#include "mozilla/IntegerRange.h"
23
#include "mozilla/ServoBindings.h"
24
#include "mozilla/StyleSheet.h"
25
26
using namespace mozilla::dom;
27
28
namespace mozilla {
29
30
ServoCSSRuleList::ServoCSSRuleList(already_AddRefed<ServoCssRules> aRawRules,
31
                                   StyleSheet* aSheet,
32
                                   css::GroupRule* aParentRule)
33
  : mStyleSheet(aSheet)
34
  , mParentRule(aParentRule)
35
  , mRawRules(aRawRules)
36
0
{
37
0
  Servo_CssRules_ListTypes(mRawRules, &mRules);
38
0
}
39
40
// QueryInterface implementation for ServoCSSRuleList
41
0
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ServoCSSRuleList)
42
0
NS_INTERFACE_MAP_END_INHERITING(dom::CSSRuleList)
43
44
NS_IMPL_ADDREF_INHERITED(ServoCSSRuleList, dom::CSSRuleList)
45
NS_IMPL_RELEASE_INHERITED(ServoCSSRuleList, dom::CSSRuleList)
46
47
NS_IMPL_CYCLE_COLLECTION_CLASS(ServoCSSRuleList)
48
49
0
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ServoCSSRuleList)
50
0
  tmp->DropAllRules();
51
0
NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(dom::CSSRuleList)
52
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ServoCSSRuleList,
53
0
                                                  dom::CSSRuleList)
54
0
  tmp->EnumerateInstantiatedRules([&](css::Rule* aRule) {
55
0
    if (!aRule->IsCCLeaf()) {
56
0
      NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mRules[i]");
57
0
      cb.NoteXPCOMChild(aRule);
58
0
    }
59
0
  });
60
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
61
62
css::Rule*
63
ServoCSSRuleList::GetRule(uint32_t aIndex)
64
0
{
65
0
  uintptr_t rule = mRules[aIndex];
66
0
  if (rule <= kMaxRuleType) {
67
0
    RefPtr<css::Rule> ruleObj = nullptr;
68
0
    switch (rule) {
69
0
#define CASE_RULE(const_, name_)                                            \
70
0
      case CSSRule_Binding::const_##_RULE: {                                \
71
0
        uint32_t line = 0, column = 0;                                      \
72
0
        RefPtr<RawServo##name_##Rule> rule =                                \
73
0
          Servo_CssRules_Get##name_##RuleAt(                                \
74
0
              mRawRules, aIndex, &line, &column                             \
75
0
          ).Consume();                                                      \
76
0
        MOZ_ASSERT(rule);                                                   \
77
0
        ruleObj = new CSS##name_##Rule(rule.forget(), mStyleSheet,          \
78
0
                                       mParentRule, line, column);          \
79
0
        break;                                                              \
80
0
      }
81
0
      CASE_RULE(STYLE, Style)
82
0
      CASE_RULE(KEYFRAMES, Keyframes)
83
0
      CASE_RULE(MEDIA, Media)
84
0
      CASE_RULE(NAMESPACE, Namespace)
85
0
      CASE_RULE(PAGE, Page)
86
0
      CASE_RULE(SUPPORTS, Supports)
87
0
      CASE_RULE(DOCUMENT, MozDocument)
88
0
      CASE_RULE(IMPORT, Import)
89
0
      CASE_RULE(FONT_FEATURE_VALUES, FontFeatureValues)
90
0
      CASE_RULE(FONT_FACE, FontFace)
91
0
      CASE_RULE(COUNTER_STYLE, CounterStyle)
92
0
#undef CASE_RULE
93
0
      case CSSRule_Binding::KEYFRAME_RULE:
94
0
        MOZ_ASSERT_UNREACHABLE("keyframe rule cannot be here");
95
0
        return nullptr;
96
0
      default:
97
0
        NS_WARNING("stylo: not implemented yet");
98
0
        return nullptr;
99
0
    }
100
0
    rule = CastToUint(ruleObj.forget().take());
101
0
    mRules[aIndex] = rule;
102
0
  }
103
0
  return CastToPtr(rule);
104
0
}
105
106
css::Rule*
107
ServoCSSRuleList::IndexedGetter(uint32_t aIndex, bool& aFound)
108
0
{
109
0
  if (aIndex >= mRules.Length()) {
110
0
    aFound = false;
111
0
    return nullptr;
112
0
  }
113
0
  aFound = true;
114
0
  return GetRule(aIndex);
115
0
}
116
117
template<typename Func>
118
void
119
ServoCSSRuleList::EnumerateInstantiatedRules(Func aCallback)
120
0
{
121
0
  for (uintptr_t rule : mRules) {
122
0
    if (rule > kMaxRuleType) {
123
0
      aCallback(CastToPtr(rule));
124
0
    }
125
0
  }
126
0
}
Unexecuted instantiation: Unified_cpp_layout_style2.cpp:void mozilla::ServoCSSRuleList::EnumerateInstantiatedRules<mozilla::ServoCSSRuleList::cycleCollection::TraverseNative(void*, nsCycleCollectionTraversalCallback&)::$_2>(mozilla::ServoCSSRuleList::cycleCollection::TraverseNative(void*, nsCycleCollectionTraversalCallback&)::$_2)
Unexecuted instantiation: Unified_cpp_layout_style2.cpp:void mozilla::ServoCSSRuleList::EnumerateInstantiatedRules<mozilla::ServoCSSRuleList::DropAllRules()::$_3>(mozilla::ServoCSSRuleList::DropAllRules()::$_3)
Unexecuted instantiation: Unified_cpp_layout_style2.cpp:void mozilla::ServoCSSRuleList::EnumerateInstantiatedRules<mozilla::ServoCSSRuleList::DropSheetReference()::$_4>(mozilla::ServoCSSRuleList::DropSheetReference()::$_4)
Unexecuted instantiation: Unified_cpp_layout_style2.cpp:void mozilla::ServoCSSRuleList::EnumerateInstantiatedRules<mozilla::ServoCSSRuleList::DropParentRuleReference()::$_5>(mozilla::ServoCSSRuleList::DropParentRuleReference()::$_5)
127
128
static void
129
DropRule(already_AddRefed<css::Rule> aRule)
130
0
{
131
0
  RefPtr<css::Rule> rule = aRule;
132
0
  rule->DropReferences();
133
0
}
134
135
void
136
ServoCSSRuleList::DropAllRules()
137
0
{
138
0
  mStyleSheet = nullptr;
139
0
  mParentRule = nullptr;
140
0
  EnumerateInstantiatedRules([](css::Rule* rule) {
141
0
    DropRule(already_AddRefed<css::Rule>(rule));
142
0
  });
143
0
  mRules.Clear();
144
0
  mRawRules = nullptr;
145
0
}
146
147
void
148
ServoCSSRuleList::DropSheetReference()
149
0
{
150
0
  // If mStyleSheet is not set on this rule list, then it is not set on any of
151
0
  // its instantiated rules either.  To avoid O(N^2) beavhior in the depth of
152
0
  // group rule nesting, which can happen if we are unlinked starting from the
153
0
  // deepest nested group rule, skip recursing into the rule list if we know we
154
0
  // don't need to.
155
0
  if (!mStyleSheet) {
156
0
    return;
157
0
  }
158
0
  mStyleSheet = nullptr;
159
0
  EnumerateInstantiatedRules([](css::Rule* rule) {
160
0
    rule->DropSheetReference();
161
0
  });
162
0
}
163
164
void
165
ServoCSSRuleList::DropParentRuleReference()
166
0
{
167
0
  mParentRule = nullptr;
168
0
  EnumerateInstantiatedRules([](css::Rule* rule) {
169
0
    rule->DropParentRuleReference();
170
0
  });
171
0
}
172
173
nsresult
174
ServoCSSRuleList::InsertRule(const nsAString& aRule, uint32_t aIndex)
175
0
{
176
0
  MOZ_ASSERT(mStyleSheet, "Caller must ensure that "
177
0
             "the list is not unlinked from stylesheet");
178
0
  NS_ConvertUTF16toUTF8 rule(aRule);
179
0
  bool nested = !!mParentRule;
180
0
  css::Loader* loader = nullptr;
181
0
  if (nsIDocument* doc = mStyleSheet->GetAssociatedDocument()) {
182
0
    loader = doc->CSSLoader();
183
0
  }
184
0
  uint16_t type;
185
0
  nsresult rv = Servo_CssRules_InsertRule(mRawRules, mStyleSheet->RawContents(),
186
0
                                          &rule, aIndex, nested,
187
0
                                          loader, mStyleSheet, &type);
188
0
  if (NS_FAILED(rv)) {
189
0
    return rv;
190
0
  }
191
0
  mRules.InsertElementAt(aIndex, type);
192
0
  return rv;
193
0
}
194
195
nsresult
196
ServoCSSRuleList::DeleteRule(uint32_t aIndex)
197
0
{
198
0
  nsresult rv = Servo_CssRules_DeleteRule(mRawRules, aIndex);
199
0
  if (!NS_FAILED(rv)) {
200
0
    uintptr_t rule = mRules[aIndex];
201
0
    if (rule > kMaxRuleType) {
202
0
      DropRule(already_AddRefed<css::Rule>(CastToPtr(rule)));
203
0
    }
204
0
    mRules.RemoveElementAt(aIndex);
205
0
  }
206
0
  return rv;
207
0
}
208
209
uint16_t
210
ServoCSSRuleList::GetDOMCSSRuleType(uint32_t aIndex) const
211
0
{
212
0
  uintptr_t rule = mRules[aIndex];
213
0
  if (rule <= kMaxRuleType) {
214
0
    return rule;
215
0
  }
216
0
  return CastToPtr(rule)->Type();
217
0
}
218
219
ServoCSSRuleList::~ServoCSSRuleList()
220
0
{
221
0
  MOZ_ASSERT(!mStyleSheet, "Backpointer should have been cleared");
222
0
  MOZ_ASSERT(!mParentRule, "Backpointer should have been cleared");
223
0
  DropAllRules();
224
0
}
225
226
} // namespace mozilla