diff --git a/layout/style/CSSStyleSheet.cpp b/layout/style/CSSStyleSheet.cpp index 40a4ee4d84..4cefdfad95 100644 --- a/layout/style/CSSStyleSheet.cpp +++ b/layout/style/CSSStyleSheet.cpp @@ -1618,6 +1618,12 @@ CSSStyleSheet::DidDirty() ClearRuleCascades(); } +void +CSSStyleSheet::AssertHasUniqueInner() +{ + MOZ_ASSERT(mInner->mSheets.Length() == 1, "expected unique inner"); +} + nsresult CSSStyleSheet::RegisterNamespaceRule(css::Rule* aRule) { diff --git a/layout/style/CSSStyleSheet.h b/layout/style/CSSStyleSheet.h index 89189d7816..d777b1f652 100644 --- a/layout/style/CSSStyleSheet.h +++ b/layout/style/CSSStyleSheet.h @@ -217,6 +217,7 @@ public: void WillDirty(); void DidDirty(); + void AssertHasUniqueInner(); private: CSSStyleSheet(const CSSStyleSheet& aCopy, diff --git a/layout/style/StyleRule.cpp b/layout/style/StyleRule.cpp index bf5eefa156..8fe19bb34a 100644 --- a/layout/style/StyleRule.cpp +++ b/layout/style/StyleRule.cpp @@ -1571,9 +1571,43 @@ StyleRule::GetSelectorText(nsAString& aSelectorText) void StyleRule::SetSelectorText(const nsAString& aSelectorText) { - // XXX TBI - get a parser and re-parse the selectors, - // XXX then need to re-compute the cascade - // XXX and dirty sheet + CSSStyleSheet* sheet = GetStyleSheet(); + + nsIDocument* doc = GetDocument(); + RefPtr loader; + + if (doc) { + loader = doc->CSSLoader(); + } + + // NOTE: Passing a null loader means that the parser is always in + // standards mode and never in quirks mode. + nsCSSParser css(loader, sheet); + + // StyleRule lives inside of the Inner, it is unsafe to call WillDirty + // if sheet does not already have a unique Inner. + sheet->AssertHasUniqueInner(); + sheet->WillDirty(); + + nsCSSSelectorList* selectorList = nullptr; + + nsresult result = css.ParseSelectorString( + aSelectorText, sheet->GetSheetURI(), 0, &selectorList); + if (NS_FAILED(result)) { + // Ignore parsing errors and continue to use the previous value. + return; + } + + // Replace selector. + delete mSelector; + mSelector = selectorList; + + sheet->DidDirty(); + + if (doc) { + mozAutoDocUpdate updateBatch(doc, UPDATE_STYLE, true); + doc->StyleRuleChanged(sheet, this); + } } /* virtual */ size_t diff --git a/layout/style/StyleSheet.h b/layout/style/StyleSheet.h index 55d1147005..0b4af9f13b 100644 --- a/layout/style/StyleSheet.h +++ b/layout/style/StyleSheet.h @@ -186,6 +186,7 @@ public: // WillDirty and then make no change and skip the DidDirty call. inline void WillDirty(); inline void DidDirty(); + inline void AssertHasUniqueInner(); private: // Get a handle to the various stylesheet bits which live on the 'inner' for