--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -34,16 +34,21 @@ ServoStyleSet::ServoStyleSet()
, mUniqueIDCounter(0)
, mAllowResolveStaleStyles(false)
, mAuthorStyleDisabled(false)
{
}
ServoStyleSet::~ServoStyleSet()
{
+ for (auto& entryArray : mEntries) {
+ for (auto& entry : entryArray) {
+ entry.sheet->DropStyleSet(StyleSetHandle(this));
+ }
+ }
}
void
ServoStyleSet::Init(nsPresContext* aPresContext)
{
mPresContext = aPresContext;
mRawSet.reset(Servo_StyleSet_Init(aPresContext));
@@ -556,16 +561,20 @@ ServoStyleSet::AppendStyleSheet(SheetTyp
MOZ_ASSERT(aSheet->RawSheet(), "Raw sheet should be in place before insertion.");
// If we were already tracking aSheet, the newUniqueID will be the same
// as the oldUniqueID. In that case, Servo will remove aSheet from its
// original position as part of the call to Servo_StyleSet_AppendStyleSheet.
uint32_t oldUniqueID = RemoveSheetOfType(aType, aSheet);
uint32_t newUniqueID = AppendSheetOfType(aType, aSheet, oldUniqueID);
+ if (!oldUniqueID) {
+ aSheet->AddStyleSet(StyleSetHandle(this));
+ }
+
if (mRawSet) {
// Maintain a mirrored list of sheets on the servo side.
Servo_StyleSet_AppendStyleSheet(mRawSet.get(),
aSheet->RawSheet(),
newUniqueID,
!mBatching);
}
@@ -582,16 +591,20 @@ ServoStyleSet::PrependStyleSheet(SheetTy
MOZ_ASSERT(aSheet->RawSheet(), "Raw sheet should be in place before insertion.");
// If we were already tracking aSheet, the newUniqueID will be the same
// as the oldUniqueID. In that case, Servo will remove aSheet from its
// original position as part of the call to Servo_StyleSet_PrependStyleSheet.
uint32_t oldUniqueID = RemoveSheetOfType(aType, aSheet);
uint32_t newUniqueID = PrependSheetOfType(aType, aSheet, oldUniqueID);
+ if (!oldUniqueID) {
+ aSheet->AddStyleSet(StyleSetHandle(this));
+ }
+
if (mRawSet) {
// Maintain a mirrored list of sheets on the servo side.
Servo_StyleSet_PrependStyleSheet(mRawSet.get(),
aSheet->RawSheet(),
newUniqueID,
!mBatching);
}
@@ -601,44 +614,61 @@ ServoStyleSet::PrependStyleSheet(SheetTy
nsresult
ServoStyleSet::RemoveStyleSheet(SheetType aType,
ServoStyleSheet* aSheet)
{
MOZ_ASSERT(aSheet);
MOZ_ASSERT(nsStyleSet::IsCSSSheetType(aType));
uint32_t uniqueID = RemoveSheetOfType(aType, aSheet);
- if (mRawSet && uniqueID) {
- // Maintain a mirrored list of sheets on the servo side.
- Servo_StyleSet_RemoveStyleSheet(mRawSet.get(), uniqueID, !mBatching);
+
+ if (uniqueID) {
+ aSheet->DropStyleSet(StyleSetHandle(this));
+
+ if (mRawSet) {
+ // Maintain a mirrored list of sheets on the servo side.
+ Servo_StyleSet_RemoveStyleSheet(mRawSet.get(), uniqueID, !mBatching);
+ }
}
return NS_OK;
}
nsresult
ServoStyleSet::ReplaceSheets(SheetType aType,
const nsTArray<RefPtr<ServoStyleSheet>>& aNewSheets)
{
+ MOZ_ASSERT(nsStyleSet::IsCSSSheetType(aType));
+
// Gecko uses a two-dimensional array keyed by sheet type, whereas Servo
// stores a flattened list. This makes ReplaceSheets a pretty clunky thing
// to express. If the need ever arises, we can easily make this more efficent,
// probably by aligning the representations better between engines.
- // Remove all the existing sheets first.
- if (mRawSet) {
- for (const Entry& entry : mEntries[aType]) {
+ StyleSetHandle styleSetHandleThis(this);
+
+ // Remove all the existing sheets.
+ for (const Entry& entry : mEntries[aType]) {
+ // Make the sheets stop tracking this ServoStyleSet.
+ entry.sheet->DropStyleSet(styleSetHandleThis);
+
+ if (mRawSet) {
+ // Remove them from Servo tracking.
Servo_StyleSet_RemoveStyleSheet(mRawSet.get(), entry.uniqueID, false);
}
}
+
+ // Now we can clear out the entries.
mEntries[aType].Clear();
// Add in all the new sheets.
for (auto& sheet : aNewSheets) {
uint32_t uniqueID = AppendSheetOfType(aType, sheet);
+ sheet->AddStyleSet(styleSetHandleThis);
+
if (mRawSet) {
MOZ_ASSERT(sheet->RawSheet(), "Raw sheet should be in place before replacement.");
Servo_StyleSet_AppendStyleSheet(mRawSet.get(),
sheet->RawSheet(),
uniqueID,
false);
}
}
@@ -671,16 +701,20 @@ ServoStyleSet::InsertStyleSheetBefore(Sh
// as the oldUniqueID. In that case, Servo will remove aNewSheet from its
// original position as part of the call to Servo_StyleSet_InsertStyleSheetBefore.
uint32_t oldUniqueID = RemoveSheetOfType(aType, aNewSheet);
uint32_t newUniqueID = InsertSheetOfType(aType,
aNewSheet,
beforeUniqueID,
oldUniqueID);
+ if (!oldUniqueID) {
+ aNewSheet->AddStyleSet(StyleSetHandle(this));
+ }
+
if (mRawSet) {
// Maintain a mirrored list of sheets on the servo side.
Servo_StyleSet_InsertStyleSheetBefore(mRawSet.get(),
aNewSheet->RawSheet(),
newUniqueID,
beforeUniqueID,
!mBatching);
}
@@ -715,16 +749,20 @@ ServoStyleSet::AddDocStyleSheet(ServoSty
{
MOZ_ASSERT(aSheet->IsApplicable());
MOZ_ASSERT(aSheet->RawSheet(), "Raw sheet should be in place by this point.");
RefPtr<StyleSheet> strong(aSheet);
uint32_t oldUniqueID = RemoveSheetOfType(SheetType::Doc, aSheet);
+ if (!oldUniqueID) {
+ aSheet->AddStyleSet(StyleSetHandle(this));
+ }
+
size_t index =
aDocument->FindDocStyleSheetInsertionPoint(mEntries[SheetType::Doc], aSheet);
if (index < mEntries[SheetType::Doc].Length()) {
// This case is insert before.
uint32_t beforeUniqueID = mEntries[SheetType::Doc][index].uniqueID;
uint32_t newUniqueID = InsertSheetOfType(SheetType::Doc,
aSheet,