Bug 1436059: Fix inspector. r?xidorn
This removes a hack, but adds slightly more complex code in inspector-only code.
I'm not excited about this code, but this fixes ServoStyleRuleMap for XBL.
MozReview-Commit-ID: 6h0dCsiIWKU
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -178,16 +178,18 @@ SERVO_BINDING_FUNC(Servo_UACache_AddSize
// AuthorStyles
SERVO_BINDING_FUNC(Servo_AuthorStyles_Create, RawServoAuthorStyles*)
// TODO(emilio): This will need to take an optional master style set to
// implement invalidation for Shadow DOM.
SERVO_BINDING_FUNC(Servo_AuthorStyles_AppendStyleSheet, void,
RawServoAuthorStylesBorrowedMut self,
const mozilla::ServoStyleSheet* gecko_sheet)
+SERVO_BINDING_FUNC(Servo_AuthorStyles_ForceDirty, void,
+ RawServoAuthorStylesBorrowedMut self)
// TODO(emilio): This will need to take an element to implement invalidation for
// Shadow DOM.
SERVO_BINDING_FUNC(Servo_AuthorStyles_Flush, void,
RawServoAuthorStylesBorrowedMut self,
RawServoStyleSetBorrowed document_styles)
SERVO_BINDING_FUNC(Servo_StyleContext_AddRef, void, ServoStyleContextBorrowed ctx);
SERVO_BINDING_FUNC(Servo_StyleContext_Release, void, ServoStyleContextBorrowed ctx);
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -1265,45 +1265,71 @@ ServoStyleSet::ComputeAnimationValue(
aDeclarations,
aContext,
mRawSet.get()).Consume();
}
bool
ServoStyleSet::EnsureUniqueInnerOnCSSSheets()
{
- AutoTArray<StyleSheet*, 32> queue;
+ using SheetOwner = Variant<ServoStyleSet*, nsXBLPrototypeBinding*>;
+
+ AutoTArray<Pair<StyleSheet*, SheetOwner>, 32> queue;
for (auto& entryArray : mSheets) {
for (auto& sheet : entryArray) {
- queue.AppendElement(sheet);
+ StyleSheet* downcasted = sheet;
+ queue.AppendElement(MakePair(downcasted, SheetOwner { this }));
}
}
- // This is a stub until more of the functionality of nsStyleSet is
- // replicated for Servo here.
- // Bug 1290276 will replicate the nsStyleSet work of checking
- // a nsBindingManager
+ mDocument->BindingManager()->EnumerateBoundContentBindings(
+ [&](nsXBLBinding* aBinding) {
+ AutoTArray<StyleSheet*, 3> sheets;
+ aBinding->PrototypeBinding()->AppendStyleSheetsTo(sheets);
+ for (auto* sheet : sheets) {
+ queue.AppendElement(MakePair(sheet, SheetOwner { aBinding->PrototypeBinding() }));
+ }
+ return true;
+ });
+ bool anyXBLSheetChanged = false;
while (!queue.IsEmpty()) {
uint32_t idx = queue.Length() - 1;
- StyleSheet* sheet = queue[idx];
+ auto* sheet = queue[idx].first();
+ SheetOwner owner = queue[idx].second();
queue.RemoveElementAt(idx);
+ if (!sheet->HasUniqueInner() && owner.is<nsXBLPrototypeBinding*>()) {
+ if (auto* styles = owner.as<nsXBLPrototypeBinding*>()->GetServoStyles()) {
+ Servo_AuthorStyles_ForceDirty(styles);
+ mNeedsRestyleAfterEnsureUniqueInner = true;
+ anyXBLSheetChanged = true;
+ }
+ }
+
// Only call EnsureUniqueInner for complete sheets. If we do call it on
// incomplete sheets, we'll cause problems when the sheet is actually
// loaded. We don't care about incomplete sheets here anyway, because this
// method is only invoked by nsPresContext::EnsureSafeToHandOutCSSRules.
// The CSSRule objects we are handing out won't contain any rules derived
// from incomplete sheets (because they aren't yet applied in styling).
if (sheet->IsComplete()) {
sheet->EnsureUniqueInner();
}
// Enqueue all the sheet's children.
- sheet->AppendAllChildSheets(queue);
+ AutoTArray<StyleSheet*, 3> children;
+ sheet->AppendAllChildSheets(children);
+ for (auto* sheet : children) {
+ queue.AppendElement(MakePair(sheet, owner));
+ }
+ }
+
+ if (anyXBLSheetChanged) {
+ SetStylistXBLStyleSheetsDirty();
}
if (mNeedsRestyleAfterEnsureUniqueInner) {
// TODO(emilio): We could make this faster if needed tracking the specific
// origins and all that, but the only caller of this doesn't seem to really
// care about perf.
MarkOriginsDirty(OriginFlags::All);
}
--- a/layout/style/StyleSheet.cpp
+++ b/layout/style/StyleSheet.cpp
@@ -396,33 +396,16 @@ StyleSheet::EnsureUniqueInner()
"unexpected number of outers");
mDirtyFlags |= FORCED_UNIQUE_INNER;
if (HasUniqueInner()) {
// already unique
return;
}
- // If this stylesheet is for XBL with Servo, don't bother cloning
- // it, as it may break ServoStyleRuleMap. XBL stylesheets are not
- // supposed to change anyway.
- //
- // The mDocument check is used as a fast reject path because no
- // XBL stylesheets would have associated document, but in normal
- // cases, content stylesheets should usually have one.
- //
- // FIXME(emilio): Shadow DOM definitely modifies stylesheets! Right now all of
- // them are unique anyway because we don't support <link>, but that needs to
- // change.
- if (!mDocument && IsServo() &&
- mStyleSets.Length() == 1 &&
- mStyleSets[0]->AsServo()->IsForXBL()) {
- return;
- }
-
StyleSheetInfo* clone = mInner->CloneFor(this);
MOZ_ASSERT(clone);
mInner->RemoveSheet(this);
mInner = clone;
if (IsGecko()) {
#ifdef MOZ_OLD_STYLE
// Ensure we're using the new rules.
--- a/layout/style/StyleSheet.h
+++ b/layout/style/StyleSheet.h
@@ -127,21 +127,30 @@ public:
inline bool IsApplicable() const;
inline bool HasRules() const;
virtual already_AddRefed<StyleSheet> Clone(StyleSheet* aCloneParent,
dom::CSSImportRule* aCloneOwnerRule,
nsIDocument* aCloneDocument,
nsINode* aCloneOwningNode) const = 0;
- bool HasForcedUniqueInner() const { return mDirtyFlags &
- FORCED_UNIQUE_INNER; }
- bool HasModifiedRules() const { return mDirtyFlags &
- MODIFIED_RULES; }
- void ClearModifiedRules() { mDirtyFlags &= ~MODIFIED_RULES; }
+ bool HasForcedUniqueInner() const
+ {
+ return mDirtyFlags & FORCED_UNIQUE_INNER;
+ }
+
+ bool HasModifiedRules() const
+ {
+ return mDirtyFlags & MODIFIED_RULES;
+ }
+
+ void ClearModifiedRules()
+ {
+ mDirtyFlags &= ~MODIFIED_RULES;
+ }
inline bool HasUniqueInner() const;
void EnsureUniqueInner();
// Append all of this sheet's child sheets to aArray.
void AppendAllChildSheets(nsTArray<StyleSheet*>& aArray);
// style sheet owner info
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -1143,16 +1143,24 @@ pub unsafe extern "C" fn Servo_AuthorSty
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();
let sheet = GeckoStyleSheet::new(sheet);
styles.stylesheets.append_stylesheet(None, sheet, &guard);
}
#[no_mangle]
+pub unsafe extern "C" fn Servo_AuthorStyles_ForceDirty(
+ styles: RawServoAuthorStylesBorrowedMut,
+) {
+ let styles = AuthorStyles::<GeckoStyleSheet>::from_ffi_mut(styles);
+ styles.stylesheets.force_dirty();
+}
+
+#[no_mangle]
pub unsafe extern "C" fn Servo_AuthorStyles_Flush(
styles: RawServoAuthorStylesBorrowedMut,
document_set: RawServoStyleSetBorrowed,
) {
let styles = AuthorStyles::<GeckoStyleSheet>::from_ffi_mut(styles);
// Try to avoid the atomic borrow below if possible.
if !styles.stylesheets.dirty() {
return;