Bug 1345206 - Create ServoPageRule. r=xidorn draft
authorJ. Ryan Stinnett <jryans@gmail.com>
Fri, 31 Mar 2017 16:13:12 -0500
changeset 559396 80da119b72fb19938be462c1c291e4829f527c53
parent 559395 4b96f3c39b90e7c32e2ae924eb01d9457205fa15
child 559397 f356a7deba13a793e744246e0d2074dbc5768143
push id53073
push userbmo:jryans@gmail.com
push dateMon, 10 Apr 2017 02:45:18 +0000
reviewersxidorn
bugs1345206
milestone55.0a1
Bug 1345206 - Create ServoPageRule. r=xidorn Adds `ServoPageRule` for use as the CSSOM representation of @page rules parsed by Servo. MozReview-Commit-ID: 7AIErJmoZN
layout/style/ServoPageRule.cpp
layout/style/ServoPageRule.h
layout/style/ServoStyleRule.cpp
layout/style/ServoStyleRule.h
layout/style/moz.build
new file mode 100644
--- /dev/null
+++ b/layout/style/ServoPageRule.cpp
@@ -0,0 +1,205 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* representation of CSSPageRule for stylo */
+
+#include "mozilla/ServoPageRule.h"
+
+#include "mozilla/DeclarationBlockInlines.h"
+#include "mozilla/ServoBindings.h"
+#include "mozilla/ServoDeclarationBlock.h"
+
+using namespace mozilla::dom;
+
+namespace mozilla {
+
+// -- ServoPageRuleDeclaration ---------------------------------------
+
+ServoPageRuleDeclaration::ServoPageRuleDeclaration(
+  already_AddRefed<RawServoDeclarationBlock> aDecls)
+  : mDecls(new ServoDeclarationBlock(Move(aDecls)))
+{
+}
+
+ServoPageRuleDeclaration::~ServoPageRuleDeclaration()
+{
+}
+
+// QueryInterface implementation for ServoPageRuleDeclaration
+NS_INTERFACE_MAP_BEGIN(ServoPageRuleDeclaration)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+  // We forward the cycle collection interfaces to Rule(), which is
+  // never null (in fact, we're part of that object!)
+  if (aIID.Equals(NS_GET_IID(nsCycleCollectionISupports)) ||
+      aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant))) {
+    return Rule()->QueryInterface(aIID, aInstancePtr);
+  }
+  else
+NS_IMPL_QUERY_TAIL_INHERITING(nsDOMCSSDeclaration)
+
+NS_IMPL_ADDREF_USING_AGGREGATOR(ServoPageRuleDeclaration, Rule())
+NS_IMPL_RELEASE_USING_AGGREGATOR(ServoPageRuleDeclaration, Rule())
+
+/* nsDOMCSSDeclaration implementation */
+
+NS_IMETHODIMP
+ServoPageRuleDeclaration::GetParentRule(nsIDOMCSSRule** aParent)
+{
+  *aParent = do_AddRef(Rule()).take();
+  return NS_OK;
+}
+
+nsINode*
+ServoPageRuleDeclaration::GetParentObject()
+{
+  return Rule()->GetDocument();
+}
+
+DeclarationBlock*
+ServoPageRuleDeclaration::GetCSSDeclaration(Operation aOperation)
+{
+  return mDecls;
+}
+
+nsresult
+ServoPageRuleDeclaration::SetCSSDeclaration(DeclarationBlock* aDecl)
+{
+  MOZ_ASSERT(aDecl, "must be non-null");
+  ServoPageRule* rule = Rule();
+
+  if (aDecl != mDecls) {
+    mDecls->SetOwningRule(nullptr);
+    RefPtr<ServoDeclarationBlock> decls = aDecl->AsServo();
+    Servo_PageRule_SetStyle(rule->Raw(), decls->Raw());
+    mDecls = decls.forget();
+    mDecls->SetOwningRule(rule);
+  }
+
+  return NS_OK;
+}
+
+nsIDocument*
+ServoPageRuleDeclaration::DocToUpdate()
+{
+  return nullptr;
+}
+
+void
+ServoPageRuleDeclaration::GetCSSParsingEnvironment(
+  CSSParsingEnvironment& aCSSParseEnv)
+{
+  MOZ_ASSERT_UNREACHABLE("GetCSSParsingEnvironment "
+                         "shouldn't be calling for a Servo rule");
+  GetCSSParsingEnvironmentForRule(Rule(), aCSSParseEnv);
+}
+
+URLExtraData*
+ServoPageRuleDeclaration::GetURLData() const
+{
+  return GetURLDataForRule(Rule());
+}
+
+// -- ServoPageRule --------------------------------------------------
+
+ServoPageRule::ServoPageRule(RefPtr<RawServoPageRule> aRawRule)
+  : CSSPageRule(0, 0)
+  , mRawRule(Move(aRawRule))
+  , mDecls(Servo_PageRule_GetStyle(mRawRule).Consume())
+{
+}
+
+ServoPageRule::~ServoPageRule()
+{
+}
+
+NS_IMPL_ADDREF_INHERITED(ServoPageRule, CSSPageRule)
+NS_IMPL_RELEASE_INHERITED(ServoPageRule, CSSPageRule)
+
+// QueryInterface implementation for PageRule
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServoPageRule)
+NS_INTERFACE_MAP_END_INHERITING(CSSPageRule)
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(ServoPageRule)
+
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(ServoPageRule, CSSPageRule)
+  // Keep this in sync with IsCCLeaf.
+
+  // Trace the wrapper for our declaration.  This just expands out
+  // NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER which we can't use
+  // directly because the wrapper is on the declaration, not on us.
+  tmp->mDecls.TraceWrapper(aCallbacks, aClosure);
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ServoPageRule, CSSPageRule)
+  // Keep this in sync with IsCCLeaf.
+
+  // Unlink the wrapper for our declaraton.  This just expands out
+  // NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER which we can't use
+  // directly because the wrapper is on the declaration, not on us.
+  tmp->mDecls.ReleaseWrapper(static_cast<nsISupports*>(p));
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ServoPageRule, CSSPageRule)
+  // Keep this in sync with IsCCLeaf.
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+bool
+ServoPageRule::IsCCLeaf() const
+{
+  if (!Rule::IsCCLeaf()) {
+    return false;
+  }
+
+  return !mDecls.PreservingWrapper();
+}
+
+already_AddRefed<css::Rule>
+ServoPageRule::Clone() const
+{
+  // Rule::Clone is only used when CSSStyleSheetInner is cloned in
+  // preparation of being mutated. However, ServoStyleSheet never clones
+  // anything, so this method should never be called.
+  MOZ_ASSERT_UNREACHABLE("Shouldn't be cloning ServoPageRule");
+  return nullptr;
+}
+
+size_t
+ServoPageRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
+{
+  // TODO Implement this!
+  return aMallocSizeOf(this);
+}
+
+#ifdef DEBUG
+void
+ServoPageRule::List(FILE* out, int32_t aIndent) const
+{
+  nsAutoCString str;
+  for (int32_t i = 0; i < aIndent; i++) {
+    str.AppendLiteral("  ");
+  }
+  Servo_PageRule_Debug(mRawRule, &str);
+  fprintf_stderr(out, "%s\n", str.get());
+}
+#endif
+
+/* CSSRule implementation */
+
+void
+ServoPageRule::GetCssTextImpl(nsAString& aCssText) const
+{
+  Servo_PageRule_GetCssText(mRawRule, &aCssText);
+}
+
+/* CSSPageRule implementation */
+
+nsICSSDeclaration*
+ServoPageRule::Style()
+{
+  return &mDecls;
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/layout/style/ServoPageRule.h
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* representation of CSSPageRule for stylo */
+
+#ifndef mozilla_ServoPageRule_h
+#define mozilla_ServoPageRule_h
+
+#include "mozilla/dom/CSSPageRule.h"
+#include "mozilla/ServoBindingTypes.h"
+
+#include "nsDOMCSSDeclaration.h"
+
+namespace mozilla {
+
+class ServoDeclarationBlock;
+class ServoPageRule;
+
+class ServoPageRuleDeclaration final : public nsDOMCSSDeclaration
+{
+public:
+  NS_DECL_ISUPPORTS_INHERITED
+
+  NS_IMETHOD GetParentRule(nsIDOMCSSRule** aParent) final;
+  nsINode* GetParentObject() final;
+
+protected:
+  DeclarationBlock* GetCSSDeclaration(Operation aOperation) final;
+  nsresult SetCSSDeclaration(DeclarationBlock* aDecl) final;
+  nsIDocument* DocToUpdate() final;
+  void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv) final;
+  URLExtraData* GetURLData() const final;
+
+private:
+  // For accessing the constructor.
+  friend class ServoPageRule;
+
+  explicit ServoPageRuleDeclaration(
+    already_AddRefed<RawServoDeclarationBlock> aDecls);
+  ~ServoPageRuleDeclaration();
+
+  inline ServoPageRule* Rule();
+  inline const ServoPageRule* Rule() const;
+
+  RefPtr<ServoDeclarationBlock> mDecls;
+};
+
+class ServoPageRule final : public dom::CSSPageRule
+{
+public:
+  explicit ServoPageRule(RefPtr<RawServoPageRule> aRawRule);
+
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(
+    ServoPageRule, dom::CSSPageRule
+  )
+  bool IsCCLeaf() const final;
+
+  RawServoPageRule* Raw() const { return mRawRule; }
+
+  // WebIDL interface
+  void GetCssTextImpl(nsAString& aCssText) const final;
+  nsICSSDeclaration* Style() final;
+
+  // Methods of mozilla::css::Rule
+  already_AddRefed<css::Rule> Clone() const final;
+  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
+    const final;
+#ifdef DEBUG
+  void List(FILE* out = stdout, int32_t aIndent = 0) const final;
+#endif
+
+private:
+  virtual ~ServoPageRule();
+
+  // For computing the offset of mDecls.
+  friend class ServoPageRuleDeclaration;
+
+  RefPtr<RawServoPageRule> mRawRule;
+  ServoPageRuleDeclaration mDecls;
+};
+
+ServoPageRule*
+ServoPageRuleDeclaration::Rule()
+{
+  return reinterpret_cast<ServoPageRule*>(
+    reinterpret_cast<uint8_t*>(this) - offsetof(ServoPageRule, mDecls));
+}
+
+const ServoPageRule*
+ServoPageRuleDeclaration::Rule() const
+{
+  return reinterpret_cast<const ServoPageRule*>(
+    reinterpret_cast<const uint8_t*>(this) - offsetof(ServoPageRule, mDecls));
+}
+
+} // namespace mozilla
+
+#endif // mozilla_ServoPageRule_h
--- a/layout/style/ServoStyleRule.cpp
+++ b/layout/style/ServoStyleRule.cpp
@@ -68,19 +68,21 @@ ServoStyleRuleDeclaration::GetCSSDeclara
 nsresult
 ServoStyleRuleDeclaration::SetCSSDeclaration(DeclarationBlock* aDecl)
 {
   ServoStyleRule* rule = Rule();
   if (RefPtr<ServoStyleSheet> sheet = rule->GetStyleSheet()->AsServo()) {
     nsCOMPtr<nsIDocument> doc = sheet->GetAssociatedDocument();
     mozAutoDocUpdate updateBatch(doc, UPDATE_STYLE, true);
     if (aDecl != mDecls) {
+      mDecls->SetOwningRule(nullptr);
       RefPtr<ServoDeclarationBlock> decls = aDecl->AsServo();
       Servo_StyleRule_SetStyle(rule->Raw(), decls->Raw());
       mDecls = decls.forget();
+      mDecls->SetOwningRule(rule);
     }
     if (doc) {
       doc->StyleRuleChanged(sheet, rule);
     }
   }
   return NS_OK;
 }
 
--- a/layout/style/ServoStyleRule.h
+++ b/layout/style/ServoStyleRule.h
@@ -53,23 +53,23 @@ class ServoStyleRule final : public Bind
                            , public nsIDOMCSSStyleRule
 {
 public:
   explicit ServoStyleRule(already_AddRefed<RawServoStyleRule> aRawRule);
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(ServoStyleRule,
                                                          css::Rule)
-  virtual bool IsCCLeaf() const override MOZ_MUST_OVERRIDE;
+  virtual bool IsCCLeaf() const final MOZ_MUST_OVERRIDE;
   NS_DECL_NSIDOMCSSSTYLERULE
 
   // WebIDL interface
-  uint16_t Type() const override;
-  void GetCssTextImpl(nsAString& aCssText) const override;
-  virtual nsICSSDeclaration* Style() override;
+  uint16_t Type() const final;
+  void GetCssTextImpl(nsAString& aCssText) const final;
+  virtual nsICSSDeclaration* Style() final;
 
   RawServoStyleRule* Raw() const { return mRawRule; }
 
   // Methods of mozilla::css::Rule
   int32_t GetType() const final { return css::Rule::STYLE_RULE; }
   using Rule::GetType;
   already_AddRefed<Rule> Clone() const final;
   size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const final;
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -101,16 +101,17 @@ EXPORTS.mozilla += [
     'ServoBindings.h',
     'ServoBindingTypes.h',
     'ServoCSSRuleList.h',
     'ServoDeclarationBlock.h',
     'ServoElementSnapshot.h',
     'ServoMediaList.h',
     'ServoMediaRule.h',
     'ServoNamespaceRule.h',
+    'ServoPageRule.h',
     'ServoPropPrefList.h',
     'ServoSpecifiedValues.h',
     'ServoStyleRule.h',
     'ServoStyleSet.h',
     'ServoStyleSheet.h',
     'ServoTypes.h',
     'ServoUtils.h',
     'SheetType.h',
@@ -220,16 +221,17 @@ UNIFIED_SOURCES += [
     'RuleProcessorCache.cpp',
     'ServoBindings.cpp',
     'ServoCSSRuleList.cpp',
     'ServoDeclarationBlock.cpp',
     'ServoElementSnapshot.cpp',
     'ServoMediaList.cpp',
     'ServoMediaRule.cpp',
     'ServoNamespaceRule.cpp',
+    'ServoPageRule.cpp',
     'ServoSpecifiedValues.cpp',
     'ServoStyleRule.cpp',
     'ServoStyleSet.cpp',
     'ServoStyleSheet.cpp',
     'StyleAnimationValue.cpp',
     'StyleRule.cpp',
     'StyleSheet.cpp',
     'URLExtraData.cpp',