Bug 1358993 - (Part 2) Add ServoStyleSheet::ReparseSheet function to collect reusable style sheets and clean up the child sheets of the parent sheet. draft
authorKuoE0 <kuoe0.tw@gmail.com>
Fri, 26 May 2017 16:01:40 +0800
changeset 588876 327c79f285c5452307cf30946bb4815f5e62b6f4
parent 588875 21ef67bb7bab815b4fce03087e89516054072c2a
child 588877 3ab0c7c2d97b3999ec89065ffa6da479d2a46dbd
push id62193
push userbmo:kuoe0@mozilla.com
push dateMon, 05 Jun 2017 08:46:15 +0000
bugs1358993
milestone55.0a1
Bug 1358993 - (Part 2) Add ServoStyleSheet::ReparseSheet function to collect reusable style sheets and clean up the child sheets of the parent sheet. MozReview-Commit-ID: CKqKFenXvVs
layout/style/ServoStyleSheet.cpp
layout/style/ServoStyleSheet.h
--- a/layout/style/ServoStyleSheet.cpp
+++ b/layout/style/ServoStyleSheet.cpp
@@ -9,16 +9,17 @@
 #include "mozilla/css/Rule.h"
 #include "mozilla/StyleBackendType.h"
 #include "mozilla/ServoBindings.h"
 #include "mozilla/ServoMediaList.h"
 #include "mozilla/ServoCSSRuleList.h"
 #include "mozilla/css/GroupRule.h"
 #include "mozilla/dom/CSSRuleList.h"
 #include "mozilla/dom/MediaList.h"
+#include "nsIStyleSheetLinkingElement.h"
 #include "Loader.h"
 
 
 #include "mozAutoDocUpdate.h"
 #include "nsIDOMCSSStyleSheet.h"
 
 using namespace mozilla::dom;
 
@@ -174,16 +175,68 @@ ServoStyleSheet::ParseSheet(css::Loader*
 
 void
 ServoStyleSheet::LoadFailed()
 {
   Inner()->mSheet = Servo_StyleSheet_Empty(mParsingMode).Consume();
   Inner()->mURLData = URLExtraData::Dummy();
 }
 
+nsresult
+ServoStyleSheet::ReparseSheet(const nsAString& aInput)
+{
+  // TODO(kuoe0): Bug 1367996 - Need to call document notification
+  // (StyleRuleAdded() and StyleRuleRemoved()) like what we do in
+  // CSSStyleSheet::ReparseSheet().
+
+  if (!mInner->mComplete) {
+    return NS_ERROR_DOM_INVALID_ACCESS_ERR;
+  }
+
+  RefPtr<css::Loader> loader;
+  if (mDocument) {
+    loader = mDocument->CSSLoader();
+    NS_ASSERTION(loader, "Document with no CSS loader!");
+  } else {
+    loader = new css::Loader(StyleBackendType::Servo, nullptr);
+  }
+
+  // cache child sheets to reuse
+  css::LoaderReusableStyleSheets reusableSheets;
+  for (StyleSheet* child = GetFirstChild(); child; child = child->mNext) {
+    if (child->GetOriginalURI()) {
+      reusableSheets.AddReusableSheet(child);
+    }
+  }
+
+  // clean up child sheets list
+  for (StyleSheet* child = GetFirstChild(); child; ) {
+    StyleSheet* next = child->mNext;
+    child->mParent = nullptr;
+    child->SetAssociatedDocument(nullptr, NotOwnedByDocument);
+    child->mNext = nullptr;
+    child = next;
+  }
+  Inner()->mFirstChild = nullptr;
+
+  uint32_t lineNumber = 1;
+  if (mOwningNode) {
+    nsCOMPtr<nsIStyleSheetLinkingElement> link = do_QueryInterface(mOwningNode);
+    if (link) {
+      lineNumber = link->GetLineNumber();
+    }
+  }
+
+  nsresult rv = ParseSheet(loader, aInput, mInner->mSheetURI, mInner->mBaseURI,
+                           mInner->mPrincipal, lineNumber,
+                           eCompatibility_FullStandards, &reusableSheets);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return NS_OK;
+}
+
 // nsICSSLoaderObserver implementation
 NS_IMETHODIMP
 ServoStyleSheet::StyleSheetLoaded(StyleSheet* aSheet,
                                   bool aWasAlternate,
                                   nsresult aStatus)
 {
   MOZ_ASSERT(aSheet->IsServo(),
              "why we were called back with a CSSStyleSheet?");
--- a/layout/style/ServoStyleSheet.h
+++ b/layout/style/ServoStyleSheet.h
@@ -90,16 +90,18 @@ public:
 
   /**
    * Called instead of ParseSheet to initialize the Servo stylesheet object
    * for a failed load. Either ParseSheet or LoadFailed must be called before
    * adding a ServoStyleSheet to a ServoStyleSet.
    */
   void LoadFailed();
 
+  nsresult ReparseSheet(const nsAString& aInput);
+
   const RawServoStyleSheet* RawSheet() const {
     return Inner()->mSheet;
   }
   void SetSheetForImport(const RawServoStyleSheet* aSheet) {
     MOZ_ASSERT(!Inner()->mSheet);
     Inner()->mSheet = aSheet;
   }