Bug 1307357 part 3 - Implement CSSRuleList interface for stylo. r=heycam,manishearth
authorXidorn Quan <me@upsuper.org>
Wed, 23 Nov 2016 10:26:20 +1100
changeset 323892 2ba29077a23e4fbbc79bbf54efb2c1a563056295
parent 323891 7a9d6a3cdf1a68952f8fb88a0999db1f9486b921
child 323893 31fdda2f930d856d0786563d5ea1a3e8a6d076b4
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersheycam, manishearth
bugs1307357
milestone53.0a1
Bug 1307357 part 3 - Implement CSSRuleList interface for stylo. r=heycam,manishearth MozReview-Commit-ID: Ecnbj66yKOE
layout/style/ServoBindingList.h
layout/style/ServoBindingTypes.h
layout/style/ServoBindings.cpp
layout/style/ServoBindings.h
layout/style/ServoCSSRuleList.cpp
layout/style/ServoCSSRuleList.h
layout/style/ServoStyleSheet.cpp
layout/style/ServoStyleSheet.h
layout/style/moz.build
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -32,28 +32,35 @@ SERVO_BINDING_FUNC(Servo_StyleSheet_From
                    ThreadSafeURIHolder* referrer,
                    ThreadSafePrincipalHolder* principal)
 SERVO_BINDING_FUNC(Servo_StyleSheet_AddRef, void,
                    RawServoStyleSheetBorrowed sheet)
 SERVO_BINDING_FUNC(Servo_StyleSheet_Release, void,
                    RawServoStyleSheetBorrowed sheet)
 SERVO_BINDING_FUNC(Servo_StyleSheet_HasRules, bool,
                    RawServoStyleSheetBorrowed sheet)
+SERVO_BINDING_FUNC(Servo_StyleSheet_GetRules, ServoCssRulesStrong,
+                   RawServoStyleSheetBorrowed sheet)
 SERVO_BINDING_FUNC(Servo_StyleSet_Init, RawServoStyleSetOwned)
 SERVO_BINDING_FUNC(Servo_StyleSet_Drop, void, RawServoStyleSetOwned set)
 SERVO_BINDING_FUNC(Servo_StyleSet_AppendStyleSheet, void,
                    RawServoStyleSetBorrowed set, RawServoStyleSheetBorrowed sheet)
 SERVO_BINDING_FUNC(Servo_StyleSet_PrependStyleSheet, void,
                    RawServoStyleSetBorrowed set, RawServoStyleSheetBorrowed sheet)
 SERVO_BINDING_FUNC(Servo_StyleSet_RemoveStyleSheet, void,
                    RawServoStyleSetBorrowed set, RawServoStyleSheetBorrowed sheet)
 SERVO_BINDING_FUNC(Servo_StyleSet_InsertStyleSheetBefore, void,
                    RawServoStyleSetBorrowed set, RawServoStyleSheetBorrowed sheet,
                    RawServoStyleSheetBorrowed reference)
 
+// CSSRuleList
+SERVO_BINDING_FUNC(Servo_CssRules_ListTypes, void,
+                   ServoCssRulesBorrowed rules,
+                   nsTArrayBorrowed_uintptr_t result)
+
 // Animations API
 SERVO_BINDING_FUNC(Servo_ParseProperty,
                    RawServoDeclarationBlockStrong,
                    const nsACString* property, const nsACString* value,
                    const nsACString* base_url, ThreadSafeURIHolder* base,
                    ThreadSafeURIHolder* referrer,
                    ThreadSafePrincipalHolder* principal)
 SERVO_BINDING_FUNC(Servo_RestyleWithAddedDeclaration,
--- a/layout/style/ServoBindingTypes.h
+++ b/layout/style/ServoBindingTypes.h
@@ -6,16 +6,17 @@
 
 #ifndef mozilla_ServoBindingTypes_h
 #define mozilla_ServoBindingTypes_h
 
 #include "mozilla/RefPtr.h"
 #include "mozilla/UniquePtr.h"
 
 struct ServoComputedValues;
+struct ServoCssRules;
 struct RawServoStyleSheet;
 struct RawServoStyleSet;
 struct RawServoDeclarationBlock;
 
 namespace mozilla {
 namespace dom {
 class Element;
 class StyleChildrenIterator;
@@ -67,16 +68,17 @@ typedef nsIDocument RawGeckoDocument;
   DECL_BORROWED_MUT_REF_TYPE_FOR(type_)
 
 #define DECL_NULLABLE_OWNED_REF_TYPE_FOR(type_)    \
   typedef type_* type_##OwnedOrNull;               \
   DECL_NULLABLE_BORROWED_REF_TYPE_FOR(type_)       \
   DECL_NULLABLE_BORROWED_MUT_REF_TYPE_FOR(type_)
 
 DECL_ARC_REF_TYPE_FOR(ServoComputedValues)
+DECL_ARC_REF_TYPE_FOR(ServoCssRules)
 DECL_ARC_REF_TYPE_FOR(RawServoStyleSheet)
 DECL_ARC_REF_TYPE_FOR(RawServoDeclarationBlock)
 // This is a reference to a reference of RawServoDeclarationBlock, which
 // corresponds to Option<&Arc<RawServoDeclarationBlock>> in Servo side.
 DECL_NULLABLE_BORROWED_REF_TYPE_FOR(RawServoDeclarationBlockStrong)
 
 DECL_OWNED_REF_TYPE_FOR(RawServoStyleSet)
 DECL_NULLABLE_OWNED_REF_TYPE_FOR(StyleChildrenIterator)
@@ -116,16 +118,17 @@ DECL_BORROWED_MUT_REF_TYPE_FOR(nsCSSValu
       Servo_##name_##_AddRef(aPtr);                  \
     }                                                \
     static void Release(type_* aPtr) {               \
       Servo_##name_##_Release(aPtr);                 \
     }                                                \
   };                                                 \
   }
 
+DEFINE_REFPTR_TRAITS(CssRules, ServoCssRules)
 DEFINE_REFPTR_TRAITS(StyleSheet, RawServoStyleSheet)
 DEFINE_REFPTR_TRAITS(ComputedValues, ServoComputedValues)
 DEFINE_REFPTR_TRAITS(DeclarationBlock, RawServoDeclarationBlock)
 
 #undef DEFINE_REFPTR_TRAITS
 
 extern "C" void Servo_StyleSet_Drop(RawServoStyleSetOwned ptr);
 
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -40,16 +40,17 @@ using namespace mozilla::dom;
   already_AddRefed<type_>               \
   type_##Strong::Consume() {            \
     RefPtr<type_> result;               \
     result.swap(mPtr);                  \
     return result.forget();             \
   }
 
 IMPL_STRONG_REF_TYPE_FOR(ServoComputedValues)
+IMPL_STRONG_REF_TYPE_FOR(ServoCssRules)
 IMPL_STRONG_REF_TYPE_FOR(RawServoStyleSheet)
 IMPL_STRONG_REF_TYPE_FOR(RawServoDeclarationBlock)
 
 #undef IMPL_STRONG_REF_TYPE_FOR
 
 uint32_t
 Gecko_ChildrenCount(RawGeckoNodeBorrowed aNode)
 {
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -59,16 +59,26 @@ struct nsStyleDisplay;
   void Gecko_AddRef##name_##ArbitraryThread(ThreadSafe##name_##Holder* aPtr); \
   void Gecko_Release##name_##ArbitraryThread(ThreadSafe##name_##Holder* aPtr);
 #define NS_IMPL_HOLDER_FFI_REFCOUNTING(class_, name_)                         \
   void Gecko_AddRef##name_##ArbitraryThread(ThreadSafe##name_##Holder* aPtr)  \
   { NS_ADDREF(aPtr); }                                                        \
   void Gecko_Release##name_##ArbitraryThread(ThreadSafe##name_##Holder* aPtr) \
   { NS_RELEASE(aPtr); }                                                       \
 
+
+#define DEFINE_ARRAY_TYPE_FOR(type_)                                \
+  struct nsTArrayBorrowed_##type_ {                                 \
+    nsTArray<type_>* mArray;                                        \
+    MOZ_IMPLICIT nsTArrayBorrowed_##type_(nsTArray<type_>* aArray)  \
+      : mArray(aArray) {}                                           \
+  }
+DEFINE_ARRAY_TYPE_FOR(uintptr_t);
+#undef DEFINE_ARRAY_TYPE_FOR
+
 extern "C" {
 
 // Object refcounting.
 NS_DECL_HOLDER_FFI_REFCOUNTING(nsIPrincipal, Principal)
 NS_DECL_HOLDER_FFI_REFCOUNTING(nsIURI, URI)
 
 // DOM Traversal.
 uint32_t Gecko_ChildrenCount(RawGeckoNodeBorrowed node);
new file mode 100644
--- /dev/null
+++ b/layout/style/ServoCSSRuleList.cpp
@@ -0,0 +1,79 @@
+/* -*- 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 CSSRuleList for stylo */
+
+#include "mozilla/ServoCSSRuleList.h"
+
+#include "mozilla/ServoBindings.h"
+
+namespace mozilla {
+
+ServoCSSRuleList::ServoCSSRuleList(ServoStyleSheet* aStyleSheet,
+                                   already_AddRefed<ServoCssRules> aRawRules)
+  : mStyleSheet(aStyleSheet)
+  , 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)
+{
+  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:
+      case nsIDOMCSSRule::MEDIA_RULE:
+      case nsIDOMCSSRule::FONT_FACE_RULE:
+      case nsIDOMCSSRule::KEYFRAMES_RULE:
+      case nsIDOMCSSRule::NAMESPACE_RULE:
+        // XXX create corresponding rules
+      default:
+        MOZ_CRASH("stylo: not implemented yet");
+    }
+    ruleObj->SetStyleSheet(mStyleSheet);
+    rule = CastToUint(ruleObj.forget().take());
+    mRules[aIndex] = rule;
+  }
+  return CastToPtr(rule)->GetDOMRule();
+}
+
+template<typename Func>
+void
+ServoCSSRuleList::EnumerateInstantiatedRules(Func aCallback)
+{
+  for (uintptr_t rule : mRules) {
+    if (rule > kMaxRuleType) {
+      aCallback(CastToPtr(rule));
+    }
+  }
+}
+
+void
+ServoCSSRuleList::DropReference()
+{
+  mStyleSheet = nullptr;
+  EnumerateInstantiatedRules([](css::Rule* rule) {
+    rule->SetStyleSheet(nullptr);
+  });
+}
+
+ServoCSSRuleList::~ServoCSSRuleList()
+{
+  EnumerateInstantiatedRules([](css::Rule* rule) { rule->Release(); });
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/layout/style/ServoCSSRuleList.h
@@ -0,0 +1,65 @@
+/* -*- 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 CSSRuleList for stylo */
+
+#ifndef mozilla_ServoCSSRuleList_h
+#define mozilla_ServoCSSRuleList_h
+
+#include "mozilla/ServoBindingTypes.h"
+#include "mozilla/dom/CSSRuleList.h"
+
+namespace mozilla {
+
+class ServoStyleSheet;
+namespace css {
+class Rule;
+} // namespace css
+
+class ServoCSSRuleList final : public CSSRuleList
+{
+public:
+  ServoCSSRuleList(ServoStyleSheet* aStyleSheet,
+                   already_AddRefed<ServoCssRules> aRawRules);
+
+  ServoStyleSheet* GetParentObject() final { return mStyleSheet; }
+
+  nsIDOMCSSRule* IndexedGetter(uint32_t aIndex, bool& aFound) final;
+  uint32_t Length() final { return mRules.Length(); }
+
+  void DropReference();
+
+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) {
+    return reinterpret_cast<uintptr_t>(aPtr);
+  }
+  static css::Rule* CastToPtr(uintptr_t aInt) {
+    MOZ_ASSERT(aInt > kMaxRuleType);
+    return reinterpret_cast<css::Rule*>(aInt);
+  }
+
+  template<typename Func>
+  void EnumerateInstantiatedRules(Func aCallback);
+
+  // mStyleSheet may be nullptr when it drops the reference to us.
+  ServoStyleSheet* mStyleSheet;
+  RefPtr<ServoCssRules> mRawRules;
+  // Array stores either a number indicating rule type, or a pointer to
+  // css::Rule. If the value is less than kMaxRuleType, the given rule
+  // instance has not been constructed, and the value means the type
+  // of the rule. Otherwise, it is a pointer.
+  nsTArray<uintptr_t> mRules;
+};
+
+} // namespace mozilla
+
+#endif // mozilla_ServoCSSRuleList_h
--- a/layout/style/ServoStyleSheet.cpp
+++ b/layout/style/ServoStyleSheet.cpp
@@ -1,31 +1,37 @@
 /* -*- 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/. */
 
 #include "mozilla/ServoStyleSheet.h"
 #include "mozilla/StyleBackendType.h"
+#include "mozilla/ServoBindings.h"
+#include "mozilla/ServoCSSRuleList.h"
+#include "mozilla/dom/CSSRuleList.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)
 {
 }
 
 ServoStyleSheet::~ServoStyleSheet()
 {
   DropSheet();
+  if (mRuleList) {
+    mRuleList->DropReference();
+  }
 }
 
 bool
 ServoStyleSheet::HasRules() const
 {
   return mSheet && Servo_StyleSheet_HasRules(mSheet);
 }
 
@@ -117,18 +123,21 @@ nsIDOMCSSRule*
 ServoStyleSheet::GetDOMOwnerRule() const
 {
   return nullptr;
 }
 
 CSSRuleList*
 ServoStyleSheet::GetCssRulesInternal(ErrorResult& aRv)
 {
-  aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
-  return nullptr;
+  if (!mRuleList) {
+    RefPtr<ServoCssRules> rawRules = Servo_StyleSheet_GetRules(mSheet).Consume();
+    mRuleList = new ServoCSSRuleList(this, rawRules.forget());
+  }
+  return mRuleList;
 }
 
 uint32_t
 ServoStyleSheet::InsertRuleInternal(const nsAString& aRule,
                                     uint32_t aIndex, ErrorResult& aRv)
 {
   aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
   return 0;
--- a/layout/style/ServoStyleSheet.h
+++ b/layout/style/ServoStyleSheet.h
@@ -11,16 +11,18 @@
 #include "mozilla/RefPtr.h"
 #include "mozilla/ServoBindingTypes.h"
 #include "mozilla/StyleSheet.h"
 #include "mozilla/StyleSheetInfo.h"
 #include "nsStringFwd.h"
 
 namespace mozilla {
 
+class ServoCSSRuleList;
+
 /**
  * CSS style sheet object that is a wrapper for a Servo Stylesheet.
  */
 class ServoStyleSheet : public StyleSheet
 {
 public:
   ServoStyleSheet(css::SheetParsingMode aParsingMode,
                   CORSMode aCORSMode,
@@ -75,16 +77,17 @@ protected:
   uint32_t InsertRuleInternal(const nsAString& aRule,
                               uint32_t aIndex, ErrorResult& aRv);
   void DeleteRuleInternal(uint32_t aIndex, ErrorResult& aRv);
 
 private:
   void DropSheet();
 
   RefPtr<RawServoStyleSheet> mSheet;
+  RefPtr<ServoCSSRuleList> mRuleList;
   StyleSheetInfo mSheetInfo;
 
   friend class StyleSheet;
 };
 
 } // namespace mozilla
 
 #endif // mozilla_ServoStyleSheet_h
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -91,16 +91,17 @@ EXPORTS.mozilla += [
     'HandleRefPtr.h',
     'IncrementalClearCOMRuleArray.h',
     'LayerAnimationInfo.h',
     'RuleNodeCacheConditions.h',
     'RuleProcessorCache.h',
     'ServoBindingList.h',
     'ServoBindings.h',
     'ServoBindingTypes.h',
+    'ServoCSSRuleList.h',
     'ServoDeclarationBlock.h',
     'ServoElementSnapshot.h',
     'ServoStyleSet.h',
     'ServoStyleSheet.h',
     'ServoTypes.h',
     'ServoUtils.h',
     'SheetType.h',
     'StyleAnimationValue.h',
@@ -191,16 +192,17 @@ UNIFIED_SOURCES += [
     'nsStyleSet.cpp',
     'nsStyleStruct.cpp',
     'nsStyleTransformMatrix.cpp',
     'nsStyleUtil.cpp',
     'nsTransitionManager.cpp',
     'RuleNodeCacheConditions.cpp',
     'RuleProcessorCache.cpp',
     'ServoBindings.cpp',
+    'ServoCSSRuleList.cpp',
     'ServoDeclarationBlock.cpp',
     'ServoElementSnapshot.cpp',
     'ServoStyleSet.cpp',
     'ServoStyleSheet.cpp',
     'StyleAnimationValue.cpp',
     'StyleRule.cpp',
     'StyleSheet.cpp',
     'SVGAttrAnimationRuleProcessor.cpp',