Bug 1326167 - Hook ServoStyleSheet and ServoCSSRuleList into cycle collection. r=bz
MozReview-Commit-ID: 6n1rjB8aMqp
--- a/layout/style/ServoCSSRuleList.cpp
+++ b/layout/style/ServoCSSRuleList.cpp
@@ -19,16 +19,43 @@ ServoCSSRuleList::ServoCSSRuleList(Servo
, mRawRules(aRawRules)
{
Servo_CssRules_ListTypes(mRawRules, &mRules);
// XXX We may want to eagerly create object for import rule, so that
// we don't lose the reference to child stylesheet when our own
// stylesheet goes away.
}
+// QueryInterface implementation for ServoCSSRuleList
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServoCSSRuleList)
+NS_INTERFACE_MAP_END_INHERITING(dom::CSSRuleList)
+
+NS_IMPL_ADDREF_INHERITED(ServoCSSRuleList, dom::CSSRuleList)
+NS_IMPL_RELEASE_INHERITED(ServoCSSRuleList, dom::CSSRuleList)
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(ServoCSSRuleList)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ServoCSSRuleList)
+ for (uintptr_t& rule : tmp->mRules) {
+ if (rule > kMaxRuleType) {
+ CastToPtr(rule)->Release();
+ // Safest to set it to zero, in case someone else pokes at it
+ // during their own unlinking process.
+ rule = 0;
+ }
+ }
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(dom::CSSRuleList)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ServoCSSRuleList,
+ dom::CSSRuleList)
+ tmp->EnumerateInstantiatedRules([&](css::Rule* aRule) {
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mRules[i]");
+ cb.NoteXPCOMChild(aRule->GetExistingDOMRule());
+ });
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
css::Rule*
ServoCSSRuleList::GetRule(uint32_t aIndex)
{
uintptr_t rule = mRules[aIndex];
if (rule <= kMaxRuleType) {
RefPtr<css::Rule> ruleObj = nullptr;
switch (rule) {
case nsIDOMCSSRule::STYLE_RULE: {
--- a/layout/style/ServoCSSRuleList.h
+++ b/layout/style/ServoCSSRuleList.h
@@ -20,16 +20,19 @@ class Rule;
} // namespace css
class ServoCSSRuleList final : public dom::CSSRuleList
{
public:
ServoCSSRuleList(ServoStyleSheet* aStyleSheet,
already_AddRefed<ServoCssRules> aRawRules);
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServoCSSRuleList, dom::CSSRuleList)
+
ServoStyleSheet* GetParentObject() final { return mStyleSheet; }
nsIDOMCSSRule* IndexedGetter(uint32_t aIndex, bool& aFound) final;
uint32_t Length() final { return mRules.Length(); }
void DropReference();
css::Rule* GetRule(uint32_t aIndex);
--- a/layout/style/ServoStyleSheet.cpp
+++ b/layout/style/ServoStyleSheet.cpp
@@ -25,21 +25,34 @@ ServoStyleSheet::ServoStyleSheet(css::Sh
: StyleSheet(StyleBackendType::Servo, aParsingMode)
, mSheetInfo(aCORSMode, aReferrerPolicy, aIntegrity)
{
}
ServoStyleSheet::~ServoStyleSheet()
{
DropSheet();
- if (mRuleList) {
- mRuleList->DropReference();
- }
}
+// QueryInterface implementation for ServoStyleSheet
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServoStyleSheet)
+NS_INTERFACE_MAP_END_INHERITING(StyleSheet)
+
+NS_IMPL_ADDREF_INHERITED(ServoStyleSheet, StyleSheet)
+NS_IMPL_RELEASE_INHERITED(ServoStyleSheet, StyleSheet)
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(ServoStyleSheet)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ServoStyleSheet)
+ tmp->DropRuleList();
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(StyleSheet)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ServoStyleSheet, StyleSheet)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRuleList)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
bool
ServoStyleSheet::HasRules() const
{
return mSheet && Servo_StyleSheet_HasRules(mSheet);
}
void
ServoStyleSheet::SetOwningDocument(nsIDocument* aDocument)
@@ -101,16 +114,26 @@ ServoStyleSheet::LoadFailed()
{
mSheet = Servo_StyleSheet_Empty(mParsingMode).Consume();
}
void
ServoStyleSheet::DropSheet()
{
mSheet = nullptr;
+ DropRuleList();
+}
+
+void
+ServoStyleSheet::DropRuleList()
+{
+ if (mRuleList) {
+ mRuleList->DropReference();
+ mRuleList = nullptr;
+ }
}
size_t
ServoStyleSheet::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
{
MOZ_CRASH("stylo: not implemented");
}
--- a/layout/style/ServoStyleSheet.h
+++ b/layout/style/ServoStyleSheet.h
@@ -28,16 +28,19 @@ class Loader;
class ServoStyleSheet : public StyleSheet
{
public:
ServoStyleSheet(css::SheetParsingMode aParsingMode,
CORSMode aCORSMode,
net::ReferrerPolicy aReferrerPolicy,
const dom::SRIMetadata& aIntegrity);
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServoStyleSheet, StyleSheet)
+
bool HasRules() const;
void SetOwningDocument(nsIDocument* aDocument);
ServoStyleSheet* GetParentSheet() const;
void AppendStyleSheet(ServoStyleSheet* aSheet);
MOZ_MUST_USE nsresult ParseSheet(css::Loader* aLoader,
@@ -84,16 +87,17 @@ protected:
// Internal methods which do not have security check and completeness check.
dom::CSSRuleList* GetCssRulesInternal(ErrorResult& aRv);
uint32_t InsertRuleInternal(const nsAString& aRule,
uint32_t aIndex, ErrorResult& aRv);
void DeleteRuleInternal(uint32_t aIndex, ErrorResult& aRv);
private:
void DropSheet();
+ void DropRuleList();
RefPtr<RawServoStyleSheet> mSheet;
RefPtr<ServoCSSRuleList> mRuleList;
StyleSheetInfo mSheetInfo;
friend class StyleSheet;
};