Bug 1362302 part 1 - Use nsIAtom for counter style names. r?dbaron draft
authorXidorn Quan <me@upsuper.org>
Sat, 06 May 2017 11:34:35 +1000
changeset 573660 f8d3d63a2e950f516fff50c44f008ea2a6304535
parent 573075 68308b4aec5c15867f6a5b6eff6c9ea348aa9341
child 573661 441396e3317772aec797384137ca312445785f9a
push id57456
push userxquan@mozilla.com
push dateSat, 06 May 2017 03:07:54 +0000
reviewersdbaron
bugs1362302
milestone55.0a1
Bug 1362302 part 1 - Use nsIAtom for counter style names. r?dbaron MozReview-Commit-ID: 5VK6BgGRVRs
dom/base/nsGkAtomList.h
layout/base/nsCounterManager.cpp
layout/style/CounterStyleManager.cpp
layout/style/CounterStyleManager.h
layout/style/nsCSSParser.cpp
layout/style/nsCSSParser.h
layout/style/nsCSSRuleProcessor.cpp
layout/style/nsCSSRuleProcessor.h
layout/style/nsCSSRules.cpp
layout/style/nsCSSRules.h
layout/style/nsCSSValue.cpp
layout/style/nsCSSValue.h
layout/style/nsRuleNode.cpp
layout/style/nsStyleSet.cpp
layout/style/nsStyleSet.h
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -195,16 +195,17 @@ GK_ATOM(children, "children")
 GK_ATOM(childList, "childList")
 GK_ATOM(choose, "choose")
 GK_ATOM(chromemargin, "chromemargin")
 GK_ATOM(chromeOnlyContent, "chromeOnlyContent")
 GK_ATOM(exposeToUntrustedContent, "exposeToUntrustedContent")
 GK_ATOM(circ, "circ")
 GK_ATOM(circle, "circle")
 GK_ATOM(cite, "cite")
+GK_ATOM(cjkDecimal, "cjk-decimal")
 GK_ATOM(_class, "class")
 GK_ATOM(classid, "classid")
 GK_ATOM(clear, "clear")
 GK_ATOM(click, "click")
 GK_ATOM(clickcount, "clickcount")
 GK_ATOM(clickthrough, "clickthrough")
 GK_ATOM(movetoclick, "movetoclick")
 GK_ATOM(clip, "clip")
@@ -268,16 +269,17 @@ GK_ATOM(datalist, "datalist")
 GK_ATOM(dataType, "data-type")
 GK_ATOM(dateTime, "date-time")
 GK_ATOM(datasources, "datasources")
 GK_ATOM(datetime, "datetime")
 GK_ATOM(datetimebox, "datetimebox")
 GK_ATOM(dblclick, "dblclick")
 GK_ATOM(dd, "dd")
 GK_ATOM(debug, "debug")
+GK_ATOM(decimal, "decimal")
 GK_ATOM(decimalFormat, "decimal-format")
 GK_ATOM(decimalSeparator, "decimal-separator")
 GK_ATOM(deck, "deck")
 GK_ATOM(declare, "declare")
 GK_ATOM(decoderDoctor, "decoder-doctor")
 GK_ATOM(decrement, "decrement")
 GK_ATOM(_default, "default")
 GK_ATOM(headerDefaultStyle, "default-style")
@@ -557,17 +559,19 @@ GK_ATOM(listitem, "listitem")
 GK_ATOM(listrows, "listrows")
 GK_ATOM(load, "load")
 GK_ATOM(loadingprincipal, "loadingprincipal")
 GK_ATOM(localedir, "localedir")
 GK_ATOM(localName, "local-name")
 GK_ATOM(longdesc, "longdesc")
 GK_ATOM(loop, "loop")
 GK_ATOM(low, "low")
+GK_ATOM(lowerAlpha, "lower-alpha")
 GK_ATOM(lowerFirst, "lower-first")
+GK_ATOM(lowerRoman, "lower-roman")
 GK_ATOM(lowest, "lowest")
 GK_ATOM(lowsrc, "lowsrc")
 GK_ATOM(ltr, "ltr")
 GK_ATOM(lwtheme, "lwtheme")
 GK_ATOM(lwthemetextcolor, "lwthemetextcolor")
 GK_ATOM(main, "main")
 GK_ATOM(map, "map")
 GK_ATOM(manifest, "manifest")
@@ -1282,17 +1286,19 @@ GK_ATOM(tv, "tv")
 GK_ATOM(type, "type")
 GK_ATOM(typemustmatch, "typemustmatch")
 GK_ATOM(u, "u")
 GK_ATOM(ul, "ul")
 GK_ATOM(underflow, "underflow")
 GK_ATOM(undetermined, "undetermined")
 GK_ATOM(unload, "unload")
 GK_ATOM(unparsedEntityUri, "unparsed-entity-uri")
+GK_ATOM(upperAlpha, "upper-alpha")
 GK_ATOM(upperFirst, "upper-first")
+GK_ATOM(upperRoman, "upper-roman")
 GK_ATOM(uri, "uri")
 GK_ATOM(use, "use")
 GK_ATOM(useAttributeSets, "use-attribute-sets")
 GK_ATOM(usemap, "usemap")
 GK_ATOM(user_scalable, "user-scalable")
 GK_ATOM(userInput, "userInput")
 GK_ATOM(validate, "validate")
 GK_ATOM(valign, "valign")
@@ -1386,16 +1392,17 @@ GK_ATOM(d, "d")
 GK_ATOM(darken, "darken")
 GK_ATOM(defs, "defs")
 GK_ATOM(deg, "deg")
 GK_ATOM(desc, "desc")
 GK_ATOM(diffuseConstant, "diffuseConstant")
 GK_ATOM(dilate, "dilate")
 GK_ATOM(direction, "direction")
 GK_ATOM(disable, "disable")
+GK_ATOM(disc, "disc")
 GK_ATOM(discrete, "discrete")
 GK_ATOM(divisor, "divisor")
 GK_ATOM(dominant_baseline, "dominant-baseline")
 GK_ATOM(duplicate, "duplicate")
 GK_ATOM(dx, "dx")
 GK_ATOM(dy, "dy")
 GK_ATOM(edgeMode, "edgeMode")
 GK_ATOM(ellipse, "ellipse")
--- a/layout/base/nsCounterManager.cpp
+++ b/layout/base/nsCounterManager.cpp
@@ -44,20 +44,18 @@ nsCounterUseNode::InitTextFrame(nsGenCon
 }
 
 CounterStyle*
 nsCounterUseNode::GetCounterStyle()
 {
     if (!mCounterStyle) {
         const nsCSSValue& style = mCounterFunction->Item(mAllCounters ? 2 : 1);
         CounterStyleManager* manager = mPresContext->CounterStyleManager();
-        if (style.GetUnit() == eCSSUnit_Ident) {
-            nsString ident;
-            style.GetStringValue(ident);
-            mCounterStyle = manager->BuildCounterStyle(ident);
+        if (style.GetUnit() == eCSSUnit_AtomIdent) {
+            mCounterStyle = manager->BuildCounterStyle(style.GetAtomValue());
         } else if (style.GetUnit() == eCSSUnit_Symbols) {
             mCounterStyle = new AnonymousCounterStyle(style.GetArrayValue());
         } else {
             NS_NOTREACHED("Unknown counter style");
             mCounterStyle = CounterStyleManager::GetDecimalStyle();
         }
     }
     return mCounterStyle;
--- a/layout/style/CounterStyleManager.cpp
+++ b/layout/style/CounterStyleManager.cpp
@@ -1015,29 +1015,29 @@ DependentBuiltinCounterStyle::GetFallbac
     case NS_STYLE_LIST_STYLE_SIMP_CHINESE_INFORMAL:
     case NS_STYLE_LIST_STYLE_SIMP_CHINESE_FORMAL:
     case NS_STYLE_LIST_STYLE_TRAD_CHINESE_INFORMAL:
     case NS_STYLE_LIST_STYLE_TRAD_CHINESE_FORMAL:
       // These styles all have a larger range than cjk-decimal, so the
       // only case fallback is accessed is that they are extended.
       // Since extending styles will cache the data themselves, we need
       // not cache it here.
-      return mManager->BuildCounterStyle(NS_LITERAL_STRING("cjk-decimal"));
+      return mManager->BuildCounterStyle(nsGkAtoms::cjkDecimal);
     default:
       NS_NOTREACHED("Not a valid dependent builtin style");
       return BuiltinCounterStyle::GetFallback();
   }
 }
 
 class CustomCounterStyle final : public CounterStyle
 {
 private:
   ~CustomCounterStyle() {}
 public:
-  CustomCounterStyle(const nsAString& aName,
+  CustomCounterStyle(nsIAtom* aName,
                      CounterStyleManager* aManager,
                      nsCSSCounterStyleRule* aRule)
     : CounterStyle(NS_STYLE_LIST_STYLE_CUSTOM),
       mName(aName),
       mManager(aManager),
       mRule(aRule),
       mRuleGeneration(aRule->GetGeneration()),
       mSystem(aRule->GetSystem()),
@@ -1129,17 +1129,17 @@ private:
   void ComputeRawSpeakAs(uint8_t& aSpeakAs,
                          CounterStyle*& aSpeakAsCounter);
   CounterStyle* ComputeSpeakAs();
 
   CounterStyle* ComputeExtends();
   CounterStyle* GetExtends();
   CounterStyle* GetExtendsRoot();
 
-  nsString mName;
+  nsCOMPtr<nsIAtom> 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;
   uint32_t mRuleGeneration;
@@ -1229,17 +1229,18 @@ CustomCounterStyle::ResetDependentData()
                 FLAG_SUFFIX_INITED |
                 FLAG_PAD_INITED);
   }
 }
 
 /* virtual */ void
 CustomCounterStyle::GetStyleName(nsSubstring& aResult)
 {
-  aResult.Assign(mName);
+  nsDependentAtomString name(mName);
+  aResult.Assign(name);
 }
 
 /* virtual */ void
 CustomCounterStyle::GetPrefix(nsSubstring& aResult)
 {
   if (!(mFlags & FLAG_PREFIX_INITED)) {
     mFlags |= FLAG_PREFIX_INITED;
 
@@ -1407,23 +1408,25 @@ CustomCounterStyle::GetPad(PadType& aRes
   aResult = mPad;
 }
 
 /* virtual */ CounterStyle*
 CustomCounterStyle::GetFallback()
 {
   if (!mFallback) {
     const nsCSSValue& value = mRule->GetDesc(eCSSCounterDesc_Fallback);
-    if (value.UnitHasStringValue()) {
-      mFallback = mManager->BuildCounterStyle(
-          nsDependentString(value.GetStringBufferValue()));
+    mFallback = CounterStyleManager::GetDecimalStyle();
+    if (value.GetUnit() != eCSSUnit_Null) {
+      if (value.GetUnit() == eCSSUnit_AtomIdent) {
+        mFallback = mManager->BuildCounterStyle(value.GetAtomValue());
+      } else {
+        MOZ_ASSERT_UNREACHABLE("Unknown unit!");
+      }
     } else if (IsExtendsSystem()) {
       mFallback = GetExtends()->GetFallback();
-    } else {
-      mFallback = CounterStyleManager::GetDecimalStyle();
     }
   }
   return mFallback;
 }
 
 /* virtual */ uint8_t
 CustomCounterStyle::GetSpeakAs()
 {
@@ -1549,20 +1552,19 @@ CustomCounterStyle::ComputeRawSpeakAs(ui
   const nsCSSValue& value = mRule->GetDesc(eCSSCounterDesc_SpeakAs);
   switch (value.GetUnit()) {
     case eCSSUnit_Auto:
       aSpeakAs = GetSpeakAsAutoValue();
       break;
     case eCSSUnit_Enumerated:
       aSpeakAs = value.GetIntValue();
       break;
-    case eCSSUnit_Ident:
+    case eCSSUnit_AtomIdent:
       aSpeakAs = NS_STYLE_COUNTER_SPEAKAS_OTHER;
-      aSpeakAsCounter = mManager->BuildCounterStyle(
-          nsDependentString(value.GetStringBufferValue()));
+      aSpeakAsCounter = mManager->BuildCounterStyle(value.GetAtomValue());
       break;
     case eCSSUnit_Null: {
       if (!IsExtendsSystem()) {
         aSpeakAs = GetSpeakAsAutoValue();
       } else {
         CounterStyle* extended = GetExtends();
         if (!extended->IsCustomStyle()) {
           // It is safe to call GetSpeakAs on non-custom style.
@@ -1659,18 +1661,17 @@ CustomCounterStyle::ComputeExtends()
   }
   if (mFlags & FLAG_EXTENDS_VISITED) {
     // loop detected
     mFlags |= FLAG_EXTENDS_LOOP;
     return nullptr;
   }
 
   const nsCSSValue& value = mRule->GetSystemArgument();
-  CounterStyle* nextCounter = mManager->BuildCounterStyle(
-      nsDependentString(value.GetStringBufferValue()));
+  CounterStyle* nextCounter = mManager->BuildCounterStyle(value.GetAtomValue());
   CounterStyle* target = nextCounter;
   if (nextCounter->IsCustomStyle()) {
     mFlags |= FLAG_EXTENDS_VISITED;
     target = static_cast<CustomCounterStyle*>(nextCounter)->ComputeExtends();
     mFlags &= ~FLAG_EXTENDS_VISITED;
   }
 
   if (target) {
@@ -1981,18 +1982,18 @@ CounterStyle::CallFallbackStyle(CounterV
 }
 
 static BuiltinCounterStyle gBuiltinStyleTable[NS_STYLE_LIST_STYLE__MAX];
 
 CounterStyleManager::CounterStyleManager(nsPresContext* aPresContext)
   : mPresContext(aPresContext)
 {
   // Insert the static styles into cache table
-  mCacheTable.Put(NS_LITERAL_STRING("none"), GetNoneStyle());
-  mCacheTable.Put(NS_LITERAL_STRING("decimal"), GetDecimalStyle());
+  mCacheTable.Put(nsGkAtoms::none, GetNoneStyle());
+  mCacheTable.Put(nsGkAtoms::decimal, GetDecimalStyle());
 }
 
 CounterStyleManager::~CounterStyleManager()
 {
   MOZ_ASSERT(!mPresContext, "Disconnect should have been called");
 }
 
 /* static */ void
@@ -2015,17 +2016,17 @@ CounterStyleManager::Disconnect()
                  "Counter style is still referenced by other objects.");
   }
 #endif
   mCacheTable.Clear();
   mPresContext = nullptr;
 }
 
 CounterStyle*
-CounterStyleManager::BuildCounterStyle(const nsSubstring& aName)
+CounterStyleManager::BuildCounterStyle(nsIAtom* aName)
 {
   CounterStyle* data = mCacheTable.GetWeak(aName);
   if (data) {
     return data;
   }
 
   // It is intentional that the predefined names are case-insensitive
   // but the user-defined names case-sensitive.
@@ -2035,20 +2036,22 @@ CounterStyleManager::BuildCounterStyle(c
   // When this assertion is removed, please remove the hack to avoid it in
   // nsStyleList::nsStyleList.
   NS_ASSERTION(styleSet->IsGecko(),
                "stylo: ServoStyleSets do not support custom counter "
                "styles yet");
   nsCSSCounterStyleRule* rule = styleSet->IsGecko() ?
     styleSet->AsGecko()->CounterStyleRuleForName(aName) : nullptr;
   if (rule) {
+    MOZ_ASSERT(rule->Name() == aName);
     data = new (mPresContext) CustomCounterStyle(aName, this, rule);
   } else {
     int32_t type;
-    nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(aName);
+    nsDependentAtomString name(aName);
+    nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(name);
     if (nsCSSProps::FindKeyword(keyword, nsCSSProps::kListStyleKTable, type)) {
       if (gBuiltinStyleTable[type].IsDependentStyle()) {
         data = new (mPresContext) DependentBuiltinCounterStyle(type, this);
       } else {
         data = GetBuiltinStyle(type);
       }
     }
   }
--- a/layout/style/CounterStyleManager.h
+++ b/layout/style/CounterStyleManager.h
@@ -154,17 +154,17 @@ public:
   void Disconnect();
 
   bool IsInitial() const
   {
     // only 'none' and 'decimal'
     return mCacheTable.Count() == 2;
   }
 
-  CounterStyle* BuildCounterStyle(const nsSubstring& aName);
+  CounterStyle* BuildCounterStyle(nsIAtom* aName);
 
   static CounterStyle* GetBuiltinStyle(int32_t aStyle);
   static CounterStyle* GetNoneStyle()
   {
     return GetBuiltinStyle(NS_STYLE_LIST_STYLE_NONE);
   }
   static CounterStyle* GetDecimalStyle()
   {
@@ -178,14 +178,14 @@ public:
   bool NotifyRuleChanged();
 
   nsPresContext* PresContext() const { return mPresContext; }
 
   NS_INLINE_DECL_REFCOUNTING(CounterStyleManager)
 
 private:
   nsPresContext* mPresContext;
-  nsRefPtrHashtable<nsStringHashKey, CounterStyle> mCacheTable;
+  nsRefPtrHashtable<nsRefPtrHashKey<nsIAtom>, CounterStyle> mCacheTable;
 };
 
 } // namespace mozilla
 
 #endif /* !defined(mozilla_CounterStyleManager_h_) */
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -258,19 +258,18 @@ public:
                                    nsIURI* aBaseURL,
                                    nsIPrincipal* aDocPrincipal);
 
   bool EvaluateSupportsCondition(const nsAString& aCondition,
                                  nsIURI* aDocURL,
                                  nsIURI* aBaseURL,
                                  nsIPrincipal* aDocPrincipal);
 
-  bool ParseCounterStyleName(const nsAString& aBuffer,
-                             nsIURI* aURL,
-                             nsAString& aName);
+  already_AddRefed<nsIAtom> ParseCounterStyleName(const nsAString& aBuffer,
+                                                  nsIURI* aURL);
 
   bool ParseCounterDescriptor(nsCSSCounterDesc aDescID,
                               const nsAString& aBuffer,
                               nsIURI* aSheetURL,
                               nsIURI* aBaseURL,
                               nsIPrincipal* aSheetPrincipal,
                               nsCSSValue& aValue);
 
@@ -702,17 +701,17 @@ protected:
   bool ParseSupportsConditionInParensInsideParens(bool& aConditionMet);
   bool ParseSupportsConditionTerms(bool& aConditionMet);
   enum SupportsConditionTermOperator { eAnd, eOr };
   bool ParseSupportsConditionTermsAfterOperator(
                                        bool& aConditionMet,
                                        SupportsConditionTermOperator aOperator);
 
   bool ParseCounterStyleRule(RuleAppendFunc aAppendFunc, void* aProcessData);
-  bool ParseCounterStyleName(nsAString& aName, bool aForDefinition);
+  already_AddRefed<nsIAtom> ParseCounterStyleName(bool aForDefinition);
   bool ParseCounterStyleNameValue(nsCSSValue& aValue);
   bool ParseCounterDescriptor(nsCSSCounterStyleRule *aRule);
   bool ParseCounterDescriptorValue(nsCSSCounterDesc aDescID,
                                    nsCSSValue& aValue);
   bool ParseCounterRange(nsCSSValuePair& aPair);
 
   /**
    * Parses the current input stream for a CSS token stream value and resolves
@@ -3038,31 +3037,30 @@ CSSParserImpl::ParsePropertyWithVariable
 
   // Copy the property value into the rule data.
   mTempData.MapRuleInfoInto(aPropertyID, aRuleData);
 
   mTempData.ClearProperty(propertyToParse);
   mTempData.AssertInitialState();
 }
 
-bool
-CSSParserImpl::ParseCounterStyleName(const nsAString& aBuffer,
-                                     nsIURI* aURL,
-                                     nsAString& aName)
+already_AddRefed<nsIAtom>
+CSSParserImpl::ParseCounterStyleName(const nsAString& aBuffer, nsIURI* aURL)
 {
   nsCSSScanner scanner(aBuffer, 0);
   css::ErrorReporter reporter(scanner, mSheet, mChildLoader, aURL);
   InitScanner(scanner, reporter, aURL, aURL, nullptr);
 
-  bool success = ParseCounterStyleName(aName, true) && !GetToken(true);
+  nsCOMPtr<nsIAtom> name = ParseCounterStyleName(true);
+  bool success = name && !GetToken(true);
 
   OUTPUT_ERROR();
   ReleaseScanner();
 
-  return success;
+  return success ? name.forget() : nullptr;
 }
 
 bool
 CSSParserImpl::ParseCounterDescriptor(nsCSSCounterDesc aDescID,
                                       const nsAString& aBuffer,
                                       nsIURI* aSheetURL,
                                       nsIURI* aBaseURL,
                                       nsIPrincipal* aSheetPrincipal,
@@ -4824,20 +4822,20 @@ CSSParserImpl::ParseSupportsConditionTer
       return true;
     }
   }
 }
 
 bool
 CSSParserImpl::ParseCounterStyleRule(RuleAppendFunc aAppendFunc, void* aData)
 {
-  nsAutoString name;
+  nsCOMPtr<nsIAtom> name;
   uint32_t linenum, colnum;
   if (!GetNextTokenLocation(true, &linenum, &colnum) ||
-      !ParseCounterStyleName(name, true)) {
+      !(name = ParseCounterStyleName(true))) {
     REPORT_UNEXPECTED_TOKEN(PECounterStyleNotIdent);
     return false;
   }
 
   if (!ExpectSymbol('{', true)) {
     REPORT_UNEXPECTED_TOKEN(PECounterStyleBadBlockStart);
     return false;
   }
@@ -4909,55 +4907,54 @@ CSSParserImpl::ParseCounterStyleRule(Rul
   }
 
   if (isCorrect) {
     (*aAppendFunc)(rule, aData);
   }
   return true;
 }
 
-bool
-CSSParserImpl::ParseCounterStyleName(nsAString& aName, bool aForDefinition)
+already_AddRefed<nsIAtom>
+CSSParserImpl::ParseCounterStyleName(bool aForDefinition)
 {
   if (!GetToken(true)) {
-    return false;
+    return nullptr;
   }
 
   if (mToken.mType != eCSSToken_Ident) {
     UngetToken();
-    return false;
+    return nullptr;
   }
 
   static const nsCSSKeyword kReservedNames[] = {
     eCSSKeyword_none,
     eCSSKeyword_decimal,
     eCSSKeyword_UNKNOWN
   };
 
   nsCSSValue value; // we don't actually care about the value
   if (!ParseCustomIdent(value, mToken.mIdent,
                         aForDefinition ? kReservedNames : nullptr)) {
     REPORT_UNEXPECTED_TOKEN(PECounterStyleBadName);
     UngetToken();
-    return false;
-  }
-
-  aName = mToken.mIdent;
-  if (nsCSSProps::IsPredefinedCounterStyle(aName)) {
-    ToLowerCase(aName);
-  }
-  return true;
+    return nullptr;
+  }
+
+  nsString name = mToken.mIdent;
+  if (nsCSSProps::IsPredefinedCounterStyle(name)) {
+    ToLowerCase(name);
+  }
+  return NS_Atomize(name);
 }
 
 bool
 CSSParserImpl::ParseCounterStyleNameValue(nsCSSValue& aValue)
 {
-  nsString name;
-  if (ParseCounterStyleName(name, false)) {
-    aValue.SetStringValue(name, eCSSUnit_Ident);
+  if (nsCOMPtr<nsIAtom> name = ParseCounterStyleName(false)) {
+    aValue.SetAtomIdentValue(name.forget());
     return true;
   }
   return false;
 }
 
 bool
 CSSParserImpl::ParseCounterDescriptor(nsCSSCounterStyleRule* aRule)
 {
@@ -8041,17 +8038,17 @@ CSSParserImpl::ParseCounter(nsCSSValue& 
     // get optional type
     int32_t typeItem = eCSSUnit_Counters == unit ? 2 : 1;
     nsCSSValue& type = val->Item(typeItem);
     if (ExpectSymbol(',', true)) {
       if (!ParseCounterStyleNameValue(type) && !ParseSymbols(type)) {
         break;
       }
     } else {
-      type.SetStringValue(NS_LITERAL_STRING("decimal"), eCSSUnit_Ident);
+      type.SetAtomIdentValue(do_AddRef(nsGkAtoms::decimal));
     }
 
     if (!ExpectSymbol(')', true)) {
       break;
     }
 
     aValue.SetArrayValue(val, unit);
     return true;
@@ -15276,19 +15273,18 @@ CSSParserImpl::ParseListStyle()
   }
 
   if ((found & 2) == 0) {
     values[1].SetIntValue(NS_STYLE_LIST_STYLE_POSITION_OUTSIDE,
                           eCSSUnit_Enumerated);
   }
   if ((found & 4) == 0) {
     // Provide default values
-    nsString type = (found & 1) ?
-      NS_LITERAL_STRING("none") : NS_LITERAL_STRING("disc");
-    values[2].SetStringValue(type, eCSSUnit_Ident);
+    nsIAtom* type = (found & 1) ? nsGkAtoms::none : nsGkAtoms::disc;
+    values[2].SetAtomIdentValue(do_AddRef(type));
   }
   if ((found & 8) == 0) {
     values[3].SetNoneValue();
   }
 
   // Start at 1 to avoid appending fake value.
   for (uint32_t index = 1; index < ArrayLength(listStyleIDs); ++index) {
     AppendValue(listStyleIDs[index], values[index]);
@@ -18217,23 +18213,21 @@ nsCSSParser::ParsePropertyWithVariableRe
 {
   static_cast<CSSParserImpl*>(mImpl)->
     ParsePropertyWithVariableReferences(aPropertyID, aShorthandPropertyID,
                                         aValue, aVariables, aRuleData, aDocURL,
                                         aBaseURL, aDocPrincipal, aSheet,
                                         aLineNumber, aLineOffset);
 }
 
-bool
-nsCSSParser::ParseCounterStyleName(const nsAString& aBuffer,
-                                   nsIURI* aURL,
-                                   nsAString& aName)
+already_AddRefed<nsIAtom>
+nsCSSParser::ParseCounterStyleName(const nsAString& aBuffer, nsIURI* aURL)
 {
   return static_cast<CSSParserImpl*>(mImpl)->
-    ParseCounterStyleName(aBuffer, aURL, aName);
+    ParseCounterStyleName(aBuffer, aURL);
 }
 
 bool
 nsCSSParser::ParseCounterDescriptor(nsCSSCounterDesc aDescID,
                                     const nsAString& aBuffer,
                                     nsIURI* aSheetURL,
                                     nsIURI* aBaseURL,
                                     nsIPrincipal* aSheetPrincipal,
--- a/layout/style/nsCSSParser.h
+++ b/layout/style/nsCSSParser.h
@@ -299,19 +299,21 @@ public:
                                    nsRuleData* aRuleData,
                                    nsIURI* aDocURL,
                                    nsIURI* aBaseURL,
                                    nsIPrincipal* aDocPrincipal,
                                    mozilla::CSSStyleSheet* aSheet,
                                    uint32_t aLineNumber,
                                    uint32_t aLineOffset);
 
-  bool ParseCounterStyleName(const nsAString& aBuffer,
-                             nsIURI* aURL,
-                             nsAString& aName);
+  /**
+   * Parses a string as a counter-style name. Returns nullptr if fails.
+   */
+  already_AddRefed<nsIAtom> ParseCounterStyleName(const nsAString& aBuffer,
+                                                  nsIURI* aURL);
 
   bool ParseCounterDescriptor(nsCSSCounterDesc aDescID,
                               const nsAString& aBuffer,
                               nsIURI* aSheetURL,
                               nsIURI* aBaseURL,
                               nsIPrincipal* aSheetPrincipal,
                               nsCSSValue& aValue);
 
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -888,17 +888,21 @@ struct RuleCascadeData {
 
   nsTArray<nsFontFaceRuleContainer> mFontFaceRules;
   nsTArray<nsCSSKeyframesRule*> mKeyframesRules;
   nsTArray<nsCSSFontFeatureValuesRule*> mFontFeatureValuesRules;
   nsTArray<nsCSSPageRule*> mPageRules;
   nsTArray<nsCSSCounterStyleRule*> mCounterStyleRules;
 
   nsDataHashtable<nsStringHashKey, nsCSSKeyframesRule*> mKeyframesRuleTable;
-  nsDataHashtable<nsStringHashKey, nsCSSCounterStyleRule*> mCounterStyleRuleTable;
+  // The hashtable doesn't need to hold a strong reference to the name
+  // atom, because nsCSSCounterStyleRule always does. If the name changes
+  // we need to discard this table and rebuild it anyway.
+  nsDataHashtable<nsPtrHashKey<nsIAtom>,
+                  nsCSSCounterStyleRule*> mCounterStyleRuleTable;
 
   // Looks up or creates the appropriate list in |mAttributeSelectors|.
   // Returns null only on allocation failure.
   nsTArray<SelectorPair>* AttributeListFor(nsIAtom* aAttribute);
 
   nsMediaQueryResultCacheKey mCacheKey;
   RuleCascadeData*  mNext; // for a different medium
 
@@ -3113,17 +3117,17 @@ nsCSSRuleProcessor::KeyframesRuleForName
     return cascade->mKeyframesRuleTable.Get(aName);
   }
 
   return nullptr;
 }
 
 nsCSSCounterStyleRule*
 nsCSSRuleProcessor::CounterStyleRuleForName(nsPresContext* aPresContext,
-                                            const nsAString& aName)
+                                            nsIAtom* aName)
 {
   RuleCascadeData* cascade = GetRuleCascade(aPresContext);
 
   if (cascade) {
     return cascade->mCounterStyleRuleTable.Get(aName);
   }
 
   return nullptr;
@@ -3832,17 +3836,17 @@ nsCSSRuleProcessor::RefreshRuleCascade(n
         nsCSSKeyframesRule* rule = newCascade->mKeyframesRules[i];
         newCascade->mKeyframesRuleTable.Put(rule->GetName(), rule);
       }
 
       // Build mCounterStyleRuleTable
       for (nsTArray<nsCSSCounterStyleRule*>::size_type i = 0,
            iEnd = newCascade->mCounterStyleRules.Length(); i < iEnd; ++i) {
         nsCSSCounterStyleRule* rule = newCascade->mCounterStyleRules[i];
-        newCascade->mCounterStyleRuleTable.Put(rule->GetName(), rule);
+        newCascade->mCounterStyleRuleTable.Put(rule->Name(), rule);
       }
 
       // mMustGatherDocumentRules controls whether we build mDocumentRules
       // and mDocumentCacheKey so that they can be used as keys by the
       // RuleProcessorCache, as obtained by TakeDocumentRulesAndCacheKey
       // later.  We set it to false just below so that we only do this
       // the first time we build a RuleProcessorCache for a shared rule
       // processor.
--- a/layout/style/nsCSSRuleProcessor.h
+++ b/layout/style/nsCSSRuleProcessor.h
@@ -205,17 +205,17 @@ public:
   // true for success and false for failure.
   bool AppendFontFaceRules(nsPresContext* aPresContext,
                            nsTArray<nsFontFaceRuleContainer>& aArray);
 
   nsCSSKeyframesRule* KeyframesRuleForName(nsPresContext* aPresContext,
                                            const nsString& aName);
 
   nsCSSCounterStyleRule* CounterStyleRuleForName(nsPresContext* aPresContext,
-                                                 const nsAString& aName);
+                                                 nsIAtom* aName);
 
   bool AppendPageRules(nsPresContext* aPresContext,
                        nsTArray<nsCSSPageRule*>& aArray);
 
   bool AppendFontFeatureValuesRules(nsPresContext* aPresContext,
                               nsTArray<nsCSSFontFeatureValuesRule*>& aArray);
 
   /**
--- a/layout/style/nsCSSRules.cpp
+++ b/layout/style/nsCSSRules.cpp
@@ -2414,18 +2414,19 @@ nsCSSCounterStyleRule::List(FILE* out, i
 {
   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(mName).get(),
+                 baseInd.get(), NS_ConvertUTF16toUTF8(name).get(),
                  mGeneration);
   // TODO
   fprintf_stderr(out, "%s}\n", baseInd.get());
 }
 #endif
 
 /* virtual */ int32_t
 nsCSSCounterStyleRule::GetType() const
@@ -2438,17 +2439,18 @@ nsCSSCounterStyleRule::Type() const
 {
   return nsIDOMCSSRule::COUNTER_STYLE_RULE;
 }
 
 void
 nsCSSCounterStyleRule::GetCssTextImpl(nsAString& aCssText) const
 {
   aCssText.AssignLiteral(u"@counter-style ");
-  nsStyleUtil::AppendEscapedCSSIdent(mName, aCssText);
+  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,
@@ -2464,26 +2466,26 @@ nsCSSCounterStyleRule::GetCssTextImpl(ns
   aCssText.AppendLiteral(u"}");
 }
 
 // nsIDOMCSSCounterStyleRule methods
 NS_IMETHODIMP
 nsCSSCounterStyleRule::GetName(nsAString& aName)
 {
   aName.Truncate();
-  nsStyleUtil::AppendEscapedCSSIdent(mName, aName);
+  nsDependentAtomString name(mName);
+  nsStyleUtil::AppendEscapedCSSIdent(name, aName);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCSSCounterStyleRule::SetName(const nsAString& aName)
 {
   nsCSSParser parser;
-  nsAutoString name;
-  if (parser.ParseCounterStyleName(aName, nullptr, name)) {
+  if (nsCOMPtr<nsIAtom> name = parser.ParseCounterStyleName(aName, nullptr)) {
     nsIDocument* doc = GetDocument();
     MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
 
     mName = name;
 
     if (StyleSheet* sheet = GetStyleSheet()) {
       sheet->AsGecko()->SetModifiedByChildRule();
       if (doc) {
@@ -2664,23 +2666,28 @@ nsCSSCounterStyleRule::GetSpeakAs(nsAStr
           aSpeakAs.AssignLiteral(u"spell-out");
           break;
         default:
           NS_NOTREACHED("Unknown speech synthesis");
       }
       break;
 
     case eCSSUnit_Auto:
-    case eCSSUnit_Ident:
+    case eCSSUnit_AtomIdent:
       aSpeakAs.Truncate();
       value.AppendToString(eCSSProperty_UNKNOWN,
                            aSpeakAs, nsCSSValue::eNormalized);
       break;
 
+    case eCSSUnit_Null:
+      aSpeakAs.Truncate();
+      break;
+
     default:
+      NS_NOTREACHED("Unknown speech synthesis");
       aSpeakAs.Truncate();
   }
   return NS_OK;
 }
 
 nsresult
 nsCSSCounterStyleRule::GetDescriptor(nsCSSCounterDesc aDescID,
                                      nsAString& aValue)
--- a/layout/style/nsCSSRules.h
+++ b/layout/style/nsCSSRules.h
@@ -481,22 +481,23 @@ protected:
 };
 
 } // namespace mozilla
 
 class nsCSSCounterStyleRule final : public mozilla::css::Rule,
                                     public nsIDOMCSSCounterStyleRule
 {
 public:
-  explicit nsCSSCounterStyleRule(const nsAString& aName,
+  explicit nsCSSCounterStyleRule(nsIAtom* 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:
   NS_DECL_ISUPPORTS_INHERITED
@@ -539,17 +540,17 @@ public:
   // The XPCOM SetFallback is OK
 
   // 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);
 
-  const nsString& GetName() const { return mName; }
+  nsIAtom* Name() const { return mName; }
 
   uint32_t GetGeneration() const { return mGeneration; }
 
   int32_t GetSystem() const;
   const nsCSSValue& GetSystemArgument() const;
 
   const nsCSSValue& GetDesc(nsCSSCounterDesc aDescID) const
   {
@@ -568,14 +569,14 @@ public:
 private:
   typedef NS_STDCALL_FUNCPROTO(nsresult, Getter, nsCSSCounterStyleRule,
                                GetSymbols, (nsAString&));
   static const Getter kGetters[];
 
   nsresult GetDescriptor(nsCSSCounterDesc aDescID, nsAString& aValue);
   nsresult SetDescriptor(nsCSSCounterDesc aDescID, const nsAString& aValue);
 
-  nsString   mName;
+  nsCOMPtr<nsIAtom> mName;
   nsCSSValue mValues[eCSSCounterDesc_COUNT];
   uint32_t   mGeneration;
 };
 
 #endif /* !defined(nsCSSRules_h_) */
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -502,16 +502,24 @@ void nsCSSValue::SetStringValue(const ns
   mUnit = aUnit;
   MOZ_ASSERT(UnitHasStringValue(), "not a string unit");
   if (UnitHasStringValue()) {
     mValue.mString = BufferFromString(aValue).take();
   } else
     mUnit = eCSSUnit_Null;
 }
 
+void
+nsCSSValue::SetAtomIdentValue(already_AddRefed<nsIAtom> aValue)
+{
+  Reset();
+  mUnit = eCSSUnit_AtomIdent;
+  mValue.mAtom = aValue.take();
+}
+
 void nsCSSValue::SetColorValue(nscolor aValue)
 {
   SetIntegerColorValue(aValue, eCSSUnit_RGBAColor);
 }
 
 
 
 void nsCSSValue::SetIntegerColorValue(nscolor aValue, nsCSSUnit aUnit)
--- a/layout/style/nsCSSValue.h
+++ b/layout/style/nsCSSValue.h
@@ -900,16 +900,17 @@ public:
   {
     static_assert(mozilla::EnumTypeFitsWithin<T, int32_t>::value,
                   "aValue must be an enum that fits within mValue.mInt");
     SetIntValue(static_cast<int32_t>(aValue), eCSSUnit_Enumerated);
   }
   void SetPercentValue(float aValue);
   void SetFloatValue(float aValue, nsCSSUnit aUnit);
   void SetStringValue(const nsString& aValue, nsCSSUnit aUnit);
+  void SetAtomIdentValue(already_AddRefed<nsIAtom> aValue);
   void SetColorValue(nscolor aValue);
   void SetIntegerColorValue(nscolor aValue, nsCSSUnit aUnit);
   // converts the nscoord to pixels
   void SetIntegerCoordValue(nscoord aCoord);
   void SetFloatColorValue(float aComponent1,
                           float aComponent2,
                           float aComponent3,
                           float aAlpha, nsCSSUnit aUnit);
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -8091,51 +8091,49 @@ nsRuleNode::ComputeListData(void* aStart
   switch (typeValue->GetUnit()) {
     case eCSSUnit_Unset:
     case eCSSUnit_Inherit: {
       conditions.SetUncacheable();
       list->SetCounterStyle(parentList->GetCounterStyle());
       break;
     }
     case eCSSUnit_Initial:
-      list->SetListStyleType(NS_LITERAL_STRING("disc"), mPresContext);
-      break;
-    case eCSSUnit_Ident: {
-      nsString typeIdent;
-      typeValue->GetStringValue(typeIdent);
-      list->SetListStyleType(typeIdent, mPresContext);
+      list->SetListStyleType(nsGkAtoms::disc, mPresContext);
+      break;
+    case eCSSUnit_AtomIdent: {
+      list->SetListStyleType(typeValue->GetAtomValue(), mPresContext);
       break;
     }
     case eCSSUnit_String: {
       nsString str;
       typeValue->GetStringValue(str);
       list->SetCounterStyle(new AnonymousCounterStyle(str));
       break;
     }
     case eCSSUnit_Enumerated: {
       // For compatibility with html attribute map.
       // This branch should never be called for value from CSS.
       int32_t intValue = typeValue->GetIntValue();
-      nsAutoString name;
+      nsCOMPtr<nsIAtom> name;
       switch (intValue) {
         case NS_STYLE_LIST_STYLE_LOWER_ROMAN:
-          name.AssignLiteral(u"lower-roman");
+          name = nsGkAtoms::lowerRoman;
           break;
         case NS_STYLE_LIST_STYLE_UPPER_ROMAN:
-          name.AssignLiteral(u"upper-roman");
+          name = nsGkAtoms::upperRoman;
           break;
         case NS_STYLE_LIST_STYLE_LOWER_ALPHA:
-          name.AssignLiteral(u"lower-alpha");
+          name = nsGkAtoms::lowerAlpha;
           break;
         case NS_STYLE_LIST_STYLE_UPPER_ALPHA:
-          name.AssignLiteral(u"upper-alpha");
+          name = nsGkAtoms::upperAlpha;
           break;
         default:
-          CopyASCIItoUTF16(nsCSSProps::ValueToKeyword(
-                  intValue, nsCSSProps::kListStyleKTable), name);
+          name = NS_Atomize(nsCSSProps::ValueToKeyword(
+                  intValue, nsCSSProps::kListStyleKTable));
           break;
       }
       list->SetListStyleType(name, mPresContext);
       break;
     }
     case eCSSUnit_Symbols:
       list->SetCounterStyle(new AnonymousCounterStyle(typeValue->GetArrayValue()));
       break;
--- a/layout/style/nsStyleSet.cpp
+++ b/layout/style/nsStyleSet.cpp
@@ -2250,17 +2250,17 @@ nsStyleSet::KeyframesRuleForName(const n
       ruleProc->KeyframesRuleForName(presContext, aName);
     if (result)
       return result;
   }
   return nullptr;
 }
 
 nsCSSCounterStyleRule*
-nsStyleSet::CounterStyleRuleForName(const nsAString& aName)
+nsStyleSet::CounterStyleRuleForName(nsIAtom* aName)
 {
   NS_ENSURE_FALSE(mInShutdown, nullptr);
   NS_ASSERTION(mBatching == 0, "rule processors out of date");
 
   nsPresContext* presContext = PresContext();
   for (uint32_t i = ArrayLength(gCSSSheetTypes); i-- != 0; ) {
     if (gCSSSheetTypes[i] == SheetType::ScopedDoc)
       continue;
--- a/layout/style/nsStyleSet.h
+++ b/layout/style/nsStyleSet.h
@@ -303,17 +303,17 @@ class nsStyleSet final
   // Append all the currently-active font face rules to aArray.  Return
   // true for success and false for failure.
   bool AppendFontFaceRules(nsTArray<nsFontFaceRuleContainer>& aArray);
 
   // Return the winning (in the cascade) @keyframes rule for the given name.
   nsCSSKeyframesRule* KeyframesRuleForName(const nsString& aName);
 
   // Return the winning (in the cascade) @counter-style rule for the given name.
-  nsCSSCounterStyleRule* CounterStyleRuleForName(const nsAString& aName);
+  nsCSSCounterStyleRule* CounterStyleRuleForName(nsIAtom* aName);
 
   // Fetch object for looking up font feature values
   already_AddRefed<gfxFontFeatureValueSet> GetFontFeatureValuesLookup();
 
   // Append all the currently-active font feature values rules to aArray.
   // Return true for success and false for failure.
   bool AppendFontFeatureValuesRules(
                               nsTArray<nsCSSFontFeatureValuesRule*>& aArray);
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -600,18 +600,18 @@ nsStyleList::nsStyleList(const nsPresCon
   : mListStylePosition(NS_STYLE_LIST_STYLE_POSITION_OUTSIDE)
 {
   MOZ_COUNT_CTOR(nsStyleList);
   if (aContext->StyleSet()->IsServo()) {
     // FIXME: bug 1328319.
     mCounterStyle =
       CounterStyleManager::GetBuiltinStyle(NS_STYLE_LIST_STYLE_DISC);
   } else {
-    mCounterStyle = aContext->CounterStyleManager()->
-      BuildCounterStyle(NS_LITERAL_STRING("disc"));
+    mCounterStyle = aContext->
+      CounterStyleManager()->BuildCounterStyle(nsGkAtoms::disc);
   }
   SetQuotesInitial();
 }
 
 nsStyleList::~nsStyleList()
 {
   MOZ_COUNT_DTOR(nsStyleList);
 }
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1477,18 +1477,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   }
   void SetCounterStyle(mozilla::CounterStyle* aStyle)
   {
     // NB: This function is called off-main-thread during parallel restyle, but
     // only with builtin styles that use dummy refcounting.
     MOZ_ASSERT(NS_IsMainThread() || !aStyle->IsDependentStyle());
     mCounterStyle = aStyle;
   }
-  void SetListStyleType(const nsSubstring& aType,
-                        nsPresContext* aPresContext)
+  void SetListStyleType(nsIAtom* aType, nsPresContext* aPresContext)
   {
     SetCounterStyle(aPresContext->CounterStyleManager()->BuildCounterStyle(aType));
   }
 
   const nsStyleQuoteValues::QuotePairArray& GetQuotePairs() const;
 
   void SetQuotesInherit(const nsStyleList* aOther);
   void SetQuotesInitial();