Bug 1307357 part 4 - Add impl class of CSSStyleRule for stylo. r?heycam,manishearth draft
authorXidorn Quan <me@upsuper.org>
Fri, 18 Nov 2016 17:02:03 +1100
changeset 441105 4b1ee8b0a5529db11f315f6765a6f61140a3eeae
parent 441104 5fd53408e83895508cf201283285596a4c4b5117
child 441106 2a2aedd5085b709d0632dd2c17ee3b5e40b91d2d
child 441110 6ed9999655f03ae101eb4524c4c2ff14960b93f1
push id36358
push userxquan@mozilla.com
push dateFri, 18 Nov 2016 11:59:57 +0000
reviewersheycam, manishearth
bugs1307357
milestone53.0a1
Bug 1307357 part 4 - Add impl class of CSSStyleRule for stylo. r?heycam,manishearth MozReview-Commit-ID: CNrvA0HuuL6
layout/style/ServoBindingList.h
layout/style/ServoBindingTypes.h
layout/style/ServoBindings.cpp
layout/style/ServoCSSRuleList.cpp
layout/style/ServoStyleRule.cpp
layout/style/ServoStyleRule.h
layout/style/moz.build
servo/components/style/binding_tools/regen.py
servo/components/style/gecko/conversions.rs
servo/components/style/gecko_bindings/bindings.rs
servo/ports/geckolib/glue.rs
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -50,16 +50,18 @@ SERVO_BINDING_FUNC(Servo_StyleSet_Remove
 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)
+SERVO_BINDING_FUNC(Servo_CssRules_GetStyleRuleAt, RawServoStyleRuleStrong,
+                   ServoCssRulesBorrowed rules, uint32_t index)
 
 // Animations API
 SERVO_BINDING_FUNC(Servo_ParseProperty,
                    RawServoDeclarationBlockStrong,
                    const nsACString* property, const nsACString* value,
                    const nsACString* base_url, ThreadSafeURIHolder* base,
                    ThreadSafeURIHolder* referrer,
                    ThreadSafePrincipalHolder* principal)
--- a/layout/style/ServoBindingTypes.h
+++ b/layout/style/ServoBindingTypes.h
@@ -10,16 +10,17 @@
 #include "mozilla/RefPtr.h"
 #include "mozilla/UniquePtr.h"
 
 struct ServoComputedValues;
 struct ServoCssRules;
 struct RawServoStyleSheet;
 struct RawServoStyleSet;
 struct RawServoDeclarationBlock;
+struct RawServoStyleRule;
 
 namespace mozilla {
 namespace dom {
 class Element;
 class StyleChildrenIterator;
 } // namespace dom
 } // namespace mozilla
 
@@ -71,16 +72,17 @@ typedef nsIDocument RawGeckoDocument;
   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)
+DECL_ARC_REF_TYPE_FOR(RawServoStyleRule)
 // 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)
 DECL_OWNED_REF_TYPE_FOR(StyleChildrenIterator)
 
@@ -122,16 +124,17 @@ DECL_BORROWED_MUT_REF_TYPE_FOR(nsCSSValu
     }                                                \
   };                                                 \
   }
 
 DEFINE_REFPTR_TRAITS(CssRules, ServoCssRules)
 DEFINE_REFPTR_TRAITS(StyleSheet, RawServoStyleSheet)
 DEFINE_REFPTR_TRAITS(ComputedValues, ServoComputedValues)
 DEFINE_REFPTR_TRAITS(DeclarationBlock, RawServoDeclarationBlock)
+DEFINE_REFPTR_TRAITS(StyleRule, RawServoStyleRule)
 
 #undef DEFINE_REFPTR_TRAITS
 
 extern "C" void Servo_StyleSet_Drop(RawServoStyleSetOwned ptr);
 
 namespace mozilla {
 template<>
 class DefaultDelete<RawServoStyleSet>
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -43,16 +43,17 @@ using namespace mozilla::dom;
     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)
+IMPL_STRONG_REF_TYPE_FOR(RawServoStyleRule)
 
 #undef IMPL_STRONG_REF_TYPE_FOR
 
 uint32_t
 Gecko_ChildrenCount(RawGeckoNodeBorrowed aNode)
 {
   return aNode->GetChildCount();
 }
--- a/layout/style/ServoCSSRuleList.cpp
+++ b/layout/style/ServoCSSRuleList.cpp
@@ -4,16 +4,17 @@
  * 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"
+#include "mozilla/ServoStyleRule.h"
 
 namespace mozilla {
 
 ServoCSSRuleList::ServoCSSRuleList(ServoStyleSheet* aStyleSheet,
                                    already_AddRefed<ServoCssRules> aRawRules)
   : mStyleSheet(aStyleSheet)
   , mRawRules(aRawRules)
 {
@@ -30,17 +31,21 @@ ServoCSSRuleList::IndexedGetter(uint32_t
     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::STYLE_RULE: {
+        ruleObj = new ServoStyleRule(
+          Servo_CssRules_GetStyleRuleAt(mRawRules, aIndex).Consume());
+        break;
+      }
       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");
     }
new file mode 100644
--- /dev/null
+++ b/layout/style/ServoStyleRule.cpp
@@ -0,0 +1,114 @@
+/* -*- 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 CSSStyleRule for stylo */
+
+#include "mozilla/ServoStyleRule.h"
+
+#include "nsDOMClassInfoID.h"
+
+namespace mozilla {
+
+// -- ServoStyleRule --------------------------------------------------
+
+// QueryInterface implementation for ServoStyleRule
+NS_INTERFACE_MAP_BEGIN(ServoStyleRule)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMCSSStyleRule)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, css::Rule)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSStyleRule)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_ADDREF(ServoStyleRule)
+NS_IMPL_RELEASE(ServoStyleRule)
+
+already_AddRefed<css::Rule>
+ServoStyleRule::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 ServoStyleRule");
+  return nullptr;
+}
+
+size_t
+ServoStyleRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
+{
+  // TODO Implement this!
+  return aMallocSizeOf(this);
+}
+
+#ifdef DEBUG
+void
+ServoStyleRule::List(FILE* out, int32_t aIndent) const
+{
+  // TODO Implement this!
+}
+#endif
+
+/* CSSRule implementation */
+
+NS_IMETHODIMP
+ServoStyleRule::GetType(uint16_t* aType)
+{
+  *aType = nsIDOMCSSRule::STYLE_RULE;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ServoStyleRule::GetCssText(nsAString& aCssText)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+ServoStyleRule::SetCssText(const nsAString& aCssText)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ServoStyleRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
+{
+  return css::Rule::GetParentStyleSheet(aSheet);
+}
+
+NS_IMETHODIMP
+ServoStyleRule::GetParentRule(nsIDOMCSSRule** aParentRule)
+{
+  *aParentRule = nullptr;
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+css::Rule*
+ServoStyleRule::GetCSSRule()
+{
+  return this;
+}
+
+/* CSSStyleRule implementation */
+
+NS_IMETHODIMP
+ServoStyleRule::GetSelectorText(nsAString& aSelectorText)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+ServoStyleRule::SetSelectorText(const nsAString& aSelectorText)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+ServoStyleRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
+{
+  *aStyle = nullptr;
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/layout/style/ServoStyleRule.h
@@ -0,0 +1,50 @@
+/* -*- 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 CSSStyleRule for stylo */
+
+#ifndef mozilla_ServoStyleRule_h
+#define mozilla_ServoStyleRule_h
+
+#include "mozilla/css/Rule.h"
+#include "mozilla/ServoBindingTypes.h"
+
+#include "nsIDOMCSSStyleRule.h"
+
+namespace mozilla {
+
+class ServoStyleRule final : public css::Rule
+                           , public nsIDOMCSSStyleRule
+{
+public:
+  explicit ServoStyleRule(already_AddRefed<RawServoStyleRule> aRawRule)
+    : css::Rule(0, 0)
+    , mRawRule(aRawRule)
+  {}
+
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIDOMCSSRULE
+  NS_DECL_NSIDOMCSSSTYLERULE
+
+  // Methods of mozilla::css::Rule
+  int32_t GetType() const final { return css::Rule::STYLE_RULE; }
+  already_AddRefed<Rule> Clone() const final;
+  nsIDOMCSSRule* GetDOMRule() final { return this; }
+  nsIDOMCSSRule* GetExistingDOMRule() final { return this; }
+  size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const final;
+#ifdef DEBUG
+  void List(FILE* out = stdout, int32_t aIndent = 0) const final;
+#endif
+
+private:
+  ~ServoStyleRule() {}
+
+  RefPtr<RawServoStyleRule> mRawRule;
+};
+
+} // namespace mozilla
+
+#endif // mozilla_ServoStyleRule_h
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -94,16 +94,17 @@ EXPORTS.mozilla += [
     'RuleNodeCacheConditions.h',
     'RuleProcessorCache.h',
     'ServoBindingList.h',
     'ServoBindings.h',
     'ServoBindingTypes.h',
     'ServoCSSRuleList.h',
     'ServoDeclarationBlock.h',
     'ServoElementSnapshot.h',
+    'ServoStyleRule.h',
     'ServoStyleSet.h',
     'ServoStyleSheet.h',
     'ServoTypes.h',
     'ServoUtils.h',
     'SheetType.h',
     'StyleAnimationValue.h',
     'StyleBackendType.h',
     'StyleComplexColor.h',
@@ -195,16 +196,17 @@ UNIFIED_SOURCES += [
     'nsStyleUtil.cpp',
     'nsTransitionManager.cpp',
     'RuleNodeCacheConditions.cpp',
     'RuleProcessorCache.cpp',
     'ServoBindings.cpp',
     'ServoCSSRuleList.cpp',
     'ServoDeclarationBlock.cpp',
     'ServoElementSnapshot.cpp',
+    'ServoStyleRule.cpp',
     'ServoStyleSet.cpp',
     'ServoStyleSheet.cpp',
     'StyleAnimationValue.cpp',
     'StyleRule.cpp',
     'StyleSheet.cpp',
     'SVGAttrAnimationRuleProcessor.cpp',
 ]
 
--- a/servo/components/style/binding_tools/regen.py
+++ b/servo/components/style/binding_tools/regen.py
@@ -328,17 +328,18 @@ COMPILATION_TARGETS = {
         ],
         "array_types": {
             "uintptr_t": "usize",
         },
         "servo_nullable_arc_types": [
             "ServoComputedValues",
             "ServoCssRules",
             "RawServoStyleSheet",
-            "RawServoDeclarationBlock"
+            "RawServoDeclarationBlock",
+            "RawServoStyleRule",
         ],
         "servo_owned_types": [
             "RawServoStyleSet",
             "StyleChildrenIterator",
         ],
         "servo_immutable_borrow_types": [
             "RawGeckoNode",
             "RawGeckoElement",
--- a/servo/components/style/gecko/conversions.rs
+++ b/servo/components/style/gecko/conversions.rs
@@ -6,23 +6,24 @@
 //! Ideally, it would be in geckolib itself, but coherence
 //! forces us to keep the traits and implementations here
 
 #![allow(unsafe_code)]
 
 use app_units::Au;
 use gecko::values::{convert_rgba_to_nscolor, StyleCoordHelpers};
 use gecko_bindings::bindings::{Gecko_CreateGradient, Gecko_SetGradientImageValue, Gecko_SetUrlImageValue};
-use gecko_bindings::bindings::{RawServoStyleSheet, RawServoDeclarationBlock, ServoComputedValues, ServoCssRules};
+use gecko_bindings::bindings::{RawServoStyleSheet, RawServoDeclarationBlock, RawServoStyleRule};
+use gecko_bindings::bindings::{ServoComputedValues, ServoCssRules};
 use gecko_bindings::structs::{nsStyleCoord_CalcValue, nsStyleImage};
 use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordDataMut};
 use gecko_bindings::sugar::ownership::{HasArcFFI, HasFFI};
 use parking_lot::RwLock;
 use properties::{ComputedValues, PropertyDeclarationBlock};
-use stylesheets::{CssRule, Stylesheet};
+use stylesheets::{CssRule, Stylesheet, StyleRule};
 use values::computed::{CalcLengthOrPercentage, Gradient, Image, LengthOrPercentage, LengthOrPercentageOrAuto};
 
 unsafe impl HasFFI for Stylesheet {
     type FFIType = RawServoStyleSheet;
 }
 unsafe impl HasArcFFI for Stylesheet {}
 unsafe impl HasFFI for ComputedValues {
     type FFIType = ServoComputedValues;
@@ -34,16 +35,21 @@ unsafe impl HasFFI for RwLock<PropertyDe
 }
 unsafe impl HasArcFFI for RwLock<PropertyDeclarationBlock> {}
 
 unsafe impl HasFFI for RwLock<Vec<CssRule>> {
     type FFIType = ServoCssRules;
 }
 unsafe impl HasArcFFI for RwLock<Vec<CssRule>> {}
 
+unsafe impl HasFFI for RwLock<StyleRule> {
+    type FFIType = RawServoStyleRule;
+}
+unsafe impl HasArcFFI for RwLock<StyleRule> {}
+
 impl From<CalcLengthOrPercentage> for nsStyleCoord_CalcValue {
     fn from(other: CalcLengthOrPercentage) -> nsStyleCoord_CalcValue {
         let has_percentage = other.percentage.is_some();
         nsStyleCoord_CalcValue {
             mLength: other.length.0,
             mPercent: other.percentage.unwrap_or(0.0),
             mHasPercent: has_percentage,
         }
--- a/servo/components/style/gecko_bindings/bindings.rs
+++ b/servo/components/style/gecko_bindings/bindings.rs
@@ -19,16 +19,21 @@ pub type RawServoStyleSheetBorrowedOrNul
 pub type RawServoStyleSheetBorrowed<'a> = &'a RawServoStyleSheet;
 enum RawServoStyleSheetVoid{ }
 pub struct RawServoStyleSheet(RawServoStyleSheetVoid);
 pub type RawServoDeclarationBlockStrong = ::gecko_bindings::sugar::ownership::Strong<RawServoDeclarationBlock>;
 pub type RawServoDeclarationBlockBorrowedOrNull<'a> = Option<&'a RawServoDeclarationBlock>;
 pub type RawServoDeclarationBlockBorrowed<'a> = &'a RawServoDeclarationBlock;
 enum RawServoDeclarationBlockVoid{ }
 pub struct RawServoDeclarationBlock(RawServoDeclarationBlockVoid);
+pub type RawServoStyleRuleStrong = ::gecko_bindings::sugar::ownership::Strong<RawServoStyleRule>;
+pub type RawServoStyleRuleBorrowedOrNull<'a> = Option<&'a RawServoStyleRule>;
+pub type RawServoStyleRuleBorrowed<'a> = &'a RawServoStyleRule;
+enum RawServoStyleRuleVoid{ }
+pub struct RawServoStyleRule(RawServoStyleRuleVoid);
 pub type RawGeckoNodeBorrowed<'a> = &'a RawGeckoNode;
 pub type RawGeckoNodeBorrowedOrNull<'a> = Option<&'a RawGeckoNode>;
 pub type RawGeckoElementBorrowed<'a> = &'a RawGeckoElement;
 pub type RawGeckoElementBorrowedOrNull<'a> = Option<&'a RawGeckoElement>;
 pub type RawGeckoDocumentBorrowed<'a> = &'a RawGeckoDocument;
 pub type RawGeckoDocumentBorrowedOrNull<'a> = Option<&'a RawGeckoDocument>;
 pub type RawServoDeclarationBlockStrongBorrowed<'a> = &'a RawServoDeclarationBlockStrong;
 pub type RawServoDeclarationBlockStrongBorrowedOrNull<'a> = Option<&'a RawServoDeclarationBlockStrong>;
@@ -215,16 +220,22 @@ extern "C" {
     pub fn Servo_DeclarationBlock_AddRef(ptr:
                                              RawServoDeclarationBlockBorrowed);
 }
 extern "C" {
     pub fn Servo_DeclarationBlock_Release(ptr:
                                               RawServoDeclarationBlockBorrowed);
 }
 extern "C" {
+    pub fn Servo_StyleRule_AddRef(ptr: RawServoStyleRuleBorrowed);
+}
+extern "C" {
+    pub fn Servo_StyleRule_Release(ptr: RawServoStyleRuleBorrowed);
+}
+extern "C" {
     pub fn Servo_StyleSet_Drop(ptr: RawServoStyleSetOwned);
 }
 extern "C" {
     pub fn Gecko_EnsureTArrayCapacity(aArray: *mut ::std::os::raw::c_void,
                                       aCapacity: usize, aElementSize: usize);
 }
 extern "C" {
     pub fn Gecko_ClearPODTArray(aArray: *mut ::std::os::raw::c_void,
@@ -946,16 +957,21 @@ extern "C" {
     pub fn Servo_StyleSheet_HasRules(sheet: RawServoStyleSheetBorrowed)
      -> bool;
 }
 extern "C" {
     pub fn Servo_StyleSheet_GetRules(sheet: RawServoStyleSheetBorrowed)
      -> ServoCssRulesStrong;
 }
 extern "C" {
+    pub fn Servo_StyleSheet_GetStyleRuleAt(sheet: RawServoStyleSheetBorrowed,
+                                           index: u32)
+     -> RawServoStyleRuleStrong;
+}
+extern "C" {
     pub fn Servo_StyleSet_Init() -> RawServoStyleSetOwned;
 }
 extern "C" {
     pub fn Servo_StyleSet_AppendStyleSheet(set: RawServoStyleSetBorrowed,
                                            sheet: RawServoStyleSheetBorrowed);
 }
 extern "C" {
     pub fn Servo_StyleSet_PrependStyleSheet(set: RawServoStyleSetBorrowed,
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -17,16 +17,17 @@ use style::error_reporting::StdoutErrorR
 use style::gecko::data::{NUM_THREADS, PerDocumentStyleData};
 use style::gecko::selector_impl::{GeckoSelectorImpl, PseudoElement};
 use style::gecko::snapshot::GeckoElementSnapshot;
 use style::gecko::traversal::RecalcStyleOnly;
 use style::gecko::wrapper::{GeckoElement, GeckoNode};
 use style::gecko::wrapper::DUMMY_BASE_URL;
 use style::gecko_bindings::bindings::{RawGeckoElementBorrowed, RawGeckoNodeBorrowed};
 use style::gecko_bindings::bindings::{RawServoDeclarationBlockBorrowed, RawServoDeclarationBlockStrong};
+use style::gecko_bindings::bindings::{RawServoStyleRuleBorrowed, RawServoStyleRuleStrong};
 use style::gecko_bindings::bindings::{RawServoStyleSetBorrowed, RawServoStyleSetOwned};
 use style::gecko_bindings::bindings::{RawServoStyleSheetBorrowed, ServoComputedValuesBorrowed};
 use style::gecko_bindings::bindings::{RawServoStyleSheetStrong, ServoComputedValuesStrong};
 use style::gecko_bindings::bindings::{ServoCssRulesBorrowed, ServoCssRulesStrong};
 use style::gecko_bindings::bindings::{ThreadSafePrincipalHolder, ThreadSafeURIHolder};
 use style::gecko_bindings::bindings::{nsACString, nsAString};
 use style::gecko_bindings::bindings::Gecko_Utf8SliceToString;
 use style::gecko_bindings::bindings::ServoComputedValuesBorrowedOrNull;
@@ -41,17 +42,17 @@ use style::gecko_bindings::sugar::refptr
 use style::parallel;
 use style::parser::{ParserContext, ParserContextExtraData};
 use style::properties::{CascadeFlags, ComputedValues, Importance, PropertyDeclaration};
 use style::properties::{PropertyDeclarationParseResult, PropertyDeclarationBlock};
 use style::properties::{apply_declarations, parse_one_declaration};
 use style::selector_impl::PseudoElementCascadeType;
 use style::sequential;
 use style::string_cache::Atom;
-use style::stylesheets::{CssRule, Origin, Stylesheet};
+use style::stylesheets::{CssRule, Origin, Stylesheet, StyleRule};
 use style::timer::Timer;
 use style_traits::ToCss;
 use url::Url;
 
 /*
  * For Gecko->Servo function calls, we need to redeclare the same signature that was declared in
  * the C header in Gecko. In order to catch accidental mismatches, we run rust-bindgen against
  * those signatures as well, giving us a second declaration of all the Servo_* functions in this
@@ -282,26 +283,48 @@ pub extern "C" fn Servo_CssRules_ListTyp
     let iter = rules.iter().map(|rule| rule.rule_type() as usize);
     let (size, upper) = iter.size_hint();
     debug_assert_eq!(size, upper.unwrap());
     unsafe { result.set_len(size as u32) };
     result.iter_mut().zip(iter).fold((), |_, (r, v)| *r = v);
 }
 
 #[no_mangle]
+pub extern "C" fn Servo_CssRules_GetStyleRuleAt(rules: ServoCssRulesBorrowed, index: u32)
+                                                -> RawServoStyleRuleStrong {
+    let rules = RwLock::<Vec<CssRule>>::as_arc(&rules).read();
+    match rules[index as usize] {
+        CssRule::Style(ref rule) => rule.clone().into_strong(),
+        _ => {
+            unreachable!("GetStyleRuleAt should only be called on a style rule");
+        }
+    }
+}
+
+#[no_mangle]
 pub extern "C" fn Servo_CssRules_AddRef(rules: ServoCssRulesBorrowed) -> () {
     unsafe { RwLock::<Vec<CssRule>>::addref(rules) };
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_CssRules_Release(rules: ServoCssRulesBorrowed) -> () {
     unsafe { RwLock::<Vec<CssRule>>::release(rules) };
 }
 
 #[no_mangle]
+pub extern "C" fn Servo_StyleRule_AddRef(rule: RawServoStyleRuleBorrowed) -> () {
+    unsafe { RwLock::<StyleRule>::addref(rule) };
+}
+
+#[no_mangle]
+pub extern "C" fn Servo_StyleRule_Release(rule: RawServoStyleRuleBorrowed) -> () {
+    unsafe { RwLock::<StyleRule>::release(rule) };
+}
+
+#[no_mangle]
 pub extern "C" fn Servo_ComputedValues_Get(node: RawGeckoNodeBorrowed)
      -> ServoComputedValuesStrong {
     let node = GeckoNode(node);
 
     // Gecko erroneously calls this function from ServoRestyleManager::RecreateStyleContexts.
     // We plan to fix that, but just support it for now until that code gets rewritten.
     if node.is_text_node() {
         error!("Don't call Servo_ComputedValue_Get() for text nodes");