Bug 1397626 - Part 2: Replace uses of FontFamilyListRefCnt with SharedFontList. r=xidorn draft
authorCameron McCormack <cam@mcc.id.au>
Mon, 02 Oct 2017 10:24:25 +0800
changeset 674180 08c6f6a96d2e81c3758b6550526501db6da86a22
parent 674179 5b70ba48cf1d883e0a78433167dc640a58bae6a3
child 674181 113894ef95d977e88674442cc474e40900fe051f
push id82742
push userbmo:cam@mcc.id.au
push dateTue, 03 Oct 2017 10:03:08 +0000
reviewersxidorn
bugs1397626
milestone58.0a1
Bug 1397626 - Part 2: Replace uses of FontFamilyListRefCnt with SharedFontList. r=xidorn MozReview-Commit-ID: 7HoBae9UOks
gfx/thebes/gfxFontFamilyList.h
layout/style/FontFaceSet.cpp
layout/style/FontFaceSet.h
layout/style/ServoBindings.toml
layout/style/nsCSSParser.cpp
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/nsStyleUtil.cpp
layout/style/nsStyleUtil.h
--- a/gfx/thebes/gfxFontFamilyList.h
+++ b/gfx/thebes/gfxFontFamilyList.h
@@ -193,16 +193,31 @@ public:
     {
     }
 
     explicit SharedFontList(nsTArray<FontFamilyName>&& aNames)
         : mNames(Move(aNames))
     {
     }
 
+    FontFamilyType FirstGeneric() const
+    {
+        for (const FontFamilyName& name : mNames) {
+            if (name.IsGeneric()) {
+                return name.mType;
+            }
+        }
+        return eFamily_none;
+    }
+
+    bool HasGeneric() const
+    {
+        return FirstGeneric() != eFamily_none;
+    }
+
     size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
     {
       size_t n = 0;
       n += aMallocSizeOf(this);
       n += mNames.ShallowSizeOfExcludingThis(aMallocSizeOf);
       for (const FontFamilyName& name : mNames) {
           n += name.SizeOfExcludingThis(aMallocSizeOf);
       }
@@ -254,16 +269,22 @@ public:
     }
 
     FontFamilyList(const FontFamilyList& aOther)
         : mFontlist(aOther.mFontlist)
         , mDefaultFontType(aOther.mDefaultFontType)
     {
     }
 
+    FontFamilyList(const SharedFontList* aFontlist)
+        : mFontlist(aFontlist->mNames)
+        , mDefaultFontType(eFamily_none)
+    {
+    }
+
     void Append(const FontFamilyName& aFamilyName) {
         mFontlist.AppendElement(aFamilyName);
     }
 
     void Append(const nsTArray<nsString>& aFamilyNameList) {
         uint32_t len = aFamilyNameList.Length();
         for (uint32_t i = 0; i < len; i++) {
             mFontlist.AppendElement(FontFamilyName(aFamilyNameList[i],
@@ -287,28 +308,28 @@ public:
         return mFontlist;
     }
 
     bool Equals(const FontFamilyList& aFontlist) const {
         return mFontlist == aFontlist.mFontlist &&
                mDefaultFontType == aFontlist.mDefaultFontType;
     }
 
-    FontFamilyType FirstGeneric() const {
-        uint32_t len = mFontlist.Length();
-        for (uint32_t i = 0; i < len; i++) {
-            const FontFamilyName& name = mFontlist[i];
+    FontFamilyType FirstGeneric() const
+    {
+        for (const FontFamilyName& name : mFontlist) {
             if (name.IsGeneric()) {
                 return name.mType;
             }
         }
         return eFamily_none;
     }
 
-    bool HasGeneric() const {
+    bool HasGeneric() const
+    {
         return FirstGeneric() != eFamily_none;
     }
 
     bool HasDefaultGeneric() const {
         uint32_t len = mFontlist.Length();
         for (uint32_t i = 0; i < len; i++) {
             const FontFamilyName& name = mFontlist[i];
             if (name.mType == mDefaultFontType) {
--- a/layout/style/FontFaceSet.cpp
+++ b/layout/style/FontFaceSet.cpp
@@ -194,17 +194,17 @@ FontFaceSet::RemoveDOMContentLoadedListe
     mDocument->RemoveSystemEventListener(NS_LITERAL_STRING("DOMContentLoaded"),
                                          this, false);
   }
 }
 
 void
 FontFaceSet::ParseFontShorthandForMatching(
                             const nsAString& aFont,
-                            RefPtr<FontFamilyListRefCnt>& aFamilyList,
+                            RefPtr<SharedFontList>& aFamilyList,
                             uint32_t& aWeight,
                             int32_t& aStretch,
                             uint8_t& aStyle,
                             ErrorResult& aRv)
 {
   // Parse aFont as a 'font' property value.
   RefPtr<Declaration> declaration = new Declaration;
   declaration->InitializeEmpty();
@@ -236,18 +236,17 @@ FontFaceSet::ParseFontShorthandForMatchi
 
   const nsCSSValue* family = data->ValueFor(eCSSProperty_font_family);
   if (family->GetUnit() != eCSSUnit_FontFamilyList) {
     // We got inherit, initial, unset, a system font, or a token stream.
     aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
     return;
   }
 
-  aFamilyList =
-    static_cast<FontFamilyListRefCnt*>(family->GetFontFamilyListValue());
+  aFamilyList = family->GetFontFamilyListValue();
 
   int32_t weight = data->ValueFor(eCSSProperty_font_weight)->GetIntValue();
 
   // Resolve relative font weights against the initial of font-weight
   // (normal, which is equivalent to 400).
   if (weight == NS_STYLE_FONT_WEIGHT_BOLDER) {
     weight = NS_FONT_WEIGHT_BOLD;
   } else if (weight == NS_STYLE_FONT_WEIGHT_LIGHTER) {
@@ -277,17 +276,17 @@ HasAnyCharacterInUnicodeRange(gfxUserFon
 }
 
 void
 FontFaceSet::FindMatchingFontFaces(const nsAString& aFont,
                                    const nsAString& aText,
                                    nsTArray<FontFace*>& aFontFaces,
                                    ErrorResult& aRv)
 {
-  RefPtr<FontFamilyListRefCnt> familyList;
+  RefPtr<SharedFontList> familyList;
   uint32_t weight;
   int32_t stretch;
   uint8_t italicStyle;
   ParseFontShorthandForMatching(aFont, familyList, weight, stretch, italicStyle,
                                 aRv);
   if (aRv.Failed()) {
     return;
   }
@@ -299,17 +298,17 @@ FontFaceSet::FindMatchingFontFaces(const
 
   nsTArray<FontFaceRecord>* arrays[2];
   arrays[0] = &mNonRuleFaces;
   arrays[1] = &mRuleFaces;
 
   // Set of FontFaces that we want to return.
   nsTHashtable<nsPtrHashKey<FontFace>> matchingFaces;
 
-  for (const FontFamilyName& fontFamilyName : familyList->GetFontlist()) {
+  for (const FontFamilyName& fontFamilyName : familyList->mNames) {
     RefPtr<gfxFontFamily> family =
       mUserFontSet->LookupFamily(fontFamilyName.mName);
 
     if (!family) {
       continue;
     }
 
     AutoTArray<gfxFontEntry*,4> entries;
--- a/layout/style/FontFaceSet.h
+++ b/layout/style/FontFaceSet.h
@@ -17,19 +17,17 @@ struct gfxFontFaceSrc;
 class gfxFontSrcPrincipal;
 class gfxUserFontEntry;
 class nsFontFaceLoader;
 class nsIPrincipal;
 class nsPIDOMWindowInner;
 
 namespace mozilla {
 class PostTraversalTask;
-namespace css {
-class FontFamilyListRefCnt;
-} // namespace css
+class SharedFontList;
 namespace dom {
 class FontFace;
 class Promise;
 } // namespace dom
 } // namespace mozilla
 
 namespace mozilla {
 namespace dom {
@@ -310,17 +308,17 @@ private:
    */
   bool HasLoadingFontFaces();
 
   // Helper function for HasLoadingFontFaces.
   void UpdateHasLoadingFontFaces();
 
   void ParseFontShorthandForMatching(
               const nsAString& aFont,
-              RefPtr<mozilla::css::FontFamilyListRefCnt>& aFamilyList,
+              RefPtr<SharedFontList>& aFamilyList,
               uint32_t& aWeight,
               int32_t& aStretch,
               uint8_t& aStyle,
               ErrorResult& aRv);
   void FindMatchingFontFaces(const nsAString& aFont,
                              const nsAString& aText,
                              nsTArray<FontFace*>& aFontFaces,
                              mozilla::ErrorResult& aRv);
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -172,17 +172,16 @@ whitelist-types = [
     ".*ThreadSafe.*Holder",
     "AnonymousContent",
     "AudioContext",
     "CapturingContentInfo",
     "DefaultDelete",
     "DOMIntersectionObserverEntry",
     "Element",
     "FontFamilyList",
-    "FontFamilyListRefCnt",
     "FontFamilyName",
     "FontFamilyType",
     "FontSizePrefs",
     "FragmentOrURL",
     "FrameRequestCallback",
     "GeckoParserExtraData",
     "GeckoFontMetrics",
     "gfxAlternateValue",
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -4034,25 +4034,25 @@ CSSParserImpl::ParseFontFeatureValuesRul
   if (!ParseFamily(fontlistValue) ||
       fontlistValue.GetUnit() != eCSSUnit_FontFamilyList)
   {
     REPORT_UNEXPECTED_TOKEN(PEFFVNoFamily);
     return false;
   }
 
   // add family to rule
-  const FontFamilyList* fontlist = fontlistValue.GetFontFamilyListValue();
+  SharedFontList* fontlist = fontlistValue.GetFontFamilyListValue();
 
   // family list has generic ==> parse error
   if (fontlist->HasGeneric()) {
     REPORT_UNEXPECTED_TOKEN(PEFFVGenericInFamilyList);
     return false;
   }
 
-  valuesRule->SetFamilyList(*fontlist);
+  valuesRule->SetFamilyList(fontlist);
 
   // open brace
   if (!ExpectSymbol('{', true)) {
     REPORT_UNEXPECTED_TOKEN(PEFFVBlockStart);
     return false;
   }
 
   // list of sets of feature values, each set bound to a specific
@@ -11992,18 +11992,18 @@ CSSParserImpl::ParseFontDescriptorValue(
     // possibly with more restrictions on the values they can take.
   case eCSSFontDesc_Family: {
     nsCSSValue value;
     if (!ParseFamily(value) ||
         value.GetUnit() != eCSSUnit_FontFamilyList)
       return false;
 
     // name can only be a single, non-generic name
-    const FontFamilyList* f = value.GetFontFamilyListValue();
-    const nsTArray<FontFamilyName>& fontlist = f->GetFontlist();
+    const SharedFontList* f = value.GetFontFamilyListValue();
+    const nsTArray<FontFamilyName>& fontlist = f->mNames;
 
     if (fontlist.Length() != 1 || !fontlist[0].IsNamed()) {
       return false;
     }
 
     aValue.SetStringValue(fontlist[0].mName, eCSSUnit_String);
     return true;
   }
@@ -14766,49 +14766,48 @@ CSSParserImpl::ParseOneFamily(nsAString&
   } else {
     UngetToken();
     return false;
   }
 }
 
 
 static bool
-AppendGeneric(nsCSSKeyword aKeyword, FontFamilyList *aFamilyList)
+AppendGeneric(nsCSSKeyword aKeyword, nsTArray<FontFamilyName>& aFamilyList)
 {
   switch (aKeyword) {
     case eCSSKeyword_serif:
-      aFamilyList->Append(FontFamilyName(eFamily_serif));
+      aFamilyList.AppendElement(FontFamilyName(eFamily_serif));
       return true;
     case eCSSKeyword_sans_serif:
-      aFamilyList->Append(FontFamilyName(eFamily_sans_serif));
+      aFamilyList.AppendElement(FontFamilyName(eFamily_sans_serif));
       return true;
     case eCSSKeyword_monospace:
-      aFamilyList->Append(FontFamilyName(eFamily_monospace));
+      aFamilyList.AppendElement(FontFamilyName(eFamily_monospace));
       return true;
     case eCSSKeyword_cursive:
-      aFamilyList->Append(FontFamilyName(eFamily_cursive));
+      aFamilyList.AppendElement(FontFamilyName(eFamily_cursive));
       return true;
     case eCSSKeyword_fantasy:
-      aFamilyList->Append(FontFamilyName(eFamily_fantasy));
+      aFamilyList.AppendElement(FontFamilyName(eFamily_fantasy));
       return true;
     case eCSSKeyword__moz_fixed:
-      aFamilyList->Append(FontFamilyName(eFamily_moz_fixed));
+      aFamilyList.AppendElement(FontFamilyName(eFamily_moz_fixed));
       return true;
     default:
       break;
   }
 
   return false;
 }
 
 bool
 CSSParserImpl::ParseFamily(nsCSSValue& aValue)
 {
-  RefPtr<css::FontFamilyListRefCnt> familyList =
-    new css::FontFamilyListRefCnt();
+  nsTArray<FontFamilyName> families;
   nsAutoString family;
   bool single, quoted;
 
   // keywords only have meaning in the first position
   if (!ParseOneFamily(family, single, quoted))
     return false;
 
   // check for keywords, but only when keywords appear by themselves
@@ -14834,22 +14833,22 @@ CSSParserImpl::ParseFamily(nsCSSValue& a
         break;
       case eCSSKeyword__moz_use_system_font:
         if (!IsParsingCompoundProperty()) {
           aValue.SetSystemFontValue();
           return true;
         }
         break;
       default:
-        foundGeneric = AppendGeneric(keyword, familyList);
+        foundGeneric = AppendGeneric(keyword, families);
     }
   }
 
   if (!foundGeneric) {
-    familyList->Append(
+    families.AppendElement(
       FontFamilyName(family, (quoted ? eQuotedName : eUnquotedName)));
   }
 
   for (;;) {
     if (!ExpectSymbol(',', true))
       break;
 
     nsAutoString nextFamily;
@@ -14868,32 +14867,34 @@ CSSParserImpl::ParseFamily(nsCSSValue& a
         case eCSSKeyword__moz_use_system_font:
           return false;
         case eCSSKeyword_unset:
           if (nsLayoutUtils::UnsetValueEnabled()) {
             return false;
           }
           break;
         default:
-          foundGeneric = AppendGeneric(keyword, familyList);
+          foundGeneric = AppendGeneric(keyword, families);
           break;
       }
     }
 
     if (!foundGeneric) {
-      familyList->Append(
+      families.AppendElement(
         FontFamilyName(nextFamily, (quoted ? eQuotedName : eUnquotedName)));
     }
   }
 
-  if (familyList->IsEmpty()) {
-    return false;
-  }
-
-  aValue.SetFontFamilyListValue(familyList);
+  if (families.IsEmpty()) {
+    return false;
+  }
+
+  RefPtr<SharedFontList> familyList =
+    new SharedFontList(Move(families));
+  aValue.SetFontFamilyListValue(familyList.forget());
   return true;
 }
 
 // src: ( uri-src | local-src ) (',' ( uri-src | local-src ) )*
 // uri-src: uri [ 'format(' string ( ',' string )* ')' ]
 // local-src: 'local(' ( string | ident ) ')'
 
 bool
--- a/layout/style/nsCSSRules.cpp
+++ b/layout/style/nsCSSRules.cpp
@@ -1297,17 +1297,17 @@ FeatureValuesToString(
       aOutStr.Append(';');
     }
     aOutStr.AppendLiteral(" }\n");
   }
 }
 
 static void
 FontFeatureValuesRuleToString(
-  const mozilla::FontFamilyList& aFamilyList,
+  mozilla::SharedFontList* aFamilyList,
   const nsTArray<gfxFontFeatureValueSet::FeatureValues>& aFeatureValues,
   nsAString& aOutStr)
 {
   aOutStr.AssignLiteral("@font-feature-values ");
   nsAutoString familyListStr, valueTextStr;
   nsStyleUtil::AppendEscapedCSSFontFamilyList(aFamilyList, familyListStr);
   aOutStr.Append(familyListStr);
   aOutStr.AppendLiteral(" {\n");
@@ -1393,23 +1393,16 @@ struct MakeFamilyArray {
     return true;
   }
 
   nsTArray<nsString>& familyArray;
   bool hasGeneric;
 };
 
 void
-nsCSSFontFeatureValuesRule::SetFamilyList(
-  const mozilla::FontFamilyList& aFamilyList)
-{
-  mFamilyList = aFamilyList;
-}
-
-void
 nsCSSFontFeatureValuesRule::AddValueList(int32_t aVariantAlternate,
                      nsTArray<gfxFontFeatureValueSet::ValueList>& aValueList)
 {
   uint32_t i, len = mFeatureValues.Length();
   bool foundAlternate = false;
 
   // add to an existing list for a given property value
   for (i = 0; i < len; i++) {
--- a/layout/style/nsCSSRules.h
+++ b/layout/style/nsCSSRules.h
@@ -185,33 +185,36 @@ public:
   already_AddRefed<mozilla::css::Rule> Clone() const final;
 
   // nsIDOMCSSFontFeatureValuesRule interface
   NS_DECL_NSIDOMCSSFONTFEATUREVALUESRULE
 
   // WebIDL interface
   void GetCssTextImpl(nsAString& aCssText) const final;
 
-  const mozilla::FontFamilyList& GetFamilyList() { return mFamilyList; }
-  void SetFamilyList(const mozilla::FontFamilyList& aFamilyList);
+  mozilla::SharedFontList* GetFamilyList() const { return mFamilyList; }
+  void SetFamilyList(mozilla::SharedFontList* aFamilyList)
+  {
+    mFamilyList = aFamilyList;
+  }
 
   void AddValueList(int32_t aVariantAlternate,
                     nsTArray<gfxFontFeatureValueSet::ValueList>& aValueList);
 
   const nsTArray<gfxFontFeatureValueSet::FeatureValues>& GetFeatureValues()
   {
     return mFeatureValues;
   }
 
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const final;
 
 protected:
   ~nsCSSFontFeatureValuesRule() {}
 
-  mozilla::FontFamilyList mFamilyList;
+  RefPtr<mozilla::SharedFontList> mFamilyList;
   nsTArray<gfxFontFeatureValueSet::FeatureValues> mFeatureValues;
 };
 
 class nsCSSKeyframeRule;
 
 class nsCSSKeyframeStyleDeclaration final : public nsDOMCSSDeclaration
 {
 public:
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -125,17 +125,17 @@ nsCSSValue::nsCSSValue(nsCSSValueTokenSt
 
 nsCSSValue::nsCSSValue(mozilla::css::GridTemplateAreasValue* aValue)
   : mUnit(eCSSUnit_GridTemplateAreas)
 {
   mValue.mGridTemplateAreas = aValue;
   mValue.mGridTemplateAreas->AddRef();
 }
 
-nsCSSValue::nsCSSValue(css::FontFamilyListRefCnt* aValue)
+nsCSSValue::nsCSSValue(SharedFontList* aValue)
   : mUnit(eCSSUnit_FontFamilyList)
 {
   mValue.mFontFamilyList = aValue;
   mValue.mFontFamilyList->AddRef();
 }
 
 nsCSSValue::nsCSSValue(const nsCSSValue& aCopy)
   : mUnit(aCopy.mUnit)
@@ -315,17 +315,18 @@ bool nsCSSValue::operator==(const nsCSSV
     else if (eCSSUnit_PairList == mUnit) {
       return nsCSSValuePairList::Equal(mValue.mPairList,
                                        aOther.mValue.mPairList);
     }
     else if (eCSSUnit_GridTemplateAreas == mUnit) {
       return *mValue.mGridTemplateAreas == *aOther.mValue.mGridTemplateAreas;
     }
     else if (eCSSUnit_FontFamilyList == mUnit) {
-      return *mValue.mFontFamilyList == *aOther.mValue.mFontFamilyList;
+      return mValue.mFontFamilyList->mNames ==
+             aOther.mValue.mFontFamilyList->mNames;
     }
     else if (eCSSUnit_AtomIdent == mUnit) {
       return mValue.mAtom == aOther.mValue.mAtom;
     }
     else {
       return mValue.mFloat == aOther.mValue.mFloat;
     }
   }
@@ -612,22 +613,21 @@ void nsCSSValue::SetTokenStreamValue(nsC
 void nsCSSValue::SetGridTemplateAreas(mozilla::css::GridTemplateAreasValue* aValue)
 {
   Reset();
   mUnit = eCSSUnit_GridTemplateAreas;
   mValue.mGridTemplateAreas = aValue;
   mValue.mGridTemplateAreas->AddRef();
 }
 
-void nsCSSValue::SetFontFamilyListValue(css::FontFamilyListRefCnt* aValue)
+void nsCSSValue::SetFontFamilyListValue(already_AddRefed<SharedFontList> aValue)
 {
   Reset();
   mUnit = eCSSUnit_FontFamilyList;
-  mValue.mFontFamilyList = aValue;
-  mValue.mFontFamilyList->AddRef();
+  mValue.mFontFamilyList = aValue.take();
 }
 
 void nsCSSValue::SetPairValue(const nsCSSValuePair* aValue)
 {
   // pairs should not be used for null/inherit/initial values
   MOZ_ASSERT(aValue &&
              aValue->mXValue.GetUnit() != eCSSUnit_Null &&
              aValue->mYValue.GetUnit() != eCSSUnit_Null &&
@@ -1984,17 +1984,17 @@ nsCSSValue::AppendToString(nsCSSProperty
     MOZ_ASSERT(!areas->mTemplates.IsEmpty(),
                "Unexpected empty array in GridTemplateAreasValue");
     nsStyleUtil::AppendEscapedCSSString(areas->mTemplates[0], aResult);
     for (uint32_t i = 1; i < areas->mTemplates.Length(); i++) {
       aResult.Append(char16_t(' '));
       nsStyleUtil::AppendEscapedCSSString(areas->mTemplates[i], aResult);
     }
   } else if (eCSSUnit_FontFamilyList == unit) {
-    nsStyleUtil::AppendEscapedCSSFontFamilyList(*mValue.mFontFamilyList,
+    nsStyleUtil::AppendEscapedCSSFontFamilyList(mValue.mFontFamilyList,
                                                 aResult);
   } else if (eCSSUnit_AtomIdent == unit) {
     nsDependentAtomString buffer(GetAtomValue());
     nsStyleUtil::AppendEscapedCSSIdent(buffer, aResult);
   }
 
   switch (unit) {
     case eCSSUnit_Null:         break;
--- a/layout/style/nsCSSValue.h
+++ b/layout/style/nsCSSValue.h
@@ -331,41 +331,16 @@ private:
   {
   }
 
   GridTemplateAreasValue(const GridTemplateAreasValue& aOther) = delete;
   GridTemplateAreasValue&
   operator=(const GridTemplateAreasValue& aOther) = delete;
 };
 
-class FontFamilyListRefCnt final : public FontFamilyList {
-public:
-    FontFamilyListRefCnt()
-        : FontFamilyList()
-    {}
-
-    explicit FontFamilyListRefCnt(FontFamilyType aGenericType)
-        : FontFamilyList(aGenericType)
-    {}
-
-    FontFamilyListRefCnt(const nsAString& aFamilyName,
-                         QuotedName aQuoted)
-        : FontFamilyList(aFamilyName, aQuoted)
-    {}
-
-    FontFamilyListRefCnt(const FontFamilyListRefCnt& aOther)
-        : FontFamilyList(aOther)
-    {}
-
-    NS_INLINE_DECL_REFCOUNTING(FontFamilyListRefCnt);
-
-private:
-    ~FontFamilyListRefCnt() {}
-};
-
 struct RGBAColorData
 {
   // 1.0 means 100% for all components, but the value may fall outside
   // the range of [0.0, 1.0], so it is necessary to clamp them when
   // converting to nscolor.
   float mR;
   float mG;
   float mB;
@@ -523,17 +498,17 @@ enum nsCSSUnit {
   eCSSUnit_ListDep      = 54,     // (nsCSSValueList*) same as List
                                   //   but does not own the list
   eCSSUnit_SharedList   = 55,     // (nsCSSValueSharedList*) same as list
                                   //   but reference counted and shared
   eCSSUnit_PairList     = 56,     // (nsCSSValuePairList*) list of value pairs
   eCSSUnit_PairListDep  = 57,     // (nsCSSValuePairList*) same as PairList
                                   //   but does not own the list
 
-  eCSSUnit_FontFamilyList = 58,   // (FontFamilyList*) value
+  eCSSUnit_FontFamilyList = 58,   // (SharedFontList*) value
 
   // Atom units
   eCSSUnit_AtomIdent    = 60,     // (nsIAtom*) for its string as an identifier
 
   eCSSUnit_Integer      = 70,     // (int) simple value
   eCSSUnit_Enumerated   = 71,     // (int) value has enumerated meaning
 
   eCSSUnit_EnumColor           = 80,   // (int) enumerated color (kColorKTable)
@@ -636,17 +611,17 @@ public:
   nsCSSValue(float aValue, nsCSSUnit aUnit);
   nsCSSValue(const nsString& aValue, nsCSSUnit aUnit);
   nsCSSValue(Array* aArray, nsCSSUnit aUnit);
   explicit nsCSSValue(mozilla::css::URLValue* aValue);
   explicit nsCSSValue(mozilla::css::ImageValue* aValue);
   explicit nsCSSValue(nsCSSValueGradient* aValue);
   explicit nsCSSValue(nsCSSValueTokenStream* aValue);
   explicit nsCSSValue(mozilla::css::GridTemplateAreasValue* aValue);
-  explicit nsCSSValue(mozilla::css::FontFamilyListRefCnt* aValue);
+  explicit nsCSSValue(mozilla::SharedFontList* aValue);
   nsCSSValue(const nsCSSValue& aCopy);
   nsCSSValue(nsCSSValue&& aOther)
     : mUnit(aOther.mUnit)
     , mValue(aOther.mValue)
   {
     aOther.mUnit = eCSSUnit_Null;
   }
   ~nsCSSValue() { Reset(); }
@@ -838,17 +813,17 @@ public:
   }
 
   nsCSSValueSharedList* GetSharedListValue() const
   {
     MOZ_ASSERT(mUnit == eCSSUnit_SharedList, "not a shared list value");
     return mValue.mSharedList;
   }
 
-  mozilla::FontFamilyList* GetFontFamilyListValue() const
+  mozilla::SharedFontList* GetFontFamilyListValue() const
   {
     MOZ_ASSERT(mUnit == eCSSUnit_FontFamilyList,
                "not a font family list value");
     NS_ASSERTION(mValue.mFontFamilyList != nullptr,
                  "font family list value should never be null");
     return mValue.mFontFamilyList;
   }
 
@@ -957,17 +932,17 @@ public:
   void SetComplexColorValue(
     already_AddRefed<mozilla::css::ComplexColorValue> aValue);
   void SetArrayValue(nsCSSValue::Array* aArray, nsCSSUnit aUnit);
   void SetURLValue(mozilla::css::URLValue* aURI);
   void SetImageValue(mozilla::css::ImageValue* aImage);
   void SetGradientValue(nsCSSValueGradient* aGradient);
   void SetTokenStreamValue(nsCSSValueTokenStream* aTokenStream);
   void SetGridTemplateAreas(mozilla::css::GridTemplateAreasValue* aValue);
-  void SetFontFamilyListValue(mozilla::css::FontFamilyListRefCnt* aFontListValue);
+  void SetFontFamilyListValue(already_AddRefed<mozilla::SharedFontList> aFontListValue);
   void SetPairValue(const nsCSSValuePair* aPair);
   void SetPairValue(const nsCSSValue& xValue, const nsCSSValue& yValue);
   void SetSharedListValue(nsCSSValueSharedList* aList);
   void SetDependentListValue(nsCSSValueList* aList);
   void SetDependentPairListValue(nsCSSValuePairList* aList);
   void SetTripletValue(const nsCSSValueTriplet* aTriplet);
   void SetTripletValue(const nsCSSValue& xValue, const nsCSSValue& yValue, const nsCSSValue& zValue);
   void SetAutoValue();
@@ -1059,17 +1034,17 @@ protected:
     nsCSSRect_heap* MOZ_OWNING_REF mRect;
     nsCSSValueTriplet_heap* MOZ_OWNING_REF mTriplet;
     nsCSSValueList_heap* MOZ_OWNING_REF mList;
     nsCSSValueList* mListDependent;
     nsCSSValueSharedList* MOZ_OWNING_REF mSharedList;
     nsCSSValuePairList_heap* MOZ_OWNING_REF mPairList;
     nsCSSValuePairList* mPairListDependent;
     nsCSSValueFloatColor* MOZ_OWNING_REF mFloatColor;
-    mozilla::css::FontFamilyListRefCnt* MOZ_OWNING_REF mFontFamilyList;
+    mozilla::SharedFontList* MOZ_OWNING_REF mFontFamilyList;
     mozilla::css::ComplexColorValue* MOZ_OWNING_REF mComplexColor;
   } mValue;
 };
 
 struct nsCSSValue::Array final {
 
   // return |Array| with reference count of zero
   static Array* Create(size_t aItemCount) {
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -4371,26 +4371,23 @@ nsRuleNode::ComputeFontData(void* aStart
   // using the 'font' shorthand).
 
   // Figure out if we are a generic font
   uint8_t generic = kGenericFont_NONE;
   // XXXldb What if we would have had a string if we hadn't been doing
   // the optimization with a non-null aStartStruct?
   const nsCSSValue* familyValue = aRuleData->ValueForFontFamily();
   if (eCSSUnit_FontFamilyList == familyValue->GetUnit()) {
-    const FontFamilyList* fontlist = familyValue->GetFontFamilyListValue();
-    FontFamilyList& fl = font->mFont.fontlist;
-    fl = *fontlist;
-
-    // extract the first generic in the fontlist, if exists
-    FontFamilyType fontType = fontlist->FirstGeneric();
+    const SharedFontList* fontlist = familyValue->GetFontFamilyListValue();
+    font->mFont.fontlist = FontFamilyList(fontlist);
 
     // if only a single generic, set the generic type
-    if (fontlist->Length() == 1) {
-      switch (fontType) {
+    if (fontlist->mNames.Length() == 1) {
+      // extract the first generic in the fontlist, if exists
+      switch (font->mFont.fontlist.FirstGeneric()) {
         case eFamily_serif:
           generic = kGenericFont_serif;
           break;
         case eFamily_sans_serif:
           generic = kGenericFont_sans_serif;
           break;
         case eFamily_monospace:
           generic = kGenericFont_monospace;
--- a/layout/style/nsStyleSet.cpp
+++ b/layout/style/nsStyleSet.cpp
@@ -2291,17 +2291,17 @@ nsStyleSet::BuildFontFeatureValueSet()
   AppendFontFeatureValuesRules(rules);
 
   if (rules.IsEmpty()) {
     return nullptr;
   }
 
   RefPtr<gfxFontFeatureValueSet> set = new gfxFontFeatureValueSet();
   for (nsCSSFontFeatureValuesRule* rule : rules) {
-    const nsTArray<FontFamilyName>& familyList = rule->GetFamilyList().GetFontlist();
+    const nsTArray<FontFamilyName>& familyList = rule->GetFamilyList()->mNames;
     const nsTArray<gfxFontFeatureValueSet::FeatureValues>&
       featureValues = rule->GetFeatureValues();
 
     for (const FontFamilyName& f : familyList) {
       set->AddFontFeatureValues(f.mName, featureValues);
     }
   }
   return set.forget();
--- a/layout/style/nsStyleUtil.cpp
+++ b/layout/style/nsStyleUtil.cpp
@@ -201,49 +201,57 @@ AppendUnquotedFamilyName(const nsAString
      }
 
      ++p;
   }
 }
 
 /* static */ void
 nsStyleUtil::AppendEscapedCSSFontFamilyList(
+  const nsTArray<mozilla::FontFamilyName>& aNames,
+  nsAString& aResult)
+{
+  size_t i, len = aNames.Length();
+  for (i = 0; i < len; i++) {
+    if (i != 0) {
+      aResult.AppendLiteral(", ");
+    }
+    const FontFamilyName& name = aNames[i];
+    switch (name.mType) {
+      case eFamily_named:
+        AppendUnquotedFamilyName(name.mName, aResult);
+        break;
+      case eFamily_named_quoted:
+        AppendEscapedCSSString(name.mName, aResult);
+        break;
+      default:
+        name.AppendToString(aResult);
+    }
+  }
+}
+
+/* static */ void
+nsStyleUtil::AppendEscapedCSSFontFamilyList(
   const mozilla::FontFamilyList& aFamilyList,
   nsAString& aResult)
 {
   if (aFamilyList.IsEmpty()) {
     FontFamilyType defaultGeneric = aFamilyList.GetDefaultFontType();
     // If the font list is empty, then serialize the default generic.
     // See also: gfxFontGroup::BuildFontList()
     if (defaultGeneric != eFamily_none) {
       FontFamilyName(defaultGeneric).AppendToString(aResult);
     } else {
       NS_NOTREACHED("No fonts to serialize");
     }
     return;
   }
 
   const nsTArray<FontFamilyName>& fontlist = aFamilyList.GetFontlist();
-  size_t i, len = fontlist.Length();
-  for (i = 0; i < len; i++) {
-    if (i != 0) {
-      aResult.AppendLiteral(", ");
-    }
-    const FontFamilyName& name = fontlist[i];
-    switch (name.mType) {
-      case eFamily_named:
-        AppendUnquotedFamilyName(name.mName, aResult);
-        break;
-      case eFamily_named_quoted:
-        AppendEscapedCSSString(name.mName, aResult);
-        break;
-      default:
-        name.AppendToString(aResult);
-    }
-  }
+  AppendEscapedCSSFontFamilyList(fontlist, aResult);
 }
 
 
 /* static */ void
 nsStyleUtil::AppendBitmaskCSSValue(nsCSSPropertyID aProperty,
                                    int32_t aMaskedValue,
                                    int32_t aFirstMask,
                                    int32_t aLastMask,
--- a/layout/style/nsStyleUtil.h
+++ b/layout/style/nsStyleUtil.h
@@ -46,17 +46,29 @@ public:
   // identifier.  An exception is if aIdent contains U+0000, which
   // will be escaped as U+FFFD and then reparsed back to U+FFFD.
   static void AppendEscapedCSSIdent(const nsAString& aIdent,
                                     nsAString& aResult);
 
   static void
   AppendEscapedCSSFontFamilyList(const mozilla::FontFamilyList& aFamilyList,
                                  nsAString& aResult);
+  static void
+  AppendEscapedCSSFontFamilyList(mozilla::SharedFontList* aFontlist,
+                                 nsAString& aResult)
+  {
+    AppendEscapedCSSFontFamilyList(aFontlist->mNames, aResult);
+  }
 
+private:
+  static void
+  AppendEscapedCSSFontFamilyList(const nsTArray<mozilla::FontFamilyName>& aNames,
+                                 nsAString& aResult);
+
+public:
   // Append a bitmask-valued property's value(s) (space-separated) to aResult.
   static void AppendBitmaskCSSValue(nsCSSPropertyID aProperty,
                                     int32_t aMaskedValue,
                                     int32_t aFirstMask,
                                     int32_t aLastMask,
                                     nsAString& aResult);
 
   static void AppendAngleValue(const nsStyleCoord& aValue, nsAString& aResult);