Bug 1313293 - Implement CSSStyleSheet.insertRule and deleteRule. r=heycam
authorXidorn Quan <me@upsuper.org>
Tue, 29 Nov 2016 22:59:55 +1100
changeset 324700 19f0a7a2be1425ac8ecede607f29df47471343fc
parent 324699 48fc404b0637a7315f9960f97b2482530d73cd94
child 324701 f7834b7b40502dc6b0231829b9786e6f37c8e918
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersheycam
bugs1313293
milestone53.0a1
Bug 1313293 - Implement CSSStyleSheet.insertRule and deleteRule. r=heycam MozReview-Commit-ID: DLHWrNqVH0D
layout/style/ServoBindingList.h
layout/style/ServoCSSRuleList.cpp
layout/style/ServoCSSRuleList.h
layout/style/ServoStyleSheet.cpp
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -48,16 +48,22 @@ SERVO_BINDING_FUNC(Servo_StyleSet_Insert
                    RawServoStyleSheetBorrowed reference)
 
 // CSSRuleList
 SERVO_BINDING_FUNC(Servo_CssRules_ListTypes, void,
                    ServoCssRulesBorrowed rules,
                    nsTArrayBorrowed_uintptr_t result)
 SERVO_BINDING_FUNC(Servo_CssRules_GetStyleRuleAt, RawServoStyleRuleStrong,
                    ServoCssRulesBorrowed rules, uint32_t index)
+SERVO_BINDING_FUNC(Servo_CssRules_InsertRule, nsresult,
+                   ServoCssRulesBorrowed rules,
+                   RawServoStyleSheetBorrowed sheet, const nsACString* rule,
+                   uint32_t index, bool nested, uint16_t* rule_type)
+SERVO_BINDING_FUNC(Servo_CssRules_DeleteRule, nsresult,
+                   ServoCssRulesBorrowed rules, uint32_t index)
 
 // CSS Rules
 SERVO_BINDING_FUNC(Servo_StyleRule_Debug, void,
                    RawServoStyleRuleBorrowed rule, nsACString* result)
 SERVO_BINDING_FUNC(Servo_StyleRule_GetStyle, RawServoDeclarationBlockStrong,
                    RawServoStyleRuleBorrowed rule)
 SERVO_BINDING_FUNC(Servo_StyleRule_SetStyle, void,
                    RawServoStyleRuleBorrowed rule,
--- a/layout/style/ServoCSSRuleList.cpp
+++ b/layout/style/ServoCSSRuleList.cpp
@@ -19,24 +19,19 @@ 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.
 }
 
-nsIDOMCSSRule*
-ServoCSSRuleList::IndexedGetter(uint32_t aIndex, bool& aFound)
+css::Rule*
+ServoCSSRuleList::GetRule(uint32_t aIndex)
 {
-  if (aIndex >= mRules.Length()) {
-    aFound = false;
-    return nullptr;
-  }
-  aFound = true;
   uintptr_t rule = mRules[aIndex];
   if (rule <= kMaxRuleType) {
     RefPtr<css::Rule> ruleObj = nullptr;
     switch (rule) {
       case nsIDOMCSSRule::STYLE_RULE: {
         ruleObj = new ServoStyleRule(
           Servo_CssRules_GetStyleRuleAt(mRawRules, aIndex).Consume());
         break;
@@ -49,17 +44,31 @@ ServoCSSRuleList::IndexedGetter(uint32_t
       default:
         NS_ERROR("stylo: not implemented yet");
         return nullptr;
     }
     ruleObj->SetStyleSheet(mStyleSheet);
     rule = CastToUint(ruleObj.forget().take());
     mRules[aIndex] = rule;
   }
-  return CastToPtr(rule)->GetDOMRule();
+  return CastToPtr(rule);
+}
+
+nsIDOMCSSRule*
+ServoCSSRuleList::IndexedGetter(uint32_t aIndex, bool& aFound)
+{
+  if (aIndex >= mRules.Length()) {
+    aFound = false;
+    return nullptr;
+  }
+  aFound = true;
+  if (css::Rule* rule = GetRule(aIndex)) {
+    return rule->GetDOMRule();
+  }
+  return nullptr;
 }
 
 template<typename Func>
 void
 ServoCSSRuleList::EnumerateInstantiatedRules(Func aCallback)
 {
   for (uintptr_t rule : mRules) {
     if (rule > kMaxRuleType) {
@@ -72,14 +81,40 @@ void
 ServoCSSRuleList::DropReference()
 {
   mStyleSheet = nullptr;
   EnumerateInstantiatedRules([](css::Rule* rule) {
     rule->SetStyleSheet(nullptr);
   });
 }
 
+nsresult
+ServoCSSRuleList::InsertRule(const nsAString& aRule, uint32_t aIndex)
+{
+  NS_ConvertUTF16toUTF8 rule(aRule);
+  // XXX This needs to actually reflect whether it is nested when we
+  // support using CSSRuleList in CSSGroupingRules.
+  bool nested = false;
+  uint16_t type;
+  nsresult rv = Servo_CssRules_InsertRule(mRawRules, mStyleSheet->RawSheet(),
+                                          &rule, aIndex, nested, &type);
+  if (!NS_FAILED(rv)) {
+    mRules.InsertElementAt(type);
+  }
+  return rv;
+}
+
+nsresult
+ServoCSSRuleList::DeleteRule(uint32_t aIndex)
+{
+  nsresult rv = Servo_CssRules_DeleteRule(mRawRules, aIndex);
+  if (!NS_FAILED(rv)) {
+    mRules.RemoveElementAt(aIndex);
+  }
+  return rv;
+}
+
 ServoCSSRuleList::~ServoCSSRuleList()
 {
   EnumerateInstantiatedRules([](css::Rule* rule) { rule->Release(); });
 }
 
 } // namespace mozilla
--- a/layout/style/ServoCSSRuleList.h
+++ b/layout/style/ServoCSSRuleList.h
@@ -27,16 +27,20 @@ public:
 
   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);
+  nsresult InsertRule(const nsAString& aRule, uint32_t aIndex);
+  nsresult DeleteRule(uint32_t aIndex);
+
 private:
   virtual ~ServoCSSRuleList();
 
   // XXX Is it possible to have an address lower than or equal to 255?
   //     Is it possible to have more than 255 CSS rule types?
   static const uintptr_t kMaxRuleType = UINT8_MAX;
 
   static uintptr_t CastToUint(css::Rule* aPtr) {
--- a/layout/style/ServoStyleSheet.cpp
+++ b/layout/style/ServoStyleSheet.cpp
@@ -5,16 +5,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ServoStyleSheet.h"
 #include "mozilla/StyleBackendType.h"
 #include "mozilla/ServoBindings.h"
 #include "mozilla/ServoCSSRuleList.h"
 #include "mozilla/dom/CSSRuleList.h"
 
+#include "mozAutoDocUpdate.h"
+
 namespace mozilla {
 
 ServoStyleSheet::ServoStyleSheet(css::SheetParsingMode aParsingMode,
                                  CORSMode aCORSMode,
                                  net::ReferrerPolicy aReferrerPolicy,
                                  const dom::SRIMetadata& aIntegrity)
   : StyleSheet(StyleBackendType::Servo, aParsingMode)
   , mSheetInfo(aCORSMode, aReferrerPolicy, aIntegrity)
@@ -134,19 +136,50 @@ ServoStyleSheet::GetCssRulesInternal(Err
   }
   return mRuleList;
 }
 
 uint32_t
 ServoStyleSheet::InsertRuleInternal(const nsAString& aRule,
                                     uint32_t aIndex, ErrorResult& aRv)
 {
-  aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
-  return 0;
+  // Ensure mRuleList is constructed.
+  GetCssRulesInternal(aRv);
+
+  mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, true);
+  aRv = mRuleList->InsertRule(aRule, aIndex);
+  if (aRv.Failed()) {
+    return 0;
+  }
+  if (mDocument) {
+    // XXX When we support @import rules, we should not notify here,
+    // but rather when the sheet the rule is importing is loaded.
+    // XXX We may not want to get the rule when stylesheet change event
+    // is not enabled.
+    mDocument->StyleRuleAdded(this, mRuleList->GetRule(aIndex));
+  }
+  return aIndex;
 }
 
 void
 ServoStyleSheet::DeleteRuleInternal(uint32_t aIndex, ErrorResult& aRv)
 {
-  aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
+  // Ensure mRuleList is constructed.
+  GetCssRulesInternal(aRv);
+  if (aIndex > mRuleList->Length()) {
+    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
+    return;
+  }
+
+  mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, true);
+  // Hold a strong ref to the rule so it doesn't die when we remove it
+  // from the list. XXX We may not want to hold it if stylesheet change
+  // event is not enabled.
+  RefPtr<css::Rule> rule = mRuleList->GetRule(aIndex);
+  aRv = mRuleList->DeleteRule(aIndex);
+  MOZ_ASSERT(!aRv.ErrorCodeIs(NS_ERROR_DOM_INDEX_SIZE_ERR),
+             "IndexSizeError should have been handled earlier");
+  if (!aRv.Failed() && mDocument) {
+    mDocument->StyleRuleRemoved(this, rule);
+  }
 }
 
 } // namespace mozilla