Bug 1290218 Part 8: Implement ServoStyleSheet Clone. draft
authorBrad Werth <bwerth@mozilla.com>
Wed, 15 Feb 2017 13:33:17 -0800
changeset 488926 a80f23d967f552c0a10c4e95009e4846826c8c2b
parent 488925 2100417a1b0c7ae8cd5c6b06686abfa5b27e451e
child 488927 0b6f97472279b108b9193050ef73c0d697347bfd
push id46687
push userbwerth@mozilla.com
push dateFri, 24 Feb 2017 01:52:48 +0000
bugs1290218
milestone54.0a1
Bug 1290218 Part 8: Implement ServoStyleSheet Clone. MozReview-Commit-ID: Y2KcoMjhbn
dom/base/nsDocument.cpp
layout/style/CSSStyleSheet.cpp
layout/style/CSSStyleSheet.h
layout/style/Loader.cpp
layout/style/ServoStyleSheet.cpp
layout/style/ServoStyleSheet.h
layout/style/StyleSheet.h
layout/style/nsCSSRules.cpp
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -9931,18 +9931,18 @@ nsIDocument::CreateStaticClone(nsIDocShe
 
       int32_t sheetsCount = GetNumberOfStyleSheets();
       for (int32_t i = 0; i < sheetsCount; ++i) {
         RefPtr<StyleSheet> sheet = GetStyleSheetAt(i);
         if (sheet) {
           if (sheet->IsApplicable()) {
             // XXXheycam Need to make ServoStyleSheet cloning work.
             if (sheet->IsGecko()) {
-              RefPtr<CSSStyleSheet> clonedSheet =
-                sheet->AsGecko()->Clone(nullptr, nullptr, clonedDoc, nullptr);
+              RefPtr<StyleSheet> clonedSheet =
+                sheet->Clone(nullptr, nullptr, clonedDoc, nullptr);
               NS_WARNING_ASSERTION(clonedSheet,
                                    "Cloning a stylesheet didn't work!");
               if (clonedSheet) {
                 clonedDoc->AddStyleSheet(clonedSheet);
               }
             } else {
               NS_ERROR("stylo: ServoStyleSheet doesn't support cloning");
             }
@@ -9951,18 +9951,18 @@ nsIDocument::CreateStaticClone(nsIDocShe
       }
 
       // Iterate backwards to maintain order
       for (StyleSheet* sheet : Reversed(thisAsDoc->mOnDemandBuiltInUASheets)) {
         if (sheet) {
           if (sheet->IsApplicable()) {
             // XXXheycam Need to make ServoStyleSheet cloning work.
             if (sheet->IsGecko()) {
-              RefPtr<CSSStyleSheet> clonedSheet =
-                sheet->AsGecko()->Clone(nullptr, nullptr, clonedDoc, nullptr);
+              RefPtr<StyleSheet> clonedSheet =
+                sheet->Clone(nullptr, nullptr, clonedDoc, nullptr);
               NS_WARNING_ASSERTION(clonedSheet,
                                    "Cloning a stylesheet didn't work!");
               if (clonedSheet) {
                 clonedDoc->AddOnDemandBuiltInUASheet(clonedSheet);
               }
             } else {
               NS_ERROR("stylo: ServoStyleSheet doesn't support cloning");
             }
--- a/layout/style/CSSStyleSheet.cpp
+++ b/layout/style/CSSStyleSheet.cpp
@@ -648,27 +648,27 @@ CSSStyleSheet::AppendAllChildSheets(nsTA
 {
   for (StyleSheet* child = GetFirstChild(); child;
        child = child->mNext) {
 
     aArray.AppendElement(child->AsGecko());
   }
 }
 
-already_AddRefed<CSSStyleSheet>
-CSSStyleSheet::Clone(CSSStyleSheet* aCloneParent,
+already_AddRefed<StyleSheet>
+CSSStyleSheet::Clone(StyleSheet* aCloneParent,
                      css::ImportRule* aCloneOwnerRule,
                      nsIDocument* aCloneDocument,
                      nsINode* aCloneOwningNode) const
 {
-  RefPtr<CSSStyleSheet> clone = new CSSStyleSheet(*this,
-                                                    aCloneParent,
-                                                    aCloneOwnerRule,
-                                                    aCloneDocument,
-                                                    aCloneOwningNode);
+  RefPtr<StyleSheet> clone = new CSSStyleSheet(*this,
+    static_cast<CSSStyleSheet*>(aCloneParent),
+    aCloneOwnerRule,
+    aCloneDocument,
+    aCloneOwningNode);
   return clone.forget();
 }
 
 #ifdef DEBUG
 static void
 ListRules(const nsCOMArray<css::Rule>& aRules, FILE* aOut, int32_t aIndent)
 {
   for (int32_t index = aRules.Count() - 1; index >= 0; --index) {
--- a/layout/style/CSSStyleSheet.h
+++ b/layout/style/CSSStyleSheet.h
@@ -35,19 +35,17 @@ class nsMediaQueryResultCacheKey;
 class nsStyleSet;
 class nsPresContext;
 class nsXMLNameSpaceMap;
 
 namespace mozilla {
 class CSSStyleSheet;
 
 namespace css {
-class Rule;
 class GroupRule;
-class ImportRule;
 } // namespace css
 namespace dom {
 class CSSRuleList;
 } // namespace dom
 
   // -------------------------------
 // CSS Style Sheet Inner Data Container
 //
@@ -124,20 +122,20 @@ public:
   css::ImportRule* GetOwnerRule() const { return mOwnerRule; }
   // Workaround overloaded-virtual warning in GCC.
   using StyleSheet::GetOwnerRule;
 
   nsXMLNameSpaceMap* GetNameSpaceMap() const {
     return Inner()->mNameSpaceMap;
   }
 
-  already_AddRefed<CSSStyleSheet> Clone(CSSStyleSheet* aCloneParent,
-                                        css::ImportRule* aCloneOwnerRule,
-                                        nsIDocument* aCloneDocument,
-                                        nsINode* aCloneOwningNode) const;
+  virtual already_AddRefed<StyleSheet> Clone(StyleSheet* aCloneParent,
+    css::ImportRule* aCloneOwnerRule,
+    nsIDocument* aCloneDocument,
+    nsINode* aCloneOwningNode) const final;
 
   bool IsModified() const final { return mDirty; }
 
   void SetModifiedByChildRule() {
     NS_ASSERTION(mDirty,
                  "sheet must be marked dirty before handing out child rules");
     DidDirty();
   }
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -1212,18 +1212,18 @@ Loader::CreateSheet(nsIURI* aURI,
       }
       NS_ASSERTION(!sheet->AsGecko()->IsModified() ||
                    !sheet->AsGecko()->IsComplete(),
                    "Unexpected modified complete sheet");
       NS_ASSERTION(sheet->AsGecko()->IsComplete() ||
                    aSheetState != eSheetComplete,
                    "Sheet thinks it's not complete while we think it is");
 
-      RefPtr<CSSStyleSheet> clonedSheet =
-        sheet->AsGecko()->Clone(nullptr, nullptr, nullptr, nullptr);
+      RefPtr<StyleSheet> clonedSheet =
+        sheet->Clone(nullptr, nullptr, nullptr, nullptr);
       *aSheet = Move(clonedSheet);
       if (*aSheet && fromCompleteSheets &&
           !sheet->AsGecko()->GetOwnerNode() &&
           !sheet->AsGecko()->GetParentSheet()) {
         // The sheet we're cloning isn't actually referenced by
         // anyone.  Replace it in the cache, so that if our CSSOM is
         // later modified we don't end up with two copies of our inner
         // hanging around.
--- a/layout/style/ServoStyleSheet.cpp
+++ b/layout/style/ServoStyleSheet.cpp
@@ -34,16 +34,26 @@ ServoStyleSheet::ServoStyleSheet(css::Sh
                                  net::ReferrerPolicy aReferrerPolicy,
                                  const dom::SRIMetadata& aIntegrity)
   : StyleSheet(StyleBackendType::Servo, aParsingMode)
 {
   mInner = new ServoStyleSheetInner(aCORSMode, aReferrerPolicy, aIntegrity);
   mInner->AddSheet(this);
 }
 
+ServoStyleSheet::ServoStyleSheet(const ServoStyleSheet& aCopy,
+                                 ServoStyleSheet* aParentToUse,
+                                 css::ImportRule* aOwnerRuleToUse,
+                                 nsIDocument* aDocumentToUse,
+                                 nsINode* aOwningNodeToUse)
+  : StyleSheet(aCopy, aDocumentToUse, aOwningNodeToUse)
+{
+  mParent = aParentToUse;
+}
+
 ServoStyleSheet::~ServoStyleSheet()
 {
   UnparentChildren();
 
   DropRuleList();
 }
 
 // QueryInterface implementation for ServoStyleSheet
@@ -116,16 +126,30 @@ ServoStyleSheet::DropRuleList()
 
 css::Rule*
 ServoStyleSheet::GetDOMOwnerRule() const
 {
   NS_ERROR("stylo: Don't know how to get DOM owner rule for ServoStyleSheet");
   return nullptr;
 }
 
+already_AddRefed<StyleSheet>
+ServoStyleSheet::Clone(StyleSheet* aCloneParent,
+                       css::ImportRule* aCloneOwnerRule,
+                       nsIDocument* aCloneDocument,
+                       nsINode* aCloneOwningNode) const
+{
+  RefPtr<StyleSheet> clone = new ServoStyleSheet(*this,
+    static_cast<ServoStyleSheet*>(aCloneParent),
+    aCloneOwnerRule,
+    aCloneDocument,
+    aCloneOwningNode);
+  return clone.forget();
+}
+
 CSSRuleList*
 ServoStyleSheet::GetCssRulesInternal(ErrorResult& aRv)
 {
   if (!mRuleList) {
     RefPtr<ServoCssRules> rawRules =
       Servo_StyleSheet_GetRules(Inner()->mSheet).Consume();
     mRuleList = new ServoCSSRuleList(this, rawRules.forget());
   }
--- a/layout/style/ServoStyleSheet.h
+++ b/layout/style/ServoStyleSheet.h
@@ -15,17 +15,16 @@
 #include "nsStringFwd.h"
 
 namespace mozilla {
 
 class ServoCSSRuleList;
 
 namespace css {
 class Loader;
-class Rule;
 }
 
 // -------------------------------
 // Servo Style Sheet Inner Data Container
 //
 
 struct ServoStyleSheetInner : public StyleSheetInfo
 {
@@ -81,16 +80,21 @@ public:
   // version.
   css::Rule* GetDOMOwnerRule() const final;
 
   void WillDirty() {}
   void DidDirty() {}
 
   bool IsModified() const final { return false; }
 
+  virtual already_AddRefed<StyleSheet> Clone(StyleSheet* aCloneParent,
+    css::ImportRule* aCloneOwnerRule,
+    nsIDocument* aCloneDocument,
+    nsINode* aCloneOwningNode) const final;
+
 protected:
   virtual ~ServoStyleSheet();
 
   ServoStyleSheetInner* Inner() const
   {
     return static_cast<ServoStyleSheetInner*>(mInner);
   }
 
@@ -98,16 +102,22 @@ protected:
   dom::CSSRuleList* GetCssRulesInternal(ErrorResult& aRv);
   uint32_t InsertRuleInternal(const nsAString& aRule,
                               uint32_t aIndex, ErrorResult& aRv);
   void DeleteRuleInternal(uint32_t aIndex, ErrorResult& aRv);
 
   void EnabledStateChangedInternal() {}
 
 private:
+  ServoStyleSheet(const ServoStyleSheet& aCopy,
+                  ServoStyleSheet* aParentToUse,
+                  css::ImportRule* aOwnerRuleToUse,
+                  nsIDocument* aDocumentToUse,
+                  nsINode* aOwningNodeToUse);
+
   void DropRuleList();
 
   RefPtr<ServoCSSRuleList> mRuleList;
 
   friend class StyleSheet;
 };
 
 } // namespace mozilla
--- a/layout/style/StyleSheet.h
+++ b/layout/style/StyleSheet.h
@@ -31,16 +31,17 @@ class ServoStyleSheet;
 struct StyleSheetInfo;
 
 namespace dom {
 class CSSRuleList;
 class SRIMetadata;
 } // namespace dom
 
 namespace css {
+class ImportRule;
 class Rule;
 }
 
 /**
  * Superclass for data common to CSSStyleSheet and ServoStyleSheet.
  */
 class StyleSheet : public nsIDOMCSSStyleSheet
                  , public nsWrapperCache
@@ -103,16 +104,21 @@ public:
    * Whether the sheet is applicable.  A sheet that is not applicable
    * should never be inserted into a style set.  A sheet may not be
    * applicable for a variety of reasons including being disabled and
    * being incomplete.
    */
   inline bool IsApplicable() const;
   inline bool HasRules() const;
 
+  virtual already_AddRefed<StyleSheet> Clone(StyleSheet* aCloneParent,
+                                             css::ImportRule* aCloneOwnerRule,
+                                             nsIDocument* aCloneDocument,
+                                             nsINode* aCloneOwningNode) const = 0;
+
   virtual bool IsModified() const = 0;
 
   // style sheet owner info
   enum DocumentAssociationMode {
     // OwnedByDocument means mDocument owns us (possibly via a chain of other
     // stylesheets).
     OwnedByDocument,
     // NotOwnedByDocument means we're owned by something that might have a
--- a/layout/style/nsCSSRules.cpp
+++ b/layout/style/nsCSSRules.cpp
@@ -263,19 +263,19 @@ ImportRule::ImportRule(nsMediaList* aMed
 ImportRule::ImportRule(const ImportRule& aCopy)
   : Rule(aCopy),
     mURLSpec(aCopy.mURLSpec)
 {
   // Whether or not an @import rule has a null sheet is a permanent
   // property of that @import rule, since it is null only if the target
   // sheet failed security checks.
   if (aCopy.mChildSheet) {
-    RefPtr<CSSStyleSheet> sheet =
+    RefPtr<StyleSheet> sheet =
       aCopy.mChildSheet->Clone(nullptr, this, nullptr, nullptr);
-    SetSheet(sheet);
+    SetSheet(static_cast<CSSStyleSheet*>(sheet.get()));
     // SetSheet sets mMedia appropriately
   } else {
     // We better just copy mMedia from aCopy, since we have nowhere else to get
     // one.
     mMedia = aCopy.mMedia;
   }
 }