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 368850 2ba29077a23e4fbbc79bbf54efb2c1a563056295
parent 368849 7a9d6a3cdf1a68952f8fb88a0999db1f9486b921
child 368851 31fdda2f930d856d0786563d5ea1a3e8a6d076b4
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam, manishearth
bugs1307357
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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',