Bug 1449068 part 2 - Use Servo data to back @counter-style rule. r=emilio
authorXidorn Quan <me@upsuper.org>
Thu, 05 Apr 2018 08:41:28 +1000
changeset 411762 fe4da1136b505b0d918348e92cc7f5fc12d02108
parent 411761 3511b66ee3355f9ffa6ae263f9b85e8e64a208ac
child 411763 682e5bf710fc0c36c2b9a122dc45be7179aaddb0
push id33770
push usernerli@mozilla.com
push dateThu, 05 Apr 2018 10:01:08 +0000
treeherdermozilla-central@65e0fefdab51 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
bugs1449068
milestone61.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 1449068 part 2 - Use Servo data to back @counter-style rule. r=emilio This patch basically does: * Add descriptor setters and generation count to CounterStyleRule in Servo. (This code is mostly based on the old code inside nsCSSCounterStyleRule for handling mutation.) * Use RawServoCounterStyleRule in CounterStyleManager. * Add ServoCounterStyleRule and remove nsCSSCounterStyleRule. Test change: * "fixed" was parsed as and thus serialized to "fixed 1", but Servo doesn't do so. It preserves whether the number presents. Either way is probably fine. MozReview-Commit-ID: EtKTeu32isi
dom/bindings/Bindings.conf
layout/style/CounterStyleManager.cpp
layout/style/ServoArcTypeList.h
layout/style/ServoBindingList.h
layout/style/ServoBindings.cpp
layout/style/ServoBindings.h
layout/style/ServoBindings.toml
layout/style/ServoCSSParser.cpp
layout/style/ServoCSSParser.h
layout/style/ServoCSSRuleList.cpp
layout/style/ServoCounterStyleRule.cpp
layout/style/ServoCounterStyleRule.h
layout/style/ServoStyleSet.cpp
layout/style/ServoStyleSet.h
layout/style/moz.build
layout/style/nsCSSCounterStyleRule.cpp
layout/style/nsCSSCounterStyleRule.h
layout/style/test/test_counter_descriptor_storage.html
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -177,18 +177,18 @@ DOMInterfaces = {
 
 'CSSConditionRule': {
     'concrete': False,
     'nativeType': 'mozilla::css::ConditionRule',
     'headerFile': 'mozilla/css/GroupRule.h',
 },
 
 'CSSCounterStyleRule': {
-    'nativeType': 'nsCSSCounterStyleRule',
-    'headerFile': 'nsCSSCounterStyleRule.h',
+    'nativeType': 'mozilla::ServoCounterStyleRule',
+    'headerFile': 'mozilla/ServoCounterStyleRule.h',
 },
 
 'CSSFontFaceRule': {
     'nativeType': 'mozilla::ServoFontFaceRule',
     'headerFile': 'mozilla/ServoFontFaceRule.h',
 },
 
 'CSSGroupingRule': {
--- a/layout/style/CounterStyleManager.cpp
+++ b/layout/style/CounterStyleManager.cpp
@@ -7,21 +7,21 @@
 #include "CounterStyleManager.h"
 
 #include "mozilla/ArenaObjectID.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/Types.h"
 #include "mozilla/WritingModes.h"
-#include "nsCSSCounterStyleRule.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsTHashtable.h"
 #include "nsUnicodeProperties.h"
+#include "mozilla/ServoBindings.h"
 #include "mozilla/ServoStyleSet.h"
 
 namespace mozilla {
 
 struct AdditiveSymbol
 {
   CounterValue weight;
   nsString symbol;
@@ -1025,23 +1025,23 @@ DependentBuiltinCounterStyle::GetFallbac
   }
 }
 
 class CustomCounterStyle final : public CounterStyle
 {
 public:
   CustomCounterStyle(nsAtom* aName,
                      CounterStyleManager* aManager,
-                     nsCSSCounterStyleRule* aRule)
+                     const RawServoCounterStyleRule* aRule)
     : CounterStyle(NS_STYLE_LIST_STYLE_CUSTOM),
       mName(aName),
       mManager(aManager),
       mRule(aRule),
-      mRuleGeneration(aRule->GetGeneration()),
-      mSystem(aRule->GetSystem()),
+      mRuleGeneration(Servo_CounterStyleRule_GetGeneration(aRule)),
+      mSystem(Servo_CounterStyleRule_GetSystem(aRule)),
       mFlags(0),
       mFallback(nullptr),
       mSpeakAsCounter(nullptr),
       mExtends(nullptr),
       mExtendsRoot(nullptr)
   {
   }
 
@@ -1052,17 +1052,17 @@ public:
 
   // This method will reset all cached data which may depend on other
   // counter style. It will reset all pointers to other counter styles.
   // For counter style extends other, in addition, all fields will be
   // reset to uninitialized state. This method should be called when any
   // other counter style is added, removed, or changed.
   void ResetDependentData();
 
-  nsCSSCounterStyleRule* GetRule() const { return mRule; }
+  const RawServoCounterStyleRule* GetRule() const { return mRule; }
   uint32_t GetRuleGeneration() const { return mRuleGeneration; }
 
   virtual nsAtom* GetStyleName() const override;
   virtual void GetPrefix(nsAString& aResult) override;
   virtual void GetSuffix(nsAString& aResult) override;
   virtual void GetSpokenCounterText(CounterValue aOrdinal,
                                     WritingMode aWritingMode,
                                     nsAString& aResult,
@@ -1102,16 +1102,23 @@ public:
     nsIPresShell* shell = mManager->PresContext()->PresShell();
     this->~CustomCounterStyle();
     shell->FreeByObjectID(eArenaObjectID_CustomCounterStyle, this);
   }
 
 private:
   ~CustomCounterStyle() {}
 
+  nsCSSValue GetDesc(nsCSSCounterDesc aDesc) const
+  {
+    nsCSSValue value;
+    Servo_CounterStyleRule_GetDescriptor(mRule, aDesc, &value);
+    return value;
+  }
+
   const nsTArray<nsString>& GetSymbols();
   const nsTArray<AdditiveSymbol>& GetAdditiveSymbols();
 
   // The speak-as values of counter styles may form a loop, and the
   // loops may have complex interaction with the loop formed by
   // extending. To solve this problem, the computation of speak-as is
   // divided into two phases:
   // 1. figure out the raw value, by ComputeRawSpeakAs, and
@@ -1128,17 +1135,17 @@ private:
 
   RefPtr<nsAtom> mName;
 
   // CounterStyleManager should always overlive any CounterStyle as it
   // is owned by nsPresContext, and will be released after all nodes and
   // frames are released.
   CounterStyleManager* mManager;
 
-  RefPtr<nsCSSCounterStyleRule> mRule;
+  RefPtr<const RawServoCounterStyleRule> mRule;
   uint32_t mRuleGeneration;
 
   uint8_t mSystem;
   // GetSpeakAs will ensure that private member mSpeakAs is initialized before used
   MOZ_INIT_OUTSIDE_CTOR uint8_t mSpeakAs;
 
   enum {
     // loop detection
@@ -1193,17 +1200,17 @@ CustomCounterStyle::ResetCachedData()
               FLAG_PREFIX_INITED |
               FLAG_SUFFIX_INITED |
               FLAG_PAD_INITED |
               FLAG_SPEAKAS_INITED);
   mFallback = nullptr;
   mSpeakAsCounter = nullptr;
   mExtends = nullptr;
   mExtendsRoot = nullptr;
-  mRuleGeneration = mRule->GetGeneration();
+  mRuleGeneration = Servo_CounterStyleRule_GetGeneration(mRule);
 }
 
 void
 CustomCounterStyle::ResetDependentData()
 {
   mFlags &= ~FLAG_SPEAKAS_INITED;
   mSpeakAsCounter = nullptr;
   mFallback = nullptr;
@@ -1224,17 +1231,17 @@ CustomCounterStyle::GetStyleName() const
 }
 
 /* virtual */ void
 CustomCounterStyle::GetPrefix(nsAString& aResult)
 {
   if (!(mFlags & FLAG_PREFIX_INITED)) {
     mFlags |= FLAG_PREFIX_INITED;
 
-    const nsCSSValue& value = mRule->GetDesc(eCSSCounterDesc_Prefix);
+    nsCSSValue value = GetDesc(eCSSCounterDesc_Prefix);
     if (value.UnitHasStringValue()) {
       value.GetStringValue(mPrefix);
     } else if (IsExtendsSystem()) {
       GetExtends()->GetPrefix(mPrefix);
     } else {
       mPrefix.Truncate();
     }
   }
@@ -1242,17 +1249,17 @@ CustomCounterStyle::GetPrefix(nsAString&
 }
 
 /* virtual */ void
 CustomCounterStyle::GetSuffix(nsAString& aResult)
 {
   if (!(mFlags & FLAG_SUFFIX_INITED)) {
     mFlags |= FLAG_SUFFIX_INITED;
 
-    const nsCSSValue& value = mRule->GetDesc(eCSSCounterDesc_Suffix);
+    nsCSSValue value = GetDesc(eCSSCounterDesc_Suffix);
     if (value.UnitHasStringValue()) {
       value.GetStringValue(mSuffix);
     } else if (IsExtendsSystem()) {
       GetExtends()->GetSuffix(mSuffix);
     } else {
       mSuffix.AssignLiteral(u". ");
     }
   }
@@ -1290,17 +1297,17 @@ CustomCounterStyle::IsBullet()
   }
 }
 
 /* virtual */ void
 CustomCounterStyle::GetNegative(NegativeType& aResult)
 {
   if (!(mFlags & FLAG_NEGATIVE_INITED)) {
     mFlags |= FLAG_NEGATIVE_INITED;
-    const nsCSSValue& value = mRule->GetDesc(eCSSCounterDesc_Negative);
+    nsCSSValue value = GetDesc(eCSSCounterDesc_Negative);
     switch (value.GetUnit()) {
       case eCSSUnit_Ident:
       case eCSSUnit_String:
         value.GetStringValue(mNegative.before);
         mNegative.after.Truncate();
         break;
       case eCSSUnit_Pair: {
         const nsCSSValuePair& pair = value.GetPairValue();
@@ -1326,17 +1333,17 @@ IsRangeValueInfinite(const nsCSSValue& a
 {
   return aValue.GetUnit() == eCSSUnit_Enumerated &&
          aValue.GetIntValue() == NS_STYLE_COUNTER_RANGE_INFINITE;
 }
 
 /* virtual */ bool
 CustomCounterStyle::IsOrdinalInRange(CounterValue aOrdinal)
 {
-  const nsCSSValue& value = mRule->GetDesc(eCSSCounterDesc_Range);
+  nsCSSValue value = GetDesc(eCSSCounterDesc_Range);
   if (value.GetUnit() == eCSSUnit_PairList) {
     for (const nsCSSValuePairList* item = value.GetPairListValue();
          item != nullptr; item = item->mNext) {
       const nsCSSValue& lowerBound = item->mXValue;
       const nsCSSValue& upperBound = item->mYValue;
       if ((IsRangeValueInfinite(lowerBound) ||
            aOrdinal >= lowerBound.GetIntValue()) &&
           (IsRangeValueInfinite(upperBound) ||
@@ -1373,17 +1380,17 @@ CustomCounterStyle::IsOrdinalInAutoRange
   }
 }
 
 /* virtual */ void
 CustomCounterStyle::GetPad(PadType& aResult)
 {
   if (!(mFlags & FLAG_PAD_INITED)) {
     mFlags |= FLAG_PAD_INITED;
-    const nsCSSValue& value = mRule->GetDesc(eCSSCounterDesc_Pad);
+    nsCSSValue value = GetDesc(eCSSCounterDesc_Pad);
     if (value.GetUnit() == eCSSUnit_Pair) {
       const nsCSSValuePair& pair = value.GetPairValue();
       mPad.width = pair.mXValue.GetIntValue();
       pair.mYValue.GetStringValue(mPad.symbol);
     } else if (IsExtendsSystem()) {
       GetExtends()->GetPad(mPad);
     } else {
       mPad.width = 0;
@@ -1392,24 +1399,19 @@ CustomCounterStyle::GetPad(PadType& aRes
   }
   aResult = mPad;
 }
 
 /* virtual */ CounterStyle*
 CustomCounterStyle::GetFallback()
 {
   if (!mFallback) {
-    const nsCSSValue& value = mRule->GetDesc(eCSSCounterDesc_Fallback);
     mFallback = CounterStyleManager::GetDecimalStyle();
-    if (value.GetUnit() != eCSSUnit_Null) {
-      if (value.GetUnit() == eCSSUnit_AtomIdent) {
-        mFallback = mManager->BuildCounterStyle(value.GetAtomValue());
-      } else {
-        MOZ_ASSERT_UNREACHABLE("Unknown unit!");
-      }
+    if (nsAtom* fallback = Servo_CounterStyleRule_GetFallback(mRule)) {
+      mFallback = mManager->BuildCounterStyle(fallback);
     } else if (IsExtendsSystem()) {
       mFallback = GetExtends()->GetFallback();
     }
   }
   return mFallback;
 }
 
 /* virtual */ uint8_t
@@ -1449,17 +1451,17 @@ CustomCounterStyle::GetInitialCounterTex
                                           WritingMode aWritingMode,
                                           nsAString& aResult,
                                           bool& aIsRTL)
 {
   switch (mSystem) {
     case NS_STYLE_COUNTER_SYSTEM_CYCLIC:
       return GetCyclicCounterText(aOrdinal, aResult, GetSymbols());
     case NS_STYLE_COUNTER_SYSTEM_FIXED: {
-      int32_t start = mRule->GetSystemArgument().GetIntValue();
+      int32_t start = Servo_CounterStyleRule_GetFixedFirstValue(mRule);
       return GetFixedCounterText(aOrdinal, aResult, start, GetSymbols());
     }
     case NS_STYLE_COUNTER_SYSTEM_SYMBOLIC:
       return GetSymbolicCounterText(aOrdinal, aResult, GetSymbols());
     case NS_STYLE_COUNTER_SYSTEM_ALPHABETIC:
       return GetAlphabeticCounterText(aOrdinal, aResult, GetSymbols());
     case NS_STYLE_COUNTER_SYSTEM_NUMERIC:
       return GetNumericCounterText(aOrdinal, aResult, GetSymbols());
@@ -1473,32 +1475,32 @@ CustomCounterStyle::GetInitialCounterTex
       return false;
   }
 }
 
 const nsTArray<nsString>&
 CustomCounterStyle::GetSymbols()
 {
   if (mSymbols.IsEmpty()) {
-    const nsCSSValue& values = mRule->GetDesc(eCSSCounterDesc_Symbols);
+    nsCSSValue values = GetDesc(eCSSCounterDesc_Symbols);
     for (const nsCSSValueList* item = values.GetListValue();
          item; item = item->mNext) {
       nsString* symbol = mSymbols.AppendElement();
       item->mValue.GetStringValue(*symbol);
     }
     mSymbols.Compact();
   }
   return mSymbols;
 }
 
 const nsTArray<AdditiveSymbol>&
 CustomCounterStyle::GetAdditiveSymbols()
 {
   if (mAdditiveSymbols.IsEmpty()) {
-    const nsCSSValue& values = mRule->GetDesc(eCSSCounterDesc_AdditiveSymbols);
+    nsCSSValue values = GetDesc(eCSSCounterDesc_AdditiveSymbols);
     for (const nsCSSValuePairList* item = values.GetPairListValue();
          item; item = item->mNext) {
       AdditiveSymbol* symbol = mAdditiveSymbols.AppendElement();
       symbol->weight = item->mXValue.GetIntValue();
       item->mYValue.GetStringValue(symbol->symbol);
     }
     mAdditiveSymbols.Compact();
   }
@@ -1529,17 +1531,17 @@ CustomCounterStyle::GetSpeakAsAutoValue(
 // fields in the style.)
 void
 CustomCounterStyle::ComputeRawSpeakAs(uint8_t& aSpeakAs,
                                     CounterStyle*& aSpeakAsCounter)
 {
   NS_ASSERTION(!(mFlags & FLAG_SPEAKAS_INITED),
                "ComputeRawSpeakAs is called with speak-as inited.");
 
-  const nsCSSValue& value = mRule->GetDesc(eCSSCounterDesc_SpeakAs);
+  nsCSSValue value = GetDesc(eCSSCounterDesc_SpeakAs);
   switch (value.GetUnit()) {
     case eCSSUnit_Auto:
       aSpeakAs = GetSpeakAsAutoValue();
       break;
     case eCSSUnit_Enumerated:
       aSpeakAs = value.GetIntValue();
       break;
     case eCSSUnit_AtomIdent:
@@ -1645,18 +1647,18 @@ CustomCounterStyle::ComputeExtends()
     return this;
   }
   if (mFlags & FLAG_EXTENDS_VISITED) {
     // loop detected
     mFlags |= FLAG_EXTENDS_LOOP;
     return nullptr;
   }
 
-  const nsCSSValue& value = mRule->GetSystemArgument();
-  CounterStyle* nextCounter = mManager->BuildCounterStyle(value.GetAtomValue());
+  nsAtom* extended = Servo_CounterStyleRule_GetExtended(mRule);
+  CounterStyle* nextCounter = mManager->BuildCounterStyle(extended);
   CounterStyle* target = nextCounter;
   if (nextCounter->IsCustomStyle()) {
     mFlags |= FLAG_EXTENDS_VISITED;
     target = static_cast<CustomCounterStyle*>(nextCounter)->ComputeExtends();
     mFlags &= ~FLAG_EXTENDS_VISITED;
   }
 
   if (target) {
@@ -2030,19 +2032,19 @@ CounterStyleManager::BuildCounterStyle(n
   CounterStyle* data = GetCounterStyle(aName);
   if (data) {
     return data;
   }
 
   // Names are compared case-sensitively here. Predefined names should
   // have been lowercased by the parser.
   ServoStyleSet* styleSet = mPresContext->StyleSet();
-  nsCSSCounterStyleRule* rule = styleSet->CounterStyleRuleForName(aName);
+  auto* rule = styleSet->CounterStyleRuleForName(aName);
   if (rule) {
-    MOZ_ASSERT(rule->Name() == aName);
+    MOZ_ASSERT(Servo_CounterStyleRule_GetName(rule) == aName);
     data = new (mPresContext) CustomCounterStyle(aName, this, rule);
   } else {
     for (const BuiltinCounterStyle& item : gBuiltinStyleTable) {
       if (item.GetStyleName() == aName) {
         int32_t style = item.GetStyle();
         data = item.IsDependentStyle()
           ? new (mPresContext) DependentBuiltinCounterStyle(style, this)
           : GetBuiltinStyle(style);
@@ -2081,31 +2083,34 @@ bool
 CounterStyleManager::NotifyRuleChanged()
 {
   bool changed = false;
   for (auto iter = mStyles.Iter(); !iter.Done(); iter.Next()) {
     CounterStyle* style = iter.Data();
     bool toBeUpdated = false;
     bool toBeRemoved = false;
     ServoStyleSet* styleSet = mPresContext->StyleSet();
-    nsCSSCounterStyleRule* newRule = styleSet->CounterStyleRuleForName(iter.Key());
+    auto* newRule = styleSet->CounterStyleRuleForName(iter.Key());
     if (!newRule) {
       if (style->IsCustomStyle()) {
         toBeRemoved = true;
       }
     } else {
       if (!style->IsCustomStyle()) {
         toBeRemoved = true;
       } else {
         auto custom = static_cast<CustomCounterStyle*>(style);
         if (custom->GetRule() != newRule) {
           toBeRemoved = true;
-        } else if (custom->GetRuleGeneration() != newRule->GetGeneration()) {
-          toBeUpdated = true;
-          custom->ResetCachedData();
+        } else {
+          auto generation = Servo_CounterStyleRule_GetGeneration(newRule);
+          if (custom->GetRuleGeneration() != generation) {
+            toBeUpdated = true;
+            custom->ResetCachedData();
+          }
         }
       }
     }
     changed = changed || toBeUpdated || toBeRemoved;
     if (toBeRemoved) {
       if (style->IsDependentStyle()) {
         // Add object to retired list so we can clean them up later.
         mRetiredStyles.AppendElement(style);
--- a/layout/style/ServoArcTypeList.h
+++ b/layout/style/ServoArcTypeList.h
@@ -18,8 +18,9 @@ SERVO_ARC_TYPE(MediaList, RawServoMediaL
 SERVO_ARC_TYPE(MediaRule, RawServoMediaRule)
 SERVO_ARC_TYPE(NamespaceRule, RawServoNamespaceRule)
 SERVO_ARC_TYPE(PageRule, RawServoPageRule)
 SERVO_ARC_TYPE(SupportsRule, RawServoSupportsRule)
 SERVO_ARC_TYPE(DocumentRule, RawServoDocumentRule)
 SERVO_ARC_TYPE(FontFeatureValuesRule, RawServoFontFeatureValuesRule)
 SERVO_ARC_TYPE(RuleNode, RawServoRuleNode)
 SERVO_ARC_TYPE(FontFaceRule, RawServoFontFaceRule)
+SERVO_ARC_TYPE(CounterStyleRule, RawServoCounterStyleRule)
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -126,17 +126,18 @@ SERVO_BINDING_FUNC(Servo_StyleSet_NoteSt
 SERVO_BINDING_FUNC(Servo_StyleSet_GetKeyframesForName, bool,
                    RawServoStyleSetBorrowed set,
                    nsAtom* name,
                    nsTimingFunctionBorrowed timing_function,
                    RawGeckoKeyframeListBorrowedMut keyframe_list)
 SERVO_BINDING_FUNC(Servo_StyleSet_GetFontFaceRules, void,
                    RawServoStyleSetBorrowed set,
                    RawGeckoFontFaceRuleListBorrowedMut list)
-SERVO_BINDING_FUNC(Servo_StyleSet_GetCounterStyleRule, nsCSSCounterStyleRule*,
+SERVO_BINDING_FUNC(Servo_StyleSet_GetCounterStyleRule,
+                   const RawServoCounterStyleRule*,
                    RawServoStyleSetBorrowed set, nsAtom* name)
 // This function may return nullptr or gfxFontFeatureValueSet with zero reference.
 SERVO_BINDING_FUNC(Servo_StyleSet_BuildFontFeatureValueSet,
                    gfxFontFeatureValueSet*,
                    RawServoStyleSetBorrowed set)
 SERVO_BINDING_FUNC(Servo_StyleSet_ResolveForDeclarations,
                    ComputedStyleStrong,
                    RawServoStyleSetBorrowed set,
@@ -258,21 +259,20 @@ BASIC_RULE_FUNCS_WITHOUT_GETTER(Keyframe
 BASIC_RULE_FUNCS(Keyframes)
 GROUP_RULE_FUNCS(Media)
 BASIC_RULE_FUNCS(Namespace)
 BASIC_RULE_FUNCS(Page)
 GROUP_RULE_FUNCS(Supports)
 GROUP_RULE_FUNCS(Document)
 BASIC_RULE_FUNCS(FontFeatureValues)
 BASIC_RULE_FUNCS(FontFace)
+BASIC_RULE_FUNCS(CounterStyle)
 #undef GROUP_RULE_FUNCS
 #undef BASIC_RULE_FUNCS
 #undef BASIC_RULE_FUNCS_WITHOUT_GETTER
-SERVO_BINDING_FUNC(Servo_CssRules_GetCounterStyleRuleAt, nsCSSCounterStyleRule*,
-                   ServoCssRulesBorrowed rules, uint32_t index)
 SERVO_BINDING_FUNC(Servo_StyleRule_GetStyle, RawServoDeclarationBlockStrong,
                    RawServoStyleRuleBorrowed rule)
 SERVO_BINDING_FUNC(Servo_StyleRule_SetStyle, void,
                    RawServoStyleRuleBorrowed rule,
                    RawServoDeclarationBlockBorrowed declarations)
 SERVO_BINDING_FUNC(Servo_StyleRule_GetSelectorText, void,
                    RawServoStyleRuleBorrowed rule, nsAString* result)
 SERVO_BINDING_FUNC(Servo_StyleRule_GetSelectorTextAtIndex, void,
@@ -362,16 +362,40 @@ SERVO_BINDING_FUNC(Servo_FontFaceRule_Ge
                    nsCSSFontDesc desc, nsAString* result)
 SERVO_BINDING_FUNC(Servo_FontFaceRule_SetDescriptor, bool,
                    RawServoFontFaceRuleBorrowed rule,
                    nsCSSFontDesc desc, const nsACString* value,
                    RawGeckoURLExtraData* data)
 SERVO_BINDING_FUNC(Servo_FontFaceRule_ResetDescriptor, void,
                    RawServoFontFaceRuleBorrowed rule,
                    nsCSSFontDesc desc)
+SERVO_BINDING_FUNC(Servo_CounterStyleRule_GetName, nsAtom*,
+                   RawServoCounterStyleRuleBorrowed rule)
+SERVO_BINDING_FUNC(Servo_CounterStyleRule_SetName, bool,
+                   RawServoCounterStyleRuleBorrowed rule,
+                   const nsACString* name)
+SERVO_BINDING_FUNC(Servo_CounterStyleRule_GetGeneration, uint32_t,
+                   RawServoCounterStyleRuleBorrowed rule)
+SERVO_BINDING_FUNC(Servo_CounterStyleRule_GetSystem, uint8_t,
+                   RawServoCounterStyleRuleBorrowed rule)
+SERVO_BINDING_FUNC(Servo_CounterStyleRule_GetExtended, nsAtom*,
+                   RawServoCounterStyleRuleBorrowed rule)
+SERVO_BINDING_FUNC(Servo_CounterStyleRule_GetFixedFirstValue, int32_t,
+                   RawServoCounterStyleRuleBorrowed rule)
+SERVO_BINDING_FUNC(Servo_CounterStyleRule_GetFallback, nsAtom*,
+                   RawServoCounterStyleRuleBorrowed rule)
+SERVO_BINDING_FUNC(Servo_CounterStyleRule_GetDescriptor, void,
+                   RawServoCounterStyleRuleBorrowed rule,
+                   nsCSSCounterDesc desc, nsCSSValueBorrowedMut result)
+SERVO_BINDING_FUNC(Servo_CounterStyleRule_GetDescriptorCssText, void,
+                   RawServoCounterStyleRuleBorrowed rule,
+                   nsCSSCounterDesc desc, nsAString* result)
+SERVO_BINDING_FUNC(Servo_CounterStyleRule_SetDescriptor, bool,
+                   RawServoCounterStyleRuleBorrowed rule,
+                   nsCSSCounterDesc desc, const nsACString* value)
 
 // Animations API
 SERVO_BINDING_FUNC(Servo_ParseProperty,
                    RawServoDeclarationBlockStrong,
                    nsCSSPropertyID property, const nsACString* value,
                    RawGeckoURLExtraData* data,
                    mozilla::ParsingMode parsing_mode,
                    nsCompatibility quirks_mode,
@@ -817,23 +841,16 @@ SERVO_BINDING_FUNC(Servo_ParseIntersecti
                    nsCSSRect* result);
 // Returning false means the parsed transform contains relative lengths or
 // percentage value, so we cannot compute the matrix. In this case, we keep
 // |result| and |contains_3d_transform| as-is.
 SERVO_BINDING_FUNC(Servo_ParseTransformIntoMatrix, bool,
                    const nsAString* value,
                    bool* contains_3d_transform,
                    RawGeckoGfxMatrix4x4* result);
-SERVO_BINDING_FUNC(Servo_ParseCounterStyleName, nsAtom*,
-                   const nsACString* value);
-SERVO_BINDING_FUNC(Servo_ParseCounterStyleDescriptor, bool,
-                   nsCSSCounterDesc aDescriptor,
-                   const nsACString* aValue,
-                   RawGeckoURLExtraData* aURLExtraData,
-                   nsCSSValue* aResult);
 SERVO_BINDING_FUNC(Servo_ParseFontShorthandForMatching, bool,
                    const nsAString* value,
                    RawGeckoURLExtraData* data,
                    RefPtr<SharedFontList>* family,
                    nsCSSValueBorrowedMut style,
                    nsCSSValueBorrowedMut stretch,
                    nsCSSValueBorrowedMut weight);
 
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -8,17 +8,16 @@
 
 #include "ChildIterator.h"
 #include "ErrorReporter.h"
 #include "GeckoProfiler.h"
 #include "gfxFontFamilyList.h"
 #include "gfxFontFeatures.h"
 #include "nsAnimationManager.h"
 #include "nsAttrValueInlines.h"
-#include "nsCSSCounterStyleRule.h"
 #include "nsCSSFrameConstructor.h"
 #include "nsCSSProps.h"
 #include "nsCSSParser.h"
 #include "nsCSSPseudoElements.h"
 #include "nsContentUtils.h"
 #include "nsDOMTokenList.h"
 #include "nsDeviceContext.h"
 #include "nsIContentInlines.h"
@@ -2596,40 +2595,16 @@ Gecko_RegisterNamespace(nsAtom* aNamespa
   nsresult rv = nsContentUtils::NameSpaceManager()->RegisterNameSpace(str, id);
 
   if (NS_FAILED(rv)) {
     return -1;
   }
   return id;
 }
 
-nsCSSCounterStyleRule*
-Gecko_CSSCounterStyle_Create(nsAtom* aName)
-{
-  RefPtr<nsCSSCounterStyleRule> rule = new nsCSSCounterStyleRule(aName, 0, 0);
-  return rule.forget().take();
-}
-
-nsCSSCounterStyleRule*
-Gecko_CSSCounterStyle_Clone(const nsCSSCounterStyleRule* aRule)
-{
-  RefPtr<css::Rule> rule = aRule->Clone();
-  return static_cast<nsCSSCounterStyleRule*>(rule.forget().take());
-}
-
-void
-Gecko_CSSCounterStyle_GetCssText(const nsCSSCounterStyleRule* aRule,
-                                 nsAString* aResult)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  aRule->GetCssText(*aResult);
-}
-
-NS_IMPL_FFI_REFCOUNTING(nsCSSCounterStyleRule, CSSCounterStyleRule);
-
 NS_IMPL_THREADSAFE_FFI_REFCOUNTING(nsCSSValueSharedList, CSSValueSharedList);
 
 #define STYLE_STRUCT(name)                                                    \
                                                                               \
 void                                                                          \
 Gecko_Construct_Default_nsStyle##name(nsStyle##name* ptr,                     \
                                       const nsPresContext* pres_context)      \
 {                                                                             \
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -57,17 +57,16 @@ namespace mozilla {
   class ServoStyleSheet;
   class ServoElementSnapshotTable;
 }
 using mozilla::FontFamilyList;
 using mozilla::FontFamilyName;
 using mozilla::FontFamilyType;
 using mozilla::ServoElementSnapshot;
 using mozilla::SharedFontList;
-class nsCSSCounterStyleRule;
 struct nsMediaFeature;
 class nsSimpleContentList;
 struct nsStyleList;
 struct nsStyleImage;
 struct nsStyleGradientStop;
 class nsStyleGradient;
 class nsStyleCoord;
 struct nsStyleDisplay;
@@ -623,23 +622,16 @@ mozilla::ServoStyleSheet* Gecko_StyleShe
     const mozilla::ServoStyleSheet* aSheet,
     const mozilla::ServoStyleSheet* aNewParentSheet);
 void Gecko_StyleSheet_AddRef(const mozilla::ServoStyleSheet* aSheet);
 void Gecko_StyleSheet_Release(const mozilla::ServoStyleSheet* aSheet);
 
 nsCSSKeyword Gecko_LookupCSSKeyword(const uint8_t* string, uint32_t len);
 const char* Gecko_CSSKeywordString(nsCSSKeyword keyword, uint32_t* len);
 
-// Counter style rule
-// Creates and returns a new (already-addrefed) nsCSSCounterStyleRule object.
-nsCSSCounterStyleRule* Gecko_CSSCounterStyle_Create(nsAtom* name);
-nsCSSCounterStyleRule* Gecko_CSSCounterStyle_Clone(const nsCSSCounterStyleRule* rule);
-void Gecko_CSSCounterStyle_GetCssText(const nsCSSCounterStyleRule* rule, nsAString* result);
-NS_DECL_FFI_REFCOUNTING(nsCSSCounterStyleRule, CSSCounterStyleRule);
-
 bool Gecko_IsDocumentBody(RawGeckoElementBorrowed element);
 
 // We use an int32_t here instead of a LookAndFeel::ColorID
 // because forward-declaring a nested enum/struct is impossible
 nscolor Gecko_GetLookAndFeelSystemColor(int32_t color_id,
                                         RawGeckoPresContextBorrowed pres_context);
 
 void Gecko_AddPropertyToSet(nsCSSPropertyIDSetBorrowedMut, nsCSSPropertyID);
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -73,17 +73,16 @@ headers = [
     "mozilla/LookAndFeel.h",
     "mozilla/StaticPrefs.h",
     "mozilla/ServoBindings.h",
     "mozilla/ServoMediaList.h",
     "mozilla/ComputedStyle.h",
     "mozilla/ServoDeclarationBlock.h",
     "mozilla/ServoTraversalStatistics.h",
     "mozilla/SizeOfState.h",
-    "nsCSSCounterStyleRule.h",
     "nsContentUtils.h",
     "nsNameSpaceManager.h",
     "nsMediaFeatures.h",
     "nsXBLBinding.h",
 ]
 raw-lines = [
     # FIXME(emilio): Incrementally remove these "pub use"s. Probably
     # mozilla::css and mozilla::dom are easier.
@@ -273,17 +272,16 @@ whitelist-types = [
     "ImageURL",
     "Keyframe",
     "MediumFeaturesChangedResult",
     "nsAttrName",
     "nsAttrValue",
     "nscolor",
     "nsChangeHint",
     "nsCSSCounterDesc",
-    "nsCSSCounterStyleRule",
     "nsCSSFontDesc",
     "nsCSSKeyword",
     "nsCSSPropertyID",
     "nsCSSPropertyIDSet",
     "nsCSSProps",
     "nsCSSRect",
     "nsCSSRect_heap",
     "nsCSSShadowArray",
@@ -421,17 +419,16 @@ opaque-types = [
     "mozilla::Maybe",
     "gfxSize",  # <- union { struct { T width; T height; }; T components[2] };
     "gfxSize_Super",  # Ditto.
     "mozilla::StyleAnimationValue",
     "StyleAnimationValue", # pulls in a whole bunch of stuff we don't need in the bindings
     "mozilla::dom::.*Callback", # Pulls in ErrorResult and other things that
                                 # don't align properly on Linux 32-bit
     "mozilla::SchedulerGroup", # Non-standard-layout packing of field into superclass
-    "nsCSSCounterStyleRule_Getter", # thiscall function pointer
 ]
 mapped-generic-types = [
     { generic = true, gecko = "mozilla::ServoUnsafeCell", servo = "::std::cell::UnsafeCell" },
     { generic = true, gecko = "mozilla::ServoCell", servo = "::std::cell::Cell" },
     { generic = false, gecko = "ServoNodeData", servo = "AtomicRefCell<ElementData>" },
     { generic = false, gecko = "mozilla::ServoWritingMode", servo = "::logical_geometry::WritingMode" },
     { generic = false, gecko = "mozilla::ServoCustomPropertiesMap", servo = "Option<::servo_arc::Arc<::custom_properties::CustomPropertiesMap>>" },
     { generic = false, gecko = "mozilla::ServoRuleNode", servo = "Option<::rule_tree::StrongRuleNode>" },
@@ -528,17 +525,16 @@ structs-types = [
     "ServoElementSnapshotTable",
     "ServoStyleSetSizes",
     "SheetParsingMode",
     "StyleBasicShapeType",
     "StyleShapeSource",
     "StyleTransition",
     "gfxFontFeatureValueSet",
     "nsCSSCounterDesc",
-    "nsCSSCounterStyleRule",
     "nsCSSFontDesc",
     "nsCSSKeyword",
     "nsCSSPropertyID",
     "nsCSSPropertyIDSet",
     "nsCSSRect",
     "nsCSSShadowArray",
     "nsCSSUnit",
     "nsCSSValue",
--- a/layout/style/ServoCSSParser.cpp
+++ b/layout/style/ServoCSSParser.cpp
@@ -35,35 +35,16 @@ ServoCSSParser::ComputeColor(ServoStyleS
 
 /* static */ bool
 ServoCSSParser::ParseIntersectionObserverRootMargin(const nsAString& aValue,
                                                     nsCSSRect* aResult)
 {
   return Servo_ParseIntersectionObserverRootMargin(&aValue, aResult);
 }
 
-/* static */ already_AddRefed<nsAtom>
-ServoCSSParser::ParseCounterStyleName(const nsAString& aValue)
-{
-  NS_ConvertUTF16toUTF8 value(aValue);
-  nsAtom* atom = Servo_ParseCounterStyleName(&value);
-  return already_AddRefed<nsAtom>(atom);
-}
-
-/* static */ bool
-ServoCSSParser::ParseCounterStyleDescriptor(nsCSSCounterDesc aDescriptor,
-                                            const nsAString& aValue,
-                                            URLExtraData* aURLExtraData,
-                                            nsCSSValue& aResult)
-{
-  NS_ConvertUTF16toUTF8 value(aValue);
-  return Servo_ParseCounterStyleDescriptor(aDescriptor, &value, aURLExtraData,
-                                           &aResult);
-}
-
 /* static */ already_AddRefed<RawServoDeclarationBlock>
 ServoCSSParser::ParseProperty(nsCSSPropertyID aProperty,
                               const nsAString& aValue,
                               const ParsingEnvironment& aParsingEnvironment,
                               ParsingMode aParsingMode)
 {
   NS_ConvertUTF16toUTF8 value(aValue);
   return Servo_ParseProperty(aProperty,
--- a/layout/style/ServoCSSParser.h
+++ b/layout/style/ServoCSSParser.h
@@ -79,41 +79,16 @@ public:
    * @param aValue The rootMargin value.
    * @param aResult The nsCSSRect object to write the result into.
    * @return Whether the value was successfully parsed.
    */
   static bool ParseIntersectionObserverRootMargin(const nsAString& aValue,
                                                   nsCSSRect* aResult);
 
   /**
-   * Parses a @counter-style name.
-   *
-   * @param aValue The name to parse.
-   * @return The name as an atom, lowercased if a built-in counter style name,
-   *   or nullptr if parsing failed or if the name was invalid (like "inherit").
-   */
-  static already_AddRefed<nsAtom> ParseCounterStyleName(const nsAString& aValue);
-
-  /**
-   * Parses a @counter-style descriptor.
-   *
-   * @param aDescriptor The descriptor to parse.
-   * @param aValue The value of the descriptor.
-   * @param aURLExtraData URL data for parsing. This would be used for
-   *   image value URL resolution.
-   * @param aResult The nsCSSValue to store the result in.
-   * @return Whether parsing succeeded.
-   */
-  static bool
-  ParseCounterStyleDescriptor(nsCSSCounterDesc aDescriptor,
-                              const nsAString& aValue,
-                              URLExtraData* aURLExtraData,
-                              nsCSSValue& aResult);
-
-  /**
    * Parse a string representing a CSS property value into a
    * RawServoDeclarationBlock.
    *
    * @param aProperty The property to be parsed.
    * @param aValue The specified value.
    * @param aParsingEnvironment All the parsing environment data we need.
    * @param aParsingMode The paring mode we apply.
    * @return The parsed value as a RawServoDeclarationBlock. We put the value
--- a/layout/style/ServoCSSRuleList.cpp
+++ b/layout/style/ServoCSSRuleList.cpp
@@ -5,28 +5,28 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* representation of CSSRuleList for stylo */
 
 #include "mozilla/ServoCSSRuleList.h"
 
 #include "mozilla/IntegerRange.h"
 #include "mozilla/ServoBindings.h"
+#include "mozilla/ServoCounterStyleRule.h"
 #include "mozilla/ServoDocumentRule.h"
 #include "mozilla/ServoImportRule.h"
 #include "mozilla/ServoFontFaceRule.h"
 #include "mozilla/ServoFontFeatureValuesRule.h"
 #include "mozilla/ServoKeyframesRule.h"
 #include "mozilla/ServoMediaRule.h"
 #include "mozilla/ServoNamespaceRule.h"
 #include "mozilla/ServoPageRule.h"
 #include "mozilla/ServoStyleRule.h"
 #include "mozilla/ServoStyleSheet.h"
 #include "mozilla/ServoSupportsRule.h"
-#include "nsCSSCounterStyleRule.h"
 
 using namespace mozilla::dom;
 
 namespace mozilla {
 
 ServoCSSRuleList::ServoCSSRuleList(already_AddRefed<ServoCssRules> aRawRules,
                                    ServoStyleSheet* aDirectOwnerStyleSheet)
   : mStyleSheet(aDirectOwnerStyleSheet)
@@ -48,24 +48,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Se
   tmp->DropAllRules();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(dom::CSSRuleList)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ServoCSSRuleList,
                                                   dom::CSSRuleList)
   tmp->EnumerateInstantiatedRules([&](css::Rule* aRule) {
     if (!aRule->IsCCLeaf()) {
       NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mRules[i]");
       cb.NoteXPCOMChild(aRule);
-      // Note about @counter-style rule again, since there is an indirect owning
-      // edge through Servo's struct that CounterStyleRule in Servo owns a Gecko
-      // nsCSSCounterStyleRule object.
-      auto type = aRule->Type();
-      if (type == CSSRuleBinding::COUNTER_STYLE_RULE) {
-        NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mRawRules[i]");
-        cb.NoteXPCOMChild(aRule);
-      }
     }
   });
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 void
 ServoCSSRuleList::SetParentRule(css::GroupRule* aParentRule)
 {
   mParentRule = aParentRule;
@@ -106,25 +98,18 @@ ServoCSSRuleList::GetRule(uint32_t aInde
       CASE_RULE(MEDIA, Media)
       CASE_RULE(NAMESPACE, Namespace)
       CASE_RULE(PAGE, Page)
       CASE_RULE(SUPPORTS, Supports)
       CASE_RULE(DOCUMENT, Document)
       CASE_RULE(IMPORT, Import)
       CASE_RULE(FONT_FEATURE_VALUES, FontFeatureValues)
       CASE_RULE(FONT_FACE, FontFace)
+      CASE_RULE(COUNTER_STYLE, CounterStyle)
 #undef CASE_RULE
-      // For @counter-style rules, the function returns a borrowed Gecko
-      // rule object directly, so we don't need to create anything here.
-      // But we still need to have the style sheet and parent rule set
-      // properly.
-      case CSSRuleBinding::COUNTER_STYLE_RULE: {
-        ruleObj = Servo_CssRules_GetCounterStyleRuleAt(mRawRules, aIndex);
-        break;
-      }
       case CSSRuleBinding::KEYFRAME_RULE:
         MOZ_ASSERT_UNREACHABLE("keyframe rule cannot be here");
         return nullptr;
       default:
         NS_WARNING("stylo: not implemented yet");
         return nullptr;
     }
     ruleObj->SetStyleSheet(mStyleSheet);
new file mode 100644
--- /dev/null
+++ b/layout/style/ServoCounterStyleRule.cpp
@@ -0,0 +1,113 @@
+/* -*- 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/ServoCounterStyleRule.h"
+
+#include "mozAutoDocUpdate.h"
+#include "mozilla/dom/CSSCounterStyleRuleBinding.h"
+#include "mozilla/ServoBindings.h"
+#include "nsStyleUtil.h"
+
+namespace mozilla {
+
+/* virtual */ already_AddRefed<css::Rule>
+ServoCounterStyleRule::Clone() const
+{
+  MOZ_ASSERT_UNREACHABLE("Shouldn't be cloning ServoCounterStyleRule");
+  return nullptr;
+}
+
+bool
+ServoCounterStyleRule::IsCCLeaf() const
+{
+  return Rule::IsCCLeaf();
+}
+
+#ifdef DEBUG
+void
+ServoCounterStyleRule::List(FILE* out, int32_t aIndent) const
+{
+  nsAutoCString str;
+  for (int32_t i = 0; i < aIndent; i++) {
+    str.AppendLiteral("  ");
+  }
+  Servo_CounterStyleRule_Debug(mRawRule, &str);
+  fprintf_stderr(out, "%s\n", str.get());
+}
+#endif
+
+uint16_t
+ServoCounterStyleRule::Type() const
+{
+  return CSSRuleBinding::COUNTER_STYLE_RULE;
+}
+
+void
+ServoCounterStyleRule::GetCssText(nsAString& aCssText) const
+{
+  Servo_CounterStyleRule_GetCssText(mRawRule, &aCssText);
+}
+
+void
+ServoCounterStyleRule::GetName(nsAString& aName)
+{
+  aName.Truncate();
+  nsAtom* name = Servo_CounterStyleRule_GetName(mRawRule);
+  nsDependentAtomString nameStr(name);
+  nsStyleUtil::AppendEscapedCSSIdent(nameStr, aName);
+}
+
+void
+ServoCounterStyleRule::SetName(const nsAString& aName)
+{
+  nsIDocument* doc = GetDocument();
+  NS_ConvertUTF16toUTF8 name(aName);
+  if (Servo_CounterStyleRule_SetName(mRawRule, &name)) {
+    MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
+    if (StyleSheet* sheet = GetStyleSheet()) {
+      sheet->RuleChanged(this);
+    }
+  }
+}
+
+#define CSS_COUNTER_DESC(name_, method_)                        \
+  void                                                          \
+  ServoCounterStyleRule::Get##method_(nsAString& aValue)        \
+  {                                                             \
+    aValue.Truncate();                                          \
+    Servo_CounterStyleRule_GetDescriptorCssText(                \
+      mRawRule, eCSSCounterDesc_##method_, &aValue);            \
+  }                                                             \
+  void                                                          \
+  ServoCounterStyleRule::Set##method_(const nsAString& aValue)  \
+  {                                                             \
+    NS_ConvertUTF16toUTF8 value(aValue);                        \
+    if (Servo_CounterStyleRule_SetDescriptor(                   \
+          mRawRule, eCSSCounterDesc_##method_, &value)) {       \
+      nsIDocument* doc = GetDocument();                         \
+      MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);             \
+      if (StyleSheet* sheet = GetStyleSheet()) {                \
+        sheet->RuleChanged(this);                               \
+      }                                                         \
+    }                                                           \
+  }
+#include "nsCSSCounterDescList.h"
+#undef CSS_COUNTER_DESC
+
+/* virtual */ size_t
+ServoCounterStyleRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
+{
+  return aMallocSizeOf(this);
+}
+
+/* virtual */ JSObject*
+ServoCounterStyleRule::WrapObject(JSContext* aCx,
+                                  JS::Handle<JSObject*> aGivenProto)
+{
+  return CSSCounterStyleRuleBinding::Wrap(aCx, this, aGivenProto);
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/layout/style/ServoCounterStyleRule.h
@@ -0,0 +1,60 @@
+/* -*- 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/. */
+
+#ifndef mozilla_ServoCounterStyleRule_h
+#define mozilla_ServoCounterStyleRule_h
+
+#include "mozilla/css/Rule.h"
+#include "mozilla/ServoBindingTypes.h"
+
+struct RawServoCounterStyleRule;
+
+namespace mozilla {
+
+class ServoCounterStyleRule final : public css::Rule
+{
+public:
+  ServoCounterStyleRule(already_AddRefed<RawServoCounterStyleRule> aRawRule,
+                        uint32_t aLine, uint32_t aColumn)
+    : mozilla::css::Rule(aLine, aColumn)
+    , mRawRule(Move(aRawRule))
+  {
+  }
+
+private:
+  ServoCounterStyleRule(const ServoCounterStyleRule& aCopy) = delete;
+  ~ServoCounterStyleRule() = default;
+
+public:
+  bool IsCCLeaf() const final;
+
+#ifdef DEBUG
+  void List(FILE* out = stdout, int32_t aIndent = 0) const final;
+#endif
+  already_AddRefed<mozilla::css::Rule> Clone() const final;
+
+  // WebIDL interface
+  uint16_t Type() const override;
+  void GetCssText(nsAString& aCssText) const override;
+  void GetName(nsAString& aName);
+  void SetName(const nsAString& aName);
+#define CSS_COUNTER_DESC(name_, method_) \
+  void Get##method_(nsAString& aValue); \
+  void Set##method_(const nsAString& aValue);
+#include "nsCSSCounterDescList.h"
+#undef CSS_COUNTER_DESC
+
+  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const final;
+
+  JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) final;
+
+private:
+  RefPtr<RawServoCounterStyleRule> mRawRule;
+};
+
+} // namespace mozilla
+
+#endif // mozilla_ServoCounterStyleRule_h
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -1431,17 +1431,17 @@ ServoStyleSet::ResolveStyleLazilyInterna
 bool
 ServoStyleSet::AppendFontFaceRules(nsTArray<nsFontFaceRuleContainer>& aArray)
 {
   UpdateStylistIfNeeded();
   Servo_StyleSet_GetFontFaceRules(mRawSet.get(), &aArray);
   return true;
 }
 
-nsCSSCounterStyleRule*
+const RawServoCounterStyleRule*
 ServoStyleSet::CounterStyleRuleForName(nsAtom* aName)
 {
   MOZ_ASSERT(!StylistNeedsUpdate());
   return Servo_StyleSet_GetCounterStyleRule(mRawSet.get(), aName);
 }
 
 already_AddRefed<gfxFontFeatureValueSet>
 ServoStyleSet::BuildFontFeatureValueSet()
--- a/layout/style/ServoStyleSet.h
+++ b/layout/style/ServoStyleSet.h
@@ -37,17 +37,16 @@ class ServoRestyleManager;
 class ServoStyleSheet;
 struct Keyframe;
 class ServoElementSnapshotTable;
 class ComputedStyle;
 class ServoStyleRuleMap;
 class StyleSheet;
 } // namespace mozilla
 class gfxFontFeatureValueSet;
-class nsCSSCounterStyleRule;
 class nsIContent;
 class nsIDocument;
 class nsPresContext;
 struct nsTimingFunction;
 struct RawServoRuleNode;
 struct TreeMatchContext;
 
 namespace mozilla {
@@ -355,17 +354,17 @@ public:
   void
   GetAnimationValues(RawServoDeclarationBlock* aDeclarations,
                      dom::Element* aElement,
                      const mozilla::ComputedStyle* aStyle,
                      nsTArray<RefPtr<RawServoAnimationValue>>& aAnimationValues);
 
   bool AppendFontFaceRules(nsTArray<nsFontFaceRuleContainer>& aArray);
 
-  nsCSSCounterStyleRule* CounterStyleRuleForName(nsAtom* aName);
+  const RawServoCounterStyleRule* CounterStyleRuleForName(nsAtom* aName);
 
   // Get all the currently-active font feature values set.
   already_AddRefed<gfxFontFeatureValueSet> BuildFontFeatureValueSet();
 
   already_AddRefed<ComputedStyle>
   GetBaseContextForElement(dom::Element* aElement,
                            const ComputedStyle* aStyle);
 
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -25,17 +25,16 @@ TEST_DIRS += ['test']
 EXPORTS += [
     'AnimationCommon.h',
     'CounterStyleManager.h',
     'nsAnimationManager.h',
     'nsComputedDOMStylePropertyList.h',
     'nsCSSAnonBoxes.h',
     'nsCSSAnonBoxList.h',
     'nsCSSCounterDescList.h',
-    'nsCSSCounterStyleRule.h',
     'nsCSSFontDescList.h',
     'nsCSSKeywordList.h',
     'nsCSSKeywords.h',
     'nsCSSParser.h',
     'nsCSSPropAliasList.h',
     'nsCSSPropertyID.h',
     'nsCSSPropertyIDSet.h',
     'nsCSSPropList.h',
@@ -78,16 +77,17 @@ EXPORTS.mozilla += [
     'LayerAnimationInfo.h',
     'MediaFeatureChange.h',
     'PostTraversalTask.h',
     'PreloadedStyleSheet.h',
     'ServoArcTypeList.h',
     'ServoBindingList.h',
     'ServoBindings.h',
     'ServoBindingTypes.h',
+    'ServoCounterStyleRule.h',
     'ServoCSSParser.h',
     'ServoCSSRuleList.h',
     'ServoDeclarationBlock.h',
     'ServoDocumentRule.h',
     'ServoElementSnapshot.h',
     'ServoElementSnapshotTable.h',
     'ServoFontFaceRule.h',
     'ServoFontFeatureValuesRule.h',
@@ -175,17 +175,16 @@ UNIFIED_SOURCES += [
     'GroupRule.cpp',
     'ImageLoader.cpp',
     'LayerAnimationInfo.cpp',
     'Loader.cpp',
     'MediaList.cpp',
     'MediaQueryList.cpp',
     'nsAnimationManager.cpp',
     'nsComputedDOMStyle.cpp',
-    'nsCSSCounterStyleRule.cpp',
     'nsCSSKeywords.cpp',
     'nsCSSProps.cpp',
     'nsCSSScanner.cpp',
     'nsCSSValue.cpp',
     'nsDOMCSSAttrDeclaration.cpp',
     'nsDOMCSSDeclaration.cpp',
     'nsDOMCSSRect.cpp',
     'nsDOMCSSRGBColor.cpp',
@@ -201,16 +200,17 @@ UNIFIED_SOURCES += [
     'nsStyleStruct.cpp',
     'nsStyleTransformMatrix.cpp',
     'nsStyleUtil.cpp',
     'nsTransitionManager.cpp',
     'PostTraversalTask.cpp',
     'PreloadedStyleSheet.cpp',
     'Rule.cpp',
     'ServoBindings.cpp',
+    'ServoCounterStyleRule.cpp',
     'ServoCSSParser.cpp',
     'ServoCSSRuleList.cpp',
     'ServoDeclarationBlock.cpp',
     'ServoDocumentRule.cpp',
     'ServoElementSnapshot.cpp',
     'ServoFontFaceRule.cpp',
     'ServoFontFeatureValuesRule.cpp',
     'ServoImportRule.cpp',
deleted file mode 100644
--- a/layout/style/nsCSSCounterStyleRule.cpp
+++ /dev/null
@@ -1,427 +0,0 @@
-/* -*- 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/. */
-
-/* a Gecko @counter-style rule */
-
-#include "nsCSSCounterStyleRule.h"
-
-#include "mozAutoDocUpdate.h"
-#include "mozilla/ArrayUtils.h"
-#include "mozilla/dom/CSSCounterStyleRuleBinding.h"
-#include "mozilla/ServoCSSParser.h"
-#include "nsCSSParser.h"
-#include "nsStyleUtil.h"
-
-using namespace mozilla;
-using namespace mozilla::dom;
-
-nsCSSCounterStyleRule::nsCSSCounterStyleRule(const nsCSSCounterStyleRule& aCopy)
-  : Rule(aCopy)
-  , mName(aCopy.mName)
-  , mGeneration(aCopy.mGeneration)
-{
-  for (size_t i = 0; i < ArrayLength(mValues); ++i) {
-    mValues[i] = aCopy.mValues[i];
-  }
-}
-
-nsCSSCounterStyleRule::~nsCSSCounterStyleRule()
-{
-}
-
-/* virtual */ already_AddRefed<css::Rule>
-nsCSSCounterStyleRule::Clone() const
-{
-  RefPtr<css::Rule> clone = new nsCSSCounterStyleRule(*this);
-  return clone.forget();
-}
-
-nsCSSCounterStyleRule::Getter const
-nsCSSCounterStyleRule::kGetters[] = {
-#define CSS_COUNTER_DESC(name_, method_) &nsCSSCounterStyleRule::Get##method_,
-#include "nsCSSCounterDescList.h"
-#undef CSS_COUNTER_DESC
-};
-
-// If this class gets its own cycle-collection bits, reevaluate our IsCCLeaf
-// implementation.
-
-bool
-nsCSSCounterStyleRule::IsCCLeaf() const
-{
-  return Rule::IsCCLeaf();
-}
-
-#ifdef DEBUG
-void
-nsCSSCounterStyleRule::List(FILE* out, int32_t aIndent) const
-{
-  nsCString baseInd, descInd;
-  for (int32_t indent = aIndent; --indent >= 0; ) {
-    baseInd.AppendLiteral("  ");
-  }
-  descInd = baseInd;
-  descInd.AppendLiteral("  ");
-
-  nsDependentAtomString name(mName);
-  fprintf_stderr(out, "%s@counter-style %s (rev.%u) {\n",
-                 baseInd.get(), NS_ConvertUTF16toUTF8(name).get(),
-                 mGeneration);
-  // TODO
-  fprintf_stderr(out, "%s}\n", baseInd.get());
-}
-#endif
-
-uint16_t
-nsCSSCounterStyleRule::Type() const
-{
-  return CSSRuleBinding::COUNTER_STYLE_RULE;
-}
-
-void
-nsCSSCounterStyleRule::GetCssText(nsAString& aCssText) const
-{
-  aCssText.AssignLiteral(u"@counter-style ");
-  nsDependentAtomString name(mName);
-  nsStyleUtil::AppendEscapedCSSIdent(name, aCssText);
-  aCssText.AppendLiteral(u" {\n");
-  for (nsCSSCounterDesc id = nsCSSCounterDesc(0);
-       id < eCSSCounterDesc_COUNT;
-       id = nsCSSCounterDesc(id + 1)) {
-    if (mValues[id].GetUnit() != eCSSUnit_Null) {
-      nsAutoString tmp;
-      // This is annoying.  We want to be a const method, but kGetters stores
-      // XPCOM method pointers, which aren't const methods.  The thing is,
-      // none of those mutate "this".  So it's OK to cast away const here.
-      (const_cast<nsCSSCounterStyleRule*>(this)->*kGetters[id])(tmp);
-      aCssText.AppendLiteral(u"  ");
-      AppendASCIItoUTF16(nsCSSProps::GetStringValue(id), aCssText);
-      aCssText.AppendLiteral(u": ");
-      aCssText.Append(tmp);
-      aCssText.AppendLiteral(u";\n");
-    }
-  }
-  aCssText.AppendLiteral(u"}");
-}
-
-void
-nsCSSCounterStyleRule::GetName(nsAString& aName)
-{
-  aName.Truncate();
-  nsDependentAtomString name(mName);
-  nsStyleUtil::AppendEscapedCSSIdent(name, aName);
-}
-
-void
-nsCSSCounterStyleRule::SetName(const nsAString& aName)
-{
-
-  nsIDocument* doc = GetDocument();
-  if (RefPtr<nsAtom> name = ServoCSSParser::ParseCounterStyleName(aName)) {
-    MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
-
-    mName = name;
-
-    if (StyleSheet* sheet = GetStyleSheet()) {
-      sheet->RuleChanged(this);
-    }
-  }
-}
-
-int32_t
-nsCSSCounterStyleRule::GetSystem() const
-{
-  const nsCSSValue& system = GetDesc(eCSSCounterDesc_System);
-  switch (system.GetUnit()) {
-    case eCSSUnit_Enumerated:
-      return system.GetIntValue();
-    case eCSSUnit_Pair:
-      return system.GetPairValue().mXValue.GetIntValue();
-    default:
-      return NS_STYLE_COUNTER_SYSTEM_SYMBOLIC;
-  }
-}
-
-const nsCSSValue&
-nsCSSCounterStyleRule::GetSystemArgument() const
-{
-  const nsCSSValue& system = GetDesc(eCSSCounterDesc_System);
-  MOZ_ASSERT(system.GetUnit() == eCSSUnit_Pair,
-             "Invalid system value");
-  return system.GetPairValue().mYValue;
-}
-
-void
-nsCSSCounterStyleRule::SetDesc(nsCSSCounterDesc aDescID, const nsCSSValue& aValue)
-{
-  MOZ_ASSERT(aDescID >= 0 && aDescID < eCSSCounterDesc_COUNT,
-             "descriptor ID out of range");
-
-  nsIDocument* doc = GetDocument();
-  MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
-
-  mValues[aDescID] = aValue;
-  mGeneration++;
-
-  if (StyleSheet* sheet = GetStyleSheet()) {
-    sheet->RuleChanged(this);
-  }
-}
-
-void
-nsCSSCounterStyleRule::GetSystem(nsAString& aSystem)
-{
-  const nsCSSValue& value = GetDesc(eCSSCounterDesc_System);
-  if (value.GetUnit() == eCSSUnit_Null) {
-    aSystem.Truncate();
-    return;
-  }
-
-  aSystem = NS_ConvertASCIItoUTF16(nsCSSProps::ValueToKeyword(
-          GetSystem(), nsCSSProps::kCounterSystemKTable));
-  if (value.GetUnit() == eCSSUnit_Pair) {
-    aSystem.Append(' ');
-    GetSystemArgument().AppendToString(eCSSProperty_UNKNOWN, aSystem);
-  }
-}
-
-void
-nsCSSCounterStyleRule::GetSymbols(nsAString& aSymbols)
-{
-  const nsCSSValue& value = GetDesc(eCSSCounterDesc_Symbols);
-
-  aSymbols.Truncate();
-  if (value.GetUnit() == eCSSUnit_List) {
-    for (const nsCSSValueList* item = value.GetListValue();
-         item; item = item->mNext) {
-      item->mValue.AppendToString(eCSSProperty_UNKNOWN, aSymbols);
-      if (item->mNext) {
-        aSymbols.Append(' ');
-      }
-    }
-  }
-}
-
-void
-nsCSSCounterStyleRule::GetAdditiveSymbols(nsAString& aSymbols)
-{
-  const nsCSSValue& value = GetDesc(eCSSCounterDesc_AdditiveSymbols);
-
-  aSymbols.Truncate();
-  if (value.GetUnit() == eCSSUnit_PairList) {
-    for (const nsCSSValuePairList* item = value.GetPairListValue();
-         item; item = item->mNext) {
-      item->mXValue.AppendToString(eCSSProperty_UNKNOWN, aSymbols);
-      aSymbols.Append(' ');
-      item->mYValue.AppendToString(eCSSProperty_UNKNOWN, aSymbols);
-      if (item->mNext) {
-        aSymbols.AppendLiteral(", ");
-      }
-    }
-  }
-}
-
-void
-nsCSSCounterStyleRule::GetRange(nsAString& aRange)
-{
-  const nsCSSValue& value = GetDesc(eCSSCounterDesc_Range);
-
-  switch (value.GetUnit()) {
-    case eCSSUnit_Auto:
-      aRange.AssignLiteral(u"auto");
-      break;
-
-    case eCSSUnit_PairList:
-      aRange.Truncate();
-      for (const nsCSSValuePairList* item = value.GetPairListValue();
-          item; item = item->mNext) {
-        const nsCSSValue& lower = item->mXValue;
-        const nsCSSValue& upper = item->mYValue;
-        if (lower.GetUnit() == eCSSUnit_Enumerated) {
-          NS_ASSERTION(lower.GetIntValue() ==
-                       NS_STYLE_COUNTER_RANGE_INFINITE,
-                       "Unrecognized keyword");
-          aRange.AppendLiteral("infinite");
-        } else {
-          aRange.AppendInt(lower.GetIntValue());
-        }
-        aRange.Append(' ');
-        if (upper.GetUnit() == eCSSUnit_Enumerated) {
-          NS_ASSERTION(upper.GetIntValue() ==
-                       NS_STYLE_COUNTER_RANGE_INFINITE,
-                       "Unrecognized keyword");
-          aRange.AppendLiteral("infinite");
-        } else {
-          aRange.AppendInt(upper.GetIntValue());
-        }
-        if (item->mNext) {
-          aRange.AppendLiteral(", ");
-        }
-      }
-      break;
-
-    default:
-      aRange.Truncate();
-  }
-}
-
-void
-nsCSSCounterStyleRule::GetSpeakAs(nsAString& aSpeakAs)
-{
-  const nsCSSValue& value = GetDesc(eCSSCounterDesc_SpeakAs);
-
-  switch (value.GetUnit()) {
-    case eCSSUnit_Enumerated:
-      switch (value.GetIntValue()) {
-        case NS_STYLE_COUNTER_SPEAKAS_BULLETS:
-          aSpeakAs.AssignLiteral(u"bullets");
-          break;
-        case NS_STYLE_COUNTER_SPEAKAS_NUMBERS:
-          aSpeakAs.AssignLiteral(u"numbers");
-          break;
-        case NS_STYLE_COUNTER_SPEAKAS_WORDS:
-          aSpeakAs.AssignLiteral(u"words");
-          break;
-        case NS_STYLE_COUNTER_SPEAKAS_SPELL_OUT:
-          aSpeakAs.AssignLiteral(u"spell-out");
-          break;
-        default:
-          NS_NOTREACHED("Unknown speech synthesis");
-      }
-      break;
-
-    case eCSSUnit_Auto:
-    case eCSSUnit_AtomIdent:
-      aSpeakAs.Truncate();
-      value.AppendToString(eCSSProperty_UNKNOWN, aSpeakAs);
-      break;
-
-    case eCSSUnit_Null:
-      aSpeakAs.Truncate();
-      break;
-
-    default:
-      NS_NOTREACHED("Unknown speech synthesis");
-      aSpeakAs.Truncate();
-  }
-}
-
-void
-nsCSSCounterStyleRule::GetDescriptor(nsCSSCounterDesc aDescID,
-                                     nsAString& aValue)
-{
-  NS_ASSERTION(aDescID == eCSSCounterDesc_Negative ||
-               aDescID == eCSSCounterDesc_Prefix ||
-               aDescID == eCSSCounterDesc_Suffix ||
-               aDescID == eCSSCounterDesc_Pad ||
-               aDescID == eCSSCounterDesc_Fallback,
-               "Unexpected descriptor");
-  const nsCSSValue& value = GetDesc(aDescID);
-  aValue.Truncate();
-  if (value.GetUnit() != eCSSUnit_Null) {
-    value.AppendToString(eCSSProperty_UNKNOWN, aValue);
-  }
-}
-
-#define CSS_COUNTER_DESC_GETTER(name_)                    \
-void                                                      \
-nsCSSCounterStyleRule::Get##name_(nsAString& a##name_)    \
-{                                                         \
-  GetDescriptor(eCSSCounterDesc_##name_, a##name_);       \
-}
-CSS_COUNTER_DESC_GETTER(Negative)
-CSS_COUNTER_DESC_GETTER(Prefix)
-CSS_COUNTER_DESC_GETTER(Suffix)
-CSS_COUNTER_DESC_GETTER(Pad)
-CSS_COUNTER_DESC_GETTER(Fallback)
-#undef CSS_COUNTER_DESC_GETTER
-
-/* static */ bool
-nsCSSCounterStyleRule::CheckDescValue(int32_t aSystem,
-                                      nsCSSCounterDesc aDescID,
-                                      const nsCSSValue& aValue)
-{
-  switch (aDescID) {
-    case eCSSCounterDesc_System:
-      if (aValue.GetUnit() != eCSSUnit_Pair) {
-        return aValue.GetIntValue() == aSystem;
-      } else {
-        return aValue.GetPairValue().mXValue.GetIntValue() == aSystem;
-      }
-
-    case eCSSCounterDesc_Symbols:
-      switch (aSystem) {
-        case NS_STYLE_COUNTER_SYSTEM_NUMERIC:
-        case NS_STYLE_COUNTER_SYSTEM_ALPHABETIC:
-          // for these two system, the list must contain at least 2 elements
-          return aValue.GetListValue()->mNext;
-        case NS_STYLE_COUNTER_SYSTEM_EXTENDS:
-          // for extends system, no symbols should be set
-          return false;
-        default:
-          return true;
-      }
-
-    case eCSSCounterDesc_AdditiveSymbols:
-      switch (aSystem) {
-        case NS_STYLE_COUNTER_SYSTEM_EXTENDS:
-          return false;
-        default:
-          return true;
-      }
-
-    default:
-      return true;
-  }
-}
-
-void
-nsCSSCounterStyleRule::SetDescriptor(nsCSSCounterDesc aDescID,
-                                     const nsAString& aValue)
-{
-  nsCSSValue value;
-
-  StyleSheet* sheet = GetStyleSheet();
-
-  URLExtraData* data = sheet ? sheet->AsServo()->URLData() : nullptr;
-  bool ok = ServoCSSParser::ParseCounterStyleDescriptor(aDescID, aValue, data,
-                                                        value);
-
-  if (ok && CheckDescValue(GetSystem(), aDescID, value)) {
-    SetDesc(aDescID, value);
-  }
-}
-
-#define CSS_COUNTER_DESC_SETTER(name_)                        \
-void                                                          \
-nsCSSCounterStyleRule::Set##name_(const nsAString& a##name_)  \
-{                                                             \
-  SetDescriptor(eCSSCounterDesc_##name_, a##name_);           \
-}
-CSS_COUNTER_DESC_SETTER(System)
-CSS_COUNTER_DESC_SETTER(Symbols)
-CSS_COUNTER_DESC_SETTER(AdditiveSymbols)
-CSS_COUNTER_DESC_SETTER(Negative)
-CSS_COUNTER_DESC_SETTER(Prefix)
-CSS_COUNTER_DESC_SETTER(Suffix)
-CSS_COUNTER_DESC_SETTER(Range)
-CSS_COUNTER_DESC_SETTER(Pad)
-CSS_COUNTER_DESC_SETTER(Fallback)
-CSS_COUNTER_DESC_SETTER(SpeakAs)
-#undef CSS_COUNTER_DESC_SETTER
-
-/* virtual */ size_t
-nsCSSCounterStyleRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
-{
-  return aMallocSizeOf(this);
-}
-
-/* virtual */ JSObject*
-nsCSSCounterStyleRule::WrapObject(JSContext* aCx,
-                                  JS::Handle<JSObject*> aGivenProto)
-{
-  return CSSCounterStyleRuleBinding::Wrap(aCx, this, aGivenProto);
-}
deleted file mode 100644
--- a/layout/style/nsCSSCounterStyleRule.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/* -*- 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/. */
-
-#ifndef nsCSSCounterStyleRule_h
-#define nsCSSCounterStyleRule_h
-
-#include "mozilla/css/Rule.h"
-#include "nsCSSValue.h"
-
-class nsCSSCounterStyleRule final : public mozilla::css::Rule
-{
-public:
-  explicit nsCSSCounterStyleRule(nsAtom* aName,
-                                 uint32_t aLineNumber, uint32_t aColumnNumber)
-    : mozilla::css::Rule(aLineNumber, aColumnNumber)
-    , mName(aName)
-    , mGeneration(0)
-  {
-    MOZ_ASSERT(aName, "Must have non-null name");
-  }
-
-private:
-  nsCSSCounterStyleRule(const nsCSSCounterStyleRule& aCopy);
-  ~nsCSSCounterStyleRule();
-
-public:
-  virtual bool IsCCLeaf() const override;
-
-#ifdef DEBUG
-  virtual void List(FILE* out = stdout, int32_t aIndent = 0) const override;
-#endif
-  virtual already_AddRefed<mozilla::css::Rule> Clone() const override;
-
-  // WebIDL interface
-  uint16_t Type() const override;
-  void GetCssText(nsAString& aCssText) const override;
-  void GetName(nsAString& aName);
-  void SetName(const nsAString& aName);
-  void GetSystem(nsAString& aSystem);
-  void SetSystem(const nsAString& aSystem);
-  void GetSymbols(nsAString& aSymbols);
-  void SetSymbols(const nsAString& aSymbols);
-  void GetAdditiveSymbols(nsAString& aAdditiveSymbols);
-  void SetAdditiveSymbols(const nsAString& aAdditiveSymbols);
-  void GetNegative(nsAString& aNegative);
-  void SetNegative(const nsAString& aNegative);
-  void GetPrefix(nsAString& aPrefix);
-  void SetPrefix(const nsAString& aPrefix);
-  void GetSuffix(nsAString& aSuffix);
-  void SetSuffix(const nsAString& aSuffix);
-  void GetRange(nsAString& aRange);
-  void SetRange(const nsAString& aRange);
-  void GetPad(nsAString& aPad);
-  void SetPad(const nsAString& aPad);
-  void GetSpeakAs(nsAString& aSpeakAs);
-  void SetSpeakAs(const nsAString& aSpeakAs);
-  void GetFallback(nsAString& aFallback);
-  void SetFallback(const nsAString& aFallback);
-
-  // This function is only used to check whether a non-empty value, which has
-  // been accepted by parser, is valid for the given system and descriptor.
-  static bool CheckDescValue(int32_t aSystem,
-                             nsCSSCounterDesc aDescID,
-                             const nsCSSValue& aValue);
-
-  nsAtom* Name() const { return mName; }
-
-  uint32_t GetGeneration() const { return mGeneration; }
-
-  int32_t GetSystem() const;
-  const nsCSSValue& GetSystemArgument() const;
-
-  const nsCSSValue& GetDesc(nsCSSCounterDesc aDescID) const
-  {
-    MOZ_ASSERT(aDescID >= 0 && aDescID < eCSSCounterDesc_COUNT,
-               "descriptor ID out of range");
-    return mValues[aDescID];
-  }
-
-  void SetDesc(nsCSSCounterDesc aDescID, const nsCSSValue& aValue);
-
-  virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
-
-  virtual JSObject* WrapObject(JSContext* aCx,
-                               JS::Handle<JSObject*> aGivenProto) override;
-
-private:
-  typedef decltype(&nsCSSCounterStyleRule::GetSymbols) Getter;
-  static const Getter kGetters[];
-
-  void GetDescriptor(nsCSSCounterDesc aDescID, nsAString& aValue);
-  void SetDescriptor(nsCSSCounterDesc aDescID, const nsAString& aValue);
-
-  RefPtr<nsAtom> mName;
-  nsCSSValue mValues[eCSSCounterDesc_COUNT];
-  uint32_t   mGeneration;
-};
-
-#endif // nsCSSCounterStyleRule_h
--- a/layout/style/test/test_counter_descriptor_storage.html
+++ b/layout/style/test/test_counter_descriptor_storage.html
@@ -74,24 +74,25 @@ function test_system_dep_desc() {
         ],
         symbols: oneSymbolTests
       }
     },
     {
       system: "fixed",
       base: "symbols: x",
       base_tests: {
-        system: "fixed 1",
+        system: "fixed",
         symbols: "x"
       },
       tests: {
         system: [
           [null, "", "symbolic"],
           ["fixed 0"],
-          ["fixed 1", "fixed", "FixeD"],
+          ["fixed", "FixeD"],
+          ["fixed 1", "FixeD 1"],
           ["fixed -1"],
           [null, "fixed a", "fixed \"0\"", "fixed 0 1"],
         ],
         symbols: oneSymbolTests
       }
     },
     {
       system: "symbolic",